JCRVLT-649 improve logging of errors in ActivityLog and ProgressTracker (#242)
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AutoSave.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AutoSave.java
index fd67aa4..f9c05dd 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AutoSave.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AutoSave.java
@@ -194,7 +194,7 @@
try {
session.save();
} catch (RepositoryException e) {
- log.error("Error during auto save: {} - retrying after refresh...", e.getMessage());
+ log.error("Error during auto save, retrying after refresh: {}", Importer.getExtendedThrowableMessage(e));
session.refresh(true);
session.save();
}
@@ -202,7 +202,7 @@
}
} catch (RepositoryException e) {
if (isPotentiallyTransientException(e) && isIntermediate) {
- log.warn("Could not auto-save even after refresh due to potentially transient exception: {}", e.getMessage());
+ log.warn("Could not auto-save even after refresh due to potentially transient exception: {}", Importer.getExtendedThrowableMessage(e));
log.debug("Auto save exception", e);
return false;
} else {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java
index 3925091..1d066e2 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java
@@ -24,6 +24,7 @@
import java.io.OutputStream;
import java.io.Reader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -45,6 +46,7 @@
import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
import org.apache.jackrabbit.spi.commons.namespace.SessionNamespaceResolver;
+import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.vault.fs.api.Artifact;
import org.apache.jackrabbit.vault.fs.api.ArtifactType;
import org.apache.jackrabbit.vault.fs.api.ImportInfo;
@@ -83,7 +85,6 @@
import org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry;
import org.apache.jackrabbit.vault.util.Constants;
import org.apache.jackrabbit.vault.util.PlatformNameFormat;
-import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.vault.util.Tree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -477,8 +478,8 @@
log.error("Error while committing changes. Aborting.");
throw e;
} else {
- log.warn("Error while committing changes. Retrying import from checkpoint at {}. Retries {}/10",
- cpTxInfo == null ? "/" : cpTxInfo.path, recoveryRetryCounter);
+ log.warn("Error while committing changes: Retrying import from checkpoint at {}. Retries {}/10. {}",
+ cpTxInfo == null ? "/" : cpTxInfo.path, recoveryRetryCounter, getExtendedThrowableMessage(e));
autoSave = cpAutosave.copy();
// build skip list
skipList.clear();
@@ -508,6 +509,7 @@
if (hasErrors) {
track("Package import simulation finished. (with errors, check logs!)", "");
log.error("There were errors during package install simulation. Please check the logs for details.");
+ track("First error was " + getExtendedThrowableMessage(firstException), "");
} else {
track("Package import simulation finished.", "");
}
@@ -518,12 +520,46 @@
throw new RepositoryException("Some errors occurred while installing packages. Please check the logs for details. First exception is logged as cause.", firstException);
}
log.error("There were errors during package install. Please check the logs for details.");
+ track("First error was " + getExtendedThrowableMessage(firstException), "");
} else {
track("Package imported.", "");
}
}
}
+ /**
+ * Returns a human-readable error message from the throwable including all its causes till the root.
+ * Also the throwable class names are included in the message
+ * @param throwable from which to construct an error message
+ * @return the enhanced error message derived from the throwable
+ */
+ static String getExtendedThrowableMessage(Throwable throwable) {
+ StringBuilder messageBuilder = new StringBuilder();
+ if (throwable == null) {
+ return "";
+ }
+ messageBuilder.append(throwable.getClass().getName()).append(": ");
+ messageBuilder.append(throwable.getMessage());
+ Throwable cause = throwable.getCause();
+ while (cause != null) {
+ if (!isDelimiter(messageBuilder.charAt(messageBuilder.length()-1))) {
+ messageBuilder.append(".");
+ }
+ messageBuilder.append(" Caused by ")
+ .append(cause.getClass().getName())
+ .append(": ")
+ .append(cause.getMessage());
+ cause = cause.getCause();
+ }
+ return messageBuilder.toString();
+ }
+
+ /** all punctuation delimiters between sentences in English */
+ private static final List<Character> DELIMITERS = Arrays.asList('.', '?', '!');
+ static boolean isDelimiter(char character) {
+ return DELIMITERS.contains(character);
+ }
+
private TxInfo postFilter(TxInfo root) {
TxInfo modifierRoot = root;
if (filter.contains(modifierRoot.path)){
diff --git a/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/ImporterTest.java b/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/ImporterTest.java
new file mode 100644
index 0000000..4a05597
--- /dev/null
+++ b/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/ImporterTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.vault.fs.io;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+public class ImporterTest {
+
+ @Test
+ public void testGetExtendedThrowableMessage() {
+ Throwable testThrowable =
+ new IOException("my exception",
+ new IllegalArgumentException("intermediate cause!",
+ new IllegalStateException("root cause")));
+ String expectedMessage = "java.io.IOException: my exception. " +
+ "Caused by java.lang.IllegalArgumentException: intermediate cause! " +
+ "Caused by java.lang.IllegalStateException: root cause";
+ assertEquals(expectedMessage, Importer.getExtendedThrowableMessage(testThrowable));
+ assertEquals("", Importer.getExtendedThrowableMessage(null));
+ }
+}