Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ The example below shows how to add them as dependencies in your `build.gradle` f

```groovy
dependencies {
implementation("com.newrelic.opentracing:newrelic-java-lambda:2.0.0")
implementation("com.newrelic.opentracing:java-aws-lambda:2.0.0")
implementation("com.newrelic.opentracing:newrelic-java-lambda:2.1.1")
implementation("com.newrelic.opentracing:java-aws-lambda:2.1.0")
}
```

Expand All @@ -34,8 +34,8 @@ The New Relic Lambda Tracer and SDK support different versions of OpenTracing as
* Lambda Tracer: [com.newrelic.opentracing:newrelic-java-lambda:1.1.1](https://search.maven.org/artifact/com.newrelic.opentracing/newrelic-java-lambda/1.1.1/jar)
* Lambda SDK: [com.newrelic.opentracing:java-aws-lambda:1.0.0](https://search.maven.org/artifact/com.newrelic.opentracing/java-aws-lambda/1.0.0/jar)
* OpenTracing `0.32.0`, `0.33.0`:
* Lambda Tracer: [com.newrelic.opentracing:newrelic-java-lambda:2.0.0](https://search.maven.org/artifact/com.newrelic.opentracing/newrelic-java-lambda/2.0.0/jar)
* Lambda SDK: [com.newrelic.opentracing:java-aws-lambda:2.0.0](https://search.maven.org/artifact/com.newrelic.opentracing/java-aws-lambda/2.0.0/jar)
* Lambda Tracer: [com.newrelic.opentracing:newrelic-java-lambda:2.1.1](https://search.maven.org/artifact/com.newrelic.opentracing/newrelic-java-lambda/2.0.0/jar)
* Lambda SDK: [com.newrelic.opentracing:java-aws-lambda:2.1.0](https://search.maven.org/artifact/com.newrelic.opentracing/java-aws-lambda/2.0.0/jar)

## Getting Started

Expand All @@ -47,8 +47,10 @@ For full details on getting started please see the documentation on how to [Enab
package com.handler.example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import io.opentracing.util.GlobalTracer;
import com.newrelic.opentracing.aws.TracingRequestHandler;
import com.newrelic.opentracing.aws.LambdaTracing;
import com.newrelic.opentracing.LambdaTracer;

import java.util.Map;
Expand All @@ -59,7 +61,7 @@ import java.util.Map;
* @param Map<String, Object> The Lambda Function input
* @param String The Lambda Function output
*/
public class MyLambdaHandler implements TracingRequestHandler<Map<String, Object>, String> {
public class MyLambdaHandler implements RequestHandler<Map<String, Object>, String> {
static {
// Register the New Relic OpenTracing LambdaTracer as the Global Tracer
GlobalTracer.registerIfAbsent(LambdaTracer.INSTANCE);
Expand All @@ -74,8 +76,10 @@ public class MyLambdaHandler implements TracingRequestHandler<Map<String, Object
*/
@Override
public String doHandleRequest(Map<String, Object> input, Context context) {
// TODO Your function logic here
return "Lambda Function output";
return LambdaTracing.instrument(apiGatewayProxyRequestEvent, context, (event, ctx) -> {
// TODO Your function logic here
return "Lambda Function output";
});
}
}
```
Expand Down
25 changes: 16 additions & 9 deletions examples/distributed-tracing-example/DTCalleeFunction/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,33 @@ plugins {

repositories {
mavenCentral()
mavenLocal()
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
// New Relic AWS Lambda OpenTracing instrumentation
compile('com.newrelic.opentracing:java-aws-lambda:2.0.0')
compile('com.newrelic.opentracing:newrelic-java-lambda:2.0.0')
implementation('com.newrelic.opentracing:java-aws-lambda:2.1.0')
implementation('com.newrelic.opentracing:newrelic-java-lambda:2.1.1')

// OpenTracing
compile('io.opentracing:opentracing-util:0.33.0')
implementation('io.opentracing:opentracing-util:0.33.0')

// JSON processing
compile('com.googlecode.json-simple:json-simple:1.1')
implementation('com.googlecode.json-simple:json-simple:1.1')

// AWS Lambda Java SDK
compile('com.amazonaws:aws-lambda-java-log4j:1.0.0')
compile('com.amazonaws:aws-lambda-java-events:2.2.2')
compile('com.amazonaws:aws-java-sdk-lambda:1.11.608')
implementation('com.amazonaws:aws-lambda-java-log4j:1.0.0')
implementation('com.amazonaws:aws-lambda-java-events:2.2.2')
implementation('com.amazonaws:aws-java-sdk-lambda:1.11.608')
implementation 'com.amazonaws:aws-lambda-java-core:1.2.0'

// HTTP client
compile('com.konghq:unirest-java:3.0.00')
implementation('com.konghq:unirest-java:3.0.00')

testImplementation 'junit:junit:4.12'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@
package com.example;

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 com.newrelic.opentracing.LambdaTracer;
import com.newrelic.opentracing.aws.TracingRequestHandler;
import com.newrelic.opentracing.aws.LambdaTracing;
import io.opentracing.util.GlobalTracer;
import org.apache.log4j.Logger;

import java.util.Map;

/**
* AWS Lambda function that utilizes the AWS Lambda OpenTracing SDK and New Relic AWS Lambda OpenTracing Tracer.
* <p>
* This function simply prints out the input and headers map it received from API Gateway when invoked.
*/
public class DTCalleeFunction implements TracingRequestHandler<Map<String, Object>, Map<String, Object>> {
public class DTCalleeFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
static {
GlobalTracer.registerIfAbsent(LambdaTracer.INSTANCE);
}
Expand All @@ -28,20 +29,25 @@ public class DTCalleeFunction implements TracingRequestHandler<Map<String, Objec
/**
* Logs the input and headers map it received when invoked through API Gateway Proxy and returns an Response Map.
*
* @param input Input received from API Gateway Proxy
* @param context Lambda execution environment context object
* @param event Input received from API Gateway Proxy
* @param ctx Lambda execution environment context object
* @return Map of Response statusCode and body
*/
@Override
public Map<String, Object> doHandleRequest(Map<String, Object> input, Context context) {
// Log Lambda function input details received from API Gateway to the Cloudwatch logs
if (input != null && !input.isEmpty()) {
LOG.info("Lambda function input: " + input);
LOG.info("Headers: " + input.get("headers"));
} else {
LOG.info("Lambda function did not receive any input");
}
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context ctx) {
return LambdaTracing.instrument(event, ctx, (input, context) -> {
// Log Lambda function input details received from API Gateway to the Cloudwatch logs
if (input != null) {
LOG.info("Lambda function input: " + input);
LOG.info("Headers: " + input.getHeaders());
} else {
LOG.info("Lambda function did not receive any input");
}
APIGatewayProxyResponseEvent ret = new APIGatewayProxyResponseEvent()
.withStatusCode(200)
.withBody("OK");

return new Response(200, "OK").getMap();
return ret;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package com.example;

import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import org.junit.BeforeClass;
import org.junit.Test;

Expand Down Expand Up @@ -45,19 +47,15 @@ public void successfulResponse() {
* priority=1.112115
* }
*/
Map<String, String> newrelicHeader = new HashMap<String, String>() {{
put(NR_DT_HEADER_KEY, NR_DT_HEADER_PAYLOAD);
}};
Map<String, String> newrelicHeader = Collections.singletonMap(NR_DT_HEADER_KEY, NR_DT_HEADER_PAYLOAD);

Map<String, Object> headers = new HashMap<String, Object>() {{
put("headers", newrelicHeader);
}};
APIGatewayProxyRequestEvent requestEvent = new APIGatewayProxyRequestEvent().withHeaders(newrelicHeader);

DTCalleeFunction calleeFunction = new DTCalleeFunction();
final Map<String, Object> responseMap = calleeFunction.handleRequest(headers, new TestContext());
final APIGatewayProxyResponseEvent response = calleeFunction.handleRequest(requestEvent, new TestContext());

assertEquals(200, responseMap.get("statusCode"));
assertEquals("OK", responseMap.get("body"));
assertEquals(200, response.getStatusCode().intValue());
assertEquals("OK", response.getBody());
}

private static void setEnvironmentVariables(Map<String, String> environmentVariables) {
Expand Down
23 changes: 15 additions & 8 deletions examples/distributed-tracing-example/DTCallerFunction/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,33 @@ plugins {

repositories {
mavenCentral()
mavenLocal()
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
// New Relic AWS Lambda OpenTracing instrumentation
compile('com.newrelic.opentracing:java-aws-lambda:2.0.0')
compile('com.newrelic.opentracing:newrelic-java-lambda:2.0.0')
implementation('com.newrelic.opentracing:java-aws-lambda:2.1.0')
implementation('com.newrelic.opentracing:newrelic-java-lambda:2.1.1')

// OpenTracing
compile('io.opentracing:opentracing-util:0.33.0')
implementation('io.opentracing:opentracing-util:0.33.0')

// JSON processing
compile('com.googlecode.json-simple:json-simple:1.1')
implementation('com.googlecode.json-simple:json-simple:1.1')

// AWS Lambda Java SDK
compile('com.amazonaws:aws-lambda-java-log4j:1.0.0')
compile('com.amazonaws:aws-lambda-java-events:2.2.2')
compile('com.amazonaws:aws-java-sdk-lambda:1.11.608')
implementation('com.amazonaws:aws-lambda-java-log4j:1.0.0')
implementation('com.amazonaws:aws-lambda-java-events:2.2.2')
implementation('com.amazonaws:aws-java-sdk-lambda:1.11.608')
implementation 'com.amazonaws:aws-lambda-java-core:1.2.0'

// HTTP client
compile('com.konghq:unirest-java:3.0.00')
implementation('com.konghq:unirest-java:3.0.00')

testImplementation 'junit:junit:4.12'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
package com.example;

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 com.newrelic.opentracing.LambdaTracer;
import com.newrelic.opentracing.aws.TracingRequestHandler;
import com.newrelic.opentracing.aws.LambdaTracing;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
Expand All @@ -30,7 +32,7 @@
* <p>
* This function makes an external call to an API Gateway Proxy to invoke another AWS lambda function.
*/
public class DTCallerFunction implements TracingRequestHandler<Map<String, Object>, APIGatewayProxyResponseEvent> {
public class DTCallerFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
static {
GlobalTracer.registerIfAbsent(LambdaTracer.INSTANCE);
}
Expand All @@ -43,36 +45,38 @@ public class DTCallerFunction implements TracingRequestHandler<Map<String, Objec
* Invokes another AWS Lambda function through a call to API Gateway Proxy, logs the tracer results to the Lambda
* Cloudwatch logs, and returns an APIGatewayProxyResponseEvent.
*
* @param input Input received from API Gateway Proxy
* @param context Lambda execution environment context object
* @param event Input received from API Gateway Proxy
* @param ctx Lambda execution environment context object
* @return APIGatewayProxyResponseEvent Response received from API Gateway Proxy
*/
@Override
public APIGatewayProxyResponseEvent doHandleRequest(Map<String, Object> input, Context context) {
final HttpResponse<String> response;

// Log Lambda function input details received from API Gateway to the Cloudwatch logs
if (input != null && !input.isEmpty()) {
LOG.info("Lambda function input: " + input);
LOG.info("Headers: " + input.get("headers"));
} else {
LOG.info("Lambda function did not receive any input");
}
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context ctx) {
return LambdaTracing.instrument(event, ctx, (input, context) -> {
final HttpResponse<String> response;

// Log Lambda function input details received from API Gateway to the Cloudwatch logs
if (input != null) {
LOG.info("Lambda function input: " + input);
LOG.info("Headers: " + input.getHeaders());
} else {
LOG.info("Lambda function did not receive any input");
}

final String dtCalleeApiGatewayProxyURL = System.getenv(API_GATEWAY_PROXY_URL);
final String dtCalleeApiGatewayProxyURL = System.getenv(API_GATEWAY_PROXY_URL);

if (dtCalleeApiGatewayProxyURL == null) {
LOG.error("The API_GATEWAY_PROXY_URL environment variable must be set to properly invoke DTCalleeLambda");
return new APIGatewayProxyResponseEvent()
.withBody("Bad Request: The API_GATEWAY_PROXY_URL environment variable must be set to properly invoke DTCalleeLambda")
.withStatusCode(400);
}
response = makeExternalCallToApiGateway(dtCalleeApiGatewayProxyURL);
if (dtCalleeApiGatewayProxyURL == null) {
LOG.error("The API_GATEWAY_PROXY_URL environment variable must be set to properly invoke DTCalleeLambda");
return new APIGatewayProxyResponseEvent()
.withBody("Bad Request: The API_GATEWAY_PROXY_URL environment variable must be set to properly invoke DTCalleeLambda")
.withStatusCode(400);
}
response = makeExternalCallToApiGateway(dtCalleeApiGatewayProxyURL);

return new APIGatewayProxyResponseEvent()
.withBody(response.getBody())
.withStatusCode(response.getStatus())
.withHeaders(getResponseHeaderMap(response));
return new APIGatewayProxyResponseEvent()
.withBody(response.getBody())
.withStatusCode(response.getStatus())
.withHeaders(getResponseHeaderMap(response));
});
}

/**
Expand Down Expand Up @@ -130,7 +134,7 @@ private HttpResponse<String> makeExternalCallToApiGateway(String dtCalleeApiGate
* @param response HttpResponse
* @return Map of headers
*/
private Map<String, String> getResponseHeaderMap(HttpResponse response) {
private Map<String, String> getResponseHeaderMap(HttpResponse<?> response) {
final List<Header> headerList = response.getHeaders().all();
final Map<String, String> headerMap = new HashMap<>();
headerList.forEach((header) -> headerMap.put(header.getName(), header.getValue()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import org.junit.BeforeClass;
import org.junit.Test;
Expand Down Expand Up @@ -50,16 +51,13 @@ public void successfulResponse() {
* priority=1.112115
* }
*/
Map<String, String> newrelicHeader = new HashMap<String, String>() {{
put(NR_DT_HEADER_KEY, NR_DT_HEADER_PAYLOAD);
}};
Map<String, String> newrelicHeader = Collections.singletonMap(NR_DT_HEADER_KEY, NR_DT_HEADER_PAYLOAD);

Map<String, Object> headers = new HashMap<String, Object>() {{
put("headers", newrelicHeader);
}};
APIGatewayProxyRequestEvent input = new APIGatewayProxyRequestEvent()
.withHeaders(newrelicHeader);

DTCallerFunction callerFunction = new DTCallerFunction();
final APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent = callerFunction.handleRequest(headers, new TestContext());
final APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent = callerFunction.handleRequest(input, new TestContext());

assertEquals(Integer.valueOf(200), apiGatewayProxyResponseEvent.getStatusCode());
assertEquals("OK", apiGatewayProxyResponseEvent.getBody());
Expand Down
Loading