diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index ea26c5f..f4ac674 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # pin@v4
- - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 # pin@v1
+ - uses: gradle/actions/wrapper-validation@v3
- name: Set up JDK 11
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # pin@v4
with:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 96ba2fc..4c966e3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -37,17 +37,8 @@ Before we can accept a pull request, you must sign our [Contributor Licensing Ag
Minimally, the [test suite](#testing-guidelines) must pass for us to accept a PR. Ideally, we would love it if you also added appropriate tests if you're implementing a feature!
## Coding Style Guidelines
-Our code base is formatted according to the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html).
-
-The project is configured to use the [google-java-format-gradle-plugin](https://github.com/sherter/google-java-format-gradle-plugin) which can be utilized as follows:
-
-* Execute the task `googleJavaFormat` to format all `*.java` files in the project:
-
-`./gradlew goJF`
-
-* Execute the task `verifyGoogleJavaFormat` to verify that all `*.java` files are formatted properly:
-
-`./gradlew verGJF`
+- Use the style provided in `dev-tools/code-style/java-agent-code-style.xml` in the project.
+- We encourage you to reduce tech debt you might find in the area. Leave the code better than you found it.
## Testing Guidelines
The AWS Lambda OpenTracing Java SDK comes with tests in `src/test` that can be run with `./gradlew test`.
diff --git a/README.md b/README.md
index 2e1c671..465c1c2 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,17 @@ This SDK provides Open Tracing instrumentation for AWS Lambda. Releases for this
Versioning will have the following format: {majorVersion}.{minorVersion}.{pointVersion}
+### Version 3.0.0
+
+Version 3.0.0 of this library made changes to the versions of AWS dependencies. The following dependencies are now used:
+- `com.amazonaws:aws-lambda-java-core:1.2.3` (previous version: 1.1.0)
+- `com.amazonaws:aws-lambda-java-events:3.15.0` (previous version: 2.2.7)
+- `software.amazon.awssdk:s3:2.31.43` (replaces com.amazonaws:aws-java-sdk-s3:1.12.771)
+- `software.amazon.awssdk:s3-event-notifications:2.31.43` (replaces com.amazonaws:aws-java-sdk-s3:1.12.771)
+
+It is recommended that functions that utilize the New Relic AWS Lamdba OpenTracing Java SDK utilize the same (or higher) versions
+of the underlying AWS libraries as noted above. Functions that are unable to upgrade should remain on version 2.2.0 of this library.
+
### Supported OpenTracing Versions
* OpenTracing 0.31.0: [com.newrelic.opentracing:java-aws-lambda:1.0.0](https://mvnrepository.com/artifact/com.newrelic.opentracing/java-aws-lambda/1.0.0)
diff --git a/build.gradle b/build.gradle
index b7edb71..ea5fab0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,9 +7,6 @@ buildscript {
}
}
- dependencies {
- classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.9"
- }
}
plugins {
@@ -25,8 +22,6 @@ java {
withJavadocJar()
}
-apply plugin: 'com.github.sherter.google-java-format'
-
repositories {
mavenCentral()
maven {
@@ -35,12 +30,12 @@ repositories {
}
dependencies {
- implementation 'com.amazonaws:aws-lambda-java-core:1.1.0'
- // 2.2.7 is earliest version that has all needed event sources
- implementation 'com.amazonaws:aws-lambda-java-events:2.2.7'
- implementation 'com.amazonaws:aws-java-sdk-s3:1.12.771'
- implementation 'com.amazonaws:aws-java-sdk-kinesis:1.11.163'
- implementation 'com.amazonaws:aws-java-sdk-dynamodb:1.11.163'
+ implementation 'software.amazon.awssdk:s3:2.31.43'
+ implementation 'software.amazon.awssdk:s3-event-notifications:2.31.43'
+
+ implementation 'com.amazonaws:aws-lambda-java-core:1.2.3'
+ implementation 'com.amazonaws:aws-lambda-java-events:3.15.0'
+
implementation('io.opentracing:opentracing-api:0.33.0')
implementation('io.opentracing:opentracing-util:0.33.0')
implementation('io.opentracing:opentracing-noop:0.33.0')
diff --git a/dev-tools/code-style/java-agent-code-style.xml b/dev-tools/code-style/java-agent-code-style.xml
new file mode 100644
index 0000000..9f56849
--- /dev/null
+++ b/dev-tools/code-style/java-agent-code-style.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index d7b0471..9a9e852 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,2 @@
group = com.newrelic.opentracing
-version = 2.3.0
+version = 3.0.0
diff --git a/src/main/java/com/newrelic/opentracing/aws/EnhancedSpanBuilder.java b/src/main/java/com/newrelic/opentracing/aws/EnhancedSpanBuilder.java
index eb2b30e..a68957a 100644
--- a/src/main/java/com/newrelic/opentracing/aws/EnhancedSpanBuilder.java
+++ b/src/main/java/com/newrelic/opentracing/aws/EnhancedSpanBuilder.java
@@ -10,66 +10,72 @@
import io.opentracing.Tracer;
public class EnhancedSpanBuilder {
- private final Tracer.SpanBuilder spanBuilder;
+ private final Tracer.SpanBuilder spanBuilder;
- public static EnhancedSpanBuilder basedOn(Tracer tracer, String operationName) {
- return new EnhancedSpanBuilder(tracer.buildSpan(operationName));
- }
+ public static EnhancedSpanBuilder basedOn(Tracer tracer, String operationName) {
+ return new EnhancedSpanBuilder(tracer.buildSpan(operationName));
+ }
- private EnhancedSpanBuilder(Tracer.SpanBuilder innerSpanBuilder) {
- spanBuilder = innerSpanBuilder;
- }
+ private EnhancedSpanBuilder(Tracer.SpanBuilder innerSpanBuilder) {
+ spanBuilder = innerSpanBuilder;
+ }
- public EnhancedSpanBuilder asChildOf(SpanContext spanContext) {
- this.spanBuilder.asChildOf(spanContext);
- return this;
- }
+ public EnhancedSpanBuilder asChildOf(SpanContext spanContext) {
+ this.spanBuilder.asChildOf(spanContext);
+ return this;
+ }
- /** Same as {@link Span#setTag(String, String)}, but for the span to be built. */
- EnhancedSpanBuilder withTag(String key, String value) {
- this.spanBuilder.withTag(key, value);
- return this;
- }
+ /**
+ * Same as {@link Span#setTag(String, String)}, but for the span to be built.
+ */
+ EnhancedSpanBuilder withTag(String key, String value) {
+ this.spanBuilder.withTag(key, value);
+ return this;
+ }
- /** Same as {@link Span#setTag(String, boolean)}, but for the span to be built. */
- EnhancedSpanBuilder withTag(String key, boolean value) {
- this.spanBuilder.withTag(key, value);
- return this;
- }
+ /**
+ * Same as {@link Span#setTag(String, boolean)}, but for the span to be built.
+ */
+ EnhancedSpanBuilder withTag(String key, boolean value) {
+ this.spanBuilder.withTag(key, value);
+ return this;
+ }
- /** Same as {@link Span#setTag(String, Number)}, but for the span to be built. */
- EnhancedSpanBuilder withTag(String key, Number value) {
- this.spanBuilder.withTag(key, value);
- return this;
- }
+ /**
+ * Same as {@link Span#setTag(String, Number)}, but for the span to be built.
+ */
+ EnhancedSpanBuilder withTag(String key, Number value) {
+ this.spanBuilder.withTag(key, value);
+ return this;
+ }
- /**
- * A shorthand for withTag("key", "value").
- *
- *
If parent==null, this is a noop.
- */
- EnhancedSpanBuilder optionallyWithTag(String key, String value) {
- if (value != null) {
- this.spanBuilder.withTag(key, value);
+ /**
+ * A shorthand for withTag("key", "value").
+ *
+ *
If parent==null, this is a noop.
+ */
+ EnhancedSpanBuilder optionallyWithTag(String key, String value) {
+ if (value != null) {
+ this.spanBuilder.withTag(key, value);
+ }
+ return this;
}
- return this;
- }
- EnhancedSpanBuilder optionallyWithTag(String key, boolean value) {
- if (value) {
- this.spanBuilder.withTag(key, true);
+ EnhancedSpanBuilder optionallyWithTag(String key, boolean value) {
+ if (value) {
+ this.spanBuilder.withTag(key, true);
+ }
+ return this;
}
- return this;
- }
- EnhancedSpanBuilder optionallyWithTag(String key, Number value) {
- if (value != null) {
- this.spanBuilder.withTag(key, value);
+ EnhancedSpanBuilder optionallyWithTag(String key, Number value) {
+ if (value != null) {
+ this.spanBuilder.withTag(key, value);
+ }
+ return this;
}
- return this;
- }
- public Span start() {
- return this.spanBuilder.start();
- }
+ public Span start() {
+ return this.spanBuilder.start();
+ }
}
diff --git a/src/main/java/com/newrelic/opentracing/aws/EventSourceParser.java b/src/main/java/com/newrelic/opentracing/aws/EventSourceParser.java
index 7c0faf4..3be24b1 100644
--- a/src/main/java/com/newrelic/opentracing/aws/EventSourceParser.java
+++ b/src/main/java/com/newrelic/opentracing/aws/EventSourceParser.java
@@ -11,9 +11,13 @@
import com.amazonaws.services.lambda.runtime.events.DynamodbEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent;
+import com.amazonaws.services.lambda.runtime.events.S3Event;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
-import com.amazonaws.services.s3.event.S3EventNotification;
+import software.amazon.awssdk.eventnotifications.s3.model.S3;
+import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification;
+import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotificationRecord;
+
import java.util.List;
import java.util.Map;
@@ -29,217 +33,242 @@
*/
final class EventSourceParser {
- private EventSourceParser() {}
-
- static String parseEventSourceArn(Object object) {
- if (object instanceof Map) {
- return parseFromMap((Map) object);
- } else if (object instanceof S3EventNotification) {
- return parseS3BucketArn(object);
- } else if (object instanceof SNSEvent) {
- return parseSNSEventSubscriptionArn(object);
- } else if (object instanceof SQSEvent) {
- return parseSQSEventSourceArn(object);
- } else if (object instanceof KinesisEvent) {
- return parseKinesisStreamEventSourceArn(object);
- } else if (object instanceof KinesisFirehoseEvent) {
- return parseKinesisFirehoseDeliveryStreamArn(object);
- } else if (object instanceof DynamodbEvent) {
- return parseDynamodbEventSourceArn(object);
- } else if (object instanceof CodeCommitEvent) {
- return parseCodeCommitEventSourceArn(object);
- } else if (object instanceof APIGatewayProxyRequestEvent) {
- return parseAPIGatewayProxyRequestEventUserArn(object);
- } else if (object instanceof APIGatewayV2ProxyRequestEvent) {
- return parseAPIGatewayV2ProxyRequestEventUserArn(object);
- }
- return null;
- }
-
- private static String parseFromMap(Map input) {
- try {
- if (input.get("streamArn") != null) {
- return (String) input.get("streamArn");
- } else if (input.get("deliveryStreamArn") != null) {
- return (String) input.get("deliveryStreamArn");
- } else if (input.get("requestContext") != null) {
- Map context = (Map) input.get("requestContext");
-
- // load balancer
- final Map elb = (Map) context.get("elb");
- if (elb != null) {
- return (String) elb.get("targetGroupArn");
- }
-
- // api gateway
- final Map identity = (Map) context.get("identity");
- if (identity != null) {
- return (String) identity.get("userArn");
- }
- } else if (input.get("detail") != null) { // AWS Cloudwatch
- Map detail = (Map) input.get("detail");
- return (String) detail.get("eventSource");
- }
-
- final List records = (List) input.get("Records");
- final Map record = (Map) records.get(0);
-
- if (record.get("eventSourceARN") != null) {
- return (String) record.get("eventSourceARN");
- } else if (record.get("EventSubscriptionArn") != null) {
- return (String) record.get("EventSubscriptionArn");
- } else if (record.containsKey("s3")) { // AWS S3
- final Map s3Event = (Map) record.get("s3");
- final Map bucket = (Map) s3Event.get("bucket");
- return (String) bucket.get("arn");
- }
-
- return null;
- } catch (Throwable t) {
+ private EventSourceParser() {
}
- return null;
- }
-
- private static String parseS3BucketArn(Object object) {
- final S3EventNotification notification = (S3EventNotification) object;
- if (notification.getRecords() == null || notification.getRecords().isEmpty()) {
- return null;
+ static String parseEventSourceArn(Object object) {
+ if (object instanceof Map) {
+ return parseFromMap((Map) object);
+ } else if (object instanceof S3EventNotification) {
+ return parseS3BucketArn(object);
+ } else if (object instanceof S3Event) {
+ return parseS3EventBucketArn(object);
+ } else if (object instanceof SNSEvent) {
+ return parseSNSEventSubscriptionArn(object);
+ } else if (object instanceof SQSEvent) {
+ return parseSQSEventSourceArn(object);
+ } else if (object instanceof KinesisEvent) {
+ return parseKinesisStreamEventSourceArn(object);
+ } else if (object instanceof KinesisFirehoseEvent) {
+ return parseKinesisFirehoseDeliveryStreamArn(object);
+ } else if (object instanceof DynamodbEvent) {
+ return parseDynamodbEventSourceArn(object);
+ } else if (object instanceof CodeCommitEvent) {
+ return parseCodeCommitEventSourceArn(object);
+ } else if (object instanceof APIGatewayProxyRequestEvent) {
+ return parseAPIGatewayProxyRequestEventUserArn(object);
+ } else if (object instanceof APIGatewayV2ProxyRequestEvent) {
+ return parseAPIGatewayV2ProxyRequestEventUserArn(object);
+ }
+ return null;
}
- final S3EventNotification.S3EventNotificationRecord s3EventNotificationRecord =
- notification.getRecords().get(0);
- if (s3EventNotificationRecord == null || s3EventNotificationRecord.getS3() == null) {
- return null;
+ private static String parseFromMap(Map input) {
+ try {
+ if (input.get("streamArn") != null) {
+ return (String) input.get("streamArn");
+ } else if (input.get("deliveryStreamArn") != null) {
+ return (String) input.get("deliveryStreamArn");
+ } else if (input.get("requestContext") != null) {
+ Map context = (Map) input.get("requestContext");
+
+ // load balancer
+ final Map elb = (Map) context.get("elb");
+ if (elb != null) {
+ return (String) elb.get("targetGroupArn");
+ }
+
+ // api gateway
+ final Map identity = (Map) context.get("identity");
+ if (identity != null) {
+ return (String) identity.get("userArn");
+ }
+ } else if (input.get("detail") != null) { // AWS Cloudwatch
+ Map detail = (Map) input.get("detail");
+ return (String) detail.get("eventSource");
+ }
+
+ final List records = (List) input.get("Records");
+ final Map record = (Map) records.get(0);
+
+ if (record.get("eventSourceARN") != null) {
+ return (String) record.get("eventSourceARN");
+ } else if (record.get("EventSubscriptionArn") != null) {
+ return (String) record.get("EventSubscriptionArn");
+ } else if (record.containsKey("s3")) { // AWS S3
+ final Map s3Event = (Map) record.get("s3");
+ final Map bucket = (Map) s3Event.get("bucket");
+ return (String) bucket.get("arn");
+ }
+
+ return null;
+ } catch (Throwable t) {
+ }
+ return null;
}
- final S3EventNotification.S3Entity s3 = s3EventNotificationRecord.getS3();
- if (s3.getBucket() == null) {
- return null;
- }
+ private static String parseS3BucketArn(Object object) {
+ final S3EventNotification notification = (S3EventNotification) object;
- return s3.getBucket().getArn();
- }
+ if (notification.getRecords() == null || notification.getRecords().isEmpty()) {
+ return null;
+ }
- private static String parseSNSEventSubscriptionArn(Object object) {
- final SNSEvent snsEvent = (SNSEvent) object;
+ final S3EventNotificationRecord s3EventNotificationRecord =
+ notification.getRecords().get(0);
+ if (s3EventNotificationRecord == null || s3EventNotificationRecord.getS3() == null) {
+ return null;
+ }
- final List records = snsEvent.getRecords();
- if (records == null || records.isEmpty()) {
- return null;
- }
+ final S3 s3 = s3EventNotificationRecord.getS3();
+ if (s3.getBucket() == null) {
+ return null;
+ }
- final SNSEvent.SNSRecord snsRecord = records.get(0);
- if (snsRecord == null) {
- return null;
+ return s3.getBucket().getArn();
}
- return snsRecord.getEventSubscriptionArn();
- }
+ private static String parseS3EventBucketArn(Object object) {
+ final S3Event notification = (S3Event) object;
+
+ if (notification.getRecords() == null || notification.getRecords().isEmpty()) {
+ return null;
+ }
- private static String parseSQSEventSourceArn(Object object) {
- final SQSEvent sqsEvent = (SQSEvent) object;
+ com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.S3EventNotificationRecord s3EventNotificationRecord =
+ notification.getRecords().get(0);
- final List records = sqsEvent.getRecords();
- if (records == null || records.isEmpty()) {
- return null;
- }
+ if (s3EventNotificationRecord == null || s3EventNotificationRecord.getS3() == null) {
+ return null;
+ }
- final SQSEvent.SQSMessage sqsMessage = records.get(0);
- if (sqsMessage == null) {
- return null;
+ final com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.S3Entity s3 = s3EventNotificationRecord.getS3();
+ if (s3.getBucket() == null) {
+ return null;
+ }
+
+ return s3.getBucket().getArn();
}
- return sqsMessage.getEventSourceArn();
- }
+ private static String parseSNSEventSubscriptionArn(Object object) {
+ final SNSEvent snsEvent = (SNSEvent) object;
- private static String parseKinesisStreamEventSourceArn(Object object) {
- final KinesisEvent kinesisEvent = (KinesisEvent) object;
+ final List records = snsEvent.getRecords();
+ if (records == null || records.isEmpty()) {
+ return null;
+ }
- final List records = kinesisEvent.getRecords();
- if (records == null || records.isEmpty()) {
- return null;
- }
+ final SNSEvent.SNSRecord snsRecord = records.get(0);
+ if (snsRecord == null) {
+ return null;
+ }
- final KinesisEvent.KinesisEventRecord kinesisEventRecord = records.get(0);
- if (kinesisEventRecord == null) {
- return null;
+ return snsRecord.getEventSubscriptionArn();
}
- return kinesisEventRecord.getEventSourceARN();
- }
-
- private static String parseKinesisFirehoseDeliveryStreamArn(Object object) {
- final KinesisFirehoseEvent kinesisFirehoseEvent = (KinesisFirehoseEvent) object;
+ private static String parseSQSEventSourceArn(Object object) {
+ final SQSEvent sqsEvent = (SQSEvent) object;
- return kinesisFirehoseEvent.getDeliveryStreamArn();
- }
+ final List records = sqsEvent.getRecords();
+ if (records == null || records.isEmpty()) {
+ return null;
+ }
- private static String parseDynamodbEventSourceArn(Object object) {
- final DynamodbEvent dynamodbEvent = (DynamodbEvent) object;
+ final SQSEvent.SQSMessage sqsMessage = records.get(0);
+ if (sqsMessage == null) {
+ return null;
+ }
- final List records = dynamodbEvent.getRecords();
- if (records == null || records.isEmpty()) {
- return null;
+ return sqsMessage.getEventSourceArn();
}
- final DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord = records.get(0);
- if (dynamodbStreamRecord == null) {
- return null;
- }
+ private static String parseKinesisStreamEventSourceArn(Object object) {
+ final KinesisEvent kinesisEvent = (KinesisEvent) object;
- return dynamodbStreamRecord.getEventSourceARN();
- }
+ final List records = kinesisEvent.getRecords();
+ if (records == null || records.isEmpty()) {
+ return null;
+ }
- private static String parseCodeCommitEventSourceArn(Object object) {
- final CodeCommitEvent codeCommitEvent = (CodeCommitEvent) object;
+ final KinesisEvent.KinesisEventRecord kinesisEventRecord = records.get(0);
+ if (kinesisEventRecord == null) {
+ return null;
+ }
- final List records = codeCommitEvent.getRecords();
- if (records == null || records.isEmpty()) {
- return null;
+ return kinesisEventRecord.getEventSourceARN();
}
- final CodeCommitEvent.Record record = records.get(0);
- if (record == null) {
- return null;
+ private static String parseKinesisFirehoseDeliveryStreamArn(Object object) {
+ final KinesisFirehoseEvent kinesisFirehoseEvent = (KinesisFirehoseEvent) object;
+
+ return kinesisFirehoseEvent.getDeliveryStreamArn();
}
- return record.getEventSourceArn();
- }
+ private static String parseDynamodbEventSourceArn(Object object) {
+ final DynamodbEvent dynamodbEvent = (DynamodbEvent) object;
- private static String parseAPIGatewayProxyRequestEventUserArn(Object object) {
- final APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent =
- (APIGatewayProxyRequestEvent) object;
+ final List records = dynamodbEvent.getRecords();
+ if (records == null || records.isEmpty()) {
+ return null;
+ }
- final APIGatewayProxyRequestEvent.ProxyRequestContext requestContext =
- apiGatewayProxyRequestEvent.getRequestContext();
- if (requestContext == null) {
- return null;
- }
+ final DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord = records.get(0);
+ if (dynamodbStreamRecord == null) {
+ return null;
+ }
- final APIGatewayProxyRequestEvent.RequestIdentity identity = requestContext.getIdentity();
- if (identity == null) {
- return null;
+ return dynamodbStreamRecord.getEventSourceARN();
}
- return identity.getUserArn();
- }
+ private static String parseCodeCommitEventSourceArn(Object object) {
+ final CodeCommitEvent codeCommitEvent = (CodeCommitEvent) object;
- private static String parseAPIGatewayV2ProxyRequestEventUserArn(Object object) {
- APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent =
- (APIGatewayV2ProxyRequestEvent) object;
+ final List records = codeCommitEvent.getRecords();
+ if (records == null || records.isEmpty()) {
+ return null;
+ }
- APIGatewayV2ProxyRequestEvent.RequestContext requestContext =
- apiGatewayV2ProxyRequestEvent.getRequestContext();
- if (requestContext == null) {
- return null;
+ final CodeCommitEvent.Record record = records.get(0);
+ if (record == null) {
+ return null;
+ }
+
+ return record.getEventSourceArn();
}
- APIGatewayV2ProxyRequestEvent.RequestIdentity identity = requestContext.getIdentity();
- if (identity == null) {
- return null;
+ private static String parseAPIGatewayProxyRequestEventUserArn(Object object) {
+ final APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent =
+ (APIGatewayProxyRequestEvent) object;
+
+ final APIGatewayProxyRequestEvent.ProxyRequestContext requestContext =
+ apiGatewayProxyRequestEvent.getRequestContext();
+ if (requestContext == null) {
+ return null;
+ }
+
+ final APIGatewayProxyRequestEvent.RequestIdentity identity = requestContext.getIdentity();
+ if (identity == null) {
+ return null;
+ }
+
+ return identity.getUserArn();
}
- return identity.getUserArn();
- }
+ private static String parseAPIGatewayV2ProxyRequestEventUserArn(Object object) {
+ APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent =
+ (APIGatewayV2ProxyRequestEvent) object;
+
+ APIGatewayV2ProxyRequestEvent.RequestContext requestContext =
+ apiGatewayV2ProxyRequestEvent.getRequestContext();
+ if (requestContext == null) {
+ return null;
+ }
+
+ APIGatewayV2ProxyRequestEvent.RequestIdentity identity = requestContext.getIdentity();
+ if (identity == null) {
+ return null;
+ }
+
+ return identity.getUserArn();
+ }
}
diff --git a/src/main/java/com/newrelic/opentracing/aws/HeadersParser.java b/src/main/java/com/newrelic/opentracing/aws/HeadersParser.java
index e0cb519..e6e5bfd 100644
--- a/src/main/java/com/newrelic/opentracing/aws/HeadersParser.java
+++ b/src/main/java/com/newrelic/opentracing/aws/HeadersParser.java
@@ -5,33 +5,76 @@
package com.newrelic.opentracing.aws;
-import com.amazonaws.Request;
+import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent;
+import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent;
+import com.amazonaws.services.lambda.runtime.events.SNSEvent;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMapAdapter;
+
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
final class HeadersParser {
- private HeadersParser() {}
+ private HeadersParser() {
+ }
+
+ static SpanContext parseAndExtract(Tracer tracer, Input input) {
+ try {
+ if (input instanceof Map) {
+ Map map = (Map) input;
+ final Object headers = map.get("headers");
+ if (headers instanceof Map) {
+ final Map headerStr = (Map) headers;
+ return tracer.extract(Format.Builtin.HTTP_HEADERS, new TextMapAdapter(headerStr));
+ }
+ } else if (input instanceof APIGatewayV2HTTPEvent) {
+ return tracer.extract(Format.Builtin.HTTP_HEADERS,
+ new TextMapAdapter(((APIGatewayV2HTTPEvent) input).getHeaders()));
+ } else if (input instanceof APIGatewayProxyRequestEvent) {
+ return tracer.extract(Format.Builtin.HTTP_HEADERS,
+ new TextMapAdapter(((APIGatewayProxyRequestEvent) input).getHeaders()));
+ } else if (input instanceof ApplicationLoadBalancerRequestEvent) {
+ return tracer.extract(Format.Builtin.HTTP_HEADERS,
+ new TextMapAdapter(((ApplicationLoadBalancerRequestEvent) input).getHeaders()));
+ } else if (input instanceof SNSEvent) {
+ SNSEvent snsEvent = (SNSEvent) input;
+ List records = snsEvent.getRecords();
+ Map extractedHeaders = new HashMap<>();
+ if (!records.isEmpty()) {
+ Map messageAttributes = records.get(0).getSNS().getMessageAttributes();
+
+ if (messageAttributes != null) {
+ for (Map.Entry entry : messageAttributes.entrySet()) {
+ extractedHeaders.put(entry.getKey(), entry.getValue().getValue());
+ }
+ }
+ }
+
+ return tracer.extract(Format.Builtin.HTTP_HEADERS, new TextMapAdapter(extractedHeaders));
+ } else if (input instanceof SQSEvent) {
+ SQSEvent sqsEvent = (SQSEvent) input;
+ List records = sqsEvent.getRecords();
+ Map extractedHeaders = new HashMap<>();
+ if (!records.isEmpty()) {
+ Map messageAttributes = records.get(0).getMessageAttributes();
+
+ if (messageAttributes != null) {
+ for (Map.Entry entry : messageAttributes.entrySet()) {
+ extractedHeaders.put(entry.getKey(), entry.getValue().getStringValue());
+ }
+ }
+ }
- static SpanContext parseAndExtract(Tracer tracer, Input input) {
- try {
- if (input instanceof Map) {
- Map map = (Map) input;
- final Object headers = map.get("headers");
- if (headers instanceof Map) {
- final Map headerStr = (Map) headers;
- return tracer.extract(Format.Builtin.HTTP_HEADERS, new TextMapAdapter(headerStr));
+ return tracer.extract(Format.Builtin.HTTP_HEADERS, new TextMapAdapter(extractedHeaders));
+ }
+ } catch (IllegalArgumentException exception) {
}
- } else if (input instanceof com.amazonaws.Request) {
- final Request request = (Request) input;
- final Map headers = request.getHeaders();
- return tracer.extract(Format.Builtin.HTTP_HEADERS, new TextMapAdapter(headers));
- }
- } catch (IllegalArgumentException exception) {
+ return null;
}
- return null;
- }
}
diff --git a/src/main/java/com/newrelic/opentracing/aws/LambdaTracing.java b/src/main/java/com/newrelic/opentracing/aws/LambdaTracing.java
index 33e96c3..41a2236 100644
--- a/src/main/java/com/newrelic/opentracing/aws/LambdaTracing.java
+++ b/src/main/java/com/newrelic/opentracing/aws/LambdaTracing.java
@@ -6,6 +6,7 @@
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
+
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiFunction;
@@ -15,64 +16,64 @@
* For flexibility, applications may extend this class to enhance the root span or handle novel
* invocation event types.
*
- * @param The invocation payload type for your lambda function.
+ * @param The invocation payload type for your lambda function.
* @param The result type for your lambda function.
*/
public class LambdaTracing {
- protected static final AtomicBoolean isColdStart = new AtomicBoolean(true);
+ protected static final AtomicBoolean isColdStart = new AtomicBoolean(true);
- /**
- * One-line instrumentation convenience method.
- *
- * @param input The invocation event
- * @param context The invocation context
- * @param realHandler The callback that implements the business logic for this event handler
- * @param The type of the invocation event
- * @param The type of the response
- * @return The invocation response (the return value of the realHandler callback)
- */
- public static Output instrument(
- Input input, Context context, BiFunction realHandler) {
- return new LambdaTracing ().instrumentRequest(input, context, realHandler);
- }
+ /**
+ * One-line instrumentation convenience method.
+ *
+ * @param input The invocation event
+ * @param context The invocation context
+ * @param realHandler The callback that implements the business logic for this event handler
+ * @param The type of the invocation event
+ * @param The type of the response
+ * @return The invocation response (the return value of the realHandler callback)
+ */
+ public static Output instrument(
+ Input input, Context context, BiFunction realHandler) {
+ return new LambdaTracing ().instrumentRequest(input, context, realHandler);
+ }
- /**
- * Instrument a Lambda invocation
- *
- * @param input The invocation event
- * @param context The invocation context
- * @param realHandler The function that implements the business logic. Will be invoked with the
- * input and context parameters, from within the instrumentation scope.
- * @return the return value from realHandler
- */
- public Output instrumentRequest(
- Input input, Context context, BiFunction realHandler) {
- final Tracer tracer = GlobalTracer.get();
- final SpanContext spanContext = extractContext(tracer, input);
+ /**
+ * Instrument a Lambda invocation
+ *
+ * @param input The invocation event
+ * @param context The invocation context
+ * @param realHandler The function that implements the business logic. Will be invoked with the
+ * input and context parameters, from within the instrumentation scope.
+ * @return the return value from realHandler
+ */
+ public Output instrumentRequest(
+ Input input, Context context, BiFunction realHandler) {
+ final Tracer tracer = GlobalTracer.get();
+ final SpanContext spanContext = extractContext(tracer, input);
- Span span = buildRootSpan(input, context, tracer, spanContext);
- try (Scope scope = tracer.activateSpan(span)) {
- Output output = realHandler.apply(input, context);
- parseResponse(span, output);
- return output;
- } catch (Throwable throwable) {
- span.log(SpanUtil.createErrorAttributes(throwable));
- throw throwable;
- } finally {
- span.finish();
+ Span span = buildRootSpan(input, context, tracer, spanContext);
+ try (Scope scope = tracer.activateSpan(span)) {
+ Output output = realHandler.apply(input, context);
+ parseResponse(span, output);
+ return output;
+ } catch (Throwable throwable) {
+ span.log(SpanUtil.createErrorAttributes(throwable));
+ throw throwable;
+ } finally {
+ span.finish();
+ }
}
- }
- protected SpanContext extractContext(Tracer tracer, Object input) {
- return HeadersParser.parseAndExtract(tracer, input);
- }
+ protected SpanContext extractContext(Tracer tracer, Object input) {
+ return HeadersParser.parseAndExtract(tracer, input);
+ }
- protected Span buildRootSpan(
- Input input, Context context, Tracer tracer, SpanContext spanContext) {
- return SpanUtil.buildSpan(input, context, tracer, spanContext, isColdStart);
- }
+ protected Span buildRootSpan(
+ Input input, Context context, Tracer tracer, SpanContext spanContext) {
+ return SpanUtil.buildSpan(input, context, tracer, spanContext, isColdStart);
+ }
- protected void parseResponse(Span span, Output output) {
- ResponseParser.parseResponse(output, span);
- }
+ protected void parseResponse(Span span, Output output) {
+ ResponseParser.parseResponse(output, span);
+ }
}
diff --git a/src/main/java/com/newrelic/opentracing/aws/ResponseParser.java b/src/main/java/com/newrelic/opentracing/aws/ResponseParser.java
index 87ca902..d83edfe 100644
--- a/src/main/java/com/newrelic/opentracing/aws/ResponseParser.java
+++ b/src/main/java/com/newrelic/opentracing/aws/ResponseParser.java
@@ -8,43 +8,45 @@
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2ProxyResponseEvent;
import io.opentracing.Span;
+
import java.util.Map;
public class ResponseParser {
- private ResponseParser() {}
-
- /**
- * Attempt to parse a status code from the response object, which could be present if the event
- * source type was created from an Application Load Balancer or API Gateway.
- */
- public static void parseResponse(Output response, Span span) {
- String statusCode = null;
-
- if (response instanceof Map) {
- Map map = (Map) response;
- Object statusCodeObject = map.get("statusCode");
- if (statusCodeObject instanceof String) {
- statusCode = (String) statusCodeObject;
- } else if (statusCodeObject instanceof Number) {
- statusCode = ((Number) statusCodeObject) + "";
- }
- } else if (response instanceof APIGatewayProxyResponseEvent) {
- final APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent =
- (APIGatewayProxyResponseEvent) response;
- if (response != null) {
- statusCode = apiGatewayProxyResponseEvent.getStatusCode() + "";
- }
- } else if (response instanceof APIGatewayV2ProxyResponseEvent) {
- final APIGatewayV2ProxyResponseEvent apiGatewayV2ProxyResponseEvent =
- (APIGatewayV2ProxyResponseEvent) response;
- if (response != null) {
- statusCode = apiGatewayV2ProxyResponseEvent.getStatusCode() + "";
- }
+ private ResponseParser() {
}
- if (statusCode != null && !statusCode.isEmpty()) {
- span.setTag("http.status_code", statusCode);
+ /**
+ * Attempt to parse a status code from the response object, which could be present if the event
+ * source type was created from an Application Load Balancer or API Gateway.
+ */
+ public static void parseResponse(Output response, Span span) {
+ String statusCode = null;
+
+ if (response instanceof Map) {
+ Map map = (Map) response;
+ Object statusCodeObject = map.get("statusCode");
+ if (statusCodeObject instanceof String) {
+ statusCode = (String) statusCodeObject;
+ } else if (statusCodeObject instanceof Number) {
+ statusCode = ((Number) statusCodeObject) + "";
+ }
+ } else if (response instanceof APIGatewayProxyResponseEvent) {
+ final APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent =
+ (APIGatewayProxyResponseEvent) response;
+ if (response != null) {
+ statusCode = apiGatewayProxyResponseEvent.getStatusCode() + "";
+ }
+ } else if (response instanceof APIGatewayV2ProxyResponseEvent) {
+ final APIGatewayV2ProxyResponseEvent apiGatewayV2ProxyResponseEvent =
+ (APIGatewayV2ProxyResponseEvent) response;
+ if (response != null) {
+ statusCode = apiGatewayV2ProxyResponseEvent.getStatusCode() + "";
+ }
+ }
+
+ if (statusCode != null && !statusCode.isEmpty()) {
+ span.setTag("http.status_code", statusCode);
+ }
}
- }
}
diff --git a/src/main/java/com/newrelic/opentracing/aws/SpanUtil.java b/src/main/java/com/newrelic/opentracing/aws/SpanUtil.java
index e28615e..7f20e30 100644
--- a/src/main/java/com/newrelic/opentracing/aws/SpanUtil.java
+++ b/src/main/java/com/newrelic/opentracing/aws/SpanUtil.java
@@ -10,6 +10,7 @@
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.tag.Tags;
+
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -17,31 +18,32 @@
public class SpanUtil {
- private SpanUtil() {}
+ private SpanUtil() {
+ }
- static Span buildSpan(
- Input input,
- Context context,
- Tracer tracer,
- SpanContext spanContext,
- AtomicBoolean isColdStart) {
- return EnhancedSpanBuilder.basedOn(tracer, "handleRequest")
- .asChildOf(spanContext)
- .withTag("aws.requestId", context.getAwsRequestId())
- .withTag("aws.lambda.arn", context.getInvokedFunctionArn())
- .optionallyWithTag(
- "aws.lambda.eventSource.arn", EventSourceParser.parseEventSourceArn(input))
- .optionallyWithTag("aws.lambda.coldStart", isColdStart.getAndSet(false))
- .start();
- }
+ static Span buildSpan(
+ Input input,
+ Context context,
+ Tracer tracer,
+ SpanContext spanContext,
+ AtomicBoolean isColdStart) {
+ return EnhancedSpanBuilder.basedOn(tracer, "handleRequest")
+ .asChildOf(spanContext)
+ .withTag("aws.requestId", context.getAwsRequestId())
+ .withTag("aws.lambda.arn", context.getInvokedFunctionArn())
+ .optionallyWithTag(
+ "aws.lambda.eventSource.arn", EventSourceParser.parseEventSourceArn(input))
+ .optionallyWithTag("aws.lambda.coldStart", isColdStart.getAndSet(false))
+ .start();
+ }
- public static Map createErrorAttributes(Throwable throwable) {
- final Map errorAttributes = new HashMap<>();
- errorAttributes.put("event", Tags.ERROR.getKey());
- errorAttributes.put("error.object", throwable);
- errorAttributes.put("message", throwable.getMessage());
- errorAttributes.put("stack", throwable.getStackTrace());
- errorAttributes.put("error.kind", "Exception");
- return Collections.unmodifiableMap(errorAttributes);
- }
+ public static Map createErrorAttributes(Throwable throwable) {
+ final Map errorAttributes = new HashMap<>();
+ errorAttributes.put("event", Tags.ERROR.getKey());
+ errorAttributes.put("error.object", throwable);
+ errorAttributes.put("message", throwable.getMessage());
+ errorAttributes.put("stack", throwable.getStackTrace());
+ errorAttributes.put("error.kind", "Exception");
+ return Collections.unmodifiableMap(errorAttributes);
+ }
}
diff --git a/src/main/java/com/newrelic/opentracing/aws/StreamLambdaTracing.java b/src/main/java/com/newrelic/opentracing/aws/StreamLambdaTracing.java
index b5e5560..caa167b 100644
--- a/src/main/java/com/newrelic/opentracing/aws/StreamLambdaTracing.java
+++ b/src/main/java/com/newrelic/opentracing/aws/StreamLambdaTracing.java
@@ -7,6 +7,7 @@
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -17,52 +18,52 @@
* For flexibility, applications may extend this class to enhance the root span.
*/
public class StreamLambdaTracing {
- /**
- * One-line instrumentation convenience method.
- *
- * @param input The invocation event's input stream
- * @param output The invocation response output stream
- * @param context The invocation context
- * @param realHandler The callback that implements the business logic for this event handler
- */
- public static void instrument(
- InputStream input, OutputStream output, Context context, RequestStreamHandler realHandler)
- throws IOException {
- new StreamLambdaTracing().instrumentRequest(input, output, context, realHandler);
- }
+ /**
+ * One-line instrumentation convenience method.
+ *
+ * @param input The invocation event's input stream
+ * @param output The invocation response output stream
+ * @param context The invocation context
+ * @param realHandler The callback that implements the business logic for this event handler
+ */
+ public static void instrument(
+ InputStream input, OutputStream output, Context context, RequestStreamHandler realHandler)
+ throws IOException {
+ new StreamLambdaTracing().instrumentRequest(input, output, context, realHandler);
+ }
- /**
- * Instrument a Lambda invocation
- *
- * @param input The invocation event's input stream
- * @param output The invocation response output stream
- * @param context The invocation context
- * @param realHandler The function that implements the business logic. Will be invoked with the
- * input and context parameters, from within the instrumentation scope.
- */
- public void instrumentRequest(
- InputStream input, OutputStream output, Context context, RequestStreamHandler realHandler)
- throws IOException {
- final Tracer tracer = GlobalTracer.get();
- final SpanContext spanContext = extractContext(tracer, input);
+ /**
+ * Instrument a Lambda invocation
+ *
+ * @param input The invocation event's input stream
+ * @param output The invocation response output stream
+ * @param context The invocation context
+ * @param realHandler The function that implements the business logic. Will be invoked with the
+ * input and context parameters, from within the instrumentation scope.
+ */
+ public void instrumentRequest(
+ InputStream input, OutputStream output, Context context, RequestStreamHandler realHandler)
+ throws IOException {
+ final Tracer tracer = GlobalTracer.get();
+ final SpanContext spanContext = extractContext(tracer, input);
- Span span = buildRootSpan(input, context, tracer, spanContext);
- try (Scope scope = tracer.activateSpan(span)) {
- realHandler.handleRequest(input, output, context);
- } catch (Throwable throwable) {
- span.log(SpanUtil.createErrorAttributes(throwable));
- throw throwable;
- } finally {
- span.finish();
+ Span span = buildRootSpan(input, context, tracer, spanContext);
+ try (Scope scope = tracer.activateSpan(span)) {
+ realHandler.handleRequest(input, output, context);
+ } catch (Throwable throwable) {
+ span.log(SpanUtil.createErrorAttributes(throwable));
+ throw throwable;
+ } finally {
+ span.finish();
+ }
}
- }
- protected Span buildRootSpan(
- InputStream input, Context context, Tracer tracer, SpanContext spanContext) {
- return SpanUtil.buildSpan(input, context, tracer, spanContext, LambdaTracing.isColdStart);
- }
+ protected Span buildRootSpan(
+ InputStream input, Context context, Tracer tracer, SpanContext spanContext) {
+ return SpanUtil.buildSpan(input, context, tracer, spanContext, LambdaTracing.isColdStart);
+ }
- protected SpanContext extractContext(Tracer tracer, InputStream input) {
- return null;
- }
+ protected SpanContext extractContext(Tracer tracer, InputStream input) {
+ return null;
+ }
}
diff --git a/src/main/java/com/newrelic/opentracing/aws/TracingRequestHandler.java b/src/main/java/com/newrelic/opentracing/aws/TracingRequestHandler.java
index 0881f80..2bd9d13 100644
--- a/src/main/java/com/newrelic/opentracing/aws/TracingRequestHandler.java
+++ b/src/main/java/com/newrelic/opentracing/aws/TracingRequestHandler.java
@@ -19,40 +19,40 @@
*
Due to an interaction between Java's type erasure and method inheritance, Input effectively
* must be a Map. For that reason, this interface is deprecated in favor of {@link LambdaTracing}.
*
- * @param The input parameter type
+ * @param The input parameter type
* @param The output parameter type
*/
@Deprecated
public interface TracingRequestHandler
- extends com.amazonaws.services.lambda.runtime.RequestHandler {
+ extends com.amazonaws.services.lambda.runtime.RequestHandler {
- /**
- * Method that handles the Lambda function request.
- *
- * Override this method in your code.
- *
- * @param input The Lambda Function input
- * @param context The Lambda execution environment context object
- * @return The Lambda Function output
- */
- Output doHandleRequest(Input input, Context context);
+ /**
+ * Method that handles the Lambda function request.
+ *
+ *
Override this method in your code.
+ *
+ * @param input The Lambda Function input
+ * @param context The Lambda execution environment context object
+ * @return The Lambda Function output
+ */
+ Output doHandleRequest(Input input, Context context);
- default Output handleRequest(Input input, Context context) {
- return LambdaTracing.instrument(input, context, this::doHandleRequest);
- }
+ default Output handleRequest(Input input, Context context) {
+ return LambdaTracing.instrument(input, context, this::doHandleRequest);
+ }
- /**
- * Override to extract context from Input.
- *
- *
Implementations should call {@link Tracer#extract(Format, Object)} and return the extracted
- * SpanContext.
- *
- * @param tracer OpenTracing tracer
- * @param input input to Lambda function
- * @return SpanContext extracted from input, null if there was no context or there was an issue
- * extracting this context
- */
- default SpanContext extractContext(Tracer tracer, Input input) {
- return HeadersParser.parseAndExtract(tracer, input);
- }
+ /**
+ * Override to extract context from Input.
+ *
+ *
Implementations should call {@link Tracer#extract(Format, Object)} and return the extracted
+ * SpanContext.
+ *
+ * @param tracer OpenTracing tracer
+ * @param input input to Lambda function
+ * @return SpanContext extracted from input, null if there was no context or there was an issue
+ * extracting this context
+ */
+ default SpanContext extractContext(Tracer tracer, Input input) {
+ return HeadersParser.parseAndExtract(tracer, input);
+ }
}
diff --git a/src/main/java/com/newrelic/opentracing/aws/TracingRequestStreamHandler.java b/src/main/java/com/newrelic/opentracing/aws/TracingRequestStreamHandler.java
index 6e1aed1..5a3c485 100644
--- a/src/main/java/com/newrelic/opentracing/aws/TracingRequestStreamHandler.java
+++ b/src/main/java/com/newrelic/opentracing/aws/TracingRequestStreamHandler.java
@@ -9,6 +9,7 @@
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -24,39 +25,39 @@
*/
@Deprecated
public interface TracingRequestStreamHandler
- extends com.amazonaws.services.lambda.runtime.RequestStreamHandler {
+ extends com.amazonaws.services.lambda.runtime.RequestStreamHandler {
- /**
- * Method that handles the Lambda function request.
- *
- *
Override this method in your code.
- *
- * @param input The Lambda Function input stream
- * @param output The Lambda Function output stream
- * @param context The Lambda execution environment context object
- */
- void doHandleRequest(InputStream input, OutputStream output, Context context);
+ /**
+ * Method that handles the Lambda function request.
+ *
+ *
Override this method in your code.
+ *
+ * @param input The Lambda Function input stream
+ * @param output The Lambda Function output stream
+ * @param context The Lambda execution environment context object
+ */
+ void doHandleRequest(InputStream input, OutputStream output, Context context);
- default void handleRequest(InputStream input, OutputStream output, Context context) {
- try {
- StreamLambdaTracing.instrument(input, output, context, this::doHandleRequest);
- } catch (IOException e) {
- throw new RuntimeException("Exception while processing Lambda invocation", e);
+ default void handleRequest(InputStream input, OutputStream output, Context context) {
+ try {
+ StreamLambdaTracing.instrument(input, output, context, this::doHandleRequest);
+ } catch (IOException e) {
+ throw new RuntimeException("Exception while processing Lambda invocation", e);
+ }
}
- }
- /**
- * Override to extract context from Input.
- *
- *
Implementations should call {@link Tracer#extract(Format, Object)} and return the extracted
- * SpanContext.
- *
- * @param tracer OpenTracing tracer
- * @param input Input to Lambda function
- * @return SpanContext Extracted from input, null if there was no context or there was an issue
- * extracting this context
- */
- default SpanContext extractContext(Tracer tracer, InputStream input) {
- return null;
- }
+ /**
+ * Override to extract context from Input.
+ *
+ *
Implementations should call {@link Tracer#extract(Format, Object)} and return the extracted
+ * SpanContext.
+ *
+ * @param tracer OpenTracing tracer
+ * @param input Input to Lambda function
+ * @return SpanContext Extracted from input, null if there was no context or there was an issue
+ * extracting this context
+ */
+ default SpanContext extractContext(Tracer tracer, InputStream input) {
+ return null;
+ }
}
diff --git a/src/test/java/com/newrelic/opentracing/aws/EnhancedSpanBuilderTest.java b/src/test/java/com/newrelic/opentracing/aws/EnhancedSpanBuilderTest.java
index 7cfb8cf..0f1f121 100644
--- a/src/test/java/com/newrelic/opentracing/aws/EnhancedSpanBuilderTest.java
+++ b/src/test/java/com/newrelic/opentracing/aws/EnhancedSpanBuilderTest.java
@@ -5,148 +5,153 @@
package com.newrelic.opentracing.aws;
-import static io.opentracing.propagation.Format.Builtin.TEXT_MAP;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.*;
-
import io.opentracing.References;
import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
import io.opentracing.propagation.TextMapAdapter;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import static io.opentracing.propagation.Format.Builtin.TEXT_MAP;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+
public class EnhancedSpanBuilderTest {
- private Random random = new Random();
-
- private MockTracer tracer;
- private MockSpan.MockContext context;
-
- @Before
- public void beforeEach() {
- Map parentIds = new HashMap<>();
- parentIds.put("traceid", Math.abs(this.random.nextLong()) + "");
- parentIds.put("spanid", Math.abs(this.random.nextLong()) + "");
-
- this.tracer = new MockTracer();
- this.context = (MockSpan.MockContext) tracer.extract(TEXT_MAP, new TextMapAdapter(parentIds));
- }
-
- @After
- public void afterEach() {
- this.tracer.close();
- this.tracer.reset();
- }
-
- @Test
- public void basedOn() {
- MockSpan builtSpan = (MockSpan) EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation").start();
- assertThat(builtSpan.operationName(), is(equalTo("AnOperation")));
- assertThat(builtSpan.tags().entrySet(), hasSize(0));
- }
-
- @Test
- public void asChildOf() {
- MockSpan.Reference expectedReference =
- new MockSpan.Reference(this.context, References.CHILD_OF);
-
- MockSpan builtSpan =
- (MockSpan)
- EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation").asChildOf(this.context).start();
-
- assertThat(builtSpan.operationName(), is(equalTo("AnOperation")));
- assertThat(builtSpan.references(), hasSize(1));
- assertThat(builtSpan.references(), contains(expectedReference));
- assertThat(builtSpan.tags().entrySet(), hasSize(0));
- }
-
- @Test
- public void withTagStringKeyValue() {
- MockSpan builtSpan =
- (MockSpan)
- EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
- .withTag("ATag", "SomeValue")
- .start();
-
- assertThat(builtSpan.tags(), hasEntry("ATag", "SomeValue"));
- }
-
- @Test
- public void withTagBooleanValues() {
- boolean expectedValue = this.random.nextBoolean();
- MockSpan builtSpan =
- (MockSpan)
- EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
- .withTag("ABooleanKey", expectedValue)
- .start();
-
- assertThat(builtSpan.tags().entrySet(), hasSize(1));
- assertThat(builtSpan.tags(), hasEntry("ABooleanKey", expectedValue));
- }
-
- @Test
- public void withTagNumberValues() {
- Integer expectedValue = this.random.nextInt();
- MockSpan builtSpan =
- (MockSpan)
- EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
- .withTag("ANumberKey", expectedValue)
- .start();
-
- assertThat(builtSpan.tags().entrySet(), hasSize(1));
- assertThat(builtSpan.tags(), hasEntry("ANumberKey", expectedValue));
- }
-
- @Test
- public void optionallyWithTagDoesNotSetWithNullStrings() {
- String expectedValue = null;
- MockSpan builtSpan =
- (MockSpan)
- EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
- .optionallyWithTag("ATagKey", expectedValue)
- .start();
-
- assertThat(builtSpan.tags().entrySet(), hasSize(0));
- }
-
- @Test
- public void optionallyWithTagStringKeyValue() {
- MockSpan builtSpan =
- (MockSpan)
- EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
- .optionallyWithTag("ATag", "SomeValue")
- .start();
-
- assertThat(builtSpan.tags(), hasEntry("ATag", "SomeValue"));
- }
-
- @Test
- public void optionallyWithTagDoesNotSetWithNullNumbers() {
- Number expectedValue = null;
- MockSpan builtSpan =
- (MockSpan)
- EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
- .optionallyWithTag("ATagKey", expectedValue)
- .start();
-
- assertThat(builtSpan.tags().entrySet(), hasSize(0));
- }
-
- @Test
- public void optionallyWithTagNumberValues() {
- Integer expectedValue = this.random.nextInt();
- MockSpan builtSpan =
- (MockSpan)
- EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
- .optionallyWithTag("ANumberKey", expectedValue)
- .start();
-
- assertThat(builtSpan.tags().entrySet(), hasSize(1));
- assertThat(builtSpan.tags(), hasEntry("ANumberKey", expectedValue));
- }
+ private Random random = new Random();
+
+ private MockTracer tracer;
+ private MockSpan.MockContext context;
+
+ @Before
+ public void beforeEach() {
+ Map parentIds = new HashMap<>();
+ parentIds.put("traceid", Math.abs(this.random.nextLong()) + "");
+ parentIds.put("spanid", Math.abs(this.random.nextLong()) + "");
+
+ this.tracer = new MockTracer();
+ this.context = (MockSpan.MockContext) tracer.extract(TEXT_MAP, new TextMapAdapter(parentIds));
+ }
+
+ @After
+ public void afterEach() {
+ this.tracer.close();
+ this.tracer.reset();
+ }
+
+ @Test
+ public void basedOn() {
+ MockSpan builtSpan = (MockSpan) EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation").start();
+ assertThat(builtSpan.operationName(), is(equalTo("AnOperation")));
+ assertThat(builtSpan.tags().entrySet(), hasSize(0));
+ }
+
+ @Test
+ public void asChildOf() {
+ MockSpan.Reference expectedReference =
+ new MockSpan.Reference(this.context, References.CHILD_OF);
+
+ MockSpan builtSpan =
+ (MockSpan)
+ EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation").asChildOf(this.context).start();
+
+ assertThat(builtSpan.operationName(), is(equalTo("AnOperation")));
+ assertThat(builtSpan.references(), hasSize(1));
+ assertThat(builtSpan.references(), contains(expectedReference));
+ assertThat(builtSpan.tags().entrySet(), hasSize(0));
+ }
+
+ @Test
+ public void withTagStringKeyValue() {
+ MockSpan builtSpan =
+ (MockSpan)
+ EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
+ .withTag("ATag", "SomeValue")
+ .start();
+
+ assertThat(builtSpan.tags(), hasEntry("ATag", "SomeValue"));
+ }
+
+ @Test
+ public void withTagBooleanValues() {
+ boolean expectedValue = this.random.nextBoolean();
+ MockSpan builtSpan =
+ (MockSpan)
+ EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
+ .withTag("ABooleanKey", expectedValue)
+ .start();
+
+ assertThat(builtSpan.tags().entrySet(), hasSize(1));
+ assertThat(builtSpan.tags(), hasEntry("ABooleanKey", expectedValue));
+ }
+
+ @Test
+ public void withTagNumberValues() {
+ Integer expectedValue = this.random.nextInt();
+ MockSpan builtSpan =
+ (MockSpan)
+ EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
+ .withTag("ANumberKey", expectedValue)
+ .start();
+
+ assertThat(builtSpan.tags().entrySet(), hasSize(1));
+ assertThat(builtSpan.tags(), hasEntry("ANumberKey", expectedValue));
+ }
+
+ @Test
+ public void optionallyWithTagDoesNotSetWithNullStrings() {
+ String expectedValue = null;
+ MockSpan builtSpan =
+ (MockSpan)
+ EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
+ .optionallyWithTag("ATagKey", expectedValue)
+ .start();
+
+ assertThat(builtSpan.tags().entrySet(), hasSize(0));
+ }
+
+ @Test
+ public void optionallyWithTagStringKeyValue() {
+ MockSpan builtSpan =
+ (MockSpan)
+ EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
+ .optionallyWithTag("ATag", "SomeValue")
+ .start();
+
+ assertThat(builtSpan.tags(), hasEntry("ATag", "SomeValue"));
+ }
+
+ @Test
+ public void optionallyWithTagDoesNotSetWithNullNumbers() {
+ Number expectedValue = null;
+ MockSpan builtSpan =
+ (MockSpan)
+ EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
+ .optionallyWithTag("ATagKey", expectedValue)
+ .start();
+
+ assertThat(builtSpan.tags().entrySet(), hasSize(0));
+ }
+
+ @Test
+ public void optionallyWithTagNumberValues() {
+ Integer expectedValue = this.random.nextInt();
+ MockSpan builtSpan =
+ (MockSpan)
+ EnhancedSpanBuilder.basedOn(this.tracer, "AnOperation")
+ .optionallyWithTag("ANumberKey", expectedValue)
+ .start();
+
+ assertThat(builtSpan.tags().entrySet(), hasSize(1));
+ assertThat(builtSpan.tags(), hasEntry("ANumberKey", expectedValue));
+ }
}
diff --git a/src/test/java/com/newrelic/opentracing/aws/GlobalTracerTestUtils.java b/src/test/java/com/newrelic/opentracing/aws/GlobalTracerTestUtils.java
index 342c783..d01e0b3 100644
--- a/src/test/java/com/newrelic/opentracing/aws/GlobalTracerTestUtils.java
+++ b/src/test/java/com/newrelic/opentracing/aws/GlobalTracerTestUtils.java
@@ -7,18 +7,19 @@
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
+
import java.lang.reflect.Field;
public class GlobalTracerTestUtils {
- public static void initTracer(Tracer tracer) {
- try {
- Field globalTracerField = GlobalTracer.class.getDeclaredField("tracer");
- globalTracerField.setAccessible(true);
- globalTracerField.set(null, tracer);
- globalTracerField.setAccessible(false);
- } catch (Exception e) {
- throw new RuntimeException("Unable to initialize tracer: " + e);
+ public static void initTracer(Tracer tracer) {
+ try {
+ Field globalTracerField = GlobalTracer.class.getDeclaredField("tracer");
+ globalTracerField.setAccessible(true);
+ globalTracerField.set(null, tracer);
+ globalTracerField.setAccessible(false);
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to initialize tracer: " + e);
+ }
}
- }
}
diff --git a/src/test/java/com/newrelic/opentracing/aws/ReflectionTest.java b/src/test/java/com/newrelic/opentracing/aws/ReflectionTest.java
index cd30972..4c7958e 100644
--- a/src/test/java/com/newrelic/opentracing/aws/ReflectionTest.java
+++ b/src/test/java/com/newrelic/opentracing/aws/ReflectionTest.java
@@ -1,49 +1,50 @@
package com.newrelic.opentracing.aws;
-import static org.junit.Assert.assertEquals;
-
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
-import java.lang.reflect.Method;
-import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+
public class ReflectionTest {
- private static final int SYNTHETIC_MODIFIER = 0x1000;
-
- private Object handler;
-
- @Before
- public void setup() {
- handler = new TestHandler();
- }
-
- @Test
- public void testInputReflection() {
- // Ignoring synthetics, we expect handleRequest to take the declared type as its first arg.
- // This is necessary for correct payload deserialization.
- final Method handleRequest =
- Arrays.stream(handler.getClass().getMethods())
- .filter(
- m ->
- ((m.getModifiers() & SYNTHETIC_MODIFIER) == 0)
- && m.getName().equals("handleRequest"))
- .findFirst()
- .orElseThrow(AssertionError::new);
-
- assertEquals(APIGatewayProxyRequestEvent.class, handleRequest.getParameterTypes()[0]);
- }
-
- public static class TestHandler
- implements RequestHandler {
- @Override
- public APIGatewayProxyResponseEvent handleRequest(
- APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) {
- return LambdaTracing.instrument(
- apiGatewayProxyRequestEvent, context, (event, c) -> new APIGatewayProxyResponseEvent());
+ private static final int SYNTHETIC_MODIFIER = 0x1000;
+
+ private Object handler;
+
+ @Before
+ public void setup() {
+ handler = new TestHandler();
+ }
+
+ @Test
+ public void testInputReflection() {
+ // Ignoring synthetics, we expect handleRequest to take the declared type as its first arg.
+ // This is necessary for correct payload deserialization.
+ final Method handleRequest =
+ Arrays.stream(handler.getClass().getMethods())
+ .filter(
+ m ->
+ ((m.getModifiers() & SYNTHETIC_MODIFIER) == 0)
+ && m.getName().equals("handleRequest"))
+ .findFirst()
+ .orElseThrow(AssertionError::new);
+
+ assertEquals(APIGatewayProxyRequestEvent.class, handleRequest.getParameterTypes()[0]);
+ }
+
+ public static class TestHandler
+ implements RequestHandler {
+ @Override
+ public APIGatewayProxyResponseEvent handleRequest(
+ APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) {
+ return LambdaTracing.instrument(
+ apiGatewayProxyRequestEvent, context, (event, c) -> new APIGatewayProxyResponseEvent());
+ }
}
- }
}
diff --git a/src/test/java/com/newrelic/opentracing/aws/TracingRequestHandlerTest.java b/src/test/java/com/newrelic/opentracing/aws/TracingRequestHandlerTest.java
index 0bffd4c..5c852c4 100644
--- a/src/test/java/com/newrelic/opentracing/aws/TracingRequestHandlerTest.java
+++ b/src/test/java/com/newrelic/opentracing/aws/TracingRequestHandlerTest.java
@@ -22,566 +22,575 @@
import com.amazonaws.services.lambda.runtime.events.S3Event;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
-import com.amazonaws.services.s3.event.S3EventNotification;
+import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification;
import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
public class TracingRequestHandlerTest {
- private static final MockTracer mockTracer = new MockTracer();
-
- @BeforeClass
- public static void beforeClass() {
- GlobalTracerTestUtils.initTracer(mockTracer);
- }
-
- @Before
- public void before() {
- mockTracer.reset();
- // reset isColdStart before each test
- LambdaTracing.isColdStart.set(true);
- }
-
- @Test
- public void testSpan() {
- final MyRequestHandler handler = new MyRequestHandler();
- handler.handleRequest("world", createContext());
-
- final List mockSpans = mockTracer.finishedSpans();
- final MockSpan mockSpan = mockSpans.get(0);
- Assert.assertEquals("handleRequest", mockSpan.operationName());
- Assert.assertEquals("123", mockSpan.tags().get("aws.requestId"));
- Assert.assertEquals("arn", mockSpan.tags().get("aws.lambda.arn"));
- Assert.assertEquals(true, mockSpan.tags().get("aws.lambda.coldStart"));
-
- // Clear out span
- mockTracer.reset();
-
- handler.handleRequest("world", createContext());
- final MockSpan secondSpan = mockTracer.finishedSpans().get(0);
- Assert.assertNull(secondSpan.tags().get("aws.lambda.coldStart"));
- }
-
- @Test
- public void testError() {
- Error error = null;
-
- final ErrorRequestHandler handler = new ErrorRequestHandler();
- try {
- handler.handleRequest("abcdefg", createContext());
- } catch (Error e) {
- error = e;
- }
-
- // Make sure TraceRequestHandler rethrows error
- Assert.assertNotNull(error);
-
- final List mockSpans = mockTracer.finishedSpans();
- final MockSpan mockSpan = mockSpans.get(0);
- Assert.assertEquals("handleRequest", mockSpan.operationName());
- Assert.assertEquals("123", mockSpan.tags().get("aws.requestId"));
- Assert.assertEquals("arn", mockSpan.tags().get("aws.lambda.arn"));
- Assert.assertEquals(true, mockSpan.tags().get("aws.lambda.coldStart"));
-
- Assert.assertEquals(1, mockSpan.logEntries().size());
- final MockSpan.LogEntry logEntry = mockSpan.logEntries().get(0);
- final Map errorFields = logEntry.fields();
- Assert.assertNotNull(errorFields.get("stack"));
- Assert.assertEquals("Exception", errorFields.get("error.kind").toString());
- Assert.assertEquals("java.lang.Error: abcdefg", errorFields.get("error.object").toString());
- Assert.assertEquals("error", errorFields.get("event"));
- Assert.assertEquals("abcdefg", errorFields.get("message"));
- }
-
- @Test
- public void testS3Event() {
- final MyS3RequestHandler myS3RequestHandler = new MyS3RequestHandler();
-
- final List records = new ArrayList<>();
- final S3EventNotification.UserIdentityEntity userIdentity =
- new S3EventNotification.UserIdentityEntity("principalId");
- final S3EventNotification.S3BucketEntity s3BucketEntity =
- new S3EventNotification.S3BucketEntity("bucketName", userIdentity, "s3ARN");
- final S3EventNotification.S3Entity s3Entity =
- new S3EventNotification.S3Entity("s3Entity", s3BucketEntity, null, null);
- final S3EventNotification.S3EventNotificationRecord record =
- new S3EventNotification.S3EventNotificationRecord(
- "awsRegion",
- "eventName",
- "eventSource",
- "2010-06-30T01:20+02:00",
- "eventVersion",
- null,
- null,
- s3Entity,
- null);
- records.add(record);
-
- myS3RequestHandler.handleRequest(new S3Event(records), createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals("s3ARN", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- public void testSNSEvent() {
- final MySNSRequestHandler mySNSRequestHandler = new MySNSRequestHandler();
-
- final SNSEvent snsEvent = new SNSEvent();
- final SNSEvent.SNSRecord snsRecord = new SNSEvent.SNSRecord();
- snsRecord.setEventSubscriptionArn("SNSEventSubscriptionArn");
- final SNSEvent.SNS sns = new SNSEvent.SNS();
- final SNSEvent.MessageAttribute messageAttribute = new SNSEvent.MessageAttribute();
- final Map messageAttributes = new HashMap<>();
- messageAttributes.put("messageAttributes.key", messageAttribute);
- sns.setMessageAttributes(messageAttributes);
- snsRecord.setSns(sns);
- final List records = new ArrayList<>();
- records.add(snsRecord);
- snsEvent.setRecords(records);
-
- mySNSRequestHandler.handleRequest(snsEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals("SNSEventSubscriptionArn", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- public void testSQSEvent() {
- final MySQSRequestHandler mySQSRequestHandler = new MySQSRequestHandler();
-
- final SQSEvent sqsEvent = new SQSEvent();
- final SQSEvent.SQSMessage sqsMessage = new SQSEvent.SQSMessage();
- sqsMessage.setEventSourceArn("SQSEventSourceArn");
- final List records = new ArrayList<>();
- records.add(sqsMessage);
- sqsEvent.setRecords(records);
-
- mySQSRequestHandler.handleRequest(sqsEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals("SQSEventSourceArn", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- public void testKinesisStreamEvent() {
- final MyKinesisStreamRequestHandler myKinesisStreamRequestHandler =
- new MyKinesisStreamRequestHandler();
-
- final KinesisEvent kinesisStreamEvent = new KinesisEvent();
- final KinesisEvent.KinesisEventRecord kinesisEventRecord =
- new KinesisEvent.KinesisEventRecord();
- kinesisEventRecord.setEventSourceARN("KinesisStreamEventSourceARN");
- final List records = new ArrayList<>();
- records.add(kinesisEventRecord);
- kinesisStreamEvent.setRecords(records);
-
- myKinesisStreamRequestHandler.handleRequest(kinesisStreamEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals(
- "KinesisStreamEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- public void testKinesisFirehoseEvent() {
- final MyKinesisFirehoseRequestHandler myKinesisFirehoseRequestHandler =
- new MyKinesisFirehoseRequestHandler();
-
- final KinesisFirehoseEvent kinesisFirehoseEvent = new KinesisFirehoseEvent();
- kinesisFirehoseEvent.setDeliveryStreamArn("KinesisFirehoseDeliveryStreamArn");
-
- myKinesisFirehoseRequestHandler.handleRequest(kinesisFirehoseEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals(
- "KinesisFirehoseDeliveryStreamArn", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- public void testDynamoDBEvent() {
- final MyDynamoDBRequestHandler myDynamoDBRequestHandler = new MyDynamoDBRequestHandler();
-
- final DynamodbEvent dynamodbEvent = new DynamodbEvent();
- final DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord =
- new DynamodbEvent.DynamodbStreamRecord();
- dynamodbStreamRecord.setEventSourceARN("DynamodbEventSourceARN");
- List records = new ArrayList<>();
- records.add(dynamodbStreamRecord);
- dynamodbEvent.setRecords(records);
-
- myDynamoDBRequestHandler.handleRequest(dynamodbEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals("DynamodbEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- public void testCodeCommitEvent() {
- final MyCodeCommitRequestHandler myCodeCommitRequestHandler = new MyCodeCommitRequestHandler();
-
- final CodeCommitEvent codeCommitEvent = new CodeCommitEvent();
- final CodeCommitEvent.Record record = new CodeCommitEvent.Record();
- record.setEventSourceArn("CodeCommitEventSourceARN");
- List records = new ArrayList<>();
- records.add(record);
- codeCommitEvent.setRecords(records);
-
- myCodeCommitRequestHandler.handleRequest(codeCommitEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals("CodeCommitEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- public void testAPIGatewayProxyRequestEvent() {
- final MyApiGatewayProxyRequestHandler myApiGatewayProxyRequestHandler =
- new MyApiGatewayProxyRequestHandler();
-
- final APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent =
- new APIGatewayProxyRequestEvent();
- final APIGatewayProxyRequestEvent.RequestIdentity requestIdentity =
- new APIGatewayProxyRequestEvent.RequestIdentity();
- requestIdentity.setUserArn("APIGatewayProxyRequestEventUserARN");
- final APIGatewayProxyRequestEvent.ProxyRequestContext proxyRequestContext =
- new APIGatewayProxyRequestEvent.ProxyRequestContext();
- proxyRequestContext.setIdentity(requestIdentity);
- apiGatewayProxyRequestEvent.setRequestContext(proxyRequestContext);
-
- myApiGatewayProxyRequestHandler.handleRequest(apiGatewayProxyRequestEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals(
- "APIGatewayProxyRequestEventUserARN", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- public void testAPIGatewayProxyRequestResponseEvent() {
- int expectedStatusCode = 200;
- final MyApiGatewayProxyRequestResponseHandler myApiGatewayProxyRequestHandler =
- new MyApiGatewayProxyRequestResponseHandler(expectedStatusCode);
-
- final APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent =
- new APIGatewayProxyRequestEvent();
- final APIGatewayProxyRequestEvent.RequestIdentity requestIdentity =
- new APIGatewayProxyRequestEvent.RequestIdentity();
- requestIdentity.setUserArn("APIGatewayProxyRequestEventUserARN");
- final APIGatewayProxyRequestEvent.ProxyRequestContext proxyRequestContext =
- new APIGatewayProxyRequestEvent.ProxyRequestContext();
- proxyRequestContext.setIdentity(requestIdentity);
- apiGatewayProxyRequestEvent.setRequestContext(proxyRequestContext);
-
- myApiGatewayProxyRequestHandler.handleRequest(apiGatewayProxyRequestEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals(
- "APIGatewayProxyRequestEventUserARN", span.tags().get("aws.lambda.eventSource.arn"));
- Assert.assertEquals(Integer.toString(expectedStatusCode), span.tags().get("http.status_code"));
- }
-
- @Test
- public void testAPIGatewayV2ProxyRequestEvent() {
- final MyApiGatewayV2ProxyRequestHandler myApiGatewayV2ProxyRequestHandler =
- new MyApiGatewayV2ProxyRequestHandler();
-
- final APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent =
- new APIGatewayV2ProxyRequestEvent();
- final APIGatewayV2ProxyRequestEvent.RequestIdentity requestIdentity =
- new APIGatewayV2ProxyRequestEvent.RequestIdentity();
- requestIdentity.setUserArn("APIGatewayV2ProxyRequestEventUserARN");
- final APIGatewayV2ProxyRequestEvent.RequestContext proxyRequestContext =
- new APIGatewayV2ProxyRequestEvent.RequestContext();
- proxyRequestContext.setIdentity(requestIdentity);
- apiGatewayV2ProxyRequestEvent.setRequestContext(proxyRequestContext);
-
- myApiGatewayV2ProxyRequestHandler.handleRequest(apiGatewayV2ProxyRequestEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals(
- "APIGatewayV2ProxyRequestEventUserARN", span.tags().get("aws.lambda.eventSource.arn"));
- Assert.assertFalse(span.tags().containsKey("http.status_code"));
- }
-
- @Test
- public void testAPIGatewayV2ProxyRequestResponseEvent() {
- int expectedStatusCode = 200;
- final MyApiGatewayV2ProxyRequestResponseHandler myApiGatewayV2ProxyRequestHandler =
- new MyApiGatewayV2ProxyRequestResponseHandler(expectedStatusCode);
-
- final APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent =
- new APIGatewayV2ProxyRequestEvent();
- final APIGatewayV2ProxyRequestEvent.RequestIdentity requestIdentity =
- new APIGatewayV2ProxyRequestEvent.RequestIdentity();
- requestIdentity.setUserArn("APIGatewayV2ProxyRequestEventUserARN");
- final APIGatewayV2ProxyRequestEvent.RequestContext proxyRequestContext =
- new APIGatewayV2ProxyRequestEvent.RequestContext();
- proxyRequestContext.setIdentity(requestIdentity);
- apiGatewayV2ProxyRequestEvent.setRequestContext(proxyRequestContext);
-
- myApiGatewayV2ProxyRequestHandler.handleRequest(apiGatewayV2ProxyRequestEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals(
- "APIGatewayV2ProxyRequestEventUserARN", span.tags().get("aws.lambda.eventSource.arn"));
- Assert.assertEquals(Integer.toString(expectedStatusCode), span.tags().get("http.status_code"));
- }
-
- @Test
- @Ignore("We would like this but there doesn't seem to be an available arn currently")
- public void testCloudWatchLogsEvent() {
- final MyCloudWatchRequestHandler myCloudWatchRequestHandler = new MyCloudWatchRequestHandler();
-
- final CloudWatchLogsEvent cloudWatchLogsEvent = new CloudWatchLogsEvent();
-
- myCloudWatchRequestHandler.handleRequest(cloudWatchLogsEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals(
- "CloudWatchLogsEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- @Test
- @Ignore("We would like this but there doesn't seem to be an available arn currently")
- public void testCloudFrontEvent() {
- final MyCloudFrontRequestHandler myCloudFrontRequestHandler = new MyCloudFrontRequestHandler();
-
- final CloudFrontEvent cloudFrontEvent = new CloudFrontEvent();
- final CloudFrontEvent.Record record = new CloudFrontEvent.Record();
-
- myCloudFrontRequestHandler.handleRequest(cloudFrontEvent, createContext());
- final MockSpan span = mockTracer.finishedSpans().get(0);
- Assert.assertEquals(
- "CloudFrontEventEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
- }
-
- static class MyRequestHandler implements TracingRequestHandler {
+ private static final MockTracer mockTracer = new MockTracer();
- @Override
- public String doHandleRequest(String s, Context context) {
- return "Request Handler says: hello " + s;
- }
- }
-
- static class ErrorRequestHandler implements TracingRequestHandler {
+ @BeforeClass
+ public static void beforeClass() {
+ GlobalTracerTestUtils.initTracer(mockTracer);
+ }
- @Override
- public String doHandleRequest(String s, Context context) {
- throw new Error(s);
+ @Before
+ public void before() {
+ mockTracer.reset();
+ // reset isColdStart before each test
+ LambdaTracing.isColdStart.set(true);
}
- }
- // S3
- static class MyS3RequestHandler implements TracingRequestHandler {
+ @Test
+ public void testSpan() {
+ final MyRequestHandler handler = new MyRequestHandler();
+ handler.handleRequest("world", createContext());
+
+ final List mockSpans = mockTracer.finishedSpans();
+ final MockSpan mockSpan = mockSpans.get(0);
+ Assert.assertEquals("handleRequest", mockSpan.operationName());
+ Assert.assertEquals("123", mockSpan.tags().get("aws.requestId"));
+ Assert.assertEquals("arn", mockSpan.tags().get("aws.lambda.arn"));
+ Assert.assertEquals(true, mockSpan.tags().get("aws.lambda.coldStart"));
- @Override
- public Object doHandleRequest(S3Event s3Event, Context context) {
- return "null";
+ // Clear out span
+ mockTracer.reset();
+
+ handler.handleRequest("world", createContext());
+ final MockSpan secondSpan = mockTracer.finishedSpans().get(0);
+ Assert.assertNull(secondSpan.tags().get("aws.lambda.coldStart"));
}
- }
- // Simple Notification Service (SNS)
- static class MySNSRequestHandler implements TracingRequestHandler {
+ @Test
+ public void testError() {
+ Error error = null;
+
+ final ErrorRequestHandler handler = new ErrorRequestHandler();
+ try {
+ handler.handleRequest("abcdefg", createContext());
+ } catch (Error e) {
+ error = e;
+ }
+
+ // Make sure TraceRequestHandler rethrows error
+ Assert.assertNotNull(error);
+
+ final List mockSpans = mockTracer.finishedSpans();
+ final MockSpan mockSpan = mockSpans.get(0);
+ Assert.assertEquals("handleRequest", mockSpan.operationName());
+ Assert.assertEquals("123", mockSpan.tags().get("aws.requestId"));
+ Assert.assertEquals("arn", mockSpan.tags().get("aws.lambda.arn"));
+ Assert.assertEquals(true, mockSpan.tags().get("aws.lambda.coldStart"));
+
+ Assert.assertEquals(1, mockSpan.logEntries().size());
+ final MockSpan.LogEntry logEntry = mockSpan.logEntries().get(0);
+ final Map errorFields = logEntry.fields();
+ Assert.assertNotNull(errorFields.get("stack"));
+ Assert.assertEquals("Exception", errorFields.get("error.kind").toString());
+ Assert.assertEquals("java.lang.Error: abcdefg", errorFields.get("error.object").toString());
+ Assert.assertEquals("error", errorFields.get("event"));
+ Assert.assertEquals("abcdefg", errorFields.get("message"));
+ }
- @Override
- public Object doHandleRequest(SNSEvent snsEvent, Context context) {
- return "null";
+ @Test
+ public void testS3Event() {
+ final MyS3RequestHandler myS3RequestHandler = new MyS3RequestHandler();
+
+ final List records = new ArrayList<>();
+ final S3EventNotification.UserIdentityEntity userIdentity =
+ new S3EventNotification.UserIdentityEntity("principalId");
+ final S3EventNotification.S3BucketEntity s3BucketEntity =
+ new S3EventNotification.S3BucketEntity("bucketName", userIdentity, "s3ARN");
+ final S3EventNotification.S3Entity s3Entity =
+ new S3EventNotification.S3Entity("s3Entity", s3BucketEntity, null, null);
+ final S3EventNotification.S3EventNotificationRecord record =
+ new S3EventNotification.S3EventNotificationRecord(
+ "awsRegion",
+ "eventName",
+ "eventSource",
+ "2010-06-30T01:20+02:00",
+ "eventVersion",
+ null,
+ null,
+ s3Entity,
+ null);
+ records.add(record);
+
+ myS3RequestHandler.handleRequest(new S3Event(records), createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals("s3ARN", span.tags().get("aws.lambda.eventSource.arn"));
}
- }
- // Kinesis Stream
- static class MyKinesisStreamRequestHandler
- implements TracingRequestHandler {
+ @Test
+ public void testSNSEvent() {
+ final MySNSRequestHandler mySNSRequestHandler = new MySNSRequestHandler();
+
+ final SNSEvent snsEvent = new SNSEvent();
+ final SNSEvent.SNSRecord snsRecord = new SNSEvent.SNSRecord();
+ snsRecord.setEventSubscriptionArn("SNSEventSubscriptionArn");
+ final SNSEvent.SNS sns = new SNSEvent.SNS();
+ final SNSEvent.MessageAttribute messageAttribute = new SNSEvent.MessageAttribute();
+ final Map messageAttributes = new HashMap<>();
+ messageAttributes.put("messageAttributes.key", messageAttribute);
+ sns.setMessageAttributes(messageAttributes);
+ snsRecord.setSns(sns);
+ final List records = new ArrayList<>();
+ records.add(snsRecord);
+ snsEvent.setRecords(records);
+
+ mySNSRequestHandler.handleRequest(snsEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals("SNSEventSubscriptionArn", span.tags().get("aws.lambda.eventSource.arn"));
+ }
- @Override
- public Object doHandleRequest(KinesisEvent kinesisEvent, Context context) {
- return "null";
+ @Test
+ public void testSQSEvent() {
+ final MySQSRequestHandler mySQSRequestHandler = new MySQSRequestHandler();
+
+ final SQSEvent sqsEvent = new SQSEvent();
+ final SQSEvent.SQSMessage sqsMessage = new SQSEvent.SQSMessage();
+ sqsMessage.setEventSourceArn("SQSEventSourceArn");
+ final List records = new ArrayList<>();
+ records.add(sqsMessage);
+ sqsEvent.setRecords(records);
+
+ mySQSRequestHandler.handleRequest(sqsEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals("SQSEventSourceArn", span.tags().get("aws.lambda.eventSource.arn"));
+ }
+
+ @Test
+ public void testKinesisStreamEvent() {
+ final MyKinesisStreamRequestHandler myKinesisStreamRequestHandler =
+ new MyKinesisStreamRequestHandler();
+
+ final KinesisEvent kinesisStreamEvent = new KinesisEvent();
+ final KinesisEvent.KinesisEventRecord kinesisEventRecord =
+ new KinesisEvent.KinesisEventRecord();
+ kinesisEventRecord.setEventSourceARN("KinesisStreamEventSourceARN");
+ final List records = new ArrayList<>();
+ records.add(kinesisEventRecord);
+ kinesisStreamEvent.setRecords(records);
+
+ myKinesisStreamRequestHandler.handleRequest(kinesisStreamEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals(
+ "KinesisStreamEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
}
- }
- // Kinesis Firehose
- static class MyKinesisFirehoseRequestHandler
- implements TracingRequestHandler {
+ @Test
+ public void testKinesisFirehoseEvent() {
+ final MyKinesisFirehoseRequestHandler myKinesisFirehoseRequestHandler =
+ new MyKinesisFirehoseRequestHandler();
+
+ final KinesisFirehoseEvent kinesisFirehoseEvent = new KinesisFirehoseEvent();
+ kinesisFirehoseEvent.setDeliveryStreamArn("KinesisFirehoseDeliveryStreamArn");
+
+ myKinesisFirehoseRequestHandler.handleRequest(kinesisFirehoseEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals(
+ "KinesisFirehoseDeliveryStreamArn", span.tags().get("aws.lambda.eventSource.arn"));
+ }
- @Override
- public Object doHandleRequest(KinesisFirehoseEvent kinesisFirehoseEvent, Context context) {
- return "null";
+ @Test
+ public void testDynamoDBEvent() {
+ final MyDynamoDBRequestHandler myDynamoDBRequestHandler = new MyDynamoDBRequestHandler();
+
+ final DynamodbEvent dynamodbEvent = new DynamodbEvent();
+ final DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord =
+ new DynamodbEvent.DynamodbStreamRecord();
+ dynamodbStreamRecord.setEventSourceARN("DynamodbEventSourceARN");
+ List records = new ArrayList<>();
+ records.add(dynamodbStreamRecord);
+ dynamodbEvent.setRecords(records);
+
+ myDynamoDBRequestHandler.handleRequest(dynamodbEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals("DynamodbEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
}
- }
- // Dynamo DB
- static class MyDynamoDBRequestHandler implements TracingRequestHandler {
+ @Test
+ public void testCodeCommitEvent() {
+ final MyCodeCommitRequestHandler myCodeCommitRequestHandler = new MyCodeCommitRequestHandler();
- @Override
- public Object doHandleRequest(DynamodbEvent dynamodbEvent, Context context) {
- return "null";
+ final CodeCommitEvent codeCommitEvent = new CodeCommitEvent();
+ final CodeCommitEvent.Record record = new CodeCommitEvent.Record();
+ record.setEventSourceArn("CodeCommitEventSourceARN");
+ List records = new ArrayList<>();
+ records.add(record);
+ codeCommitEvent.setRecords(records);
+
+ myCodeCommitRequestHandler.handleRequest(codeCommitEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals("CodeCommitEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
}
- }
- // Simple Queue Service (SQS)
- static class MySQSRequestHandler implements TracingRequestHandler {
+ @Test
+ public void testAPIGatewayProxyRequestEvent() {
+ final MyApiGatewayProxyRequestHandler myApiGatewayProxyRequestHandler =
+ new MyApiGatewayProxyRequestHandler();
+
+ final APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent =
+ new APIGatewayProxyRequestEvent();
+ final APIGatewayProxyRequestEvent.RequestIdentity requestIdentity =
+ new APIGatewayProxyRequestEvent.RequestIdentity();
+ requestIdentity.setUserArn("APIGatewayProxyRequestEventUserARN");
+ final APIGatewayProxyRequestEvent.ProxyRequestContext proxyRequestContext =
+ new APIGatewayProxyRequestEvent.ProxyRequestContext();
+ proxyRequestContext.setIdentity(requestIdentity);
+ apiGatewayProxyRequestEvent.setRequestContext(proxyRequestContext);
+ apiGatewayProxyRequestEvent.setHeaders(new HashMap<>());
+
+ myApiGatewayProxyRequestHandler.handleRequest(apiGatewayProxyRequestEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals(
+ "APIGatewayProxyRequestEventUserARN", span.tags().get("aws.lambda.eventSource.arn"));
+ }
- @Override
- public Object doHandleRequest(SQSEvent sqsEvent, Context context) {
- return "null";
+ @Test
+ public void testAPIGatewayProxyRequestResponseEvent() {
+ int expectedStatusCode = 200;
+ final MyApiGatewayProxyRequestResponseHandler myApiGatewayProxyRequestHandler =
+ new MyApiGatewayProxyRequestResponseHandler(expectedStatusCode);
+
+ final APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent =
+ new APIGatewayProxyRequestEvent();
+ final APIGatewayProxyRequestEvent.RequestIdentity requestIdentity =
+ new APIGatewayProxyRequestEvent.RequestIdentity();
+ requestIdentity.setUserArn("APIGatewayProxyRequestEventUserARN");
+ final APIGatewayProxyRequestEvent.ProxyRequestContext proxyRequestContext =
+ new APIGatewayProxyRequestEvent.ProxyRequestContext();
+
+ apiGatewayProxyRequestEvent.setHeaders(new HashMap<>());
+ proxyRequestContext.setIdentity(requestIdentity);
+ apiGatewayProxyRequestEvent.setRequestContext(proxyRequestContext);
+
+ myApiGatewayProxyRequestHandler.handleRequest(apiGatewayProxyRequestEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals(
+ "APIGatewayProxyRequestEventUserARN", span.tags().get("aws.lambda.eventSource.arn"));
+ Assert.assertEquals(Integer.toString(expectedStatusCode), span.tags().get("http.status_code"));
}
- }
- // Code Commit
- static class MyCodeCommitRequestHandler
- implements TracingRequestHandler {
+ @Test
+ public void testAPIGatewayV2ProxyRequestEvent() {
+ final MyApiGatewayV2ProxyRequestHandler myApiGatewayV2ProxyRequestHandler =
+ new MyApiGatewayV2ProxyRequestHandler();
+
+ final APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent =
+ new APIGatewayV2ProxyRequestEvent();
+ final APIGatewayV2ProxyRequestEvent.RequestIdentity requestIdentity =
+ new APIGatewayV2ProxyRequestEvent.RequestIdentity();
+ requestIdentity.setUserArn("APIGatewayV2ProxyRequestEventUserARN");
+ final APIGatewayV2ProxyRequestEvent.RequestContext proxyRequestContext =
+ new APIGatewayV2ProxyRequestEvent.RequestContext();
+ proxyRequestContext.setIdentity(requestIdentity);
+ apiGatewayV2ProxyRequestEvent.setRequestContext(proxyRequestContext);
+
+ myApiGatewayV2ProxyRequestHandler.handleRequest(apiGatewayV2ProxyRequestEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals(
+ "APIGatewayV2ProxyRequestEventUserARN", span.tags().get("aws.lambda.eventSource.arn"));
+ Assert.assertFalse(span.tags().containsKey("http.status_code"));
+ }
- @Override
- public Object doHandleRequest(CodeCommitEvent codeCommitEvent, Context context) {
- return "null";
+ @Test
+ public void testAPIGatewayV2ProxyRequestResponseEvent() {
+ int expectedStatusCode = 200;
+ final MyApiGatewayV2ProxyRequestResponseHandler myApiGatewayV2ProxyRequestHandler =
+ new MyApiGatewayV2ProxyRequestResponseHandler(expectedStatusCode);
+
+ final APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent =
+ new APIGatewayV2ProxyRequestEvent();
+ final APIGatewayV2ProxyRequestEvent.RequestIdentity requestIdentity =
+ new APIGatewayV2ProxyRequestEvent.RequestIdentity();
+ requestIdentity.setUserArn("APIGatewayV2ProxyRequestEventUserARN");
+ final APIGatewayV2ProxyRequestEvent.RequestContext proxyRequestContext =
+ new APIGatewayV2ProxyRequestEvent.RequestContext();
+ proxyRequestContext.setIdentity(requestIdentity);
+ apiGatewayV2ProxyRequestEvent.setRequestContext(proxyRequestContext);
+
+ myApiGatewayV2ProxyRequestHandler.handleRequest(apiGatewayV2ProxyRequestEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals(
+ "APIGatewayV2ProxyRequestEventUserARN", span.tags().get("aws.lambda.eventSource.arn"));
+ Assert.assertEquals(Integer.toString(expectedStatusCode), span.tags().get("http.status_code"));
}
- }
- // API Gateway Proxy Request Event
- static class MyApiGatewayProxyRequestHandler
- implements TracingRequestHandler {
+ @Test
+ @Ignore("We would like this but there doesn't seem to be an available arn currently")
+ public void testCloudWatchLogsEvent() {
+ final MyCloudWatchRequestHandler myCloudWatchRequestHandler = new MyCloudWatchRequestHandler();
- @Override
- public Object doHandleRequest(
- APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) {
- return "null";
+ final CloudWatchLogsEvent cloudWatchLogsEvent = new CloudWatchLogsEvent();
+
+ myCloudWatchRequestHandler.handleRequest(cloudWatchLogsEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals(
+ "CloudWatchLogsEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
}
- }
- static class MyApiGatewayProxyRequestResponseHandler
- implements TracingRequestHandler {
+ @Test
+ @Ignore("We would like this but there doesn't seem to be an available arn currently")
+ public void testCloudFrontEvent() {
+ final MyCloudFrontRequestHandler myCloudFrontRequestHandler = new MyCloudFrontRequestHandler();
- private int statusCode;
+ final CloudFrontEvent cloudFrontEvent = new CloudFrontEvent();
+ final CloudFrontEvent.Record record = new CloudFrontEvent.Record();
- public MyApiGatewayProxyRequestResponseHandler(int statusCode) {
- this.statusCode = statusCode;
+ myCloudFrontRequestHandler.handleRequest(cloudFrontEvent, createContext());
+ final MockSpan span = mockTracer.finishedSpans().get(0);
+ Assert.assertEquals(
+ "CloudFrontEventEventSourceARN", span.tags().get("aws.lambda.eventSource.arn"));
}
- @Override
- public APIGatewayProxyResponseEvent doHandleRequest(
- APIGatewayProxyRequestEvent apiGatewayV2ProxyRequestEvent, Context context) {
- APIGatewayProxyResponseEvent responseEvent = new APIGatewayProxyResponseEvent();
- responseEvent.setStatusCode(statusCode);
- responseEvent.setBody("null");
- return responseEvent;
+ static class MyRequestHandler implements TracingRequestHandler {
+
+ @Override
+ public String doHandleRequest(String s, Context context) {
+ return "Request Handler says: hello " + s;
+ }
}
- }
- static class MyApiGatewayV2ProxyRequestHandler
- implements TracingRequestHandler {
+ static class ErrorRequestHandler implements TracingRequestHandler {
- @Override
- public Object doHandleRequest(
- APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent, Context context) {
- return "null";
+ @Override
+ public String doHandleRequest(String s, Context context) {
+ throw new Error(s);
+ }
}
- }
- static class MyApiGatewayV2ProxyRequestResponseHandler
- implements TracingRequestHandler<
- APIGatewayV2ProxyRequestEvent, APIGatewayV2ProxyResponseEvent> {
+ // S3
+ static class MyS3RequestHandler implements TracingRequestHandler {
- private int statusCode;
+ @Override
+ public Object doHandleRequest(S3Event s3Event, Context context) {
+ return "null";
+ }
+ }
- public MyApiGatewayV2ProxyRequestResponseHandler(int statusCode) {
- this.statusCode = statusCode;
+ // Simple Notification Service (SNS)
+ static class MySNSRequestHandler implements TracingRequestHandler {
+
+ @Override
+ public Object doHandleRequest(SNSEvent snsEvent, Context context) {
+ return "null";
+ }
}
- @Override
- public APIGatewayV2ProxyResponseEvent doHandleRequest(
- APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent, Context context) {
- APIGatewayV2ProxyResponseEvent responseEvent = new APIGatewayV2ProxyResponseEvent();
- responseEvent.setStatusCode(statusCode);
- responseEvent.setBody("null");
- return responseEvent;
+ // Kinesis Stream
+ static class MyKinesisStreamRequestHandler
+ implements TracingRequestHandler {
+
+ @Override
+ public Object doHandleRequest(KinesisEvent kinesisEvent, Context context) {
+ return "null";
+ }
}
- }
- // Cloud Front
- static class MyCloudFrontRequestHandler
- implements TracingRequestHandler {
+ // Kinesis Firehose
+ static class MyKinesisFirehoseRequestHandler
+ implements TracingRequestHandler {
- @Override
- public Object doHandleRequest(CloudFrontEvent cloudFrontEvent, Context context) {
- return "null";
+ @Override
+ public Object doHandleRequest(KinesisFirehoseEvent kinesisFirehoseEvent, Context context) {
+ return "null";
+ }
}
- }
- // Cloud Watch
- static class MyCloudWatchRequestHandler
- implements TracingRequestHandler {
+ // Dynamo DB
+ static class MyDynamoDBRequestHandler implements TracingRequestHandler {
- @Override
- public Object doHandleRequest(CloudWatchLogsEvent cloudWatchLogsEvent, Context context) {
- return "null";
+ @Override
+ public Object doHandleRequest(DynamodbEvent dynamodbEvent, Context context) {
+ return "null";
+ }
}
- }
- private Context createContext() {
- return new Context() {
- @Override
- public String getAwsRequestId() {
- return "123";
- }
+ // Simple Queue Service (SQS)
+ static class MySQSRequestHandler implements TracingRequestHandler {
- @Override
- public String getLogGroupName() {
- return "logGroupName";
- }
+ @Override
+ public Object doHandleRequest(SQSEvent sqsEvent, Context context) {
+ return "null";
+ }
+ }
- @Override
- public String getLogStreamName() {
- return "getLogStreamName";
- }
+ // Code Commit
+ static class MyCodeCommitRequestHandler
+ implements TracingRequestHandler {
- @Override
- public String getFunctionName() {
- return null;
- }
+ @Override
+ public Object doHandleRequest(CodeCommitEvent codeCommitEvent, Context context) {
+ return "null";
+ }
+ }
- @Override
- public String getFunctionVersion() {
- return "LATEST";
- }
+ // API Gateway Proxy Request Event
+ static class MyApiGatewayProxyRequestHandler
+ implements TracingRequestHandler {
- @Override
- public String getInvokedFunctionArn() {
- return "arn";
- }
+ @Override
+ public Object doHandleRequest(
+ APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) {
+ return "null";
+ }
+ }
- @Override
- public CognitoIdentity getIdentity() {
- return new CognitoIdentity() {
- @Override
- public String getIdentityId() {
- return "identity";
- }
-
- @Override
- public String getIdentityPoolId() {
- return "identityPoolId";
- }
- };
- }
-
- @Override
- public ClientContext getClientContext() {
- return null;
- }
-
- @Override
- public int getRemainingTimeInMillis() {
- return 100;
- }
-
- @Override
- public int getMemoryLimitInMB() {
- return 510;
- }
-
- @Override
- public LambdaLogger getLogger() {
- return new LambdaLogger() {
- @Override
- public void log(String string) {}
+ static class MyApiGatewayProxyRequestResponseHandler
+ implements TracingRequestHandler {
+
+ private int statusCode;
+
+ public MyApiGatewayProxyRequestResponseHandler(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ @Override
+ public APIGatewayProxyResponseEvent doHandleRequest(
+ APIGatewayProxyRequestEvent apiGatewayV2ProxyRequestEvent, Context context) {
+ APIGatewayProxyResponseEvent responseEvent = new APIGatewayProxyResponseEvent();
+ responseEvent.setStatusCode(statusCode);
+ responseEvent.setBody("null");
+ return responseEvent;
+ }
+ }
+
+ static class MyApiGatewayV2ProxyRequestHandler
+ implements TracingRequestHandler {
+
+ @Override
+ public Object doHandleRequest(
+ APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent, Context context) {
+ return "null";
+ }
+ }
+
+ static class MyApiGatewayV2ProxyRequestResponseHandler
+ implements TracingRequestHandler<
+ APIGatewayV2ProxyRequestEvent, APIGatewayV2ProxyResponseEvent> {
+
+ private int statusCode;
+
+ public MyApiGatewayV2ProxyRequestResponseHandler(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ @Override
+ public APIGatewayV2ProxyResponseEvent doHandleRequest(
+ APIGatewayV2ProxyRequestEvent apiGatewayV2ProxyRequestEvent, Context context) {
+ APIGatewayV2ProxyResponseEvent responseEvent = new APIGatewayV2ProxyResponseEvent();
+ responseEvent.setStatusCode(statusCode);
+ responseEvent.setBody("null");
+ return responseEvent;
+ }
+ }
+
+ // Cloud Front
+ static class MyCloudFrontRequestHandler
+ implements TracingRequestHandler {
+
+ @Override
+ public Object doHandleRequest(CloudFrontEvent cloudFrontEvent, Context context) {
+ return "null";
+ }
+ }
+
+ // Cloud Watch
+ static class MyCloudWatchRequestHandler
+ implements TracingRequestHandler {
+
+ @Override
+ public Object doHandleRequest(CloudWatchLogsEvent cloudWatchLogsEvent, Context context) {
+ return "null";
+ }
+ }
+
+ private Context createContext() {
+ return new Context() {
+ @Override
+ public String getAwsRequestId() {
+ return "123";
+ }
+
+ @Override
+ public String getLogGroupName() {
+ return "logGroupName";
+ }
+
+ @Override
+ public String getLogStreamName() {
+ return "getLogStreamName";
+ }
+
+ @Override
+ public String getFunctionName() {
+ return null;
+ }
+
+ @Override
+ public String getFunctionVersion() {
+ return "LATEST";
+ }
+
+ @Override
+ public String getInvokedFunctionArn() {
+ return "arn";
+ }
+
+ @Override
+ public CognitoIdentity getIdentity() {
+ return new CognitoIdentity() {
+ @Override
+ public String getIdentityId() {
+ return "identity";
+ }
+
+ @Override
+ public String getIdentityPoolId() {
+ return "identityPoolId";
+ }
+ };
+ }
+
+ @Override
+ public ClientContext getClientContext() {
+ return null;
+ }
+
+ @Override
+ public int getRemainingTimeInMillis() {
+ return 100;
+ }
+
+ @Override
+ public int getMemoryLimitInMB() {
+ return 510;
+ }
+
+ @Override
+ public LambdaLogger getLogger() {
+ return new LambdaLogger() {
+ @Override
+ public void log(String string) {
+ }
+
+ @Override
+ public void log(byte[] message) {
+ }
+ };
+ }
};
- }
- };
- }
+ }
}
diff --git a/src/test/java/com/newrelic/opentracing/aws/TracingRequestStreamHandlerTest.java b/src/test/java/com/newrelic/opentracing/aws/TracingRequestStreamHandlerTest.java
index d149a4d..1c4f4c1 100644
--- a/src/test/java/com/newrelic/opentracing/aws/TracingRequestStreamHandlerTest.java
+++ b/src/test/java/com/newrelic/opentracing/aws/TracingRequestStreamHandlerTest.java
@@ -11,148 +11,155 @@
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
public class TracingRequestStreamHandlerTest {
- private static final MockTracer mockTracer = new MockTracer();
-
- @BeforeClass
- public static void beforeClass() {
- GlobalTracerTestUtils.initTracer(mockTracer);
- }
-
- @Before
- public void before() {
- mockTracer.reset();
- // reset isColdStart before each test
- LambdaTracing.isColdStart.set(true);
- }
-
- @Test
- public void testSpan() {
- final MyRequestHandler handler = new MyRequestHandler();
-
- byte[] input1 = {'1', '2', '3'};
- ByteArrayInputStream inputStream1 = new ByteArrayInputStream(input1);
- ByteArrayOutputStream outputStream1 = new ByteArrayOutputStream();
- handler.handleRequest(inputStream1, outputStream1, createContext());
-
- final List mockSpans = mockTracer.finishedSpans();
- final MockSpan mockSpan = mockSpans.get(0);
- Assert.assertEquals("handleRequest", mockSpan.operationName());
- Assert.assertEquals("123", mockSpan.tags().get("aws.requestId"));
- Assert.assertEquals("arn", mockSpan.tags().get("aws.lambda.arn"));
- Assert.assertEquals(true, mockSpan.tags().get("aws.lambda.coldStart"));
-
- // Clear out span
- mockTracer.reset();
-
- byte[] input2 = {'a', 'b', 'c'};
- ByteArrayInputStream inputStream2 = new ByteArrayInputStream(input2);
- ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
- handler.handleRequest(inputStream2, outputStream2, createContext());
-
- final MockSpan secondSpan = mockTracer.finishedSpans().get(0);
- Assert.assertNull(secondSpan.tags().get("aws.lambda.coldStart"));
-
- Assert.assertArrayEquals(outputStream1.toByteArray(), new byte[] {'1', '2', '3', '?'});
- Assert.assertArrayEquals(outputStream2.toByteArray(), new byte[] {'a', 'b', 'c', '?'});
- }
-
- static class MyRequestHandler implements TracingRequestStreamHandler {
-
- @Override
- public void doHandleRequest(InputStream input, OutputStream output, Context context) {
- try {
- int in;
- while ((in = input.read()) != -1) {
- output.write(in);
+ private static final MockTracer mockTracer = new MockTracer();
+
+ @BeforeClass
+ public static void beforeClass() {
+ GlobalTracerTestUtils.initTracer(mockTracer);
+ }
+
+ @Before
+ public void before() {
+ mockTracer.reset();
+ // reset isColdStart before each test
+ LambdaTracing.isColdStart.set(true);
+ }
+
+ @Test
+ public void testSpan() {
+ final MyRequestHandler handler = new MyRequestHandler();
+
+ byte[] input1 = { '1', '2', '3' };
+ ByteArrayInputStream inputStream1 = new ByteArrayInputStream(input1);
+ ByteArrayOutputStream outputStream1 = new ByteArrayOutputStream();
+ handler.handleRequest(inputStream1, outputStream1, createContext());
+
+ final List mockSpans = mockTracer.finishedSpans();
+ final MockSpan mockSpan = mockSpans.get(0);
+ Assert.assertEquals("handleRequest", mockSpan.operationName());
+ Assert.assertEquals("123", mockSpan.tags().get("aws.requestId"));
+ Assert.assertEquals("arn", mockSpan.tags().get("aws.lambda.arn"));
+ Assert.assertEquals(true, mockSpan.tags().get("aws.lambda.coldStart"));
+
+ // Clear out span
+ mockTracer.reset();
+
+ byte[] input2 = { 'a', 'b', 'c' };
+ ByteArrayInputStream inputStream2 = new ByteArrayInputStream(input2);
+ ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
+ handler.handleRequest(inputStream2, outputStream2, createContext());
+
+ final MockSpan secondSpan = mockTracer.finishedSpans().get(0);
+ Assert.assertNull(secondSpan.tags().get("aws.lambda.coldStart"));
+
+ Assert.assertArrayEquals(outputStream1.toByteArray(), new byte[] { '1', '2', '3', '?' });
+ Assert.assertArrayEquals(outputStream2.toByteArray(), new byte[] { 'a', 'b', 'c', '?' });
+ }
+
+ static class MyRequestHandler implements TracingRequestStreamHandler {
+
+ @Override
+ public void doHandleRequest(InputStream input, OutputStream output, Context context) {
+ try {
+ int in;
+ while ((in = input.read()) != -1) {
+ output.write(in);
+ }
+ output.write('?');
+ } catch (IOException e) {
+ }
}
- output.write('?');
- } catch (IOException e) {
- }
}
- }
-
- private Context createContext() {
- return new Context() {
- @Override
- public String getAwsRequestId() {
- return "123";
- }
-
- @Override
- public String getLogGroupName() {
- return "logGroupName";
- }
-
- @Override
- public String getLogStreamName() {
- return "getLogStreamName";
- }
-
- @Override
- public String getFunctionName() {
- return null;
- }
-
- @Override
- public String getFunctionVersion() {
- return "LATEST";
- }
-
- @Override
- public String getInvokedFunctionArn() {
- return "arn";
- }
-
- @Override
- public CognitoIdentity getIdentity() {
- return new CognitoIdentity() {
- @Override
- public String getIdentityId() {
- return "identity";
- }
-
- @Override
- public String getIdentityPoolId() {
- return "identityPoolId";
- }
- };
- }
-
- @Override
- public ClientContext getClientContext() {
- return null;
- }
-
- @Override
- public int getRemainingTimeInMillis() {
- return 100;
- }
-
- @Override
- public int getMemoryLimitInMB() {
- return 510;
- }
-
- @Override
- public LambdaLogger getLogger() {
- return new LambdaLogger() {
- @Override
- public void log(String string) {}
+
+ private Context createContext() {
+ return new Context() {
+ @Override
+ public String getAwsRequestId() {
+ return "123";
+ }
+
+ @Override
+ public String getLogGroupName() {
+ return "logGroupName";
+ }
+
+ @Override
+ public String getLogStreamName() {
+ return "getLogStreamName";
+ }
+
+ @Override
+ public String getFunctionName() {
+ return null;
+ }
+
+ @Override
+ public String getFunctionVersion() {
+ return "LATEST";
+ }
+
+ @Override
+ public String getInvokedFunctionArn() {
+ return "arn";
+ }
+
+ @Override
+ public CognitoIdentity getIdentity() {
+ return new CognitoIdentity() {
+ @Override
+ public String getIdentityId() {
+ return "identity";
+ }
+
+ @Override
+ public String getIdentityPoolId() {
+ return "identityPoolId";
+ }
+ };
+ }
+
+ @Override
+ public ClientContext getClientContext() {
+ return null;
+ }
+
+ @Override
+ public int getRemainingTimeInMillis() {
+ return 100;
+ }
+
+ @Override
+ public int getMemoryLimitInMB() {
+ return 510;
+ }
+
+ @Override
+ public LambdaLogger getLogger() {
+ return new LambdaLogger() {
+ @Override
+ public void log(String string) {
+ }
+
+ @Override
+ public void log(byte[] message) {
+
+ }
+ };
+ }
};
- }
- };
- }
+ }
}