From 488ca2659903df7461660f9030bb4ee88f1233bf Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Thu, 18 Mar 2021 10:53:50 +0900 Subject: [PATCH] =?UTF-8?q?Add=20instrumentation=20to=20inject=20x-ray=20f?= =?UTF-8?q?ormatted=20IDs=20into=20log4j=20and=20logb=E2=80=A6=20(#49)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add instrumentation to inject x-ray formatted IDs into log4j and logback contexts. * CLO * Remove prefix --- awsagentprovider/build.gradle.kts | 13 --- build.gradle.kts | 29 ++++++ dependencyManagement/build.gradle.kts | 3 +- instrumentation/log4j-2.13.2/build.gradle.kts | 29 ++++++ .../AwsXrayContextDataProvider.java | 48 ++++++++++ .../AwsXrayLog4jInstrumentationModule.java | 73 ++++++++++++++ ...ry.javaagent.tooling.InstrumentationModule | 1 + ...ogging.log4j.core.util.ContextDataProvider | 1 + instrumentation/logback-1.0/build.gradle.kts | 31 ++++++ .../AwsXrayLogbackInstrumentationModule.java | 40 ++++++++ .../AwsXrayLoggingEventInstrumentation.java | 96 +++++++++++++++++++ ...ry.javaagent.tooling.InstrumentationModule | 1 + otelagent/build.gradle.kts | 26 +++-- sample-apps/spark/build.gradle.kts | 3 + .../main/java/com/amazon/sampleapp/App.java | 8 ++ .../spark/src/main/resources/log4j2.xml | 13 +++ .../com/amazon/sampleapp/DemoController.java | 8 ++ .../src/main/resources/logback-spring.xml | 13 +++ settings.gradle.kts | 2 + 19 files changed, 418 insertions(+), 20 deletions(-) create mode 100644 instrumentation/log4j-2.13.2/build.gradle.kts create mode 100644 instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayContextDataProvider.java create mode 100644 instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayLog4jInstrumentationModule.java create mode 100644 instrumentation/log4j-2.13.2/src/main/resources/META-INF/services/io.opentelemetry.javaagent.tooling.InstrumentationModule create mode 100644 instrumentation/log4j-2.13.2/src/main/resources/META-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider create mode 100644 instrumentation/logback-1.0/build.gradle.kts create mode 100644 instrumentation/logback-1.0/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/logback_1_0/AwsXrayLogbackInstrumentationModule.java create mode 100644 instrumentation/logback-1.0/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/logback_1_0/AwsXrayLoggingEventInstrumentation.java create mode 100644 instrumentation/logback-1.0/src/main/resources/META-INF/services/io.opentelemetry.javaagent.tooling.InstrumentationModule create mode 100644 sample-apps/spark/src/main/resources/log4j2.xml create mode 100644 sample-apps/springboot/src/main/resources/logback-spring.xml diff --git a/awsagentprovider/build.gradle.kts b/awsagentprovider/build.gradle.kts index 5487268754..8a87591894 100644 --- a/awsagentprovider/build.gradle.kts +++ b/awsagentprovider/build.gradle.kts @@ -39,18 +39,5 @@ dependencies { tasks { shadowJar { archiveClassifier.set("") - - exclude("**/module-info.class") - - // rewrite dependencies calling Logger.getLogger - relocate("java.util.logging.Logger", "io.opentelemetry.javaagent.bootstrap.PatchLogger") - - // prevents conflict with library instrumentation - relocate("io.opentelemetry.instrumentation.api", "io.opentelemetry.javaagent.shaded.instrumentation.api") - - // relocate OpenTelemetry API usage - relocate("io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api") - relocate("io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context") - relocate("io.opentelemetry.spi", "io.opentelemetry.javaagent.shaded.io.opentelemetry.spi") } } diff --git a/build.gradle.kts b/build.gradle.kts index 8ba9a5045a..ce7c10046f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,6 +13,7 @@ * permissions and limitations under the License. */ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.github.jk1.license.render.InventoryMarkdownReportRenderer import nebula.plugin.release.git.opinion.Strategies import org.gradle.api.tasks.testing.logging.TestExceptionFormat @@ -24,6 +25,8 @@ plugins { id("com.github.jk1.dependency-license-report") id("io.github.gradle-nexus.publish-plugin") id("nebula.release") + + id("com.github.johnrengelman.shadow") apply false } release { @@ -135,6 +138,32 @@ allprojects { } } + plugins.withId("com.github.johnrengelman.shadow") { + tasks { + named("shadowJar") { + exclude("**/module-info.class") + + // rewrite library instrumentation dependencies + relocate("io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation") + + // rewrite dependencies calling Logger.getLogger + relocate("java.util.logging.Logger", "io.opentelemetry.javaagent.bootstrap.PatchLogger") + + // relocate OpenTelemetry API usage + relocate("io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api") + relocate("io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv") + relocate("io.opentelemetry.spi", "io.opentelemetry.javaagent.shaded.io.opentelemetry.spi") + relocate("io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context") + + // relocate the OpenTelemetry extensions that are used by instrumentation modules) + // these extensions live in the AgentClassLoader, and are injected into the user's class loader + // by the instrumentation modules that use them + relocate("io.opentelemetry.extension.aws", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.aws") + relocate("io.opentelemetry.extension.kotlin", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.kotlin") + } + } + } + plugins.withId("maven-publish") { plugins.apply("signing") diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 2155c35bd1..6b6d2148ae 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -66,7 +66,8 @@ val DEPENDENCIES = listOf( "commons-logging:commons-logging:1.2", "com.sparkjava:spark-core:2.9.3", "com.squareup.okhttp3:okhttp:4.9.1", - "io.opentelemetry.javaagent:opentelemetry-javaagent:${if (!TEST_SNAPSHOTS) "1.0.1" else "1.1.0-SNAPSHOT"}" + "io.opentelemetry.javaagent:opentelemetry-javaagent:${if (!TEST_SNAPSHOTS) "1.0.1" else "1.1.0-SNAPSHOT"}", + "net.bytebuddy:byte-buddy:1.10.22" ) javaPlatform { diff --git a/instrumentation/log4j-2.13.2/build.gradle.kts b/instrumentation/log4j-2.13.2/build.gradle.kts new file mode 100644 index 0000000000..97b01064be --- /dev/null +++ b/instrumentation/log4j-2.13.2/build.gradle.kts @@ -0,0 +1,29 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +plugins { + java + id("com.github.johnrengelman.shadow") +} + +base.archivesBaseName = "aws-instrumentation-log4j-2.13.2" + +dependencies { + compileOnly("io.opentelemetry:opentelemetry-api") + compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling") + compileOnly("net.bytebuddy:byte-buddy") + + compileOnly("org.apache.logging.log4j:log4j-core:2.13.2") +} diff --git a/instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayContextDataProvider.java b/instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayContextDataProvider.java new file mode 100644 index 0000000000..01c6f32ac8 --- /dev/null +++ b/instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayContextDataProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import java.util.Collections; +import java.util.Map; +import org.apache.logging.log4j.core.util.ContextDataProvider; + +/** + * A {@link ContextDataProvider} which injects the trace and span ID of the current {@link Span} in + * a format for consumption by AWS X-Ray and related services. + */ +public class AwsXrayContextDataProvider implements ContextDataProvider { + private static final String TRACE_ID_KEY = "AWS-XRAY-TRACE-ID"; + + @Override + public Map supplyContextData() { + Span currentSpan = Span.current(); + SpanContext spanContext = currentSpan.getSpanContext(); + if (!spanContext.isValid()) { + return Collections.emptyMap(); + } + + String value = + "1-" + + spanContext.getTraceId().substring(0, 8) + + "-" + + spanContext.getTraceId().substring(8) + + "@" + + spanContext.getSpanId(); + return Collections.singletonMap(TRACE_ID_KEY, value); + } +} diff --git a/instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayLog4jInstrumentationModule.java b/instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayLog4jInstrumentationModule.java new file mode 100644 index 0000000000..694d18e236 --- /dev/null +++ b/instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayLog4jInstrumentationModule.java @@ -0,0 +1,73 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2; + +import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.ClassLoaderMatcher.hasClassesNamed; +import static net.bytebuddy.matcher.ElementMatchers.named; + +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class AwsXrayLog4jInstrumentationModule extends InstrumentationModule { + + public AwsXrayLog4jInstrumentationModule() { + super("log4j", "log4j-2.13.2", "aws-log4j", "aws-log4j-2.13.2"); + } + + // The SPI will be merged with what's in the agent so we don't need to inject it, only our + // provider implementation. + @Override + protected String[] additionalHelperClassNames() { + return new String[] { + "software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2." + + "AwsXrayContextDataProvider" + }; + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + return hasClassesNamed("org.apache.logging.log4j.core.util.ContextDataProvider"); + } + + @Override + public List typeInstrumentations() { + return Collections.singletonList(new EmptyTypeInstrumentation()); + } + + public static class EmptyTypeInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + // we cannot use ContextDataProvider here because one of the classes that we inject implements + // this interface, causing the interface to be loaded while it's being transformed, which + // leads + // to duplicate class definition error after the interface is transformed and the triggering + // class loader tries to load it. + return named("org.apache.logging.log4j.core.impl.ThreadContextDataInjector"); + } + + @Override + public Map, String> transformers() { + // Nothing to instrument, no methods to match + return Collections.emptyMap(); + } + } +} diff --git a/instrumentation/log4j-2.13.2/src/main/resources/META-INF/services/io.opentelemetry.javaagent.tooling.InstrumentationModule b/instrumentation/log4j-2.13.2/src/main/resources/META-INF/services/io.opentelemetry.javaagent.tooling.InstrumentationModule new file mode 100644 index 0000000000..faf277cdad --- /dev/null +++ b/instrumentation/log4j-2.13.2/src/main/resources/META-INF/services/io.opentelemetry.javaagent.tooling.InstrumentationModule @@ -0,0 +1 @@ +software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2.AwsXrayLog4jInstrumentationModule diff --git a/instrumentation/log4j-2.13.2/src/main/resources/META-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider b/instrumentation/log4j-2.13.2/src/main/resources/META-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider new file mode 100644 index 0000000000..88b4b5b30e --- /dev/null +++ b/instrumentation/log4j-2.13.2/src/main/resources/META-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider @@ -0,0 +1 @@ +software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2.AwsXrayContextDataProvider diff --git a/instrumentation/logback-1.0/build.gradle.kts b/instrumentation/logback-1.0/build.gradle.kts new file mode 100644 index 0000000000..484b60829c --- /dev/null +++ b/instrumentation/logback-1.0/build.gradle.kts @@ -0,0 +1,31 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +plugins { + java + id("com.github.johnrengelman.shadow") +} + +base.archivesBaseName = "aws-instrumentation-logback-1.0" + +dependencies { + compileOnly("io.opentelemetry:opentelemetry-api") + compileOnly("io.opentelemetry.instrumentation:opentelemetry-logback-1.0") + compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-api") + compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling") + compileOnly("net.bytebuddy:byte-buddy") + + compileOnly("ch.qos.logback:logback-classic:1.0.0") +} diff --git a/instrumentation/logback-1.0/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/logback_1_0/AwsXrayLogbackInstrumentationModule.java b/instrumentation/logback-1.0/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/logback_1_0/AwsXrayLogbackInstrumentationModule.java new file mode 100644 index 0000000000..9b0c7a0174 --- /dev/null +++ b/instrumentation/logback-1.0/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/logback_1_0/AwsXrayLogbackInstrumentationModule.java @@ -0,0 +1,40 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 software.amazon.opentelemetry.javaagent.instrumentation.logback_1_0; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class AwsXrayLogbackInstrumentationModule extends InstrumentationModule { + public AwsXrayLogbackInstrumentationModule() { + super("logback", "logback-1.0", "aws-logback", "aws-logback-1.0"); + } + + @Override + public List typeInstrumentations() { + return Collections.singletonList(new AwsXrayLoggingEventInstrumentation()); + } + + @Override + public Map contextStore() { + return Collections.singletonMap( + "ch.qos.logback.classic.spi.ILoggingEvent", Span.class.getName()); + } +} diff --git a/instrumentation/logback-1.0/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/logback_1_0/AwsXrayLoggingEventInstrumentation.java b/instrumentation/logback-1.0/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/logback_1_0/AwsXrayLoggingEventInstrumentation.java new file mode 100644 index 0000000000..d23faec99e --- /dev/null +++ b/instrumentation/logback-1.0/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/logback_1_0/AwsXrayLoggingEventInstrumentation.java @@ -0,0 +1,96 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 software.amazon.opentelemetry.javaagent.instrumentation.logback_1_0; + +import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; +import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.ClassLoaderMatcher.hasClassesNamed; +import static java.util.Collections.singletonMap; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.instrumentation.logback.v1_0.internal.UnionMap; +import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; +import java.util.Map; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.implementation.bytecode.assign.Assigner.Typing; +import net.bytebuddy.matcher.ElementMatcher; + +public class AwsXrayLoggingEventInstrumentation implements TypeInstrumentation { + private static final String TRACE_ID_KEY = "AWS-XRAY-TRACE-ID"; + + @Override + public ElementMatcher classLoaderOptimization() { + return hasClassesNamed("ch.qos.logback.classic.spi.ILoggingEvent"); + } + + @Override + public ElementMatcher typeMatcher() { + return implementsInterface(named("ch.qos.logback.classic.spi.ILoggingEvent")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(isPublic()) + .and(named("getMDCPropertyMap").or(named("getMdc"))) + .and(takesArguments(0)), + AwsXrayLoggingEventInstrumentation.class.getName() + "$GetMdcAdvice"); + } + + public static class GetMdcAdvice { + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit( + @Advice.This ILoggingEvent event, + @Advice.Return(typing = Typing.DYNAMIC, readOnly = false) Map contextData) { + if (contextData != null && contextData.containsKey(TRACE_ID_KEY)) { + // Assume already instrumented event if traceId is present. + return; + } + + Span currentSpan = InstrumentationContext.get(ILoggingEvent.class, Span.class).get(event); + if (currentSpan == null || !currentSpan.getSpanContext().isValid()) { + return; + } + + SpanContext spanContext = currentSpan.getSpanContext(); + String value = + "1-" + + spanContext.getTraceId().substring(0, 8) + + "-" + + spanContext.getTraceId().substring(8) + + "@" + + spanContext.getSpanId(); + + Map spanContextData = Collections.singletonMap(TRACE_ID_KEY, value); + + if (contextData == null) { + contextData = spanContextData; + } else { + contextData = new UnionMap<>(contextData, spanContextData); + } + } + } +} diff --git a/instrumentation/logback-1.0/src/main/resources/META-INF/services/io.opentelemetry.javaagent.tooling.InstrumentationModule b/instrumentation/logback-1.0/src/main/resources/META-INF/services/io.opentelemetry.javaagent.tooling.InstrumentationModule new file mode 100644 index 0000000000..87a61234f2 --- /dev/null +++ b/instrumentation/logback-1.0/src/main/resources/META-INF/services/io.opentelemetry.javaagent.tooling.InstrumentationModule @@ -0,0 +1 @@ +software.amazon.opentelemetry.javaagent.instrumentation.logback_1_0.AwsXrayLogbackInstrumentationModule diff --git a/otelagent/build.gradle.kts b/otelagent/build.gradle.kts index 3e0ed2fb60..aae7d6c423 100644 --- a/otelagent/build.gradle.kts +++ b/otelagent/build.gradle.kts @@ -34,15 +34,27 @@ dependencies { implementation("io.opentelemetry.javaagent", "opentelemetry-javaagent", classifier = "all") } -val agentProviderShadowJarTask = project(":awsagentprovider").tasks.named("shadowJar") +val bundledProjects = listOf( + project(":awsagentprovider"), + project(":instrumentation:log4j-2.13.2"), + project(":instrumentation:logback-1.0") +) + +for (bundled in bundledProjects) { + evaluationDependsOn(bundled.path) +} + tasks { processResources { - val providerArchive = agentProviderShadowJarTask.get().archiveFile - from(zipTree(providerArchive)) { - into("inst") - rename("(^.*)\\.class$", "$1.classdata") + for (bundled in bundledProjects) { + val task = bundled.tasks.named("shadowJar").get() + val providerArchive = task.archiveFile + from(zipTree(providerArchive)) { + into("inst") + rename("(^.*)\\.class$", "$1.classdata") + } + dependsOn(task) } - dependsOn(agentProviderShadowJarTask) } shadowJar { @@ -50,6 +62,8 @@ tasks { exclude("**/module-info.class") + mergeServiceFiles("inst/META-INF/services") + manifest { attributes.put("Main-Class", "io.opentelemetry.javaagent.OpenTelemetryAgent") attributes.put("Agent-Class", "software.amazon.opentelemetry.javaagent.bootstrap.AwsAgentBootstrap") diff --git a/sample-apps/spark/build.gradle.kts b/sample-apps/spark/build.gradle.kts index 9ca645a2f0..b899976334 100644 --- a/sample-apps/spark/build.gradle.kts +++ b/sample-apps/spark/build.gradle.kts @@ -11,7 +11,10 @@ dependencies { implementation("com.squareup.okhttp3:okhttp") implementation("io.opentelemetry:opentelemetry-api") implementation("io.opentelemetry:opentelemetry-api-metrics") + implementation("org.apache.logging.log4j:log4j-core") implementation("software.amazon.awssdk:s3") + + runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl") } application { diff --git a/sample-apps/spark/src/main/java/com/amazon/sampleapp/App.java b/sample-apps/spark/src/main/java/com/amazon/sampleapp/App.java index d0797fa6f9..f5cf213189 100644 --- a/sample-apps/spark/src/main/java/com/amazon/sampleapp/App.java +++ b/sample-apps/spark/src/main/java/com/amazon/sampleapp/App.java @@ -10,9 +10,13 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import software.amazon.awssdk.services.s3.S3Client; public class App { + private static final Logger logger = LogManager.getLogger(); + static final String REQUEST_START_TIME = "requestStartTime"; static int mimicQueueSize; @@ -51,6 +55,8 @@ public static void main(String[] args) { get( "/outgoing-http-call", (req, res) -> { + logger.info("Executing outgoing-http-call"); + try (Response response = httpClient .newCall(new Request.Builder().url("https://aws.amazon.com").build()) @@ -66,6 +72,8 @@ public static void main(String[] args) { get( "/aws-sdk-call", (req, res) -> { + logger.info("Executing aws-sdk-all"); + s3.listBuckets(); return getXrayTraceId(); diff --git a/sample-apps/spark/src/main/resources/log4j2.xml b/sample-apps/spark/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..0d10a4cbba --- /dev/null +++ b/sample-apps/spark/src/main/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/sample-apps/springboot/src/main/java/com/amazon/sampleapp/DemoController.java b/sample-apps/springboot/src/main/java/com/amazon/sampleapp/DemoController.java index 8523ac97fa..310c44b285 100644 --- a/sample-apps/springboot/src/main/java/com/amazon/sampleapp/DemoController.java +++ b/sample-apps/springboot/src/main/java/com/amazon/sampleapp/DemoController.java @@ -6,6 +6,8 @@ import okhttp3.Call; import okhttp3.Request; import okhttp3.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @@ -14,6 +16,8 @@ @Controller public class DemoController { + private static final Logger logger = LoggerFactory.getLogger(DemoController.class); + private final Call.Factory httpClient; private final S3Client s3; @@ -34,6 +38,8 @@ public String healthCheck() { @GetMapping("/outgoing-http-call") @ResponseBody public String httpCall() { + logger.info("Executing outgoing-http-call"); + try (Response response = httpClient.newCall(new Request.Builder().url("https://aws.amazon.com").build()).execute()) { } catch (IOException e) { @@ -47,6 +53,8 @@ public String httpCall() { @GetMapping("/aws-sdk-call") @ResponseBody public String awssdkCall() { + logger.info("Executing aws-sdk-all"); + s3.listBuckets(); return getXrayTraceId(); diff --git a/sample-apps/springboot/src/main/resources/logback-spring.xml b/sample-apps/springboot/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..6669686b8c --- /dev/null +++ b/sample-apps/springboot/src/main/resources/logback-spring.xml @@ -0,0 +1,13 @@ + + + + + + %clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(%X{AWS-XRAY-TRACE-ID}){faint} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}} + ${CONSOLE_LOG_CHARSET} + + + + + + diff --git a/settings.gradle.kts b/settings.gradle.kts index 82a786f5a1..b2e9a0e06e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,6 +39,8 @@ dependencyResolutionManagement { include(":awsagentprovider") include(":dependencyManagement") +include(":instrumentation:logback-1.0") +include(":instrumentation:log4j-2.13.2") include(":otelagent") include(":smoke-tests:fakebackend") include(":smoke-tests:runner")