diff --git a/li.strolch.agent/src/main/java/li/strolch/handler/operationslog/LogMessage.java b/li.strolch.agent/src/main/java/li/strolch/handler/operationslog/LogMessage.java index 4be50c8ba..f2760401f 100644 --- a/li.strolch.agent/src/main/java/li/strolch/handler/operationslog/LogMessage.java +++ b/li.strolch.agent/src/main/java/li/strolch/handler/operationslog/LogMessage.java @@ -18,6 +18,7 @@ public class LogMessage extends I18nMessage { private final String realm; private final Locator locator; private final LogSeverity severity; + private String stackTrace; public LogMessage(String realm, Locator locator, LogSeverity logSeverity, ResourceBundle bundle, String key) { super(bundle, key); @@ -48,6 +49,15 @@ public class LogMessage extends I18nMessage { return this.severity; } + public LogMessage withException(Throwable t) { + this.stackTrace = ExceptionHelper.formatException(t); + return this; + } + + public String getStackTrace() { + return this.stackTrace; + } + @Override public LogMessage value(String key, String value) { super.value(key, value); @@ -70,6 +80,7 @@ public class LogMessage extends I18nMessage { jsonObject.addProperty(Json.SEVERITY, this.severity.name()); jsonObject.addProperty(Json.REALM, this.realm); jsonObject.addProperty(Json.LOCATOR, this.locator.toString()); + jsonObject.addProperty(Json.EXCEPTION, this.stackTrace); JsonObject values = new JsonObject(); for (String key : getValues().stringPropertyNames()) { values.addProperty(key, getValues().getProperty(key)); diff --git a/li.strolch.agent/src/main/java/li/strolch/job/StrolchJob.java b/li.strolch.agent/src/main/java/li/strolch/job/StrolchJob.java index 37dea128b..2e91f172b 100644 --- a/li.strolch.agent/src/main/java/li/strolch/job/StrolchJob.java +++ b/li.strolch.agent/src/main/java/li/strolch/job/StrolchJob.java @@ -1,14 +1,22 @@ package li.strolch.job; +import static li.strolch.model.Tags.AGENT; + import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; +import java.util.ResourceBundle; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.StrolchAgent; +import li.strolch.agent.api.StrolchRealm; +import li.strolch.handler.operationslog.LogMessage; +import li.strolch.handler.operationslog.LogSeverity; +import li.strolch.handler.operationslog.OperationsLog; +import li.strolch.model.Locator; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.privilege.base.PrivilegeException; import li.strolch.privilege.model.Certificate; @@ -23,6 +31,7 @@ public abstract class StrolchJob implements Runnable { protected static final Logger logger = LoggerFactory.getLogger(StrolchJob.class); private StrolchAgent agent; + private String realmName; private boolean first; private Future future; @@ -72,15 +81,27 @@ public abstract class StrolchJob implements Runnable { * @return the newly created transaction */ protected StrolchTransaction openTx(Certificate cert) { - return getContainer().getRealm(cert).openTx(cert, this.getClass()); + StrolchRealm realm = getContainer().getRealm(cert); + this.realmName = realm.getRealm(); + return realm.openTx(cert, this.getClass()); } @Override public final void run() { try { runAsAgent(this::execute); - } catch (Exception e) { + } catch (Throwable e) { logger.error("Execution of Job " + this.getClass().getSimpleName() + " failed.", e); + + OperationsLog operationsLog = getContainer().getComponent(OperationsLog.class); + if (operationsLog != null) { + operationsLog.addMessage( + new LogMessage(this.realmName == null ? StrolchConstants.DEFAULT_REALM : this.realmName, + Locator.valueOf(AGENT, "strolch-agent", StrolchAgent.getUniqueId()), + LogSeverity.Exception, ResourceBundle.getBundle("strolch-agent"), + "strolchjob.failed").withException(e).value("jobName", getClass().getName()) + .value("reason", e)); + } } this.first = false; diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java index ec99bd841..da95621e8 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java @@ -1321,7 +1321,7 @@ public abstract class AbstractTransaction implements StrolchTransaction { if (this.operationsLog != null) { this.operationsLog.addMessage(new LogMessage(this.realm.getRealm(), Locator.valueOf(AGENT, "tx", this.action, StrolchAgent.getUniqueId()), LogSeverity.Exception, - ResourceBundle.getBundle("strolch-agent"), "agent.tx.failed").value("reason", e)); + ResourceBundle.getBundle("strolch-agent"), "agent.tx.failed").withException(e).value("reason", e)); } String msg = "Strolch Transaction for realm {0} failed due to {1}\n{2}"; //$NON-NLS-1$ diff --git a/li.strolch.agent/src/main/resources/strolch-agent.properties b/li.strolch.agent/src/main/resources/strolch-agent.properties index a67353e87..8bf1d536a 100644 --- a/li.strolch.agent/src/main/resources/strolch-agent.properties +++ b/li.strolch.agent/src/main/resources/strolch-agent.properties @@ -1 +1,2 @@ agent.tx.failed=Transaction has failed due to {reason} +strolchjob.failed=xecution of Job {jobName} has failed due to {reason} \ No newline at end of file diff --git a/li.strolch.model/src/main/java/li/strolch/model/Tags.java b/li.strolch.model/src/main/java/li/strolch/model/Tags.java index 213e8dd35..b7e056e21 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/Tags.java +++ b/li.strolch.model/src/main/java/li/strolch/model/Tags.java @@ -1,12 +1,12 @@ /* * Copyright 2013 Robert von Burg - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,7 +19,7 @@ package li.strolch.model; public class Tags { public static final String AGENT = "Agent"; - + public static final String RESOURCE = "Resource"; public static final String ORDER = "Order"; public static final String ACTIVITY = "Activity"; @@ -131,6 +131,7 @@ public class Tags { public static final String TYPES = "types"; public static final String REALMS = "realms"; public static final String SIZE = "size"; + public static final String EXCEPTION = "exception"; } public static class Audit { diff --git a/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java b/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java index 0137dfe34..7c2462c80 100644 --- a/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java +++ b/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java @@ -165,7 +165,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler { if (getContainer().hasComponent(OperationsLog.class)) { getComponent(OperationsLog.class).addMessage(new LogMessage(realm, locator, LogSeverity.Exception, ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.execution") - .value("reason", e)); + .withException(e).value("reason", e)); } } }); @@ -188,7 +188,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler { if (getContainer().hasComponent(OperationsLog.class)) { getComponent(OperationsLog.class).addMessage(new LogMessage(realm, locator, LogSeverity.Exception, ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.executed") - .value("reason", e)); + .withException(e).value("reason", e)); } } }); @@ -207,7 +207,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler { if (getContainer().hasComponent(OperationsLog.class)) { getComponent(OperationsLog.class).addMessage(new LogMessage(realm, locator, LogSeverity.Exception, ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.stopped") - .value("reason", e)); + .withException(e).value("reason", e)); } } }); @@ -226,7 +226,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler { if (getContainer().hasComponent(OperationsLog.class)) { getComponent(OperationsLog.class).addMessage(new LogMessage(realm, locator, LogSeverity.Exception, ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.error") - .value("reason", e)); + .withException(e).value("reason", e)); } } }); @@ -245,7 +245,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler { if (getContainer().hasComponent(OperationsLog.class)) { getComponent(OperationsLog.class).addMessage(new LogMessage(realm, locator, LogSeverity.Exception, ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.warning") - .value("reason", e)); + .withException(e).value("reason", e)); } } }); @@ -285,7 +285,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler { getComponent(OperationsLog.class).addMessage( new LogMessage(realm, activityLoc, LogSeverity.Exception, ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.archive") - .value("reason", e)); + .withException(e).value("reason", e)); } } }); diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java index 324b636fb..d83034da2 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java @@ -203,7 +203,7 @@ public class MigrationsHandler extends StrolchComponent { getComponent(OperationsLog.class).addMessage( new LogMessage(Tags.AGENT, getLocator().append(StrolchAgent.getUniqueId()), LogSeverity.Exception, ResourceBundle.getBundle("strolch-service"), - "execution.handler.failed.executed").value("reason", e)); + "execution.handler.failed.executed").withException(e).value("reason", e)); } } }