From 7af0e72af36ed2ff4fb0a192d9aa1539a4051478 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Tue, 7 Jul 2026 23:45:57 +0000 Subject: [PATCH 01/11] ci: Update Go version in all workflows from 1.24.3 to 1.26.2 PR #1135 bumped Go from 1.24.0 to 1.26.2 in go.mod files (adot/collector/lambdacomponents, opentelemetry-lambda submodule). The GitHub Actions workflows still referenced Go ~1.24.3 via actions/setup-go, causing build/runtime failures in the soak tests because the installed Go toolchain was too old for the go directive. Update all 8 workflow files to use go-version: '~1.26.2' to match the project's go.mod requirements. --- .github/workflows/canary.yml | 2 +- .github/workflows/main-build-java.yml | 2 +- .github/workflows/main-build-nodejs.yml | 2 +- .github/workflows/main-build-python.yml | 2 +- .github/workflows/main-build.yml | 2 +- .github/workflows/pr-build.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/soaking.yml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 66cd13c4f..588c084c2 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -67,7 +67,7 @@ jobs: submodules: recursive - uses: actions/setup-go@v5 with: - go-version: '~1.24.3' + go-version: '~1.26.2' check-latest: true - uses: actions/setup-java@v4 if: ${{ matrix.language == 'java' }} diff --git a/.github/workflows/main-build-java.yml b/.github/workflows/main-build-java.yml index 126b762cb..d7817457d 100644 --- a/.github/workflows/main-build-java.yml +++ b/.github/workflows/main-build-java.yml @@ -85,7 +85,7 @@ jobs: submodules: recursive - uses: actions/setup-go@v5 with: - go-version: '~1.24.3' + go-version: '~1.26.2' check-latest: true - uses: actions/setup-java@v4 with: diff --git a/.github/workflows/main-build-nodejs.yml b/.github/workflows/main-build-nodejs.yml index d99e6534d..de4c816b7 100644 --- a/.github/workflows/main-build-nodejs.yml +++ b/.github/workflows/main-build-nodejs.yml @@ -30,7 +30,7 @@ jobs: submodules: recursive - uses: actions/setup-go@v5 with: - go-version: '~1.24.3' + go-version: '~1.26.2' check-latest: true - uses: actions/setup-node@v4 with: diff --git a/.github/workflows/main-build-python.yml b/.github/workflows/main-build-python.yml index b326316ee..cac1c010c 100644 --- a/.github/workflows/main-build-python.yml +++ b/.github/workflows/main-build-python.yml @@ -30,7 +30,7 @@ jobs: submodules: recursive - uses: actions/setup-go@v5 with: - go-version: '~1.24.3' + go-version: '~1.26.2' check-latest: true - uses: actions/setup-python@v5 with: diff --git a/.github/workflows/main-build.yml b/.github/workflows/main-build.yml index 7060250d1..6724552e5 100644 --- a/.github/workflows/main-build.yml +++ b/.github/workflows/main-build.yml @@ -40,7 +40,7 @@ jobs: submodules: recursive - uses: actions/setup-go@v5 with: - go-version: '~1.24.3' + go-version: '~1.26.2' check-latest: true - uses: actions/setup-dotnet@v4 if: ${{ matrix.language == 'dotnet' }} diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 66fc404bf..0f43d2393 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -24,7 +24,7 @@ jobs: submodules: true - uses: actions/setup-go@v5 with: - go-version: '~1.24.3' + go-version: '~1.26.2' check-latest: true - uses: actions/setup-java@v4 if: ${{ matrix.language == 'java' }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7385b0d9f..f1d360fac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -273,7 +273,7 @@ jobs: # above, always setup go 1.18. # if: ${{ env.TEST_LANGUAGE == 'go' }} with: - go-version: '~1.24.3' + go-version: '~1.26.2' check-latest: true - name: download layer tf file uses: actions/download-artifact@v4 diff --git a/.github/workflows/soaking.yml b/.github/workflows/soaking.yml index a17e6b662..e23a93028 100644 --- a/.github/workflows/soaking.yml +++ b/.github/workflows/soaking.yml @@ -67,7 +67,7 @@ jobs: submodules: recursive - uses: actions/setup-go@v5 with: - go-version: '~1.24.3' + go-version: '~1.26.2' check-latest: true - uses: actions/setup-java@v4 if: ${{ matrix.language == 'java' }} From 4774e0ad7df86a7cd89fc8a3487f93c8bf8fdcff Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Wed, 8 Jul 2026 00:33:59 +0000 Subject: [PATCH 02/11] fix(nodejs): Repair soak-test terraform and expected trace for OTel v0.151.0 The OTel Collector v0.151.0 submodule bump introduced two nodejs-only breakages in the soak/integration tests: 1. Terraform "Unsupported argument": upstream nodejs/sample-apps/aws-sdk/deploy/wrapper was refactored to build layer ARNs internally from published layer versions and no longer accepts collector_layer_arn / sdk_layer_arn. Rework the integration test to instantiate terraform-aws-modules/lambda/aws + api-gateway-proxy directly and attach the locally-built layers, mirroring the python test. Go and Java deploy modules still accept the ARN inputs and are unchanged. 2. TraceValidator "data model not matched": the upstream nodejs sample app switched its AWS call from S3 ListBuckets to STS GetCallerIdentity. Update the expected trace template accordingly. Java/Go samples still use S3. sim: https://taskei.amazon.dev/tasks/PROMET-11975 --- .../nodejs-aws-sdk-wrapper.json | 9 +++- .../integration-tests/aws-sdk/wrapper/main.tf | 50 +++++++++++++++---- .../aws-sdk/wrapper/outputs.tf | 4 +- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/adot/utils/expected-templates/nodejs-aws-sdk-wrapper.json b/adot/utils/expected-templates/nodejs-aws-sdk-wrapper.json index d0879b91f..6dcfff14d 100644 --- a/adot/utils/expected-templates/nodejs-aws-sdk-wrapper.json +++ b/adot/utils/expected-templates/nodejs-aws-sdk-wrapper.json @@ -12,6 +12,11 @@ "name": "lambda-nodejs.*" }, { - "name": "s3" + "name": "STS", + "origin": "AWS::STS", + "inferred": true, + "aws": { + "operation": "GetCallerIdentity" + } } -] \ No newline at end of file +] diff --git a/nodejs/integration-tests/aws-sdk/wrapper/main.tf b/nodejs/integration-tests/aws-sdk/wrapper/main.tf index c50596ec2..bcd94383f 100644 --- a/nodejs/integration-tests/aws-sdk/wrapper/main.tf +++ b/nodejs/integration-tests/aws-sdk/wrapper/main.tf @@ -19,22 +19,54 @@ resource "aws_lambda_layer_version" "collector_layer" { source_code_hash = filebase64sha256("${path.module}/../../../../opentelemetry-lambda/collector/build/opentelemetry-collector-layer-${local.architecture}.zip") } -module "hello-lambda-function" { - source = "../../../../opentelemetry-lambda/nodejs/sample-apps/aws-sdk/deploy/wrapper" +# NOTE: The upstream `nodejs/sample-apps/aws-sdk/deploy/wrapper` module was +# refactored (OTel Collector v0.151.0) to build layer ARNs internally from +# published layer versions and no longer accepts `collector_layer_arn` / +# `sdk_layer_arn` inputs. The integration/soak test must attach the layers we +# just built locally, so we instantiate the Lambda function directly here - +# mirroring the python integration test - instead of consuming that module. +module "test-function" { + source = "terraform-aws-modules/lambda/aws" + version = "7.19.0" + + architectures = compact([var.architecture]) + function_name = var.function_name + handler = "index.handler" + runtime = var.runtime + + create_package = false + local_existing_package = "${path.module}/../../../../opentelemetry-lambda/nodejs/sample-apps/aws-sdk/build/function.zip" + + memory_size = 384 + timeout = 20 + + layers = compact([ + var.enable_collector_layer ? aws_lambda_layer_version.collector_layer[0].arn : null, + aws_lambda_layer_version.sdk_layer.arn + ]) + + environment_variables = { + AWS_LAMBDA_EXEC_WRAPPER = "/opt/otel-handler" + } + + tracing_mode = var.tracing_mode +} + +module "api-gateway" { + source = "../../../../opentelemetry-lambda/utils/terraform/api-gateway-proxy" + name = var.function_name - architecture = var.architecture - collector_layer_arn = var.enable_collector_layer ? aws_lambda_layer_version.collector_layer[0].arn : null - sdk_layer_arn = aws_lambda_layer_version.sdk_layer.arn - tracing_mode = var.tracing_mode - runtime = var.runtime + function_name = module.test-function.lambda_function_name + function_invoke_arn = module.test-function.lambda_function_invoke_arn + enable_xray_tracing = var.tracing_mode == "Active" } resource "aws_iam_role_policy_attachment" "hello-lambda-cloudwatch-insights" { - role = module.hello-lambda-function.function_role_name + role = module.test-function.lambda_role_name policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" } resource "aws_iam_role_policy_attachment" "test_xray" { - role = module.hello-lambda-function.function_role_name + role = module.test-function.lambda_role_name policy_arn = "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess" } diff --git a/nodejs/integration-tests/aws-sdk/wrapper/outputs.tf b/nodejs/integration-tests/aws-sdk/wrapper/outputs.tf index a40152815..9ef20e2ff 100644 --- a/nodejs/integration-tests/aws-sdk/wrapper/outputs.tf +++ b/nodejs/integration-tests/aws-sdk/wrapper/outputs.tf @@ -1,9 +1,9 @@ output "api-gateway-url" { - value = module.hello-lambda-function.api-gateway-url + value = module.api-gateway.api_gateway_url } output "function_role_name" { - value = module.hello-lambda-function.function_role_name + value = module.test-function.lambda_role_name } output "collector_layer_arn" { From b1cbf24055428de9196193e07ccb4a48345ed9b6 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Wed, 8 Jul 2026 01:44:19 +0000 Subject: [PATCH 03/11] fix(collector): remove deprecated telemetry.metrics.address for OTel v0.151.0 The collector v0.151.0 bump surfaced a runtime INIT/invoke failure across soak jobs: - java-agent: FUNCTION_ERROR_INIT_FAILURE during provisioned-concurrency warm-up (surfaces as the aws_lambda_provisioned_concurrency_config waiter erroring) - go/python/java wrappers: sample app returns HTTP 500, so no trace is produced and TraceValidator reports "data model not matched" Both paths share the collector extension. The ADOT config override retained `service.telemetry.metrics.address: localhost:8888`, a field deprecated in collector v0.123.0 and dropped by upstream in the v0.151.0 default config. Upstream opentelemetry-collector issue #3911 documents this field causing port conflicts and collector crashes, which would crash the Lambda extension and produce the observed INIT/invoke failures. Remove the telemetry block from the default ADOT collector config and the java-agent integration test's inline config to realign with upstream v0.151.0. NOT YET VERIFIED: soak cannot be run locally (deploys real Lambdas) and the failing run's CloudWatch logs were already torn down. A soak run is required to confirm this resolves the INIT failures. sim: https://taskei.amazon.dev/tasks/PROMET-11975 --- adot/collector/config.yaml | 3 --- java/integration-tests/aws-sdk/agent/main.tf | 3 --- 2 files changed, 6 deletions(-) diff --git a/adot/collector/config.yaml b/adot/collector/config.yaml index 195b2a678..4e252032e 100644 --- a/adot/collector/config.yaml +++ b/adot/collector/config.yaml @@ -18,6 +18,3 @@ service: metrics: receivers: [otlp] exporters: [debug] - telemetry: - metrics: - address: localhost:8888 diff --git a/java/integration-tests/aws-sdk/agent/main.tf b/java/integration-tests/aws-sdk/agent/main.tf index 51c913f1e..51f0e8d2c 100644 --- a/java/integration-tests/aws-sdk/agent/main.tf +++ b/java/integration-tests/aws-sdk/agent/main.tf @@ -79,9 +79,6 @@ service: metrics: receivers: [otlp] exporters: [debug, prometheusremotewrite] - telemetry: - metrics: - address: localhost:8888 EOT filename = "config.yaml" } From d1d7e6b924c6ae682642322f49ac5be800afe439 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Fri, 10 Jul 2026 22:00:03 +0000 Subject: [PATCH 04/11] fix(collector): set required Telemetry factory for OTel Collector v0.151.0 v0.151.0 made otelcol.Factories.Telemetry a required field. The ADOT lambdacomponents builder (adot/collector/lambdacomponents/default.go), which patch-upstream.sh copies over the submodule, did not set it, so the collector extension failed at INIT ("otelcol.Factories.Telemetry must not be nil") -> Extension.InitError on every invoke -> instrumented Lambdas returned HTTP 500 with no trace in soak (go/python/java-wrapper) and java-agent FUNCTION_ERROR_INIT_FAILURE. Set Telemetry: otelconftelemetry.NewFactory(), mirroring upstream lambdacomponents/custom.go, and add the collector/service require via go mod tidy. Ref: V2153606376 --- adot/collector/lambdacomponents/default.go | 2 ++ adot/collector/lambdacomponents/go.mod | 4 +++- adot/collector/lambdacomponents/go.sum | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/adot/collector/lambdacomponents/default.go b/adot/collector/lambdacomponents/default.go index 70de30e1b..f5f157a54 100644 --- a/adot/collector/lambdacomponents/default.go +++ b/adot/collector/lambdacomponents/default.go @@ -27,6 +27,7 @@ import ( "go.opentelemetry.io/collector/exporter/otlphttpexporter" "go.opentelemetry.io/collector/otelcol" "go.opentelemetry.io/collector/receiver/otlpreceiver" + "go.opentelemetry.io/collector/service/telemetry/otelconftelemetry" "go.uber.org/multierr" ) @@ -68,6 +69,7 @@ func Components() ( Extensions: extensions, Receivers: receivers, Exporters: exporters, + Telemetry: otelconftelemetry.NewFactory(), } return factories, errs diff --git a/adot/collector/lambdacomponents/go.mod b/adot/collector/lambdacomponents/go.mod index 5a8832789..31e04ead2 100644 --- a/adot/collector/lambdacomponents/go.mod +++ b/adot/collector/lambdacomponents/go.mod @@ -14,6 +14,7 @@ require ( go.opentelemetry.io/collector/exporter/otlphttpexporter v0.151.0 go.opentelemetry.io/collector/otelcol v0.151.0 go.opentelemetry.io/collector/receiver/otlpreceiver v0.151.0 + go.opentelemetry.io/collector/service v0.151.0 go.uber.org/multierr v1.11.0 ) @@ -172,11 +173,12 @@ require ( go.opentelemetry.io/collector/receiver/receiverhelper v0.151.0 // indirect go.opentelemetry.io/collector/receiver/receivertest v0.151.0 // indirect go.opentelemetry.io/collector/receiver/xreceiver v0.151.0 // indirect - go.opentelemetry.io/collector/service v0.151.0 // indirect go.opentelemetry.io/collector/service/hostcapabilities v0.151.0 // indirect + go.opentelemetry.io/contrib/bridges/otelzap v0.18.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect go.opentelemetry.io/contrib/otelconf v0.23.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.43.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 // indirect diff --git a/adot/collector/lambdacomponents/go.sum b/adot/collector/lambdacomponents/go.sum index 2b953e934..7ea353ce9 100644 --- a/adot/collector/lambdacomponents/go.sum +++ b/adot/collector/lambdacomponents/go.sum @@ -547,12 +547,16 @@ go.opentelemetry.io/collector/service/hostcapabilities v0.151.0 h1:+VbDE5ZRXKD6n go.opentelemetry.io/collector/service/hostcapabilities v0.151.0/go.mod h1:GlnaFXJAqeTgAnEDIz7HI28ydwoZcbJ7Niyom+wVBMo= go.opentelemetry.io/collector/service/telemetry/telemetrytest v0.151.0 h1:L4r/rZBeDBaVnU/EeQT6H2/msGAyzpKMHXTP8Vwr1NE= go.opentelemetry.io/collector/service/telemetry/telemetrytest v0.151.0/go.mod h1:/e2FJ+CEpIttRTzP37HdrgKuwfIj6dcZsa2jZajL6Vw= +go.opentelemetry.io/contrib/bridges/otelzap v0.18.0 h1:EkWTww6Nqs2P29r01NeuNsG7qNJtoWWaT1fx/CKode8= +go.opentelemetry.io/contrib/bridges/otelzap v0.18.0/go.mod h1:lj3bgA/c7nJy0NhxqyvWJFC30aTgB+G0RKDdLbvJ4QM= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= go.opentelemetry.io/contrib/otelconf v0.23.0 h1:s3C7KdMYiutf4rC8hKFA0WOIDG+gIru8ajjQKS59ir8= go.opentelemetry.io/contrib/otelconf v0.23.0/go.mod h1:0kN2tcccZS82e7IZlo045gkcL8/8dup1k25sf9ypGxM= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0 h1:CETqV3QLLPTy5yNrqyMr41VnAOOD4lsRved7n4QG00A= +go.opentelemetry.io/contrib/propagators/b3 v1.43.0/go.mod h1:Q4mCiCdziYzpNR0g+6UqVotAlCDZdzz6L8jwY4knOrw= go.opentelemetry.io/contrib/zpages v0.68.0 h1:H5yrUwxPrbvhzdBxjQD+VXMtPjIBfp8NWNVvQT8E30M= go.opentelemetry.io/contrib/zpages v0.68.0/go.mod h1:sZGctYYO4UOHItj9bx3F+t/s+u1Fv8CHCJ5s2eR2cjU= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= @@ -581,6 +585,8 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU= go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= +go.opentelemetry.io/otel/log/logtest v0.19.0 h1:HdSsl4ndTK15LtJGLWBfMsSlLrCgSeE3VMzwOrLYiYs= +go.opentelemetry.io/otel/log/logtest v0.19.0/go.mod h1:c1sH1nOHTwfMCWhhQTdWGqxgDjZhtkbkzAqGGyj0Ijs= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= From b937800dd47a459ddba53f85233285b54590dae3 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Tue, 14 Jul 2026 18:19:41 +0000 Subject: [PATCH 05/11] fix(soak): update go-wrapper expected trace for OTel v0.151.0 span naming The rebuilt go sample app (opentelemetry-lambda submodule @ v0.151.0) emits new span names via updated otelaws/otelhttp instrumentation, which flow to X-Ray inferred-segment names: - S3 AWS SDK call: inferred segment S3 -> S3.ListBuckets - HTTP client call: inferred segment api.github.com -> HTTP GET The inferred S3 segment no longer carries origin/aws.operation, so those fields are dropped. Regenerated from the real trace in soak run 29127081461. --- adot/utils/expected-templates/go-aws-sdk-wrapper.json | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/adot/utils/expected-templates/go-aws-sdk-wrapper.json b/adot/utils/expected-templates/go-aws-sdk-wrapper.json index 774f89c69..79198c32e 100644 --- a/adot/utils/expected-templates/go-aws-sdk-wrapper.json +++ b/adot/utils/expected-templates/go-aws-sdk-wrapper.json @@ -12,15 +12,11 @@ "name":"lambda-go.*" }, { - "name":"S3", - "origin":"AWS::S3", - "inferred":true, - "aws":{ - "operation":"ListBuckets" - } + "name":"S3.ListBuckets", + "inferred":true }, { - "name":"api.github.com", + "name":"HTTP GET", "inferred":true, "http":{ "request":{ From 480086febcdf97faeedd229717c1a9ddb23d2bf7 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Tue, 14 Jul 2026 18:39:37 +0000 Subject: [PATCH 06/11] fix(soak): nodejs sample app must return _X_AMZN_TRACE_ID for validator The nodejs aws-sdk sample app returned a caller-identity JSON payload, so the soak trace validator could not extract a trace ID (trace_id=null) and never fetched the trace, failing with 'data model not matched'. Mirror the go/python sample apps: still call STS GetCallerIdentity (to emit the STS segment) but return process.env._X_AMZN_TRACE_ID as the response body. Placed under adot/ so patch-upstream.sh (cp -rf adot/* opentelemetry-lambda/) overrides the submodule sample app at build time. --- .../sample-apps/aws-sdk/lambda/index.ts | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 adot/nodejs/sample-apps/aws-sdk/lambda/index.ts diff --git a/adot/nodejs/sample-apps/aws-sdk/lambda/index.ts b/adot/nodejs/sample-apps/aws-sdk/lambda/index.ts new file mode 100644 index 000000000..a37231bd6 --- /dev/null +++ b/adot/nodejs/sample-apps/aws-sdk/lambda/index.ts @@ -0,0 +1,39 @@ +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context, +} from 'aws-lambda'; + +import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts'; + +const sts = new STSClient({}); + +export const handler = async ( + event: APIGatewayProxyEvent, + _context: Context, +): Promise => { + console.log('Received event:', JSON.stringify(event, null, 2)); + console.log('Received context:', JSON.stringify(_context, null, 2)); + + try { + // Make an instrumented AWS SDK call so the emitted trace contains an + // STS GetCallerIdentity segment (asserted by the soak trace validator). + await sts.send(new GetCallerIdentityCommand({})); + + // The soak trace validator extracts the X-Ray trace ID from the HTTP + // response body (see the go and python sample apps, which return + // `_X_AMZN_TRACE_ID`). Returning the caller-identity payload instead + // leaves the validator with no trace ID (`trace_id=null`) and it can + // never fetch the trace. Return the trace header so validation can run. + return { + statusCode: 200, + body: JSON.stringify(process.env._X_AMZN_TRACE_ID ?? ''), + }; + } catch (error) { + console.error('Error retrieving caller identity:', error); + return { + statusCode: 500, + body: 'Internal Server Error', + }; + } +}; From 4e9b0a57f698e7c40fe021244fc87067be029590 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Tue, 14 Jul 2026 18:56:24 +0000 Subject: [PATCH 07/11] fix(soak): correct go-wrapper expected trace segment order for v0.151.0 The soak TraceValidator matches strictly by flattened index key ([N].name), and orders actual segments by start_time. In the v0.151.0 trace the inferred S3.ListBuckets segment sorts to index [3] (between the instrumented segment and the Lambda::Function segment), not [4]. The prior fix renamed correctly but left S3 at [4], colliding stored [3]=lambda-go.* with actual [3]=S3.ListBuckets. Reorder: S3.ListBuckets at [3], lambda-go.* at [4]. --- adot/utils/expected-templates/go-aws-sdk-wrapper.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adot/utils/expected-templates/go-aws-sdk-wrapper.json b/adot/utils/expected-templates/go-aws-sdk-wrapper.json index 79198c32e..fa10d650b 100644 --- a/adot/utils/expected-templates/go-aws-sdk-wrapper.json +++ b/adot/utils/expected-templates/go-aws-sdk-wrapper.json @@ -8,13 +8,13 @@ { "name":"lambda-go.*" }, - { - "name":"lambda-go.*" - }, { "name":"S3.ListBuckets", "inferred":true }, + { + "name":"lambda-go.*" + }, { "name":"HTTP GET", "inferred":true, From ade4b80b9469c85977552863d5cb21412cce4648 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Tue, 14 Jul 2026 18:59:27 +0000 Subject: [PATCH 08/11] debug(java-wrapper): instrument awssdk-autoconfigure interceptor [TEMP] Temporary [ADOT-DEBUG] diagnostics to localize why AWS SDK calls are not traced in wrapper mode (PROMET-11975). Logs: (1) static block = SPI class loaded, (2) constructor = captured GlobalOpenTelemetry + TracerProvider class, (3) beforeExecution = interceptor actually invoked per SDK call. Distinguishes 'never registered' vs 'noop OTel' vs 'not attached' vs 'span dropped'. Revert before release. --- ...configuredTracingExecutionInterceptor.java | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java diff --git a/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java b/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java new file mode 100644 index 000000000..a048a5edc --- /dev/null +++ b/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java @@ -0,0 +1,172 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; +import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.Optional; +import org.reactivestreams.Publisher; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.SdkResponse; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.SdkHttpResponse; + +/** + * A {@link ExecutionInterceptor} for use as an SPI by the AWS SDK to automatically trace all + * requests. + * + *

NOTE: This copy carries temporary [ADOT-DEBUG] diagnostics to localize why AWS SDK calls are + * not traced in wrapper mode under OTel Collector v0.151.0 (PROMET-11975). Remove before release. + */ +public class AutoconfiguredTracingExecutionInterceptor implements ExecutionInterceptor { + + static { + // Prints iff the AWS SDK reads the global interceptors SPI file and loads this class at all. + System.out.println( + "[ADOT-DEBUG] AutoconfiguredTracingExecutionInterceptor class loaded (SPI registration hit)"); + } + + private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.aws-sdk.experimental-span-attributes", false); + + private final ExecutionInterceptor delegate; + + public AutoconfiguredTracingExecutionInterceptor() { + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + // Prints what OpenTelemetry the delegate captured at construction time. A Noop/Default + // TracerProvider here means traces will be silently dropped even though metrics work. + System.out.println( + "[ADOT-DEBUG] interceptor constructed; GlobalOpenTelemetry=" + + openTelemetry.getClass().getName() + + " tracerProvider=" + + openTelemetry.getTracerProvider().getClass().getName()); + this.delegate = + AwsSdkTelemetry.builder(openTelemetry) + .setCaptureExperimentalSpanAttributes(CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) + .build() + .createExecutionInterceptor(); + } + + @Override + public void beforeExecution( + Context.BeforeExecution context, ExecutionAttributes executionAttributes) { + // Prints iff the interceptor is actually attached to the SDK client and invoked per call. + System.out.println("[ADOT-DEBUG] beforeExecution fired for an AWS SDK request"); + delegate.beforeExecution(context, executionAttributes); + } + + @Override + public SdkRequest modifyRequest( + Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + return delegate.modifyRequest(context, executionAttributes); + } + + @Override + public void beforeMarshalling( + Context.BeforeMarshalling context, ExecutionAttributes executionAttributes) { + delegate.beforeMarshalling(context, executionAttributes); + } + + @Override + public void afterMarshalling( + Context.AfterMarshalling context, ExecutionAttributes executionAttributes) { + delegate.afterMarshalling(context, executionAttributes); + } + + @Override + public SdkHttpRequest modifyHttpRequest( + Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { + return delegate.modifyHttpRequest(context, executionAttributes); + } + + @Override + public Optional modifyHttpContent( + Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { + return delegate.modifyHttpContent(context, executionAttributes); + } + + @Override + public Optional modifyAsyncHttpContent( + Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { + return delegate.modifyAsyncHttpContent(context, executionAttributes); + } + + @Override + public void beforeTransmission( + Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { + delegate.beforeTransmission(context, executionAttributes); + } + + @Override + public void afterTransmission( + Context.AfterTransmission context, ExecutionAttributes executionAttributes) { + delegate.afterTransmission(context, executionAttributes); + } + + @Override + public SdkHttpResponse modifyHttpResponse( + Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { + return delegate.modifyHttpResponse(context, executionAttributes); + } + + @Override + public Optional> modifyAsyncHttpResponseContent( + Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { + return delegate.modifyAsyncHttpResponseContent(context, executionAttributes); + } + + @Override + public Optional modifyHttpResponseContent( + Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { + return delegate.modifyHttpResponseContent(context, executionAttributes); + } + + @Override + public void beforeUnmarshalling( + Context.BeforeUnmarshalling context, ExecutionAttributes executionAttributes) { + delegate.beforeUnmarshalling(context, executionAttributes); + } + + @Override + public void afterUnmarshalling( + Context.AfterUnmarshalling context, ExecutionAttributes executionAttributes) { + delegate.afterUnmarshalling(context, executionAttributes); + } + + @Override + public SdkResponse modifyResponse( + Context.ModifyResponse context, ExecutionAttributes executionAttributes) { + return delegate.modifyResponse(context, executionAttributes); + } + + @Override + public void afterExecution( + Context.AfterExecution context, ExecutionAttributes executionAttributes) { + delegate.afterExecution(context, executionAttributes); + } + + @Override + public Throwable modifyException( + Context.FailedExecution context, ExecutionAttributes executionAttributes) { + return delegate.modifyException(context, executionAttributes); + } + + @Override + public void onExecutionFailure( + Context.FailedExecution context, ExecutionAttributes executionAttributes) { + delegate.onExecutionFailure(context, executionAttributes); + } +} From 2e85c32c555f833ba2ba6803f793b89029e2473d Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Tue, 14 Jul 2026 19:11:24 +0000 Subject: [PATCH 09/11] debug(java-wrapper): log active span context in beforeExecution [TEMP] Interceptor is confirmed registered/attached with a real tracer, yet no S3 span lands in the Lambda X-Ray trace. Add active SpanContext dump (valid/ sampled/traceId) at beforeExecution to test the context-propagation hypothesis (orphaned root span). Revert before release. --- ...configuredTracingExecutionInterceptor.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java b/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java index a048a5edc..7dd743e1f 100644 --- a/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java +++ b/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java @@ -7,6 +7,8 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; import java.io.InputStream; @@ -63,8 +65,23 @@ public AutoconfiguredTracingExecutionInterceptor() { @Override public void beforeExecution( Context.BeforeExecution context, ExecutionAttributes executionAttributes) { - // Prints iff the interceptor is actually attached to the SDK client and invoked per call. - System.out.println("[ADOT-DEBUG] beforeExecution fired for an AWS SDK request"); + // Dump the active span context. If invalid/unsampled here, the SDK span has no parent to + // attach to and becomes an orphaned root trace (context-propagation failure) that never + // shows up under the Lambda's X-Ray trace. + SpanContext sc = Span.current().getSpanContext(); + System.out.println( + "[ADOT-DEBUG] beforeExecution fired; activeSpan valid=" + + sc.isValid() + + " sampled=" + + sc.isSampled() + + " remote=" + + sc.isRemote() + + " traceId=" + + sc.getTraceId() + + " spanId=" + + sc.getSpanId() + + " xrayEnv=" + + System.getenv("_X_AMZN_TRACE_ID")); delegate.beforeExecution(context, executionAttributes); } From 09d325eccb149511cadc6d962b748e135b3cb954 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Tue, 14 Jul 2026 19:30:01 +0000 Subject: [PATCH 10/11] Revert "debug(java-wrapper): log active span context in beforeExecution [TEMP]" This reverts commit 2e85c32c555f833ba2ba6803f793b89029e2473d. --- ...configuredTracingExecutionInterceptor.java | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java b/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java index 7dd743e1f..a048a5edc 100644 --- a/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java +++ b/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java @@ -7,8 +7,6 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; import java.io.InputStream; @@ -65,23 +63,8 @@ public AutoconfiguredTracingExecutionInterceptor() { @Override public void beforeExecution( Context.BeforeExecution context, ExecutionAttributes executionAttributes) { - // Dump the active span context. If invalid/unsampled here, the SDK span has no parent to - // attach to and becomes an orphaned root trace (context-propagation failure) that never - // shows up under the Lambda's X-Ray trace. - SpanContext sc = Span.current().getSpanContext(); - System.out.println( - "[ADOT-DEBUG] beforeExecution fired; activeSpan valid=" - + sc.isValid() - + " sampled=" - + sc.isSampled() - + " remote=" - + sc.isRemote() - + " traceId=" - + sc.getTraceId() - + " spanId=" - + sc.getSpanId() - + " xrayEnv=" - + System.getenv("_X_AMZN_TRACE_ID")); + // Prints iff the interceptor is actually attached to the SDK client and invoked per call. + System.out.println("[ADOT-DEBUG] beforeExecution fired for an AWS SDK request"); delegate.beforeExecution(context, executionAttributes); } From 45c0c407dab6ed29683d1cc966de880f26f33434 Mon Sep 17 00:00:00 2001 From: Priyanka Dhingra Date: Tue, 14 Jul 2026 19:30:01 +0000 Subject: [PATCH 11/11] Revert "debug(java-wrapper): instrument awssdk-autoconfigure interceptor [TEMP]" This reverts commit ade4b80b9469c85977552863d5cb21412cce4648. --- ...configuredTracingExecutionInterceptor.java | 172 ------------------ 1 file changed, 172 deletions(-) delete mode 100644 adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java diff --git a/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java b/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java deleted file mode 100644 index a048a5edc..000000000 --- a/adot/java/awssdk-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AutoconfiguredTracingExecutionInterceptor.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure; - -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; -import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Optional; -import org.reactivestreams.Publisher; -import software.amazon.awssdk.core.SdkRequest; -import software.amazon.awssdk.core.SdkResponse; -import software.amazon.awssdk.core.async.AsyncRequestBody; -import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.http.SdkHttpResponse; - -/** - * A {@link ExecutionInterceptor} for use as an SPI by the AWS SDK to automatically trace all - * requests. - * - *

NOTE: This copy carries temporary [ADOT-DEBUG] diagnostics to localize why AWS SDK calls are - * not traced in wrapper mode under OTel Collector v0.151.0 (PROMET-11975). Remove before release. - */ -public class AutoconfiguredTracingExecutionInterceptor implements ExecutionInterceptor { - - static { - // Prints iff the AWS SDK reads the global interceptors SPI file and loads this class at all. - System.out.println( - "[ADOT-DEBUG] AutoconfiguredTracingExecutionInterceptor class loaded (SPI registration hit)"); - } - - private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.aws-sdk.experimental-span-attributes", false); - - private final ExecutionInterceptor delegate; - - public AutoconfiguredTracingExecutionInterceptor() { - OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); - // Prints what OpenTelemetry the delegate captured at construction time. A Noop/Default - // TracerProvider here means traces will be silently dropped even though metrics work. - System.out.println( - "[ADOT-DEBUG] interceptor constructed; GlobalOpenTelemetry=" - + openTelemetry.getClass().getName() - + " tracerProvider=" - + openTelemetry.getTracerProvider().getClass().getName()); - this.delegate = - AwsSdkTelemetry.builder(openTelemetry) - .setCaptureExperimentalSpanAttributes(CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) - .build() - .createExecutionInterceptor(); - } - - @Override - public void beforeExecution( - Context.BeforeExecution context, ExecutionAttributes executionAttributes) { - // Prints iff the interceptor is actually attached to the SDK client and invoked per call. - System.out.println("[ADOT-DEBUG] beforeExecution fired for an AWS SDK request"); - delegate.beforeExecution(context, executionAttributes); - } - - @Override - public SdkRequest modifyRequest( - Context.ModifyRequest context, ExecutionAttributes executionAttributes) { - return delegate.modifyRequest(context, executionAttributes); - } - - @Override - public void beforeMarshalling( - Context.BeforeMarshalling context, ExecutionAttributes executionAttributes) { - delegate.beforeMarshalling(context, executionAttributes); - } - - @Override - public void afterMarshalling( - Context.AfterMarshalling context, ExecutionAttributes executionAttributes) { - delegate.afterMarshalling(context, executionAttributes); - } - - @Override - public SdkHttpRequest modifyHttpRequest( - Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { - return delegate.modifyHttpRequest(context, executionAttributes); - } - - @Override - public Optional modifyHttpContent( - Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { - return delegate.modifyHttpContent(context, executionAttributes); - } - - @Override - public Optional modifyAsyncHttpContent( - Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { - return delegate.modifyAsyncHttpContent(context, executionAttributes); - } - - @Override - public void beforeTransmission( - Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { - delegate.beforeTransmission(context, executionAttributes); - } - - @Override - public void afterTransmission( - Context.AfterTransmission context, ExecutionAttributes executionAttributes) { - delegate.afterTransmission(context, executionAttributes); - } - - @Override - public SdkHttpResponse modifyHttpResponse( - Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { - return delegate.modifyHttpResponse(context, executionAttributes); - } - - @Override - public Optional> modifyAsyncHttpResponseContent( - Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { - return delegate.modifyAsyncHttpResponseContent(context, executionAttributes); - } - - @Override - public Optional modifyHttpResponseContent( - Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { - return delegate.modifyHttpResponseContent(context, executionAttributes); - } - - @Override - public void beforeUnmarshalling( - Context.BeforeUnmarshalling context, ExecutionAttributes executionAttributes) { - delegate.beforeUnmarshalling(context, executionAttributes); - } - - @Override - public void afterUnmarshalling( - Context.AfterUnmarshalling context, ExecutionAttributes executionAttributes) { - delegate.afterUnmarshalling(context, executionAttributes); - } - - @Override - public SdkResponse modifyResponse( - Context.ModifyResponse context, ExecutionAttributes executionAttributes) { - return delegate.modifyResponse(context, executionAttributes); - } - - @Override - public void afterExecution( - Context.AfterExecution context, ExecutionAttributes executionAttributes) { - delegate.afterExecution(context, executionAttributes); - } - - @Override - public Throwable modifyException( - Context.FailedExecution context, ExecutionAttributes executionAttributes) { - return delegate.modifyException(context, executionAttributes); - } - - @Override - public void onExecutionFailure( - Context.FailedExecution context, ExecutionAttributes executionAttributes) { - delegate.onExecutionFailure(context, executionAttributes); - } -}