diff --git a/lambda-layer/build-layer.sh b/lambda-layer/build-layer.sh index b99fce80c5..478ef68ba0 100755 --- a/lambda-layer/build-layer.sh +++ b/lambda-layer/build-layer.sh @@ -45,4 +45,4 @@ popd ## Copy ADOT Java Agent downloaded using Gradle task and bundle it with the Lambda handler script cp "$SOURCEDIR"/build/javaagent/aws-opentelemetry-agent*.jar ./opentelemetry-javaagent.jar -zip -qr opentelemetry-javaagent-layer.zip opentelemetry-javaagent.jar otel-handler +zip -qr opentelemetry-javaagent-layer.zip opentelemetry-javaagent.jar otel-instrument diff --git a/lambda-layer/otel-handler b/lambda-layer/otel-handler deleted file mode 100644 index 9104e2a7b2..0000000000 --- a/lambda-layer/otel-handler +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -export OTEL_INSTRUMENTATION_AWS_SDK_EXPERIMENTAL_SPAN_ATTRIBUTES=true - -export OTEL_PROPAGATORS="${OTEL_PROPAGATORS:-xray,tracecontext,b3,b3multi}" - -# Temporarily set OTEL_SERVICE_NAME variable to work around but in javaagent not handling -# OTEL_RESOURCE_ATTRIBUTES as set in otel-handler-upstream. It doesn't hurt to apply this -# to wrapper as well. -# TODO(anuraaga): Move to opentelemetry-lambda -export OTEL_SERVICE_NAME=${OTEL_SERVICE_NAME:-${AWS_LAMBDA_FUNCTION_NAME}} - -export JAVA_TOOL_OPTIONS="-javaagent:/opt/opentelemetry-javaagent.jar ${JAVA_TOOL_OPTIONS}" - -if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then - export OTEL_RESOURCE_ATTRIBUTES="service.name=${AWS_LAMBDA_FUNCTION_NAME},${OTEL_RESOURCE_ATTRIBUTES}" -fi - -export OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT=10000 - -# Disable the Application Signals runtime metrics since we are on Lambda -export OTEL_AWS_APPLICATION_SIGNALS_RUNTIME_ENABLED=false - -exec "$@" diff --git a/lambda-layer/otel-instrument b/lambda-layer/otel-instrument new file mode 100644 index 0000000000..450eb925a5 --- /dev/null +++ b/lambda-layer/otel-instrument @@ -0,0 +1,38 @@ +#!/bin/bash + +export OTEL_INSTRUMENTATION_AWS_SDK_EXPERIMENTAL_SPAN_ATTRIBUTES=true + +export OTEL_PROPAGATORS="${OTEL_PROPAGATORS:-xray,tracecontext,b3,b3multi}" + +export OTEL_SERVICE_NAME=${OTEL_SERVICE_NAME:-${AWS_LAMBDA_FUNCTION_NAME}} + +export JAVA_TOOL_OPTIONS="-javaagent:/opt/opentelemetry-javaagent.jar ${JAVA_TOOL_OPTIONS}" + +if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then + export OTEL_RESOURCE_ATTRIBUTES="service.name=${AWS_LAMBDA_FUNCTION_NAME},${OTEL_RESOURCE_ATTRIBUTES}" +fi + +export OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT=10000 + +# Disable the Application Signals runtime metrics since we are on Lambda +export OTEL_AWS_APPLICATION_SIGNALS_RUNTIME_ENABLED=false + +# Use OTLP traces exporter if not specified +export OTEL_TRACES_EXPORTER=${OTEL_TRACES_EXPORTER:-"otlp"} + +# Disable metrics and logs export by default if not specified +export OTEL_METRICS_EXPORTER=${OTEL_METRICS_EXPORTER:-"none"} +export OTEL_LOGS_EXPORTER=${OTEL_LOGS_EXPORTER:-"none"} + +# Enable Application Signals by default if not specified +export OTEL_AWS_APPLICATION_SIGNALS_ENABLED=${OTEL_AWS_APPLICATION_SIGNALS_ENABLED:-"true"} + +# Append Lambda Resource Attributes to OTel Resource Attribute List +LAMBDA_RESOURCE_ATTRIBUTES="cloud.region=$AWS_REGION,cloud.provider=aws,faas.name=$AWS_LAMBDA_FUNCTION_NAME,faas.version=$AWS_LAMBDA_FUNCTION_VERSION,faas.instance=$AWS_LAMBDA_LOG_STREAM_NAME,aws.log.group.names=$AWS_LAMBDA_LOG_GROUP_NAME"; +if [ -z "${OTEL_RESOURCE_ATTRIBUTES}" ]; then + export OTEL_RESOURCE_ATTRIBUTES=$LAMBDA_RESOURCE_ATTRIBUTES; +else + export OTEL_RESOURCE_ATTRIBUTES="$LAMBDA_RESOURCE_ATTRIBUTES,$OTEL_RESOURCE_ATTRIBUTES"; +fi + +exec "$@" diff --git a/sample-apps/apigateway-lambda/build.gradle.kts b/sample-apps/apigateway-lambda/build.gradle.kts new file mode 100644 index 0000000000..ea6e873e57 --- /dev/null +++ b/sample-apps/apigateway-lambda/build.gradle.kts @@ -0,0 +1,38 @@ +plugins { + java + application +} + +application { + mainClass.set("com.amazon.sampleapp.LambdaHandler") +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } +} + +dependencies { + implementation("com.amazonaws:aws-lambda-java-core:1.2.2") + implementation("com.squareup.okhttp3:okhttp:4.11.0") + implementation("software.amazon.awssdk:s3:2.20.0") + testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") +} + +tasks.jar { + manifest { + attributes["Main-Class"] = "com.amazon.sampleapp.LambdaHandler" + } +} + +tasks.register("createLambdaZip") { + dependsOn("build") + from(tasks.compileJava.get()) + from(tasks.processResources.get()) + into("lib") { + from(configurations.runtimeClasspath.get()) + } + archiveFileName.set("lambda-function.zip") + destinationDirectory.set(layout.buildDirectory.dir("distributions")) +} diff --git a/sample-apps/apigateway-lambda/src/main/java/com/amazon/sampleapp/LambdaHandler.java b/sample-apps/apigateway-lambda/src/main/java/com/amazon/sampleapp/LambdaHandler.java new file mode 100644 index 0000000000..d10f5eced4 --- /dev/null +++ b/sample-apps/apigateway-lambda/src/main/java/com/amazon/sampleapp/LambdaHandler.java @@ -0,0 +1,49 @@ +package com.amazon.sampleapp; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.ListBucketsResponse; + +public class LambdaHandler implements RequestHandler { + private final OkHttpClient httpClient; + private final S3Client s3Client; + + public LambdaHandler() { + this.httpClient = new OkHttpClient(); + this.s3Client = S3Client.create(); + } + + @Override + public String handleRequest(Object o, Context context) { + makeRemoteCall(); + listS3Buckets(); + + // Get the _X_AMZN_TRACE_ID environment variable + String traceId = System.getenv("_X_AMZN_TRACE_ID"); + + // Construct the response string + return "Trace ID: " + traceId; + } + + private void makeRemoteCall() { + try { + Request request = new Request.Builder().url("https://aws.amazon.com/").build(); + Response response = httpClient.newCall(request).execute(); + response.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void listS3Buckets() { + ListBucketsResponse response = s3Client.listBuckets(); + int bucketCount = response.buckets().size(); + + // Print bucket count + System.out.println("Number of S3 buckets: " + bucketCount); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index f4ec99f115..decf81d145 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -51,6 +51,7 @@ include(":smoke-tests:spring-boot") include(":sample-apps:springboot") include(":sample-apps:spark") include(":sample-apps:spark-awssdkv1") +include(":sample-apps:apigateway-lambda") // Used for contract tests include("appsignals-tests:images:mock-collector")