Skip to content

Commit 92252db

Browse files
authored
feat: add support for aws sdk v2 (Rd 12691) (#65)
1 parent c8292c8 commit 92252db

40 files changed

+1295
-208
lines changed

.circleci/config.yml

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,53 +33,47 @@ workflows:
3333

3434
- lumigo-orb/be-deploy:
3535
context: common
36+
save_project_folder: false
3637
requires:
3738
- lumigo-orb/is_environment_available
3839

39-
- lumigo-orb/pre_build_artifacts:
40+
- lumigo-orb/prep-it-resources:
4041
context: common
4142
requires:
4243
- lumigo-orb/is_environment_available
4344

44-
- lumigo-orb/integration-test-prep:
45-
context:
46-
- common
47-
- java
48-
install_maven_dependencies: true
49-
pre_builds_available: true
50-
run_test_cleanup: false
51-
requires:
52-
- lumigo-orb/be-deploy
53-
- lumigo-orb/pre_build_artifacts
54-
55-
- lumigo-orb/integration-test-cleanup:
56-
name: pre-test-cleanup
45+
- lumigo-orb/prep-k8s-and-operator:
5746
context: common
5847
requires:
59-
- lumigo-orb/integration-test-prep
48+
- lumigo-orb/is_environment_available
6049

6150
- lumigo-orb/integration-test-parallel:
6251
context: common
6352
run_test_cleanup: false
6453
requires:
65-
- pre-test-cleanup
54+
- lumigo-orb/be-deploy
55+
- lumigo-orb/prep-it-resources
56+
- lumigo-orb/prep-k8s-and-operator
6657

67-
- lumigo-orb/integration-test-cleanup:
68-
name: post-test-cleanup
58+
- lumigo-orb/e2e-test:
6959
context: common
7060
requires:
71-
- lumigo-orb/integration-test-parallel
61+
- lumigo-orb/be-deploy
62+
- lumigo-orb/prep-it-resources
63+
- lumigo-orb/prep-k8s-and-operator
7264

73-
- lumigo-orb/e2e-test:
65+
- lumigo-orb/integration-test-cleanup:
66+
name: post-test-cleanup
7467
context: common
7568
requires:
76-
- pre-test-cleanup
69+
- lumigo-orb/integration-test-parallel
70+
- lumigo-orb/e2e-test
7771

7872
- lumigo-orb/workflow-completed-successfully:
7973
context: common
8074
requires:
81-
- test
8275
- lumigo-orb/integration-test-parallel
76+
- test
8377
- lumigo-orb/e2e-test
8478

8579
- deploy:

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,9 @@ class MyFunction implements RequestHandler<String, String> {
102102

103103
Add the environment variable `JAVA_TOOL_OPTIONS` to your Lambda functions and set it to
104104
`-Djdk.attach.allowAttachSelf=true` in addition to the manual code mentioned above.
105+
106+
### Supported Instrumentation Libraries
107+
108+
- Aws SDK V1
109+
- Aws SDK V2
110+
- Apache HTTP Client

pom.xml

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
<jackson.version>2.9.8</jackson.version>
6363
<httpcomponents.httpclient.version>4.5.6</httpcomponents.httpclient.version>
6464
<httpcomponents.httpcore.version>4.4.10</httpcomponents.httpcore.version>
65-
<junit.version>5.4.2</junit.version>
65+
<junit.version>5.10.2</junit.version>
6666
</properties>
6767
<repositories>
6868
<repository>
@@ -96,7 +96,7 @@
9696
<dependency>
9797
<groupId>com.amazonaws</groupId>
9898
<artifactId>aws-java-sdk-s3</artifactId>
99-
<version>1.11.505</version>
99+
<version>1.12.261</version>
100100
<scope>provided</scope>
101101
</dependency>
102102
<dependency>
@@ -117,7 +117,33 @@
117117
<version>3.14.2</version>
118118
</dependency>
119119

120-
120+
<!-- AWS sdk V2 dependencies -->
121+
<dependency>
122+
<groupId>software.amazon.awssdk</groupId>
123+
<artifactId>core</artifactId>
124+
<version>2.25.45</version>
125+
<type>pom</type>
126+
</dependency>
127+
<dependency>
128+
<groupId>software.amazon.awssdk</groupId>
129+
<artifactId>dynamodb</artifactId>
130+
<version>2.25.45</version>
131+
</dependency>
132+
<dependency>
133+
<groupId>software.amazon.awssdk</groupId>
134+
<artifactId>sqs</artifactId>
135+
<version>2.25.45</version>
136+
</dependency>
137+
<dependency>
138+
<groupId>software.amazon.awssdk</groupId>
139+
<artifactId>sns</artifactId>
140+
<version>2.25.45</version>
141+
</dependency>
142+
<dependency>
143+
<groupId>software.amazon.awssdk</groupId>
144+
<artifactId>kinesis</artifactId>
145+
<version>2.25.45</version>
146+
</dependency>
121147

122148
<!-- Tracer dependencies -->
123149
<dependency>

src/main/java/io/lumigo/core/SpansContainer.java

Lines changed: 106 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
import com.amazonaws.services.lambda.runtime.Context;
66
import io.lumigo.core.configuration.Configuration;
77
import io.lumigo.core.network.Reporter;
8-
import io.lumigo.core.parsers.AwsParserFactory;
98
import io.lumigo.core.parsers.event.EventParserFactory;
9+
import io.lumigo.core.parsers.v1.AwsSdkV1ParserFactory;
10+
import io.lumigo.core.parsers.v2.AwsSdkV2ParserFactory;
1011
import io.lumigo.core.utils.AwsUtils;
1112
import io.lumigo.core.utils.JsonUtils;
1213
import io.lumigo.core.utils.StringUtils;
@@ -21,6 +22,11 @@
2122
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
2223
import org.apache.http.client.methods.HttpUriRequest;
2324
import org.pmw.tinylog.Logger;
25+
import software.amazon.awssdk.awscore.AwsResponse;
26+
import software.amazon.awssdk.core.SdkResponse;
27+
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
28+
import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
29+
import software.amazon.awssdk.core.sync.RequestBody;
2430

2531
public class SpansContainer {
2632

@@ -354,14 +360,88 @@ public void addHttpSpan(Long startTime, Request<?> request, Response<?> response
354360
response.getHttpResponse().getStatusCode())
355361
.build())
356362
.build());
357-
AwsParserFactory.getParser(request.getServiceName()).parse(httpSpan, request, response);
363+
AwsSdkV1ParserFactory.getParser(request.getServiceName())
364+
.safeParse(httpSpan, request, response);
365+
httpSpans.add(httpSpan);
366+
}
367+
368+
public void addHttpSpan(
369+
Long startTime,
370+
final software.amazon.awssdk.core.interceptor.Context.AfterExecution context,
371+
final ExecutionAttributes executionAttributes) {
372+
HttpSpan httpSpan = createBaseHttpSpan(startTime);
373+
String spanId = null;
374+
for (Map.Entry<String, List<String>> header : context.httpResponse().headers().entrySet()) {
375+
if ("x-amzn-requestid".equalsIgnoreCase(header.getKey())
376+
|| "x-amz-requestid".equalsIgnoreCase(header.getKey())) {
377+
spanId = header.getValue().get(0);
378+
}
379+
}
380+
if (spanId != null) {
381+
httpSpan.setId(spanId);
382+
}
383+
httpSpan.getInfo()
384+
.setHttpInfo(
385+
HttpSpan.HttpInfo.builder()
386+
.host(context.httpRequest().getUri().getHost())
387+
.request(
388+
HttpSpan.HttpData.builder()
389+
.headers(
390+
callIfVerbose(
391+
() ->
392+
extractHeadersV2(
393+
context.httpRequest()
394+
.headers())))
395+
.uri(
396+
callIfVerbose(
397+
() ->
398+
context.httpRequest()
399+
.getUri()
400+
.toString()))
401+
.method(context.httpRequest().method().name())
402+
.body(
403+
callIfVerbose(
404+
() ->
405+
extractBodyFromRequest(
406+
context
407+
.requestBody())))
408+
.build())
409+
.response(
410+
HttpSpan.HttpData.builder()
411+
.headers(
412+
callIfVerbose(
413+
() ->
414+
extractHeadersV2(
415+
context.httpResponse()
416+
.headers())))
417+
.body(
418+
callIfVerbose(
419+
() ->
420+
extractBodyFromResponse(
421+
context
422+
.response())))
423+
.statusCode(context.httpResponse().statusCode())
424+
.build())
425+
.build());
426+
427+
Logger.debug(
428+
"Trying to extract aws custom properties for service: "
429+
+ executionAttributes.getAttribute(SdkExecutionAttribute.SERVICE_NAME));
430+
AwsSdkV2ParserFactory.getParser(
431+
executionAttributes.getAttribute(SdkExecutionAttribute.SERVICE_NAME))
432+
.safeParse(httpSpan, context);
433+
358434
httpSpans.add(httpSpan);
359435
}
360436

361437
private static String extractHeaders(Map<String, String> headers) {
362438
return JsonUtils.getObjectAsJsonString(headers);
363439
}
364440

441+
private static String extractHeadersV2(Map<String, List<String>> headers) {
442+
return JsonUtils.getObjectAsJsonString(headers);
443+
}
444+
365445
private static String extractHeaders(Header[] headers) {
366446
Map<String, String> headersMap = new HashMap<>();
367447
if (headers != null) {
@@ -373,27 +453,31 @@ private static String extractHeaders(Header[] headers) {
373453
}
374454

375455
protected static String extractBodyFromRequest(Request<?> request) {
376-
return extractBodyFromRequest(request.getContent());
456+
return extractBodyFromStream(request.getContent());
457+
}
458+
459+
protected static String extractBodyFromRequest(Optional<RequestBody> request) {
460+
return request.map(
461+
requestBody ->
462+
extractBodyFromStream(
463+
requestBody.contentStreamProvider().newStream()))
464+
.orElse(null);
377465
}
378466

379467
protected static String extractBodyFromRequest(HttpUriRequest request) throws Exception {
380468
if (request instanceof HttpEntityEnclosingRequestBase) {
381469
HttpEntity entity = ((HttpEntityEnclosingRequestBase) request).getEntity();
382470
if (entity != null) {
383-
return extractBodyFromRequest(entity.getContent());
471+
return extractBodyFromStream(entity.getContent());
384472
}
385473
}
386474
return null;
387475
}
388476

389-
protected static String extractBodyFromRequest(InputStream stream) {
390-
return StringUtils.extractStringForStream(stream, MAX_STRING_SIZE);
391-
}
392-
393477
protected static String extractBodyFromResponse(HttpResponse response) throws IOException {
394-
return StringUtils.extractStringForStream(
395-
response.getEntity() != null ? response.getEntity().getContent() : null,
396-
MAX_STRING_SIZE);
478+
return response.getEntity() != null
479+
? extractBodyFromStream(response.getEntity().getContent())
480+
: null;
397481
}
398482

399483
protected static String extractBodyFromResponse(Response response) {
@@ -402,6 +486,17 @@ protected static String extractBodyFromResponse(Response response) {
402486
: null;
403487
}
404488

489+
protected static String extractBodyFromResponse(SdkResponse response) {
490+
if (response instanceof AwsResponse) {
491+
return JsonUtils.getObjectAsJsonString(response.toBuilder());
492+
}
493+
return null;
494+
}
495+
496+
protected static String extractBodyFromStream(InputStream stream) {
497+
return StringUtils.extractStringForStream(stream, MAX_STRING_SIZE);
498+
}
499+
405500
public String getPatchedRoot() {
406501
return String.format(
407502
"Root=%s-0000%s-%s%s",

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static net.bytebuddy.matcher.ElementMatchers.not;
55

66
import io.lumigo.core.instrumentation.impl.AmazonHttpClientInstrumentation;
7+
import io.lumigo.core.instrumentation.impl.AmazonHttpClientV2Instrumentation;
78
import io.lumigo.core.instrumentation.impl.ApacheHttpInstrumentation;
89
import net.bytebuddy.agent.builder.AgentBuilder;
910
import org.pmw.tinylog.Logger;
@@ -14,17 +15,25 @@ public static void instrument(java.lang.instrument.Instrumentation inst) {
1415
ApacheHttpInstrumentation apacheHttpInstrumentation = new ApacheHttpInstrumentation();
1516
AmazonHttpClientInstrumentation amazonHttpClientInstrumentation =
1617
new AmazonHttpClientInstrumentation();
18+
AmazonHttpClientV2Instrumentation amazonHttpClientV2Instrumentation =
19+
new AmazonHttpClientV2Instrumentation();
1720
AgentBuilder builder =
1821
new AgentBuilder.Default()
1922
.disableClassFormatChanges()
2023
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
2124
.ignore(
2225
not(nameStartsWith("com.amazonaws.http.AmazonHttpClient"))
23-
.and(not(nameStartsWith("org.apache.http.impl.client"))))
26+
.and(not(nameStartsWith("org.apache.http.impl.client")))
27+
.and(
28+
not(
29+
nameStartsWith(
30+
"software.amazon.awssdk.core.client.builder.SdkDefaultClientBuilder"))))
2431
.type(apacheHttpInstrumentation.getTypeMatcher())
2532
.transform(apacheHttpInstrumentation.getTransformer())
2633
.type(amazonHttpClientInstrumentation.getTypeMatcher())
27-
.transform(amazonHttpClientInstrumentation.getTransformer());
34+
.transform(amazonHttpClientInstrumentation.getTransformer())
35+
.type(amazonHttpClientV2Instrumentation.getTypeMatcher())
36+
.transform(amazonHttpClientV2Instrumentation.getTransformer());
2837

2938
builder.installOn(inst);
3039
Logger.debug("Finish Instrumentation");

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ public ElementMatcher<TypeDescription> getTypeMatcher() {
2424

2525
@Override
2626
public AgentBuilder.Transformer.ForAdvice getTransformer() {
27-
2827
return new AgentBuilder.Transformer.ForAdvice()
2928
.include(Loader.class.getClassLoader())
3029
.advice(isMethod().and(named("execute")), AmazonHttpClientAdvice.class.getName());

0 commit comments

Comments
 (0)