Skip to content

Commit 2f74bf6

Browse files
authored
feat: support auto-trace with layer (#73)
Java Tracer - Support auto-trace with layer RD-13012
1 parent 93a6a12 commit 2f74bf6

15 files changed

+214
-42
lines changed

.bumpversion.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ tag = True
1111

1212
[bumpversion:file:src/main/java/io/lumigo/core/configuration/Configuration.java]
1313

14+
[bumpversion:file:layer/generate.sh]
15+
1416
[bumpversion:file:src/main/resources/lumigo-version.txt]

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ Find the latest version here (the format of the version will be n.n.n):
8888
}
8989
}
9090
```
91+
92+
## Lambda Auto tracing with lambda layer
93+
94+
* Add to your lambda a new layer with the arn from here
95+
* Add environment variable `JAVA_TOOL_OPTIONS` and set it to `-javaagent:/opt/lumigo-java/lumigo-agent.jar` (This is instead of the flag for more than java11 support)
96+
* Add the `LUMIGO_TRACER_TOKEN` env var.
97+
9198

9299
### Configuration
93100

@@ -120,7 +127,7 @@ class MyFunction implements RequestHandler<String, String> {
120127
### Support Java 11 and Above
121128

122129
Add the environment variable `JAVA_TOOL_OPTIONS` to your Lambda functions and set it to
123-
`-Djdk.attach.allowAttachSelf=true` in addition to the manual code mentioned above.
130+
`-Djdk.attach.allowAttachSelf=true` in addition to the manual code mentioned above (This is not needed for the auto trace with lambda layer).
124131

125132
### Supported Instrumentation Libraries
126133

agent/pom.xml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@
3232
<organization>Lumigo</organization>
3333
<organizationUrl>https://lumigo.io/</organizationUrl>
3434
</developer>
35-
<developer>
36-
<name>Uri Parush</name>
37-
<email>uri@lumigo.io</email>
38-
<organization>Lumigo</organization>
39-
<organizationUrl>https://lumigo.io</organizationUrl>
40-
</developer>
4135
</developers>
4236

4337
<organization>
@@ -104,9 +98,12 @@
10498
<archive>
10599
<manifestEntries>
106100
<Agent-Class>io.lumigo.agent.Agent</Agent-Class>
107-
<Can-Redefine-Classes>false</Can-Redefine-Classes>
101+
<Main-Class>io.lumigo.agent.Agent</Main-Class>
102+
<Premain-Class>io.lumigo.agent.Agent</Premain-Class>
103+
<Can-Redefine-Classes>true</Can-Redefine-Classes>
108104
<Can-Retransform-Classes>true</Can-Retransform-Classes>
109105
<Can-Set-Native-Method-Prefix>false</Can-Set-Native-Method-Prefix>
106+
<Implementation-Vendor>Lumigo</Implementation-Vendor>
110107
</manifestEntries>
111108
</archive>
112109
</configuration>

agent/src/main/java/io/lumigo/agent/Agent.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,39 @@
1111
import java.nio.file.Paths;
1212
import java.util.LinkedList;
1313
import java.util.List;
14+
import java.util.jar.JarFile;
1415
import java.util.stream.Collectors;
1516
import java.util.stream.Stream;
1617

1718
public class Agent {
1819

20+
private static boolean initialized = false;
21+
22+
public static String LUMIGO_JAVA_TRACER_PATH = "/opt/lumigo-java/lumigo-tracer.jar";
23+
24+
public static void premain(String agentArgs, Instrumentation inst) {
25+
if (!isKillSwitchOn()) {
26+
agentmain(agentArgs, inst);
27+
}
28+
}
29+
1930
public static void agentmain(String agentArgs, Instrumentation inst) {
31+
if (initialized) {
32+
return;
33+
}
34+
initialized = true;
2035
try {
2136
URL[] urls;
2237
if ("lib".equalsIgnoreCase(agentArgs)) {
2338
urls = getUrls();
2439
} else {
25-
urls = new URL[] {new File("/var/task/").toURI().toURL()};
40+
urls =
41+
new URL[] {
42+
new File("/var/task/").toURI().toURL(),
43+
new File(LUMIGO_JAVA_TRACER_PATH).toURI().toURL()
44+
};
2645
}
46+
installTracerJar(inst);
2747
URLClassLoader newClassLoader = new URLClassLoader(urls, null);
2848
Thread.currentThread().setContextClassLoader(newClassLoader);
2949
final Class<?> loader =
@@ -35,6 +55,14 @@ public static void agentmain(String agentArgs, Instrumentation inst) {
3555
}
3656
}
3757

58+
private static void installTracerJar(Instrumentation inst) {
59+
try (JarFile jar = new JarFile(new File(new File(LUMIGO_JAVA_TRACER_PATH).toURI()))) {
60+
inst.appendToSystemClassLoaderSearch(jar);
61+
} catch (Exception e) {
62+
e.printStackTrace();
63+
}
64+
}
65+
3866
public static URL[] getUrls() {
3967
List<URL> jars = new LinkedList<>();
4068
try (Stream<Path> paths = Files.walk(Paths.get("/var/task/lib"))) {
@@ -56,4 +84,9 @@ public static URL[] getUrls() {
5684
}
5785
return jars.toArray(new URL[jars.size()]);
5886
}
87+
88+
public static boolean isKillSwitchOn() {
89+
String value = System.getenv("LUMIGO_SWITCH_OFF");
90+
return "true".equalsIgnoreCase(value);
91+
}
5992
}

layers/LAYERS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Java Layers
2+
----
3+
| Region | ARN |
4+
| --- | --- |

pom.xml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,28 +116,33 @@
116116
<groupId>software.amazon.awssdk</groupId>
117117
<artifactId>dynamodb</artifactId>
118118
<version>2.25.45</version>
119+
<scope>provided</scope>
119120
</dependency>
120121
<dependency>
121122
<groupId>software.amazon.awssdk</groupId>
122123
<artifactId>sqs</artifactId>
123124
<version>2.25.45</version>
125+
<scope>provided</scope>
124126
</dependency>
125127
<dependency>
126128
<groupId>software.amazon.awssdk</groupId>
127129
<artifactId>sns</artifactId>
128130
<version>2.25.45</version>
131+
<scope>provided</scope>
129132
</dependency>
130133
<dependency>
131134
<groupId>software.amazon.awssdk</groupId>
132135
<artifactId>kinesis</artifactId>
133136
<version>2.25.45</version>
137+
<scope>provided</scope>
134138
</dependency>
135139

136140
<!-- Kafka dependencies -->
137141
<dependency>
138142
<groupId>org.apache.kafka</groupId>
139143
<artifactId>kafka-clients</artifactId>
140144
<version>3.1.0</version>
145+
<scope>provided</scope>
141146
</dependency>
142147

143148
<!-- Tracer dependencies -->
@@ -182,6 +187,7 @@
182187
<artifactId>json</artifactId>
183188
<version>20210307</version>
184189
</dependency>
190+
185191
<!-- Testing dependencies -->
186192
<dependency>
187193
<groupId>org.junit.jupiter</groupId>
@@ -372,4 +378,32 @@
372378
</plugin>
373379
</plugins>
374380
</build>
381+
<profiles>
382+
<profile>
383+
<id>shade</id>
384+
<activation>
385+
<property>
386+
<name>includeShade</name>
387+
<value>true</value>
388+
</property>
389+
</activation>
390+
<build>
391+
<plugins>
392+
<plugin>
393+
<groupId>org.apache.maven.plugins</groupId>
394+
<artifactId>maven-shade-plugin</artifactId>
395+
<version>3.2.4</version>
396+
<executions>
397+
<execution>
398+
<phase>package</phase>
399+
<goals>
400+
<goal>shade</goal>
401+
</goals>
402+
</execution>
403+
</executions>
404+
</plugin>
405+
</plugins>
406+
</build>
407+
</profile>
408+
</profiles>
375409
</project>

scripts/bd_to_prod.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,26 @@ mvn -f agent/pom.xml nexus-staging:release
4040
mvn -Dmaven.test.skip=true -Dfindbugs.skip=true clean deploy
4141
mvn nexus-staging:release
4242

43+
echo "Creating lumigo-java-tracer layer"
44+
./scripts/prepare_layer_files.sh
45+
46+
echo "Creating layer latest version arn table md file (LAYERS.md)"
47+
commit_version="$(git describe --abbrev=0 --tags)"
48+
../utils/common_bash/create_layer.sh \
49+
--layer-name lumigo-java-tracer \
50+
--region ALL \
51+
--package-folder lumigo-java \
52+
--version "$commit_version" \
53+
--runtimes "java11 java17 java21"
54+
55+
cd ../larn && npm i -g
56+
larn -r java11 -n layers/LAYERS.md --filter lumigo-java-tracer -p ~/java-tracer
57+
cd ../java-tracer
58+
59+
git add layers/LAYERS.md
60+
git commit -m "docs: update layers md [skip ci]"
61+
git push origin master
62+
4363
echo "Create release tag"
4464
push_tags
4565

scripts/prepare_layer_files.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
3+
mkdir -p lumigo-java
4+
5+
MVN_DEFAULT_FLAGS="-Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.requestSentEnabled=true -Dmaven.wagon.http.retryHandler.count=10"
6+
7+
mvn "$MVN_DEFAULT_FLAGS" -Dmaven.test.skip=true -Dfindbugs.skip=true -DincludeShade=true clean package --quiet
8+
mvn "$MVN_DEFAULT_FLAGS" -f agent/pom.xml clean package --quiet
9+
10+
cp target/java-tracer-1.0.47.jar lumigo-java/lumigo-tracer.jar
11+
cp agent/target/lumigo-agent-1.0.47.jar lumigo-java/lumigo-agent.jar

src/main/java/io/lumigo/core/instrumentation/agent/Loader.java

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package io.lumigo.core.instrumentation.agent;
22

3-
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
4-
import static net.bytebuddy.matcher.ElementMatchers.not;
5-
63
import io.lumigo.core.instrumentation.impl.*;
74
import net.bytebuddy.agent.builder.AgentBuilder;
85
import org.pmw.tinylog.Logger;
96

7+
@SuppressWarnings("unused")
108
public class Loader {
119
public static void instrument(java.lang.instrument.Instrumentation inst) {
1210
Logger.debug("Start Instrumentation");
@@ -19,28 +17,12 @@ public static void instrument(java.lang.instrument.Instrumentation inst) {
1917
new ApacheKafkaProducerInstrumentation();
2018
ApacheKafkaConsumerInstrumentation apacheKafkaConsumerInstrumentation =
2119
new ApacheKafkaConsumerInstrumentation();
20+
AwsLambdaRequestHandlerInstrumentation awsLambdaRequestHandlerInstrumentation =
21+
new AwsLambdaRequestHandlerInstrumentation();
2222
AgentBuilder builder =
2323
new AgentBuilder.Default()
2424
.disableClassFormatChanges()
2525
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
26-
.ignore(
27-
not(nameStartsWith("com.amazonaws.http.AmazonHttpClient"))
28-
.and(not(nameStartsWith("org.apache.http.impl.client")))
29-
.and(
30-
not(
31-
nameStartsWith(
32-
AmazonHttpClientV2Instrumentation
33-
.INSTRUMENTATION_PACKAGE_PREFIX)))
34-
.and(
35-
not(
36-
nameStartsWith(
37-
ApacheKafkaProducerInstrumentation
38-
.INSTRUMENTATION_PACKAGE_PREFIX)))
39-
.and(
40-
not(
41-
nameStartsWith(
42-
ApacheKafkaConsumerInstrumentation
43-
.INSTRUMENTATION_PACKAGE_PREFIX))))
4426
.type(apacheHttpInstrumentation.getTypeMatcher())
4527
.transform(apacheHttpInstrumentation.getTransformer())
4628
.type(amazonHttpClientInstrumentation.getTypeMatcher())
@@ -50,7 +32,9 @@ public static void instrument(java.lang.instrument.Instrumentation inst) {
5032
.type(apacheKafkaInstrumentation.getTypeMatcher())
5133
.transform(apacheKafkaInstrumentation.getTransformer())
5234
.type(apacheKafkaConsumerInstrumentation.getTypeMatcher())
53-
.transform(apacheKafkaConsumerInstrumentation.getTransformer());
35+
.transform(apacheKafkaConsumerInstrumentation.getTransformer())
36+
.type(awsLambdaRequestHandlerInstrumentation.getTypeMatcher())
37+
.transform(awsLambdaRequestHandlerInstrumentation.getTransformer());
5438

5539
builder.installOn(inst);
5640
Logger.debug("Finish Instrumentation");

src/main/java/io/lumigo/core/instrumentation/impl/AmazonHttpClientInstrumentation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static void methodEnter(@Advice.Argument(0) final Request<?> request) {
4343
String patchedRoot = spansContainer.getPatchedRoot();
4444
request.getHeaders().put("X-Amzn-Trace-Id", patchedRoot);
4545
startTimeMap.put(request.hashCode(), System.currentTimeMillis());
46-
} catch (Exception e) {
46+
} catch (Throwable e) {
4747
Logger.error(e, "Failed to send data on http requests");
4848
}
4949
}

0 commit comments

Comments
 (0)