AWS Distro for OpenTelemetry
AWS Distro for OpenTelemetry Lambda Support For Go
AWS Distro for OpenTelemetry Lambda Support For Go
There is no ADOT Lambda layer with Application Signals support for Go. To trace a Go function, instrument it with the
OpenTelemetry Go SDK and the
otellambda
instrumentation, and add the ADOT Collector Lambda layer. The function sends spans to the collector, which runs as a
Lambda extension and forwards them to the Amazon CloudWatch OTLP traces endpoint.
Prerequisites
- Transaction Search enabled in CloudWatch. The OTLP traces endpoint requires it.
- A function that uses the
provided.al2023runtime, onx86_64orarm64. Go functions on theprovided.al2andgo1.xruntimes need to move toprovided.al2023; for how to build and package thebootstrapbinary, see Deploy Go Lambda functions with .zip file archives. - An execution role with the
CloudWatchLambdaApplicationSignalsExecutionRolePolicymanaged policy, which allowsxray:PutTraceSegments.
1. Instrument the function
Add the OpenTelemetry Go SDK and the Lambda instrumentation to your module:
go get github.com/aws/aws-lambda-go/lambda \ go.opentelemetry.io/otel \ go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda \ go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda/xrayconfig \ go.opentelemetry.io/contrib/propagators/aws/xray \ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttpCreate the tracer provider in main(), outside the handler, and wrap the handler with otellambda.InstrumentHandler.
xrayconfig exports spans over OTLP to the collector extension and flushes them at the end of each invocation. To trace
outgoing HTTP requests, use an otelhttp transport and pass the request context:
1package main2
3import (4 "context"5 "fmt"6 "net/http"7
8 "github.com/aws/aws-lambda-go/lambda"9 "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda"10 "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda/xrayconfig"11 "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"12 "go.opentelemetry.io/contrib/propagators/aws/xray"13 "go.opentelemetry.io/otel"14)15
16var client = http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}17
18func handler(ctx context.Context) (map[string]int, error) {19 req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://aws.amazon.com", nil)20 if err != nil {21 return nil, err22 }23 resp, err := client.Do(req)24 if err != nil {25 return nil, err26 }27 defer resp.Body.Close()28 return map[string]int{"statusCode": 200, "http_status": resp.StatusCode}, nil29}30
31func main() {32 ctx := context.Background()33 tp, err := xrayconfig.NewTracerProvider(ctx)34 if err != nil {35 fmt.Printf("error creating tracer provider: %v\n", err)36 }37 defer func(ctx context.Context) {38 if err := tp.Shutdown(ctx); err != nil {39 fmt.Printf("error shutting down tracer provider: %v\n", err)40 }41 }(ctx)42 otel.SetTracerProvider(tp)43 otel.SetTextMapPropagator(xray.Propagator{})44
45 lambda.Start(otellambda.InstrumentHandler(handler, xrayconfig.WithRecommendedOptions(tp)...))46}For other libraries, such as the AWS SDK for Go and gRPC, see OpenTelemetry Go instrumentation.
2. Configure the collector
By default, the ADOT Collector Lambda layer exports traces with the awsxray exporter. To send them to the CloudWatch OTLP
traces endpoint instead, add this collector.yaml to your deployment package:
1extensions:2 sigv4auth:3 region: ${env:AWS_REGION}4 service: xray5
6receivers:7 otlp:8 protocols:9 grpc:10 endpoint: localhost:431711 http:12 endpoint: localhost:431813
14exporters:15 otlp_http:16 compression: gzip17 traces_endpoint: https://xray.${env:AWS_REGION}.amazonaws.com/v1/traces18 auth:19 authenticator: sigv4auth20
21service:22 extensions: [sigv4auth]23 pipelines:24 traces:25 receivers: [otlp]26 exporters: [otlp_http]For other collector options, see the OpenTelemetry Lambda Collector configuration.
3. Build and deploy
Build the function as bootstrap and package it with the collector configuration. For arm64, set GOARCH=arm64.
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -tags lambda.norpc -o bootstrap .zip function.zip bootstrap collector.yamlCreate the function with the collector layer, the OPENTELEMETRY_COLLECTOR_CONFIG_URI environment variable, and a
service name:
1aws lambda create-function --function-name <function-name> \2 --runtime provided.al2023 --handler bootstrap --architectures x86_64 \3 --zip-file fileb://function.zip --role <execution-role-arn> \4 --layers arn:aws:lambda:<region>:901920570463:layer:aws-otel-collector-amd64-ver-0-156-0:4 \5 --tracing-config Mode=Active \6 --environment 'Variables={OPENTELEMETRY_COLLECTOR_CONFIG_URI=/var/task/collector.yaml,OTEL_SERVICE_NAME=<service-name>}' \7 --region <region>Set OTEL_SERVICE_NAME. Without it, the spans from the Go SDK have no service.name.
Collector layer ARNs
Lambda layers are Regional, so use the layer in the same Region as your function. Use amd64 for x86_64 functions
and arm64 for arm64 functions.
| Supported Regions | Lambda layer ARN format | Contents |
|---|---|---|
| ap-northeast-1 ap-northeast-2 ap-south-1 ap-southeast-1 ap-southeast-2 ca-central-1 eu-central-1 eu-north-1 eu-west-1 eu-west-2 eu-west-3 sa-east-1 us-east-1 us-east-2 us-west-1 us-west-2 | arn:aws:lambda:\<region>:901920570463:layer:aws-otel-collector-\<architecture>-ver-0-156-0:4 | Contains ADOT Collector v0.49.0 |
4. View your traces
Invoke the function, and then use Transaction Search in the CloudWatch console to find its spans. Each invocation has
a server span from otellambda and a client span for each outgoing request made through otelhttp, along with the
segments that Lambda creates when active tracing is on. Spans are stored in the aws/spans log group.
To remove tracing, remove the layer, the OPENTELEMETRY_COLLECTOR_CONFIG_URI variable, and the instrumentation code,
and turn off active tracing.