Commit 2cb0054b authored by gmantele's avatar gmantele
Browse files

[UWS,TAP] Review some log messages (in the log file but also in the error...

[UWS,TAP] Review some log messages (in the log file but also in the error summary of a job) ; particularly stack traces are added into the error summary, but are displayed just once in the logs.
parent 18f4cc58
Loading
Loading
Loading
Loading
+5 −11
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ import uws.service.log.UWSLog.LogLevel;
 * </p>
 * 
 * @author Gr&eacute;gory Mantelet (CDS;ARI)
 * @version 2.0 (11/2014)
 * @version 2.0 (12/2014)
 */
public class TAPSyncJob {

@@ -174,13 +174,7 @@ public class TAPSyncJob {
		service.getLogger().logTAP(LogLevel.INFO, this, "SYNC_START", "Synchronous job " + ID + " is starting!", null);

		// Create the object having the knowledge about how to execute an ADQL query:
		ADQLExecutor executor;
		try{
			executor = service.getFactory().createADQLExecutor();
		}catch(TAPException e){
			service.getLogger().logTAP(LogLevel.ERROR, this, "SYNC_START", "An error has prevented the synchronous thread " + getID() + " to start!", e);
			return false;
		}
		ADQLExecutor executor = service.getFactory().createADQLExecutor();

		// Give to a thread which will execute the query:
		thread = new SyncThread(executor, ID, tapParams, response);
@@ -222,14 +216,14 @@ public class TAPSyncJob {
			// INTERRUPTION:
			if (error instanceof InterruptedException){
				// log the unexpected interruption (unexpected because not caused by a timeout):
				service.getLogger().logTAP(LogLevel.WARNING, this, "SYNC_END", "The execution of the synchronous job " + ID + " has been unexpectedly interrupted!", error);
				service.getLogger().logTAP(LogLevel.WARNING, this, "SYNC_END", "The execution of the synchronous job " + ID + " has been unexpectedly interrupted!", null);
				// report the unexpected interruption to the user:
				throw new TAPException("The execution of this synchronous job " + ID + " has been unexpectedly aborted!", UWSException.ACCEPTED_BUT_NOT_COMPLETE);
			}
			// TAP EXCEPTION:
			else if (error instanceof TAPException){
				// log the error:
				service.getLogger().logTAP(LogLevel.ERROR, this, "SYNC_END", "An error occured while executing the query of the synchronous job " + ID + ".", error);
				service.getLogger().logTAP(LogLevel.ERROR, this, "SYNC_END", "An error occured while executing the query of the synchronous job " + ID + ".", null);
				// report the error to the user:
				throw (TAPException)error;
			}
@@ -349,7 +343,7 @@ public class TAPSyncJob {
					executor.getLogger().logThread(LogLevel.FATAL, this, "END", "Synchronous thread \"" + ID + "\" ended with a FATAL error.", exception);
				else
					// Error:
					executor.getLogger().logThread(LogLevel.ERROR, this, "END", "Synchronous thread \"" + ID + "\" ended with an error.", exception);
					executor.getLogger().logThread(LogLevel.ERROR, this, "END", "Synchronous thread \"" + ID + "\" ended with an error.", null);
			}
		}

+61 −5
Original line number Diff line number Diff line
@@ -20,10 +20,14 @@ package tap.error;
 *                       Astronomisches Rechen Institut (ARI)
 */

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -185,7 +189,7 @@ public class DefaultTAPErrorWriter implements ServiceErrorWriter {
		response.setContentType("application/xml");

		// List any additional information useful to report to the user:
		HashMap<String,String> addInfos = new HashMap<String,String>();
		Map<String,String> addInfos = new LinkedHashMap<String,String>();
		if (reqID != null)
			addInfos.put("REQ_ID", reqID);
		if (type != null)
@@ -211,20 +215,72 @@ public class DefaultTAPErrorWriter implements ServiceErrorWriter {
			message = "{NO MESSAGE}";

		// List any additional information useful to report to the user:
		HashMap<String,String> addInfos = new HashMap<String,String>();
		Map<String,String> addInfos = new LinkedHashMap<String,String>();
		// error type:
		if (error != null && error.getType() != null)
			addInfos.put("ERROR_TYPE", error.getType().toString());
		// infos about the exception:
		putExceptionInfos(t, addInfos);
		// job ID:
		if (job != null){
			addInfos.put("JOB_ID", job.getJobId());
			if (job.getOwner() != null)
				addInfos.put("USER", job.getOwner().getID() + ((job.getOwner().getPseudo() == null) ? "" : " (" + job.getOwner().getPseudo() + ")"));
		}
		if (error != null && error.getType() != null)
			addInfos.put("ERROR_TYPE", error.getType().toString());
		// action running while the error occurred (only one is possible here: EXECUTING an ADQL query):
		addInfos.put("ACTION", "EXECUTING");

		// Format the error in VOTable and write the document in the given HTTP response:
		getFormatter().writeError(message, addInfos, new PrintWriter(output));
	}

	/**
	 * Add all interesting additional information about the given exception inside the given map.
	 * 
	 * @param t			Exception whose some details must be added inside the given map.
	 * @param addInfos	Map of all additional information.
	 * 
	 * @since 2.0
	 */
	protected void putExceptionInfos(final Throwable t, final Map<String,String> addInfos){
		if (t != null){
			// Browse the exception stack in order to list all exceptions' messages and to get the last cause of this error:
			StringBuffer causes = new StringBuffer();
			Throwable cause = t.getCause(), lastCause = t;
			int nbCauses = 0, nbStackTraces = 1;
			while(cause != null){
				// new line:
				causes.append('\n');
				// append the message:
				causes.append("\t- ").append(cause.getMessage());
				// SQLException case:
				if (cause instanceof SQLException){
					SQLException se = (SQLException)cause;
					while(se.getNextException() != null){
						se = se.getNextException();
						causes.append("\n\t\t- ").append(se.getMessage());
					}
				}
				// go to the next message:
				lastCause = cause;
				cause = cause.getCause();
				nbCauses++;
				nbStackTraces++;
			}

			// Add the list of all causes' message:
			if (causes.length() > 0)
				addInfos.put("CAUSES", "\n" + nbCauses + causes.toString());

			// Add the stack trace of the original exception ONLY IF NOT A TAP OR A UWS EXCEPTION (only unexpected error should be detailed to the users):
			if (!(lastCause instanceof TAPException && lastCause instanceof UWSException)){
				ByteArrayOutputStream stackTrace = new ByteArrayOutputStream();
				lastCause.printStackTrace(new PrintStream(stackTrace));
				addInfos.put("ORIGIN_STACK_TRACE", "\n" + nbStackTraces + "\n" + stackTrace.toString());
			}
		}
	}

	@Override
	public String getErrorDetailsMIMEType(){
		return "application/xml";
+13 −3
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ import adql.db.DBType.DBDatatype;
 * </p>
 * 
 * @author Gr&eacute;gory Mantelet (CDS;ARI)
 * @version 2.0 (10/2014)
 * @version 2.0 (12/2014)
 */
public class VOTableFormat implements OutputFormat {

@@ -330,10 +330,20 @@ public class VOTableFormat implements OutputFormat {
			Iterator<Map.Entry<String,String>> it = otherInfo.entrySet().iterator();
			while(it.hasNext()){
				Map.Entry<String,String> entry = it.next();
				if (entry.getValue() != null){
					if (entry.getValue().startsWith("\n")){
						int sep = entry.getValue().substring(1).indexOf('\n');
						if (sep < 0)
							sep = 0;
						else
							sep++;
						out.write("<INFO " + VOSerializer.formatAttribute("name", entry.getKey()) + VOSerializer.formatAttribute("value", entry.getValue().substring(1, sep)) + ">\n" + entry.getValue().substring(sep + 1) + "\n</INFO>");
					}else
						out.write("<INFO " + VOSerializer.formatAttribute("name", entry.getKey()) + VOSerializer.formatAttribute("value", entry.getValue()) + "/>");
					out.newLine();
				}
			}
		}

		out.flush();

+30 −1
Original line number Diff line number Diff line
@@ -24,10 +24,12 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.sql.SQLException;

import tap.TAPException;
import tap.TAPExecutionReport;
import tap.TAPSyncJob;
import tap.db.DBConnection;
import tap.parameters.TAPParameters;
import uws.UWSException;
import uws.service.file.UWSFileManager;
import uws.service.log.DefaultUWSLog;

@@ -87,6 +89,33 @@ public class DefaultTAPLog extends DefaultUWSLog implements TAPLog {
		super(writer);
	}

	@Override
	protected void printException(Throwable error, final PrintWriter out){
		if (error != null){
			if (error instanceof UWSException || error instanceof TAPException || error.getClass().getPackage().getName().startsWith("adql.")){
				if (error.getCause() != null)
					printException(error.getCause(), out);
				else{
					out.println("Caused by a " + error.getClass().getName());
					if (error.getMessage() != null)
						out.println("\t" + error.getMessage());
				}
			}else if (error instanceof SQLException){
				out.println("Caused by a " + error.getClass().getName());
				out.print("\t");
				do{
					out.println(error.getMessage());
					error = ((SQLException)error).getNextException();
					if (error != null)
						out.print("\t=> ");
				}while(error != null);
			}else{
				out.print("Caused by a ");
				error.printStackTrace(out);
			}
		}
	}

	@Override
	public void logDB(final LogLevel level, final DBConnection connection, final String event, final String message, final Throwable error){
		// log the main given error:
@@ -111,7 +140,7 @@ public class DefaultTAPLog extends DefaultUWSLog implements TAPLog {
			if (event != null && obj != null){
				if (event.equals("SYNC_INIT"))
					msgAppend = "QUERY=" + ((TAPParameters)obj).getQuery().replaceAll("(\t|\r?\n)+", " ");
				else if (event.equals("SYNC_START"))
				else if (obj instanceof TAPSyncJob)
					jobId = ((TAPSyncJob)obj).getID();
				else if (obj instanceof TAPExecutionReport){
					TAPExecutionReport report = (TAPExecutionReport)obj;
+9 −4
Original line number Diff line number Diff line
@@ -660,6 +660,15 @@ public class TAP implements VOSIResource {
		if (request.getAttribute(UWS.REQ_ATTRIBUTE_ID) == null)
			request.setAttribute(UWS.REQ_ATTRIBUTE_ID, reqID);

		// Extract all parameters:
		if (request.getAttribute(UWS.REQ_ATTRIBUTE_PARAMETERS) == null){
			try{
				request.setAttribute(UWS.REQ_ATTRIBUTE_PARAMETERS, getUWS().getRequestParser().parse(request));
			}catch(UWSException ue){
				getLogger().log(LogLevel.ERROR, "REQUEST_PARSER", "Can not extract the HTTP request parameters!", ue);
			}
		}

		// Retrieve the resource path parts:
		String[] resourcePath = (request.getPathInfo() == null) ? null : request.getPathInfo().split("/");
		final String resourceName = (resourcePath == null || resourcePath.length < 1) ? "homePage" : resourcePath[1].trim().toLowerCase();
@@ -678,10 +687,6 @@ public class TAP implements VOSIResource {

		JobOwner owner = null;
		try{
			// Extract all parameters:
			if (request.getAttribute(UWS.REQ_ATTRIBUTE_PARAMETERS) == null)
				request.setAttribute(UWS.REQ_ATTRIBUTE_PARAMETERS, getUWS().getRequestParser().parse(request));

			// Identify the user:
			try{
				if (service.getUserIdentifier() != null)
Loading