When to Use the ADOT Lambda Layer
The ADOT Lambda Layer is the recommended Lambda ingestion path when your function runtime supports the OpenTelemetry SDK. It is a good fit when you want to:
- Send logs and traces from AWS Lambda directly to Bronto via OTLP, without going through CloudWatch
- Avoid CloudWatch ingestion fees on Lambda log volume
- Use the same
service.name / service.namespace routing across Lambda, ECS, and EKS workloads
The layer captures logs emitted through the OpenTelemetry logging API in your function code (for example, via the OTel SDK or a bridged framework logger). Lambda’s automatic stdout / stderr capture still goes to CloudWatch — to also ship those, use the CloudWatch Log Forwarder alongside the layer, or route your application logger through OTel.
Supported AWS Services
The ADOT Lambda Layer is Lambda-specific:
| Service | Data types |
|---|
| AWS Lambda | Function logs (via OTel SDK) and traces (auto-instrumented via the layer) |
Supported runtimes are listed in the ADOT Lambda documentation — currently Node.js, Python, Java, .NET, and Go. For runtimes without OTel SDK support (Ruby, custom runtimes), use the CloudWatch Log Forwarder. For non-Lambda compute, see ADOT — ECS / EKS or the overview.
What is the ADOT Lambda Layer?
The ADOT Lambda Layer is an AWS Lambda Layer that wraps your function with an embedded OpenTelemetry Collector. It auto-instruments your function’s runtime and exports logs and traces to any OTLP-compatible backend — including Bronto — without requiring code changes beyond adding the layer and setting environment variables.
Bronto OTLP Endpoints
| Region | Logs Endpoint | Traces Endpoint |
|---|
| EU | https://ingestion.eu.bronto.io/v1/logs | https://ingestion.eu.bronto.io/v1/traces |
| US | https://ingestion.us.bronto.io/v1/logs | https://ingestion.us.bronto.io/v1/traces |
The /v1/logs and /v1/traces endpoints accept OTLP protobuf only. The embedded OTel Collector inside the ADOT Lambda Layer handles protobuf serialisation automatically. Do not attempt to POST plain JSON or HTTP requests directly to these paths.
All requests require the header:
x-bronto-api-key: <YOUR_API_KEY>
See API Keys for how to generate a key.
Setup
Step 1 — Add the ADOT Lambda Layer
Add the ADOT managed Lambda Layer to your function. Layer ARNs are region- and architecture-specific. Find the latest ARN for your runtime in the official ADOT Lambda Layer documentation.
Via AWS CLI:
aws lambda update-function-configuration \
--function-name <YOUR_FUNCTION_NAME> \
--layers <ADOT_LAYER_ARN>
Via Terraform:
resource "aws_lambda_function" "example" {
# ... other config ...
layers = ["<ADOT_LAYER_ARN>"]
}
Set the OPENTELEMETRY_COLLECTOR_CONFIG_URI environment variable to point to a collector config stored in S3 or SSM Parameter Store, or use inline configuration.
Minimal collector config:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
processors:
batch:
exporters:
otlphttp/bronto:
logs_endpoint: "https://ingestion.<REGION>.bronto.io/v1/logs"
traces_endpoint: "https://ingestion.<REGION>.bronto.io/v1/traces"
compression: none
headers:
x-bronto-api-key: <YOUR_API_KEY>
service:
pipelines:
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp/bronto]
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp/bronto]
Step 3 — Set environment variables on your Lambda function
| Variable | Value |
|---|
OPENTELEMETRY_COLLECTOR_CONFIG_URI | S3 URI or SSM path to your collector config |
AWS_LAMBDA_EXEC_WRAPPER | /opt/otel-handler (or runtime-specific wrapper — see ADOT docs) |
Step 4 — Instrument your application code
Add the OTel SDK for your runtime and configure it to export to the local collector on localhost:4317. For per-language setup instructions, see the OpenTelemetry SDK guides.
Data Organization
The Lambda Layer uses OpenTelemetry resource attributes for routing. Bronto maps service.name to a Dataset and service.namespace to a Collection — see Data Organization for how datasets, collections, and tags work.
Set these via Lambda environment variables — the OTel SDK reads them automatically:
| Variable | Maps to |
|---|
OTEL_SERVICE_NAME | Dataset (service.name) |
OTEL_RESOURCE_ATTRIBUTES | Additional attributes — set service.namespace=<YOUR_COLLECTION_NAME> here |
You can also override routing in the collector config using HTTP headers on the exporter:
| Header | Description |
|---|
x-bronto-dataset | Overrides service.name |
x-bronto-collection | Overrides service.namespace |
x-bronto-tags | Comma-separated tags to attach to events |
exporters:
otlphttp/bronto:
traces_endpoint: "https://ingestion.<REGION>.bronto.io/v1/traces"
headers:
x-bronto-api-key: <YOUR_API_KEY>
x-bronto-dataset: <YOUR_DATASET_NAME>
x-bronto-collection: <YOUR_COLLECTION_NAME>
x-bronto-tags: env=prod,function=<FUNCTION_NAME>
Cost Notes
- The ADOT Lambda Layer itself is free.
- Logs and traces sent through the layer bypass CloudWatch entirely — no CloudWatch ingestion fees.
- Lambda’s automatic
stdout / stderr capture still writes to CloudWatch by default. To stop paying for that, route your application logger through the OTel SDK; to keep both paths, add the CloudWatch Log Forwarder alongside the layer.
For assistance, contact support@bronto.io.