Skip to content

Commit 488ca26

Browse files
authored
Add instrumentation to inject x-ray formatted IDs into log4j and logb… (#49)
* Add instrumentation to inject x-ray formatted IDs into log4j and logback contexts. * CLO * Remove prefix
1 parent 0e694a8 commit 488ca26

File tree

19 files changed

+418
-20
lines changed

19 files changed

+418
-20
lines changed

awsagentprovider/build.gradle.kts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,5 @@ dependencies {
3939
tasks {
4040
shadowJar {
4141
archiveClassifier.set("")
42-
43-
exclude("**/module-info.class")
44-
45-
// rewrite dependencies calling Logger.getLogger
46-
relocate("java.util.logging.Logger", "io.opentelemetry.javaagent.bootstrap.PatchLogger")
47-
48-
// prevents conflict with library instrumentation
49-
relocate("io.opentelemetry.instrumentation.api", "io.opentelemetry.javaagent.shaded.instrumentation.api")
50-
51-
// relocate OpenTelemetry API usage
52-
relocate("io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api")
53-
relocate("io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context")
54-
relocate("io.opentelemetry.spi", "io.opentelemetry.javaagent.shaded.io.opentelemetry.spi")
5542
}
5643
}

build.gradle.kts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
1617
import com.github.jk1.license.render.InventoryMarkdownReportRenderer
1718
import nebula.plugin.release.git.opinion.Strategies
1819
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
@@ -24,6 +25,8 @@ plugins {
2425
id("com.github.jk1.dependency-license-report")
2526
id("io.github.gradle-nexus.publish-plugin")
2627
id("nebula.release")
28+
29+
id("com.github.johnrengelman.shadow") apply false
2730
}
2831

2932
release {
@@ -135,6 +138,32 @@ allprojects {
135138
}
136139
}
137140

141+
plugins.withId("com.github.johnrengelman.shadow") {
142+
tasks {
143+
named<ShadowJar>("shadowJar") {
144+
exclude("**/module-info.class")
145+
146+
// rewrite library instrumentation dependencies
147+
relocate("io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation")
148+
149+
// rewrite dependencies calling Logger.getLogger
150+
relocate("java.util.logging.Logger", "io.opentelemetry.javaagent.bootstrap.PatchLogger")
151+
152+
// relocate OpenTelemetry API usage
153+
relocate("io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api")
154+
relocate("io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv")
155+
relocate("io.opentelemetry.spi", "io.opentelemetry.javaagent.shaded.io.opentelemetry.spi")
156+
relocate("io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context")
157+
158+
// relocate the OpenTelemetry extensions that are used by instrumentation modules)
159+
// these extensions live in the AgentClassLoader, and are injected into the user's class loader
160+
// by the instrumentation modules that use them
161+
relocate("io.opentelemetry.extension.aws", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.aws")
162+
relocate("io.opentelemetry.extension.kotlin", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.kotlin")
163+
}
164+
}
165+
}
166+
138167
plugins.withId("maven-publish") {
139168
plugins.apply("signing")
140169

dependencyManagement/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ val DEPENDENCIES = listOf(
6666
"commons-logging:commons-logging:1.2",
6767
"com.sparkjava:spark-core:2.9.3",
6868
"com.squareup.okhttp3:okhttp:4.9.1",
69-
"io.opentelemetry.javaagent:opentelemetry-javaagent:${if (!TEST_SNAPSHOTS) "1.0.1" else "1.1.0-SNAPSHOT"}"
69+
"io.opentelemetry.javaagent:opentelemetry-javaagent:${if (!TEST_SNAPSHOTS) "1.0.1" else "1.1.0-SNAPSHOT"}",
70+
"net.bytebuddy:byte-buddy:1.10.22"
7071
)
7172

7273
javaPlatform {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
plugins {
17+
java
18+
id("com.github.johnrengelman.shadow")
19+
}
20+
21+
base.archivesBaseName = "aws-instrumentation-log4j-2.13.2"
22+
23+
dependencies {
24+
compileOnly("io.opentelemetry:opentelemetry-api")
25+
compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling")
26+
compileOnly("net.bytebuddy:byte-buddy")
27+
28+
compileOnly("org.apache.logging.log4j:log4j-core:2.13.2")
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2;
17+
18+
import io.opentelemetry.api.trace.Span;
19+
import io.opentelemetry.api.trace.SpanContext;
20+
import java.util.Collections;
21+
import java.util.Map;
22+
import org.apache.logging.log4j.core.util.ContextDataProvider;
23+
24+
/**
25+
* A {@link ContextDataProvider} which injects the trace and span ID of the current {@link Span} in
26+
* a format for consumption by AWS X-Ray and related services.
27+
*/
28+
public class AwsXrayContextDataProvider implements ContextDataProvider {
29+
private static final String TRACE_ID_KEY = "AWS-XRAY-TRACE-ID";
30+
31+
@Override
32+
public Map<String, String> supplyContextData() {
33+
Span currentSpan = Span.current();
34+
SpanContext spanContext = currentSpan.getSpanContext();
35+
if (!spanContext.isValid()) {
36+
return Collections.emptyMap();
37+
}
38+
39+
String value =
40+
"1-"
41+
+ spanContext.getTraceId().substring(0, 8)
42+
+ "-"
43+
+ spanContext.getTraceId().substring(8)
44+
+ "@"
45+
+ spanContext.getSpanId();
46+
return Collections.singletonMap(TRACE_ID_KEY, value);
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2;
17+
18+
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.ClassLoaderMatcher.hasClassesNamed;
19+
import static net.bytebuddy.matcher.ElementMatchers.named;
20+
21+
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
22+
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
23+
import java.util.Collections;
24+
import java.util.List;
25+
import java.util.Map;
26+
import net.bytebuddy.description.method.MethodDescription;
27+
import net.bytebuddy.description.type.TypeDescription;
28+
import net.bytebuddy.matcher.ElementMatcher;
29+
30+
public class AwsXrayLog4jInstrumentationModule extends InstrumentationModule {
31+
32+
public AwsXrayLog4jInstrumentationModule() {
33+
super("log4j", "log4j-2.13.2", "aws-log4j", "aws-log4j-2.13.2");
34+
}
35+
36+
// The SPI will be merged with what's in the agent so we don't need to inject it, only our
37+
// provider implementation.
38+
@Override
39+
protected String[] additionalHelperClassNames() {
40+
return new String[] {
41+
"software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2."
42+
+ "AwsXrayContextDataProvider"
43+
};
44+
}
45+
46+
@Override
47+
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
48+
return hasClassesNamed("org.apache.logging.log4j.core.util.ContextDataProvider");
49+
}
50+
51+
@Override
52+
public List<TypeInstrumentation> typeInstrumentations() {
53+
return Collections.singletonList(new EmptyTypeInstrumentation());
54+
}
55+
56+
public static class EmptyTypeInstrumentation implements TypeInstrumentation {
57+
@Override
58+
public ElementMatcher<? super TypeDescription> typeMatcher() {
59+
// we cannot use ContextDataProvider here because one of the classes that we inject implements
60+
// this interface, causing the interface to be loaded while it's being transformed, which
61+
// leads
62+
// to duplicate class definition error after the interface is transformed and the triggering
63+
// class loader tries to load it.
64+
return named("org.apache.logging.log4j.core.impl.ThreadContextDataInjector");
65+
}
66+
67+
@Override
68+
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
69+
// Nothing to instrument, no methods to match
70+
return Collections.emptyMap();
71+
}
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2.AwsXrayLog4jInstrumentationModule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2.AwsXrayContextDataProvider
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
plugins {
17+
java
18+
id("com.github.johnrengelman.shadow")
19+
}
20+
21+
base.archivesBaseName = "aws-instrumentation-logback-1.0"
22+
23+
dependencies {
24+
compileOnly("io.opentelemetry:opentelemetry-api")
25+
compileOnly("io.opentelemetry.instrumentation:opentelemetry-logback-1.0")
26+
compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-api")
27+
compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling")
28+
compileOnly("net.bytebuddy:byte-buddy")
29+
30+
compileOnly("ch.qos.logback:logback-classic:1.0.0")
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.opentelemetry.javaagent.instrumentation.logback_1_0;
17+
18+
import io.opentelemetry.api.trace.Span;
19+
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
20+
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
21+
import java.util.Collections;
22+
import java.util.List;
23+
import java.util.Map;
24+
25+
public class AwsXrayLogbackInstrumentationModule extends InstrumentationModule {
26+
public AwsXrayLogbackInstrumentationModule() {
27+
super("logback", "logback-1.0", "aws-logback", "aws-logback-1.0");
28+
}
29+
30+
@Override
31+
public List<TypeInstrumentation> typeInstrumentations() {
32+
return Collections.singletonList(new AwsXrayLoggingEventInstrumentation());
33+
}
34+
35+
@Override
36+
public Map<String, String> contextStore() {
37+
return Collections.singletonMap(
38+
"ch.qos.logback.classic.spi.ILoggingEvent", Span.class.getName());
39+
}
40+
}

0 commit comments

Comments
 (0)