Skip to content

Commit 795b02e

Browse files
author
Anuraag Agrawal
authored
Fix log injection of xray ID. (#102)
1 parent 1e5ce35 commit 795b02e

File tree

5 files changed

+147
-26
lines changed

5 files changed

+147
-26
lines changed

build.gradle.kts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ allprojects {
112112

113113
spotless {
114114
java {
115-
googleJavaFormat("1.8")
115+
googleJavaFormat()
116116

117117
if (!project.path.startsWith(":sample-apps:")) {
118118
licenseHeaderFile("${rootProject.projectDir}/config/license/header.java")
@@ -157,9 +157,11 @@ allprojects {
157157

158158
plugins.withId("com.github.johnrengelman.shadow") {
159159
tasks {
160-
named<ShadowJar>("shadowJar") {
160+
withType<ShadowJar>().configureEach {
161161
exclude("**/module-info.class")
162162

163+
mergeServiceFiles()
164+
163165
// rewrite library instrumentation dependencies
164166
relocate("io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation")
165167

instrumentation/log4j-2.13.2/src/main/java/software/amazon/opentelemetry/javaagent/instrumentation/log4j_2_13_2/AwsXrayLog4jInstrumentationModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public AwsXrayLog4jInstrumentationModule() {
3535
// The SPI will be merged with what's in the agent so we don't need to inject it, only our
3636
// provider implementation.
3737
@Override
38-
public List<String> helperResourceNames() {
38+
public List<String> getMuzzleHelperClassNames() {
3939
return Collections.singletonList(
4040
"software.amazon.opentelemetry.javaagent.instrumentation.log4j_2_13_2."
4141
+ "AwsXrayContextDataProvider");

otelagent/build.gradle.kts

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

16+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
17+
1618
plugins {
1719
java
1820
`maven-publish`
@@ -27,7 +29,18 @@ java {
2729
}
2830

2931
base {
30-
archivesBaseName = "aws-opentelemetry-agent"
32+
archivesName.set("aws-opentelemetry-agent")
33+
}
34+
35+
val javaagentLibs by configurations.creating {
36+
isCanBeResolved = true
37+
isCanBeConsumed = false
38+
39+
exclude("io.opentelemetry", "opentelemetry-api")
40+
exclude("io.opentelemetry", "opentelemetry-api-metrics")
41+
exclude("io.opentelemetry", "opentelemetry-sdk")
42+
exclude("io.opentelemetry", "opentelemetry-sdk-common")
43+
exclude("io.opentelemetry", "opentelemetry-semconv")
3144
}
3245

3346
val shadowClasspath by configurations.creating {
@@ -43,38 +56,30 @@ dependencies {
4356
val agentDep = create("io.opentelemetry.javaagent", "opentelemetry-javaagent", classifier = "all")
4457
shadowClasspath(agentDep)
4558
compileOnly(agentDep)
46-
}
4759

48-
val bundledProjects = listOf(
49-
project(":awsagentprovider"),
50-
project(":instrumentation:log4j-2.13.2"),
51-
project(":instrumentation:logback-1.0")
52-
)
53-
54-
for (bundled in bundledProjects) {
55-
evaluationDependsOn(bundled.path)
60+
javaagentLibs(project(":awsagentprovider"))
61+
javaagentLibs(project(":instrumentation:log4j-2.13.2"))
62+
javaagentLibs(project(":instrumentation:logback-1.0"))
5663
}
5764

5865
tasks {
59-
processResources {
60-
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
61-
62-
for (bundled in bundledProjects) {
63-
val task = bundled.tasks.named<Jar>("shadowJar").get()
64-
val providerArchive = task.archiveFile
65-
from(zipTree(providerArchive)) {
66-
into("inst")
67-
rename("(^.*)\\.class$", "$1.classdata")
68-
}
69-
dependsOn(task)
70-
}
66+
val relocateJavaagentLibs by registering(ShadowJar::class) {
67+
configurations = listOf(javaagentLibs)
68+
69+
duplicatesStrategy = DuplicatesStrategy.FAIL
70+
71+
archiveFileName.set("javaagentLibs-relocated.jar")
7172
}
7273

7374
shadowJar {
75+
dependsOn(relocateJavaagentLibs)
76+
7477
archiveClassifier.set("")
7578

7679
configurations = listOf(shadowClasspath)
7780

81+
isolateClasses(relocateJavaagentLibs.get().outputs.files)
82+
7883
exclude("**/module-info.class")
7984

8085
mergeServiceFiles("inst/META-INF/services")
@@ -130,3 +135,18 @@ jib {
130135
}
131136
containerizingMode = "packaged"
132137
}
138+
139+
fun CopySpec.isolateClasses(jars: Iterable<File>) {
140+
jars.forEach {
141+
from(zipTree(it)) {
142+
// important to keep prefix "inst" short, as it is prefixed to lots of strings in runtime mem
143+
into("inst")
144+
rename("(^.*)\\.class\$", "\$1.classdata")
145+
// Rename LICENSE file since it clashes with license dir on non-case sensitive FSs (i.e. Mac)
146+
rename("""^LICENSE$""", "LICENSE.renamed")
147+
exclude("META-INF/INDEX.LIST")
148+
exclude("META-INF/*.DSA")
149+
exclude("META-INF/*.SF")
150+
}
151+
}
152+
}

settings.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
pluginManagement {
1717
plugins {
18-
id("com.diffplug.spotless") version "5.14.3"
18+
id("com.diffplug.spotless") version "5.17.0"
1919
id("com.github.ben-manes.versions") version "0.39.0"
2020
id("com.github.jk1.dependency-license-report") version "1.17"
2121
id("com.github.johnrengelman.shadow") version "7.0.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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 io.awsobservability.instrumentation.smoketests.runner;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import com.linecorp.armeria.client.WebClient;
21+
import java.util.regex.Pattern;
22+
import org.junit.jupiter.api.Test;
23+
import org.slf4j.LoggerFactory;
24+
import org.testcontainers.containers.GenericContainer;
25+
import org.testcontainers.containers.output.Slf4jLogConsumer;
26+
import org.testcontainers.containers.output.ToStringConsumer;
27+
import org.testcontainers.junit.jupiter.Container;
28+
import org.testcontainers.junit.jupiter.Testcontainers;
29+
import org.testcontainers.utility.MountableFile;
30+
31+
@Testcontainers(disabledWithoutDocker = true)
32+
class LogInjectionTest {
33+
34+
private static final ToStringConsumer log4jString = new ToStringConsumer();
35+
private static final ToStringConsumer logbackString = new ToStringConsumer();
36+
37+
private static final String AGENT_PATH =
38+
System.getProperty("io.awsobservability.instrumentation.smoketests.runner.agentPath");
39+
40+
@Container
41+
private static final GenericContainer<?> log4jApp =
42+
new GenericContainer<>(
43+
"public.ecr.aws/aws-otel-test/aws-otel-java-spark:f8f1ee321a1dc7f306f8354aca357ecbedfe8133")
44+
.withExposedPorts(4567)
45+
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger("log4j")))
46+
.withLogConsumer(log4jString)
47+
.withCopyFileToContainer(
48+
MountableFile.forHostPath(AGENT_PATH), "/opentelemetry-javaagent-all.jar")
49+
.withEnv("JAVA_TOOL_OPTIONS", "-javaagent:/opentelemetry-javaagent-all.jar")
50+
.withEnv("OTEL_JAVAAGENT_DEBUG", "true")
51+
.withEnv("AWS_REGION", "us-west-2")
52+
.withEnv("LISTEN_ADDRESS", "0.0.0.0:4567");
53+
54+
@Container
55+
private static final GenericContainer<?> logbackApp =
56+
new GenericContainer<>(
57+
"public.ecr.aws/aws-otel-test/aws-otel-java-springboot:f8f1ee321a1dc7f306f8354aca357ecbedfe8133")
58+
.withExposedPorts(8080)
59+
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger("logback")))
60+
.withLogConsumer(logbackString)
61+
.withCopyFileToContainer(
62+
MountableFile.forHostPath(AGENT_PATH), "/opentelemetry-javaagent-all.jar")
63+
.withEnv("JAVA_TOOL_OPTIONS", "-javaagent:/opentelemetry-javaagent-all.jar")
64+
.withEnv("OTEL_JAVAAGENT_DEBUG", "true")
65+
.withEnv("AWS_REGION", "us-west-2")
66+
.withEnv("LISTEN_ADDRESS", "0.0.0.0:8080");
67+
68+
private WebClient appClient;
69+
70+
@Test
71+
void log4j() {
72+
WebClient.of("http://localhost:" + log4jApp.getMappedPort(4567))
73+
.get("/outgoing-http-call")
74+
.aggregate()
75+
.join();
76+
77+
// Log message has X-Ray trace ID.
78+
assertThat(log4jString.toUtf8String())
79+
.matches(
80+
Pattern.compile(
81+
".*1-[0-9a-f]{8}-[0-9a-f]{24}@[0-9a-f]{16} - Executing outgoing-http-call.*",
82+
Pattern.DOTALL));
83+
}
84+
85+
@Test
86+
void logback() {
87+
WebClient.of("http://localhost:" + logbackApp.getMappedPort(8080))
88+
.get("/outgoing-http-call")
89+
.aggregate()
90+
.join();
91+
92+
// Log message has X-Ray trace ID.
93+
assertThat(logbackString.toUtf8String())
94+
.matches(
95+
Pattern.compile(
96+
".*1-[0-9a-f]{8}-[0-9a-f]{24}@[0-9a-f]{16} : Executing outgoing-http-call.*",
97+
Pattern.DOTALL));
98+
}
99+
}

0 commit comments

Comments
 (0)