OpenTelemetry AWS Lambda Instrumentation
This library provides automatic instrumentation for AWS Lambda functions, enabling OpenTelemetry tracing and metrics for incoming requests and handler execution. It is part of the `opentelemetry-python-contrib` project, following its beta release cadence (currently `0.62b0`) which aligns with the overall OpenTelemetry Python project. It helps integrate Lambda functions into distributed tracing workflows.
Warnings
- gotcha This library is currently in beta (`0.x.xb0` versioning). APIs and behavior may change significantly between minor versions without strict adherence to semantic versioning. Always pin exact versions.
- gotcha For production AWS Lambda environments, rely on AWS Distro for OpenTelemetry (ADOT) Lambda Layers or custom Docker images. Simply `pip install`ing this package is not sufficient for full instrumentation and exporting in a typical Lambda deployment, as it requires OpenTelemetry SDK setup (providers, exporters).
- gotcha While this instrumentation works with the OpenTelemetry Python SDK, it also depends on `aws-xray-sdk` and `opentelemetry-sdk-extension-aws`. Ensure there are no conflicts or unexpected behaviors if `aws-xray-sdk` is directly used elsewhere in your application, as OpenTelemetry generally aims to replace direct X-Ray SDK usage.
- gotcha Instrumentation adds overhead, which can impact Lambda cold start times and overall execution duration. Monitor your Lambda performance metrics (duration, memory usage) after deploying OpenTelemetry.
Install
-
pip install opentelemetry-instrumentation-aws-lambda -
pip install opentelemetry-distro aws-xray-sdk
Imports
- configure_lambda_handler
from opentelemetry.instrumentation.aws_lambda import configure_lambda_handler
Quickstart
import os
from opentelemetry.instrumentation.aws_lambda import configure_lambda_handler
from opentelemetry import trace
# For production in AWS Lambda, typically an ADOT Layer handles OTel SDK setup.
# For local testing, you might set up a basic console exporter (uncomment below):
# from opentelemetry.sdk.resources import Resource
# from opentelemetry.sdk.trace import TracerProvider
# from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# resource = Resource.create({"service.name": os.environ.get("OTEL_SERVICE_NAME", "my-lambda-service")})
# trace.set_tracer_provider(TracerProvider(resource=resource))
# trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
@configure_lambda_handler
def my_lambda_handler(event, context):
"""
An example AWS Lambda handler.
The `@configure_lambda_handler` decorator automatically instruments
incoming requests, creating a span for the Lambda invocation.
"""
current_span = trace.get_current_span()
current_span.set_attribute("lambda.event_keys", str(list(event.keys())))
print(f"Processing event with keys: {list(event.keys())}")
# Simulate some work
import time
time.sleep(0.05)
return {
'statusCode': 200,
'body': 'Handler processed successfully!'
}
# To run locally for testing (optional, not part of typical Lambda deployment):
if __name__ == '__main__':
mock_event = {"message": "hello world", "data": 123}
mock_context = type('Context', (object,), {
'aws_request_id': 'local-test-id',
'function_name': 'test-func',
'invoked_function_arn': 'arn:aws:lambda:us-east-1:123456789012:function:test-func',
'memory_limit_in_mb': 128,
'get_remaining_time_in_millis': lambda: 30000,
'function_version': '$LATEST',
'log_group_name': '/aws/lambda/test-func',
'log_stream_name': '2023/10/26/[LATEST]xxxxxxxxxxxx',
'identity': None,
'client_context': None
})()
os.environ["OTEL_SERVICE_NAME"] = "my-local-lambda"
# If uncommenting SDK setup above, ensure this is also uncommented for local testing output
# from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
response = my_lambda_handler(mock_event, mock_context)
print(f"Local test response: {response}")