> boolean match(T c1, T c2);
}
diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ClassLoaderUtils.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ClassLoaderUtils.java
index d21902ac98..b10c09d78a 100644
--- a/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ClassLoaderUtils.java
+++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ClassLoaderUtils.java
@@ -18,31 +18,12 @@
*/
package co.elastic.apm.agent.util;
+import co.elastic.apm.agent.bci.classloading.IndyPluginClassLoader;
+
import javax.annotation.Nullable;
public class ClassLoaderUtils {
- /**
- * Checks whether the provided {@link ClassLoader} may be unloaded like a web application class loader, for example.
- *
- * If the class loader can't be unloaded, it is safe to use {@link ThreadLocal}s and to reuse the {@code WeakConcurrentMap.LookupKey}.
- * Otherwise, the use of {@link ThreadLocal}s may lead to class loader leaks as it prevents the class loader this class
- * is loaded by to unload.
- *
- *
- * @param classLoader The class loader to check.
- * @return {@code true} if the provided class loader can be unloaded.
- */
- public static boolean isPersistentClassLoader(@Nullable ClassLoader classLoader) {
- try {
- return classLoader == null // bootstrap class loader
- || classLoader == ClassLoader.getSystemClassLoader()
- || classLoader == ClassLoader.getSystemClassLoader().getParent(); // ext/platfrom class loader;
- } catch (Throwable ignored) {
- return false;
- }
- }
-
public static boolean isAgentClassLoader(@Nullable ClassLoader classLoader) {
return (classLoader != null && classLoader.getClass().getName().startsWith("co.elastic.apm")) ||
// This one also covers unit tests, where the app class loader loads the agent
@@ -52,4 +33,11 @@ public static boolean isAgentClassLoader(@Nullable ClassLoader classLoader) {
public static boolean isBootstrapClassLoader(@Nullable ClassLoader classLoader) {
return classLoader == null;
}
+
+ public static boolean isInternalPluginClassLoader(@Nullable ClassLoader classLoader) {
+ if (classLoader == null) {
+ return false;
+ }
+ return IndyPluginClassLoader.class.getName().equals(classLoader.getClass().getName());
+ }
}
diff --git a/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml b/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml
index 644651d966..6745ad7cce 100644
--- a/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml
+++ b/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml
@@ -19,13 +19,25 @@
co.elastic.logging
log4j-ecs-layout
- 1.4.0
+ ${version.ecs.logging}
provided
co.elastic.logging
log4j2-ecs-layout
- 1.4.0
+ ${version.ecs.logging}
+ provided
+
+
+ co.elastic.logging
+ jul-ecs-formatter
+ ${version.ecs.logging}
+ provided
+
+
+ co.elastic.apm
+ apm-logging-plugin-common
+ ${project.version}
provided
@@ -39,6 +51,7 @@
ivy
test
+
diff --git a/apm-agent-plugins/apm-ecs-logging-plugin/src/main/java/co/elastic/apm/agent/ecs_logging/JulEcsFormatterInstrumentation.java b/apm-agent-plugins/apm-ecs-logging-plugin/src/main/java/co/elastic/apm/agent/ecs_logging/JulEcsFormatterInstrumentation.java
new file mode 100644
index 0000000000..424fbe3589
--- /dev/null
+++ b/apm-agent-plugins/apm-ecs-logging-plugin/src/main/java/co/elastic/apm/agent/ecs_logging/JulEcsFormatterInstrumentation.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. 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 co.elastic.apm.agent.ecs_logging;
+
+import co.elastic.apm.agent.bci.TracerAwareInstrumentation;
+import co.elastic.apm.agent.bci.bytebuddy.CustomElementMatchers;
+import co.elastic.apm.agent.loginstr.correlation.CorrelationIdMapAdapter;
+import co.elastic.logging.jul.EcsFormatter;
+import net.bytebuddy.asm.Advice;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.not;
+
+/**
+ * Instruments {@link EcsFormatter#getMdcEntries()} to provide correlation IDs at runtime.
+ * Application(s) copies of ecs-logging and the one in the agent will be instrumented, hence providing log correlation
+ * for all of them.
+ */
+@SuppressWarnings("JavadocReference")
+public class JulEcsFormatterInstrumentation extends TracerAwareInstrumentation {
+
+ @Override
+ public ElementMatcher.Junction getClassLoaderMatcher() {
+ // ECS formatter that is loaded within the agent should not be instrumented
+ return not(CustomElementMatchers.isInternalPluginClassLoader());
+ }
+
+ @Override
+ public Collection getInstrumentationGroupNames() {
+ return Arrays.asList("logging", "jul-ecs");
+ }
+
+ @Override
+ public ElementMatcher super TypeDescription> getTypeMatcher() {
+ return named("co.elastic.logging.jul.EcsFormatter");
+ }
+
+ @Override
+ public ElementMatcher super MethodDescription> getMethodMatcher() {
+ return named("getMdcEntries");
+ }
+
+ public static class AdviceClass {
+
+ @Advice.AssignReturned.ToReturned
+ @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false)
+ public static Map onExit() {
+ return CorrelationIdMapAdapter.get();
+ }
+
+ }
+
+
+}
diff --git a/apm-agent-plugins/apm-ecs-logging-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation b/apm-agent-plugins/apm-ecs-logging-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation
index 58294e83a5..55b6a4dc57 100644
--- a/apm-agent-plugins/apm-ecs-logging-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation
+++ b/apm-agent-plugins/apm-ecs-logging-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation
@@ -1,2 +1,4 @@
co.elastic.apm.agent.ecs_logging.Log4j2ServiceNameInstrumentation
co.elastic.apm.agent.ecs_logging.Log4j2ServiceVersionInstrumentation
+
+co.elastic.apm.agent.ecs_logging.JulEcsFormatterInstrumentation
diff --git a/apm-agent-plugins/apm-ecs-logging-plugin/src/test/java/co/elastic/apm/agent/ecs_logging/JulEcsFormatterInstrumentationTest.java b/apm-agent-plugins/apm-ecs-logging-plugin/src/test/java/co/elastic/apm/agent/ecs_logging/JulEcsFormatterInstrumentationTest.java
new file mode 100644
index 0000000000..d83e85f390
--- /dev/null
+++ b/apm-agent-plugins/apm-ecs-logging-plugin/src/test/java/co/elastic/apm/agent/ecs_logging/JulEcsFormatterInstrumentationTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. 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 co.elastic.apm.agent.ecs_logging;
+
+import co.elastic.apm.agent.AbstractInstrumentationTest;
+import co.elastic.apm.agent.impl.error.ErrorCapture;
+import co.elastic.apm.agent.impl.transaction.Transaction;
+import co.elastic.logging.jul.EcsFormatter;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import static co.elastic.apm.agent.testutils.assertions.Assertions.assertThat;
+
+public class JulEcsFormatterInstrumentationTest extends AbstractInstrumentationTest {
+
+ @Test
+ void testNoCorrelation() {
+ JsonNode logLine = logSomething();
+
+ assertThat(logLine.get("transaction.id")).isNull();
+ assertThat(logLine.get("trace.id")).isNull();
+ }
+
+ @Test
+ void testActiveTransaction() {
+ Transaction transaction = startTestRootTransaction("log");
+ try {
+ JsonNode logLine = logSomething();
+
+ assertThat(logLine.get("transaction.id").textValue()).isEqualTo(transaction.getTraceContext().getTransactionId().toString());
+ assertThat(logLine.get("trace.id").textValue()).isEqualTo(transaction.getTraceContext().getTraceId().toString());
+ } finally {
+ transaction.deactivate().end();
+ }
+ }
+
+ @Test
+ void testActiveError() {
+ ErrorCapture error = new ErrorCapture(tracer);
+
+ error.activate();
+ try {
+ JsonNode logLine = logSomething();
+
+ assertThat(logLine.get("error.id").textValue()).isEqualTo(error.getTraceContext().getId().toString());
+ } finally {
+ error.deactivate();
+ }
+
+ }
+
+ private static JsonNode logSomething() {
+ EcsFormatter formatter = new EcsFormatter();
+ LogRecord record = new LogRecord(Level.INFO, "msg");
+ try {
+ return new ObjectMapper().readTree(formatter.format(record));
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/JulInstrumentation.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/JulInstrumentation.java
new file mode 100644
index 0000000000..ede02eb161
--- /dev/null
+++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/JulInstrumentation.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. 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 co.elastic.apm.agent.jul;
+
+import co.elastic.apm.agent.loginstr.AbstractLogIntegrationInstrumentation;
+
+import java.util.Collection;
+
+public abstract class JulInstrumentation extends AbstractLogIntegrationInstrumentation {
+
+ @Override
+ public Collection getInstrumentationGroupNames() {
+ Collection ret = super.getInstrumentationGroupNames();
+ ret.add("jul-ecs");
+ return ret;
+ }
+}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentation.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentation.java
new file mode 100644
index 0000000000..83e54aaaff
--- /dev/null
+++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentation.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. 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 co.elastic.apm.agent.jul.error;
+
+import co.elastic.apm.agent.loginstr.error.AbstractLoggerErrorCapturingInstrumentation;
+import co.elastic.apm.agent.loginstr.error.LoggerErrorHelper;
+import net.bytebuddy.asm.Advice;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.logging.LogRecord;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
+
+public class JulLoggerErrorCapturingInstrumentation extends AbstractLoggerErrorCapturingInstrumentation {
+
+ @Override
+ public Collection getInstrumentationGroupNames() {
+ Collection ret = super.getInstrumentationGroupNames();
+ ret.add("jul-error");
+ return ret;
+ }
+
+ @Override
+ public ElementMatcher super TypeDescription> getTypeMatcher() {
+ return named("java.util.logging.Logger");
+ }
+
+ @Override
+ public ElementMatcher super MethodDescription> getMethodMatcher() {
+ return named("log")
+ .and(takesArgument(0, named("java.util.logging.LogRecord")));
+ }
+
+ @Override
+ public String getAdviceClassName() {
+ return "co.elastic.apm.agent.jul.error.JulLoggerErrorCapturingInstrumentation$LoggingAdvice";
+ }
+
+ public static class LoggingAdvice {
+
+ private static final LoggerErrorHelper helper = new LoggerErrorHelper(LoggingAdvice.class, tracer);
+
+ @Nullable
+ @Advice.OnMethodEnter(suppress = Throwable.class, inline = false)
+ public static Object onEnter(@Advice.Argument(0) LogRecord record, @Advice.Origin Class> clazz) {
+ Throwable thrown = record.getThrown();
+
+ // ignore levels < SEVERE
+ if (record.getLevel().intValue() < 1000) {
+ thrown = null;
+ }
+
+ return helper.enter(thrown, clazz);
+ }
+
+ @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false)
+ public static void onExit(@Advice.Enter @Nullable Object errorCaptureObj) {
+ helper.exit(errorCaptureObj);
+ }
+ }
+
+
+}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/JulEcsReformattingHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/JulEcsReformattingHelper.java
index 32d41785d4..b015ff0a07 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/JulEcsReformattingHelper.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/JulEcsReformattingHelper.java
@@ -18,6 +18,7 @@
*/
package co.elastic.apm.agent.jul.reformatting;
+import co.elastic.apm.agent.loginstr.correlation.CorrelationIdMapAdapter;
import co.elastic.apm.agent.loginstr.reformatting.AbstractEcsReformattingHelper;
import co.elastic.apm.agent.loginstr.reformatting.Utils;
import co.elastic.apm.agent.sdk.logging.Logger;
@@ -86,7 +87,13 @@ protected String getAppenderName(StreamHandler handler) {
protected Formatter createEcsFormatter(String eventDataset, @Nullable String serviceName, @Nullable String serviceVersion,
@Nullable String serviceNodeName, @Nullable Map additionalFields,
Formatter originalFormatter) {
- EcsFormatter ecsFormatter = new EcsFormatter();
+ EcsFormatter ecsFormatter = new EcsFormatter() {
+ @Override
+ protected Map getMdcEntries() {
+ // using internal tracer state as ECS formatter is not instrumented within the agent plugin
+ return CorrelationIdMapAdapter.get();
+ }
+ };
ecsFormatter.setServiceName(serviceName);
ecsFormatter.setServiceVersion(serviceVersion);
ecsFormatter.setServiceNodeName(serviceNodeName);
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/JulLogReformattingInstrumentation.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/JulLogReformattingInstrumentation.java
index 6a8d2eec7f..6add897e8f 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/JulLogReformattingInstrumentation.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/JulLogReformattingInstrumentation.java
@@ -18,12 +18,11 @@
*/
package co.elastic.apm.agent.jul.reformatting;
-import co.elastic.apm.agent.loginstr.AbstractLogIntegrationInstrumentation;
+import co.elastic.apm.agent.jul.JulInstrumentation;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
-import java.util.Collection;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
@@ -32,14 +31,7 @@
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
-public abstract class JulLogReformattingInstrumentation extends AbstractLogIntegrationInstrumentation {
-
- @Override
- public Collection getInstrumentationGroupNames() {
- Collection ret = super.getInstrumentationGroupNames();
- ret.add("jul-ecs");
- return ret;
- }
+public abstract class JulLogReformattingInstrumentation extends JulInstrumentation {
@Override
public ElementMatcher.Junction getClassLoaderMatcher() {
@@ -99,7 +91,8 @@ public static class StopAppenderInstrumentation extends JulLogReformattingInstru
@Override
public ElementMatcher super TypeDescription> getTypeMatcher() {
- return named("java.util.logging.ConsoleHandler").or(named("java.util.logging.FileHandler"));
+ return named("java.util.logging.ConsoleHandler")
+ .or(named("java.util.logging.FileHandler"));
}
/**
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation
index 582843d242..6a74b3bc0b 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation
+++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation
@@ -3,4 +3,8 @@ co.elastic.apm.agent.jul.reformatting.JulLogReformattingInstrumentation$FileRefo
co.elastic.apm.agent.jul.reformatting.JulLogReformattingInstrumentation$ConsoleReformattingInstrumentation
co.elastic.apm.agent.jul.reformatting.JulLogReformattingInstrumentation$StopAppenderInstrumentation
+# Trace context correlation
+# Provided through ECS logging instrumentation as there is no dedicated MDC for JUL.
+
# Error creation
+co.elastic.apm.agent.jul.error.JulLoggerErrorCapturingInstrumentation
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/JulInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/JulInstrumentationTest.java
index 568d98a36e..b3217b8253 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/JulInstrumentationTest.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/JulInstrumentationTest.java
@@ -18,8 +18,8 @@
*/
package co.elastic.apm.agent.jul;
-import co.elastic.apm.agent.loginstr.LoggingInstrumentationTest;
import co.elastic.apm.agent.loginstr.LoggerFacade;
+import co.elastic.apm.agent.loginstr.LoggingInstrumentationTest;
import java.io.File;
import java.io.IOException;
@@ -51,11 +51,6 @@ protected String getLogReformattingFilePath() {
return super.getLogReformattingFilePath() + ".0";
}
- @Override
- protected boolean isLogCorrelationSupported() {
- return false;
- }
-
/**
* Custom log levels that match other logging frameworks
*/
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentationTest.java
index 4bd53ca2e1..94388d5ee2 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentationTest.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentationTest.java
@@ -19,21 +19,47 @@
package co.elastic.apm.agent.jul.error;
import co.elastic.apm.agent.loginstr.error.AbstractErrorLoggingInstrumentationTest;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.util.logging.Level;
+import java.util.logging.LogRecord;
import java.util.logging.Logger;
-// todo: add support and enable
-@Disabled
public class JulLoggerErrorCapturingInstrumentationTest extends AbstractErrorLoggingInstrumentationTest {
private static final Logger logger = Logger.getLogger(JulLoggerErrorCapturingInstrumentationTest.class.getName());
@Test
void captureErrorExceptionWithStringMessage() {
- logger.log(Level.SEVERE, "exception captured", new RuntimeException("some business exception"));
- verifyThatExceptionCaptured(1, "some business exception", RuntimeException.class);
+ logWithMessage(Level.SEVERE);
+ verifyExceptionCaptured("some business exception", RuntimeException.class);
+ }
+
+ @Test
+ void ignoreWarningWithStringMessage() {
+ logWithMessage(Level.WARNING);
+ verifyNoExceptionCaptured();
+ }
+
+ private static void logWithMessage(Level level) {
+ logger.log(level, "exception captured", new RuntimeException("some business exception"));
+ }
+
+ @Test
+ void captureErrorExceptionWithLogRecord() {
+ logWithLogRecord(Level.SEVERE);
+ verifyExceptionCaptured("some business exception", RuntimeException.class);
+ }
+
+ @Test
+ void ignoreWarningWithLogRecord() {
+ logWithLogRecord(Level.WARNING);
+ verifyNoExceptionCaptured();
+ }
+
+ private static void logWithLogRecord(Level warning) {
+ LogRecord lr = new LogRecord(warning, "exception captured");
+ lr.setThrown(new RuntimeException("some business exception"));
+ logger.log(lr);
}
}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/error/Log4j1LoggerErrorCapturingInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/error/Log4j1LoggerErrorCapturingInstrumentationTest.java
index be7d8f67b7..d798f53178 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/error/Log4j1LoggerErrorCapturingInstrumentationTest.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/test/java/co/elastic/apm/agent/log4j1/error/Log4j1LoggerErrorCapturingInstrumentationTest.java
@@ -30,12 +30,12 @@ class Log4j1LoggerErrorCapturingInstrumentationTest extends AbstractErrorLogging
@Test
void captureErrorExceptionWithStringMessage() {
logger.error("exception captured", new RuntimeException("some business exception"));
- verifyThatExceptionCaptured(1, "some business exception", RuntimeException.class);
+ verifyExceptionCaptured("some business exception", RuntimeException.class);
}
@Test
void captureFatalException() {
logger.fatal("exception captured", new RuntimeException("some business exception"));
- verifyThatExceptionCaptured(1, "some business exception", RuntimeException.class);
+ verifyExceptionCaptured("some business exception", RuntimeException.class);
}
}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java
index 1d5547c2a0..21adbf2723 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java
@@ -22,6 +22,7 @@
import co.elastic.apm.agent.impl.Tracer;
import co.elastic.apm.agent.impl.error.ErrorCapture;
import co.elastic.apm.agent.loginstr.correlation.AbstractLogCorrelationHelper;
+import co.elastic.apm.agent.loginstr.correlation.CorrelationIdMapAdapter;
import org.apache.logging.log4j.ThreadContext;
import java.util.Map;
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/error/Log4j2LoggerErrorCapturingInstrumentation.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/error/Log4j2LoggerErrorCapturingInstrumentation.java
index 7fa79c15db..195249c6a0 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/error/Log4j2LoggerErrorCapturingInstrumentation.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/error/Log4j2LoggerErrorCapturingInstrumentation.java
@@ -43,7 +43,8 @@ public ElementMatcher super TypeDescription> getTypeMatcher() {
@Override
public ElementMatcher super MethodDescription> getMethodMatcher() {
- return named("fatal").and(takesArgument(1, named("java.lang.Throwable"))).or(super.getMethodMatcher());
+ return named("fatal").and(takesArgument(1, named("java.lang.Throwable")))
+ .or(super.getMethodMatcher());
}
@Override
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/test/java/co/elastic/apm/agent/log4j2/error/Log4j2LoggerErrorCapturingInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/test/java/co/elastic/apm/agent/log4j2/error/Log4j2LoggerErrorCapturingInstrumentationTest.java
index c50bce8aed..08fd54465a 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/test/java/co/elastic/apm/agent/log4j2/error/Log4j2LoggerErrorCapturingInstrumentationTest.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/test/java/co/elastic/apm/agent/log4j2/error/Log4j2LoggerErrorCapturingInstrumentationTest.java
@@ -37,18 +37,18 @@ public class Log4j2LoggerErrorCapturingInstrumentationTest extends AbstractError
@Test
void captureErrorExceptionWithStringMessage() {
logger.error("exception captured", new RuntimeException("some business exception"));
- verifyThatExceptionCaptured(1, "some business exception", RuntimeException.class);
+ verifyExceptionCaptured("some business exception", RuntimeException.class);
}
@Test
void captureErrorExceptionWithMessageMessage() {
logger.error(ParameterizedMessageFactory.INSTANCE.newMessage("exception captured with parameter {}", "foo"), new RuntimeException("some business exception"));
- verifyThatExceptionCaptured(1, "some business exception", RuntimeException.class);
+ verifyExceptionCaptured("some business exception", RuntimeException.class);
}
@Test
void captureFatalException() {
logger.fatal("exception captured", new RuntimeException("some business exception"));
- verifyThatExceptionCaptured(1, "some business exception", RuntimeException.class);
+ verifyExceptionCaptured("some business exception", RuntimeException.class);
}
}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/CorrelationIdMapAdapter.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapter.java
similarity index 97%
rename from apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/CorrelationIdMapAdapter.java
rename to apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapter.java
index 6ef8abaeb9..c94d8ca2cc 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/CorrelationIdMapAdapter.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapter.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package co.elastic.apm.agent.log4j2.correlation;
+package co.elastic.apm.agent.loginstr.correlation;
import co.elastic.apm.agent.impl.GlobalTracer;
import co.elastic.apm.agent.impl.Tracer;
@@ -38,7 +38,7 @@
import static co.elastic.apm.agent.loginstr.correlation.AbstractLogCorrelationHelper.TRACE_ID_MDC_KEY;
import static co.elastic.apm.agent.loginstr.correlation.AbstractLogCorrelationHelper.TRANSACTION_ID_MDC_KEY;
-class CorrelationIdMapAdapter extends AbstractMap {
+public class CorrelationIdMapAdapter extends AbstractMap {
private static final CorrelationIdMapAdapter INSTANCE = new CorrelationIdMapAdapter();
private static final Set> ENTRY_SET = new TraceIdentifierEntrySet();
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/package-info.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/package-info.java
similarity index 94%
rename from apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/package-info.java
rename to apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/package-info.java
index 3ef4e5109c..5e792ddb0e 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/test/java/co/elastic/apm/agent/jul/package-info.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/package-info.java
@@ -17,6 +17,6 @@
* under the License.
*/
@NonnullApi
-package co.elastic.apm.agent.jul;
+package co.elastic.apm.agent.loginstr.correlation;
import co.elastic.apm.agent.sdk.NonnullApi;
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/AbstractLoggerErrorCapturingInstrumentation.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/AbstractLoggerErrorCapturingInstrumentation.java
index 96647d05ab..03e61b0007 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/AbstractLoggerErrorCapturingInstrumentation.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/AbstractLoggerErrorCapturingInstrumentation.java
@@ -46,28 +46,17 @@ public String getAdviceClassName() {
public static class LoggingAdvice {
- private static final CallDepth callDepth = CallDepth.get(LoggingAdvice.class);
+ private static final LoggerErrorHelper helper = new LoggerErrorHelper(LoggingAdvice.class, tracer);
@Nullable
@Advice.OnMethodEnter(suppress = Throwable.class, inline = false)
public static Object logEnter(@Advice.Argument(1) Throwable exception, @Advice.Origin Class> clazz) {
- if (!callDepth.isNestedCallAndIncrement()) {
- ErrorCapture error = tracer.captureException(exception, tracer.getActive(), clazz.getClassLoader());
- if (error != null) {
- error.activate();
- }
- return error;
- }
- return null;
+ return helper.enter(exception, clazz);
}
@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false)
public static void logExit(@Advice.Enter @Nullable Object errorCaptureObj) {
- callDepth.decrement();
- if (errorCaptureObj instanceof ErrorCapture) {
- ErrorCapture error = (ErrorCapture) errorCaptureObj;
- error.deactivate().end();
- }
+ helper.exit(errorCaptureObj);
}
}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/LoggerErrorHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/LoggerErrorHelper.java
new file mode 100644
index 0000000000..75b3507358
--- /dev/null
+++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/LoggerErrorHelper.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. 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 co.elastic.apm.agent.loginstr.error;
+
+import co.elastic.apm.agent.impl.Tracer;
+import co.elastic.apm.agent.impl.error.ErrorCapture;
+import co.elastic.apm.agent.sdk.state.CallDepth;
+
+import javax.annotation.Nullable;
+
+public class LoggerErrorHelper {
+
+ private final CallDepth callDepth;
+ private final Tracer tracer;
+
+ public LoggerErrorHelper(Class> adviceClass, Tracer tracer) {
+ this.callDepth = CallDepth.get(adviceClass);
+ this.tracer = tracer;
+ }
+
+ /**
+ * Start error capture and make error active. Must be called even if `exception` is null for proper nested calls detection.
+ *
+ * @param exception exception to capture
+ * @param originClass origin class
+ * @return error capture, if any, {@literal null} for nested calls and when no exception provided.
+ */
+ @Nullable
+ public Object enter(@Nullable Throwable exception, Class> originClass) {
+ if (!callDepth.isNestedCallAndIncrement()) {
+ if (exception != null) {
+ ErrorCapture error = tracer.captureException(exception, tracer.getActive(), originClass.getClassLoader());
+ if (error != null) {
+ error.activate();
+ }
+ return error;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * End error capture and de-activate error. Must be called even if `exception` is null for proper nested calls detection
+ *
+ * @param errorCapture value returned by {@link #enter(Throwable, Class)}
+ */
+ public void exit(@Nullable Object errorCapture) {
+ callDepth.decrement();
+ if (errorCapture instanceof ErrorCapture) {
+ ErrorCapture error = (ErrorCapture) errorCapture;
+ error.deactivate().end();
+ }
+ }
+}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/LoggingInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/LoggingInstrumentationTest.java
index 3bb978ba80..d996800a45 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/LoggingInstrumentationTest.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/LoggingInstrumentationTest.java
@@ -323,7 +323,7 @@ private void verifyTracingMetadata(JsonNode ecsLogLineTree) {
private void verifyErrorCaptureAndCorrelation(boolean isErrorLine, JsonNode ecsLogLineTree) {
final JsonNode errorJsonNode = ecsLogLineTree.get(AbstractLogCorrelationHelper.ERROR_ID_MDC_KEY);
if (isErrorLine) {
- assertThat(errorJsonNode).isNotNull();
+ assertThat(errorJsonNode).describedAs("missing error ID").isNotNull();
List errors = reporter.getErrors().stream()
.filter(error -> errorJsonNode.textValue().equals(error.getTraceContext().getId().toString()))
.collect(Collectors.toList());
@@ -385,10 +385,10 @@ private void verifyEcsFormat(String[] splitRawLogLine, JsonNode ecsLogLineTree)
private void verifyLogCorrelation(JsonNode ecsLogLineTree, boolean isErrorLine) {
if (isLogCorrelationSupported()) {
JsonNode traceId = ecsLogLineTree.get(AbstractLogCorrelationHelper.TRACE_ID_MDC_KEY);
- assertThat(traceId).withFailMessage("Logging correlation does not work as expected").isNotNull();
+ assertThat(traceId).describedAs("Logging correlation does not work as expected: missing trace ID").isNotNull();
assertThat(traceId.textValue()).isEqualTo(transaction.getTraceContext().getTraceId().toString());
JsonNode transactionId = ecsLogLineTree.get(AbstractLogCorrelationHelper.TRANSACTION_ID_MDC_KEY);
- assertThat(transactionId).withFailMessage("Logging correlation does not work as expected").isNotNull();
+ assertThat(transactionId).describedAs("Logging correlation does not work as expected: missing transaction ID").isNotNull();
assertThat(transactionId.textValue()).isEqualTo(transaction.getTraceContext().getTransactionId().toString());
verifyErrorCaptureAndCorrelation(isErrorLine, ecsLogLineTree);
} else {
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/test/java/co/elastic/apm/agent/log4j2/correlation/CorrelationIdMapAdapterTest.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapterTest.java
similarity index 96%
rename from apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/test/java/co/elastic/apm/agent/log4j2/correlation/CorrelationIdMapAdapterTest.java
rename to apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapterTest.java
index a9b2427162..638315755c 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/test/java/co/elastic/apm/agent/log4j2/correlation/CorrelationIdMapAdapterTest.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapterTest.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package co.elastic.apm.agent.log4j2.correlation;
+package co.elastic.apm.agent.loginstr.correlation;
import co.elastic.apm.agent.MockTracer;
import co.elastic.apm.agent.impl.ElasticApmTracer;
@@ -31,7 +31,7 @@
import static org.assertj.core.api.Assertions.assertThat;
-class CorrelationIdMapAdapterTest {
+public class CorrelationIdMapAdapterTest {
private final ElasticApmTracer tracer = MockTracer.createRealTracer();
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/error/AbstractErrorLoggingInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/error/AbstractErrorLoggingInstrumentationTest.java
index 24581c44ed..bfe0fbce37 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/error/AbstractErrorLoggingInstrumentationTest.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/test/java/co/elastic/apm/agent/loginstr/error/AbstractErrorLoggingInstrumentationTest.java
@@ -23,6 +23,7 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
public abstract class AbstractErrorLoggingInstrumentationTest extends AbstractInstrumentationTest {
@@ -40,10 +41,15 @@ void endTransaction() {
transaction.deactivate().end();
}
- protected void verifyThatExceptionCaptured(int errorCount, String exceptionMessage, Class exceptionClass) {
+ protected void verifyExceptionCaptured(String exceptionMessage, Class exceptionClass) {
reporter.awaitErrorCount(1);
Throwable exception = reporter.getErrors().get(0).getException();
- assertEquals(exceptionMessage, exception.getMessage());
- assertEquals(exceptionClass, exception.getClass());
+ assertThat(exception).isNotNull();
+ assertThat(exceptionMessage).isEqualTo(exception.getMessage());
+ assertThat(exceptionClass).isEqualTo(exception.getClass());
+ }
+
+ protected void verifyNoExceptionCaptured() {
+ assertThat(reporter.getErrors()).isEmpty();
}
}
diff --git a/apm-agent-plugins/apm-logging-plugin/apm-slf4j-plugin/src/test/java/co/elastic/apm/agent/slf4j/error/Slf4jLoggerErrorCapturingInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-slf4j-plugin/src/test/java/co/elastic/apm/agent/slf4j/error/Slf4jLoggerErrorCapturingInstrumentationTest.java
index 5676b71b94..7225b4b5c0 100644
--- a/apm-agent-plugins/apm-logging-plugin/apm-slf4j-plugin/src/test/java/co/elastic/apm/agent/slf4j/error/Slf4jLoggerErrorCapturingInstrumentationTest.java
+++ b/apm-agent-plugins/apm-logging-plugin/apm-slf4j-plugin/src/test/java/co/elastic/apm/agent/slf4j/error/Slf4jLoggerErrorCapturingInstrumentationTest.java
@@ -30,7 +30,7 @@ class Slf4jLoggerErrorCapturingInstrumentationTest extends AbstractErrorLoggingI
@Test
void captureException() {
logger.error("exception captured", new RuntimeException("some business exception"));
- verifyThatExceptionCaptured(1, "some business exception", RuntimeException.class);
+ verifyExceptionCaptured("some business exception", RuntimeException.class);
}
}
diff --git a/apm-agent-plugins/apm-logging-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/pom.xml
index f38ecba0c6..8df94692e9 100644
--- a/apm-agent-plugins/apm-logging-plugin/pom.xml
+++ b/apm-agent-plugins/apm-logging-plugin/pom.xml
@@ -14,7 +14,6 @@
${project.basedir}/../..
- 1.4.0
diff --git a/docs/configuration.asciidoc b/docs/configuration.asciidoc
index 8f0cce5297..2169240ff4 100644
--- a/docs/configuration.asciidoc
+++ b/docs/configuration.asciidoc
@@ -762,7 +762,7 @@ you should add an additional entry to this list (make sure to also include the d
==== `enable_instrumentations` (added[1.28.0])
A list of instrumentations which should be selectively enabled.
-Valid options are `annotations`, `annotations-capture-span`, `annotations-capture-transaction`, `annotations-traced`, `apache-commons-exec`, `apache-httpclient`, `asynchttpclient`, `aws-lambda`, `aws-sdk`, `cassandra`, `concurrent`, `dubbo`, `elasticsearch-restclient`, `exception-handler`, `executor`, `executor-collection`, `experimental`, `fork-join`, `grails`, `grpc`, `hibernate-search`, `http-client`, `jakarta-websocket`, `javalin`, `javax-websocket`, `jax-rs`, `jax-ws`, `jboss-logging-correlation`, `jdbc`, `jdk-httpclient`, `jdk-httpserver`, `jedis`, `jms`, `jsf`, `jul-ecs`, `kafka`, `lettuce`, `log4j1-correlation`, `log4j1-ecs`, `log4j1-error`, `log4j2-correlation`, `log4j2-ecs`, `log4j2-error`, `logback-correlation`, `logback-ecs`, `logging`, `micrometer`, `mongodb`, `mongodb-client`, `okhttp`, `opentelemetry`, `opentracing`, `process`, `public-api`, `quartz`, `rabbitmq`, `reactor`, `redis`, `redisson`, `render`, `scala-future`, `scheduled`, `servlet-api`, `servlet-api-async`, `servlet-api-dispatch`, `servlet-input-stream`, `servlet-service-name`, `servlet-version`, `slf4j-error`, `sparkjava`, `spring-amqp`, `spring-mvc`, `spring-resttemplate`, `spring-service-name`, `spring-view-render`, `spring-webclient`, `spring-webflux`, `ssl-context`, `struts`, `timer-task`, `urlconnection`, `vertx`, `vertx-web`, `vertx-webclient`, `websocket`.
+Valid options are `annotations`, `annotations-capture-span`, `annotations-capture-transaction`, `annotations-traced`, `apache-commons-exec`, `apache-httpclient`, `asynchttpclient`, `aws-lambda`, `aws-sdk`, `cassandra`, `concurrent`, `dubbo`, `elasticsearch-restclient`, `exception-handler`, `executor`, `executor-collection`, `experimental`, `fork-join`, `grails`, `grpc`, `hibernate-search`, `http-client`, `jakarta-websocket`, `javalin`, `javax-websocket`, `jax-rs`, `jax-ws`, `jboss-logging-correlation`, `jdbc`, `jdk-httpclient`, `jdk-httpserver`, `jedis`, `jms`, `jsf`, `jul-ecs`, `jul-error`, `kafka`, `lettuce`, `log4j1-correlation`, `log4j1-ecs`, `log4j1-error`, `log4j2-correlation`, `log4j2-ecs`, `log4j2-error`, `logback-correlation`, `logback-ecs`, `logging`, `micrometer`, `mongodb`, `mongodb-client`, `okhttp`, `opentelemetry`, `opentracing`, `process`, `public-api`, `quartz`, `rabbitmq`, `reactor`, `redis`, `redisson`, `render`, `scala-future`, `scheduled`, `servlet-api`, `servlet-api-async`, `servlet-api-dispatch`, `servlet-input-stream`, `servlet-service-name`, `servlet-version`, `slf4j-error`, `sparkjava`, `spring-amqp`, `spring-mvc`, `spring-resttemplate`, `spring-service-name`, `spring-view-render`, `spring-webclient`, `spring-webflux`, `ssl-context`, `struts`, `timer-task`, `urlconnection`, `vertx`, `vertx-web`, `vertx-webclient`, `websocket`.
When set to non-empty value, only listed instrumentations will be enabled if they are not disabled through <> or <>.
When not set or empty (default), all instrumentations enabled by default will be enabled unless they are disabled through <> or <>.
@@ -790,7 +790,7 @@ NOTE: Changing this value at runtime can slow down the application temporarily.
==== `disable_instrumentations` (added[1.0.0,Changing this value at runtime is possible since version 1.15.0])
A list of instrumentations which should be disabled.
-Valid options are `annotations`, `annotations-capture-span`, `annotations-capture-transaction`, `annotations-traced`, `apache-commons-exec`, `apache-httpclient`, `asynchttpclient`, `aws-lambda`, `aws-sdk`, `cassandra`, `concurrent`, `dubbo`, `elasticsearch-restclient`, `exception-handler`, `executor`, `executor-collection`, `experimental`, `fork-join`, `grails`, `grpc`, `hibernate-search`, `http-client`, `jakarta-websocket`, `javalin`, `javax-websocket`, `jax-rs`, `jax-ws`, `jboss-logging-correlation`, `jdbc`, `jdk-httpclient`, `jdk-httpserver`, `jedis`, `jms`, `jsf`, `jul-ecs`, `kafka`, `lettuce`, `log4j1-correlation`, `log4j1-ecs`, `log4j1-error`, `log4j2-correlation`, `log4j2-ecs`, `log4j2-error`, `logback-correlation`, `logback-ecs`, `logging`, `micrometer`, `mongodb`, `mongodb-client`, `okhttp`, `opentelemetry`, `opentracing`, `process`, `public-api`, `quartz`, `rabbitmq`, `reactor`, `redis`, `redisson`, `render`, `scala-future`, `scheduled`, `servlet-api`, `servlet-api-async`, `servlet-api-dispatch`, `servlet-input-stream`, `servlet-service-name`, `servlet-version`, `slf4j-error`, `sparkjava`, `spring-amqp`, `spring-mvc`, `spring-resttemplate`, `spring-service-name`, `spring-view-render`, `spring-webclient`, `spring-webflux`, `ssl-context`, `struts`, `timer-task`, `urlconnection`, `vertx`, `vertx-web`, `vertx-webclient`, `websocket`.
+Valid options are `annotations`, `annotations-capture-span`, `annotations-capture-transaction`, `annotations-traced`, `apache-commons-exec`, `apache-httpclient`, `asynchttpclient`, `aws-lambda`, `aws-sdk`, `cassandra`, `concurrent`, `dubbo`, `elasticsearch-restclient`, `exception-handler`, `executor`, `executor-collection`, `experimental`, `fork-join`, `grails`, `grpc`, `hibernate-search`, `http-client`, `jakarta-websocket`, `javalin`, `javax-websocket`, `jax-rs`, `jax-ws`, `jboss-logging-correlation`, `jdbc`, `jdk-httpclient`, `jdk-httpserver`, `jedis`, `jms`, `jsf`, `jul-ecs`, `jul-error`, `kafka`, `lettuce`, `log4j1-correlation`, `log4j1-ecs`, `log4j1-error`, `log4j2-correlation`, `log4j2-ecs`, `log4j2-error`, `logback-correlation`, `logback-ecs`, `logging`, `micrometer`, `mongodb`, `mongodb-client`, `okhttp`, `opentelemetry`, `opentracing`, `process`, `public-api`, `quartz`, `rabbitmq`, `reactor`, `redis`, `redisson`, `render`, `scala-future`, `scheduled`, `servlet-api`, `servlet-api-async`, `servlet-api-dispatch`, `servlet-input-stream`, `servlet-service-name`, `servlet-version`, `slf4j-error`, `sparkjava`, `spring-amqp`, `spring-mvc`, `spring-resttemplate`, `spring-service-name`, `spring-view-render`, `spring-webclient`, `spring-webflux`, `ssl-context`, `struts`, `timer-task`, `urlconnection`, `vertx`, `vertx-web`, `vertx-webclient`, `websocket`.
For version `1.25.0` and later, use <> to enable experimental instrumentations.
NOTE: Changing this value at runtime can slow down the application temporarily.
@@ -3248,7 +3248,7 @@ Example: `5ms`.
# sanitize_field_names=password,passwd,pwd,secret,*key,*token*,*session*,*credit*,*card*,*auth*,*principal*,set-cookie
# A list of instrumentations which should be selectively enabled.
-# Valid options are `annotations`, `annotations-capture-span`, `annotations-capture-transaction`, `annotations-traced`, `apache-commons-exec`, `apache-httpclient`, `asynchttpclient`, `aws-lambda`, `aws-sdk`, `cassandra`, `concurrent`, `dubbo`, `elasticsearch-restclient`, `exception-handler`, `executor`, `executor-collection`, `experimental`, `fork-join`, `grails`, `grpc`, `hibernate-search`, `http-client`, `jakarta-websocket`, `javalin`, `javax-websocket`, `jax-rs`, `jax-ws`, `jboss-logging-correlation`, `jdbc`, `jdk-httpclient`, `jdk-httpserver`, `jedis`, `jms`, `jsf`, `jul-ecs`, `kafka`, `lettuce`, `log4j1-correlation`, `log4j1-ecs`, `log4j1-error`, `log4j2-correlation`, `log4j2-ecs`, `log4j2-error`, `logback-correlation`, `logback-ecs`, `logging`, `micrometer`, `mongodb`, `mongodb-client`, `okhttp`, `opentelemetry`, `opentracing`, `process`, `public-api`, `quartz`, `rabbitmq`, `reactor`, `redis`, `redisson`, `render`, `scala-future`, `scheduled`, `servlet-api`, `servlet-api-async`, `servlet-api-dispatch`, `servlet-input-stream`, `servlet-service-name`, `servlet-version`, `slf4j-error`, `sparkjava`, `spring-amqp`, `spring-mvc`, `spring-resttemplate`, `spring-service-name`, `spring-view-render`, `spring-webclient`, `spring-webflux`, `ssl-context`, `struts`, `timer-task`, `urlconnection`, `vertx`, `vertx-web`, `vertx-webclient`, `websocket`.
+# Valid options are `annotations`, `annotations-capture-span`, `annotations-capture-transaction`, `annotations-traced`, `apache-commons-exec`, `apache-httpclient`, `asynchttpclient`, `aws-lambda`, `aws-sdk`, `cassandra`, `concurrent`, `dubbo`, `elasticsearch-restclient`, `exception-handler`, `executor`, `executor-collection`, `experimental`, `fork-join`, `grails`, `grpc`, `hibernate-search`, `http-client`, `jakarta-websocket`, `javalin`, `javax-websocket`, `jax-rs`, `jax-ws`, `jboss-logging-correlation`, `jdbc`, `jdk-httpclient`, `jdk-httpserver`, `jedis`, `jms`, `jsf`, `jul-ecs`, `jul-error`, `kafka`, `lettuce`, `log4j1-correlation`, `log4j1-ecs`, `log4j1-error`, `log4j2-correlation`, `log4j2-ecs`, `log4j2-error`, `logback-correlation`, `logback-ecs`, `logging`, `micrometer`, `mongodb`, `mongodb-client`, `okhttp`, `opentelemetry`, `opentracing`, `process`, `public-api`, `quartz`, `rabbitmq`, `reactor`, `redis`, `redisson`, `render`, `scala-future`, `scheduled`, `servlet-api`, `servlet-api-async`, `servlet-api-dispatch`, `servlet-input-stream`, `servlet-service-name`, `servlet-version`, `slf4j-error`, `sparkjava`, `spring-amqp`, `spring-mvc`, `spring-resttemplate`, `spring-service-name`, `spring-view-render`, `spring-webclient`, `spring-webflux`, `ssl-context`, `struts`, `timer-task`, `urlconnection`, `vertx`, `vertx-web`, `vertx-webclient`, `websocket`.
# When set to non-empty value, only listed instrumentations will be enabled if they are not disabled through <> or <>.
# When not set or empty (default), all instrumentations enabled by default will be enabled unless they are disabled through <> or <>.
#
@@ -3261,7 +3261,7 @@ Example: `5ms`.
# enable_instrumentations=
# A list of instrumentations which should be disabled.
-# Valid options are `annotations`, `annotations-capture-span`, `annotations-capture-transaction`, `annotations-traced`, `apache-commons-exec`, `apache-httpclient`, `asynchttpclient`, `aws-lambda`, `aws-sdk`, `cassandra`, `concurrent`, `dubbo`, `elasticsearch-restclient`, `exception-handler`, `executor`, `executor-collection`, `experimental`, `fork-join`, `grails`, `grpc`, `hibernate-search`, `http-client`, `jakarta-websocket`, `javalin`, `javax-websocket`, `jax-rs`, `jax-ws`, `jboss-logging-correlation`, `jdbc`, `jdk-httpclient`, `jdk-httpserver`, `jedis`, `jms`, `jsf`, `jul-ecs`, `kafka`, `lettuce`, `log4j1-correlation`, `log4j1-ecs`, `log4j1-error`, `log4j2-correlation`, `log4j2-ecs`, `log4j2-error`, `logback-correlation`, `logback-ecs`, `logging`, `micrometer`, `mongodb`, `mongodb-client`, `okhttp`, `opentelemetry`, `opentracing`, `process`, `public-api`, `quartz`, `rabbitmq`, `reactor`, `redis`, `redisson`, `render`, `scala-future`, `scheduled`, `servlet-api`, `servlet-api-async`, `servlet-api-dispatch`, `servlet-input-stream`, `servlet-service-name`, `servlet-version`, `slf4j-error`, `sparkjava`, `spring-amqp`, `spring-mvc`, `spring-resttemplate`, `spring-service-name`, `spring-view-render`, `spring-webclient`, `spring-webflux`, `ssl-context`, `struts`, `timer-task`, `urlconnection`, `vertx`, `vertx-web`, `vertx-webclient`, `websocket`.
+# Valid options are `annotations`, `annotations-capture-span`, `annotations-capture-transaction`, `annotations-traced`, `apache-commons-exec`, `apache-httpclient`, `asynchttpclient`, `aws-lambda`, `aws-sdk`, `cassandra`, `concurrent`, `dubbo`, `elasticsearch-restclient`, `exception-handler`, `executor`, `executor-collection`, `experimental`, `fork-join`, `grails`, `grpc`, `hibernate-search`, `http-client`, `jakarta-websocket`, `javalin`, `javax-websocket`, `jax-rs`, `jax-ws`, `jboss-logging-correlation`, `jdbc`, `jdk-httpclient`, `jdk-httpserver`, `jedis`, `jms`, `jsf`, `jul-ecs`, `jul-error`, `kafka`, `lettuce`, `log4j1-correlation`, `log4j1-ecs`, `log4j1-error`, `log4j2-correlation`, `log4j2-ecs`, `log4j2-error`, `logback-correlation`, `logback-ecs`, `logging`, `micrometer`, `mongodb`, `mongodb-client`, `okhttp`, `opentelemetry`, `opentracing`, `process`, `public-api`, `quartz`, `rabbitmq`, `reactor`, `redis`, `redisson`, `render`, `scala-future`, `scheduled`, `servlet-api`, `servlet-api-async`, `servlet-api-dispatch`, `servlet-input-stream`, `servlet-service-name`, `servlet-version`, `slf4j-error`, `sparkjava`, `spring-amqp`, `spring-mvc`, `spring-resttemplate`, `spring-service-name`, `spring-view-render`, `spring-webclient`, `spring-webflux`, `ssl-context`, `struts`, `timer-task`, `urlconnection`, `vertx`, `vertx-web`, `vertx-webclient`, `websocket`.
# For version `1.25.0` and later, use <> to enable experimental instrumentations.
#
# NOTE: Changing this value at runtime can slow down the application temporarily.
diff --git a/docs/supported-technologies.asciidoc b/docs/supported-technologies.asciidoc
index 025d98316f..b58cb90b5d 100644
--- a/docs/supported-technologies.asciidoc
+++ b/docs/supported-technologies.asciidoc
@@ -606,8 +606,15 @@ JBoss LogManager - 1.30.0
|JUL - `java.util.logging`
|All supported Java versions
|When <> is enabled, logs will be automatically reformatted into
-ECS-compatible format
-|1.31.0
+ECS-compatible format.
+
+Trace correlation is only supported when used ECS logging library or with <> as JUL does
+not provide any MDC implementation.
+|Trace correlation - 1.35.0
+
+ECS Reformatting - 1.31.0
+
+Error capturing - 1.31.0
|===
diff --git a/pom.xml b/pom.xml
index fb74d4ff9c..c8282f51a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -114,7 +114,7 @@
(https://nvd.nist.gov/vuln/detail/CVE-2020-9488#vulnCurrentDescriptionTitle), the SMTP appender is
excluded from the build and not packaged into the agent artifacts -->
2.12.4
- 1.4.0
+ 1.5.0
5.0.15.RELEASE
2.2.2.RELEASE
9.4.11.v20180605