|
| 1 | +--- |
| 2 | +title: Tracer (OpenTelemetry) |
| 3 | +description: Core utility |
| 4 | +--- |
| 5 | + |
| 6 | +TracerOpenTelemetry is an OpenTelemetry-native tracer for AWS Lambda, providing distributed tracing with the [OpenTelemetry SDK](https://opentelemetry.io/docs/languages/python/){target="_blank" rel="nofollow"}. |
| 7 | + |
| 8 | +## Key features |
| 9 | + |
| 10 | +* Two modes: **auto** (ADOT Layer) and **manual** (custom TracerProvider) |
| 11 | +* Auto capture cold start as span attribute |
| 12 | +* Auto-disable when `POWERTOOLS_TRACE_DISABLED` is set |
| 13 | +* Support tracing async methods, generators, and context managers |
| 14 | +* SQS context propagation helpers |
| 15 | + |
| 16 | +## Getting started |
| 17 | + |
| 18 | +???+ tip |
| 19 | + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. |
| 20 | + |
| 21 | +### Install |
| 22 | + |
| 23 | +!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" |
| 24 | + |
| 25 | +Add `aws-lambda-powertools[otel]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. This will ensure you have the required dependencies before using TracerOpenTelemetry. |
| 26 | + |
| 27 | +### Auto mode (ADOT Layer) |
| 28 | + |
| 29 | +Use **auto mode** when deploying with the [AWS Distro for OpenTelemetry (ADOT) Lambda Layer](https://aws-otel.github.io/docs/getting-started/lambda){target="_blank" rel="nofollow"}. The ADOT Layer configures a global TracerProvider that exports spans automatically. |
| 30 | + |
| 31 | +```python hl_lines="1 3 7" title="Auto mode with ADOT Layer" |
| 32 | +--8<-- "examples/tracer_otel/src/getting_started_auto_mode.py" |
| 33 | +``` |
| 34 | + |
| 35 | +`capture_lambda_handler` performs these additional tasks to ease operations: |
| 36 | + |
| 37 | +* Adds a `faas.coldstart` attribute to easily filter traces that have had an initialization overhead |
| 38 | +* Adds a `service.name` attribute if `service` parameter or `POWERTOOLS_SERVICE_NAME` is set |
| 39 | +* Captures any response, or full exceptions generated by the handler, and includes as span attributes |
| 40 | + |
| 41 | +### Manual mode |
| 42 | + |
| 43 | +Use **manual mode** when you want full control over the TracerProvider configuration, or when not using the ADOT Layer. |
| 44 | + |
| 45 | +```python hl_lines="1-3 8-9 11" title="Manual mode with custom TracerProvider" |
| 46 | +--8<-- "examples/tracer_otel/src/getting_started_manual_mode.py" |
| 47 | +``` |
| 48 | + |
| 49 | +If you don't provide a `tracer_provider`, a default TracerProvider is created that respects OpenTelemetry SDK environment variables. |
| 50 | + |
| 51 | +### Synchronous functions |
| 52 | + |
| 53 | +You can trace synchronous functions using the `capture_method` decorator. |
| 54 | + |
| 55 | +```python hl_lines="7-8 12" title="Tracing an arbitrary function with capture_method" |
| 56 | +--8<-- "examples/tracer_otel/src/capture_method.py" |
| 57 | +``` |
| 58 | + |
| 59 | +### Asynchronous functions |
| 60 | + |
| 61 | +You can trace asynchronous functions using `capture_method`. |
| 62 | + |
| 63 | +```python hl_lines="8-10" title="Tracing async functions" |
| 64 | +--8<-- "examples/tracer_otel/src/capture_method_async.py" |
| 65 | +``` |
| 66 | + |
| 67 | +### Creating custom spans |
| 68 | + |
| 69 | +Use `add_span` context manager to create child spans with custom attributes: |
| 70 | + |
| 71 | +```python hl_lines="8-11" title="Creating custom spans with add_span" |
| 72 | +--8<-- "examples/tracer_otel/src/add_span.py" |
| 73 | +``` |
| 74 | + |
| 75 | +### Environment variables |
| 76 | + |
| 77 | +The following environment variables are available to configure TracerOpenTelemetry at a global scope: |
| 78 | + |
| 79 | +| Setting | Description | Environment variable | Default | |
| 80 | +|-----------------------|--------------------------------------------------|--------------------------------------|---------------| |
| 81 | +| **Disable Tracing** | Explicitly disables all tracing. | `POWERTOOLS_TRACE_DISABLED` | `false` | |
| 82 | +| **Service Name** | Sets the service name for spans. | `POWERTOOLS_SERVICE_NAME` | Function name | |
| 83 | +| **Response Capture** | Captures Lambda or method return as attribute. | `POWERTOOLS_TRACER_CAPTURE_RESPONSE` | `true` | |
| 84 | +| **Exception Capture** | Records exceptions in spans. | `POWERTOOLS_TRACER_CAPTURE_ERROR` | `true` | |
| 85 | + |
| 86 | +## Advanced |
| 87 | + |
| 88 | +### Disabling response auto-capture |
| 89 | + |
| 90 | +Use **`capture_response=False`** parameter in both `capture_lambda_handler` and `capture_method` decorators to instruct Tracer **not** to serialize function responses as span attributes. |
| 91 | + |
| 92 | +???+ info "Info: This is useful in two common scenarios" |
| 93 | + 1. You might **return sensitive** information you don't want it to be added to your traces |
| 94 | + 2. You might return **more than 1KB** of data which exceeds span attribute limits |
| 95 | + |
| 96 | +```python hl_lines="6" title="Disabling response capture" |
| 97 | +--8<-- "examples/tracer_otel/src/disable_capture_response.py" |
| 98 | +``` |
| 99 | + |
| 100 | +### SQS context propagation |
| 101 | + |
| 102 | +Propagate trace context through SQS messages to maintain distributed traces across services. This requires two separate Lambda functions: a **producer** that sends messages and a **consumer** that processes them. |
| 103 | + |
| 104 | +The producer injects trace context into the message payload before sending to SQS. The consumer extracts this context to continue the same trace, linking both functions in your distributed trace. |
| 105 | + |
| 106 | +=== "Producer Handler" |
| 107 | + |
| 108 | + ```python hl_lines="4 15-16" title="Inject trace context before sending to SQS" |
| 109 | + --8<-- "examples/tracer_otel/src/sqs_propagation_producer.py" |
| 110 | + ``` |
| 111 | + |
| 112 | +=== "Consumer Handler" |
| 113 | + |
| 114 | + ```python hl_lines="4 16" title="Extract trace context from SQS message" |
| 115 | + --8<-- "examples/tracer_otel/src/sqs_propagation_consumer.py" |
| 116 | + ``` |
| 117 | + |
| 118 | +### Cold start detection |
| 119 | + |
| 120 | +TracerOpenTelemetry automatically adds a `faas.coldstart` attribute to the handler span: |
| 121 | + |
| 122 | +* `true` on the first invocation after a cold start |
| 123 | +* `false` on subsequent warm invocations |
| 124 | + |
| 125 | +### Accessing the current span |
| 126 | + |
| 127 | +You can use `get_current_span` method to access the current active span and add custom attributes. |
| 128 | + |
| 129 | +```python |
| 130 | +span = tracer.get_current_span() |
| 131 | +if span: |
| 132 | + span.set_attribute("custom_key", "custom_value") |
| 133 | +``` |
| 134 | + |
| 135 | +## Testing your code |
| 136 | + |
| 137 | +TracerOpenTelemetry is disabled by default when `POWERTOOLS_TRACE_DISABLED` environment variable is set to `true`. This means you can disable tracing during tests without code changes. |
| 138 | + |
| 139 | +## Comparison with X-Ray Tracer |
| 140 | + |
| 141 | +| Feature | Tracer (X-Ray) | TracerOpenTelemetry | |
| 142 | +|---------|---------------|---------------------| |
| 143 | +| Backend | AWS X-Ray | Any OTel-compatible backend | |
| 144 | +| SDK | AWS X-Ray SDK | OpenTelemetry SDK | |
| 145 | +| Auto-patching | Yes (boto3, requests, etc.) | Via OTel instrumentation packages | |
| 146 | +| Annotations | `put_annotation()` | `span.set_attribute()` | |
| 147 | +| Metadata | `put_metadata()` | `span.set_attribute()` | |
| 148 | +| Cold start | Annotation | Span attribute | |
| 149 | +| Context propagation | X-Ray header | W3C Trace Context | |
| 150 | + |
| 151 | +## API Reference |
| 152 | + |
| 153 | +### TracerOpenTelemetry |
| 154 | + |
| 155 | +```python |
| 156 | +TracerOpenTelemetry( |
| 157 | + mode: Literal["auto", "manual"] = "manual", |
| 158 | + service: str | None = None, |
| 159 | + tracer_provider: TracerProvider | None = None, |
| 160 | + disabled: bool | None = None, |
| 161 | +) |
| 162 | +``` |
| 163 | + |
| 164 | +**Parameters:** |
| 165 | + |
| 166 | +| Parameter | Type | Description | |
| 167 | +|-----------|------|-------------| |
| 168 | +| `mode` | `"auto"` or `"manual"` | Instrumentation mode | |
| 169 | +| `service` | `str` | Service name for spans | |
| 170 | +| `tracer_provider` | `TracerProvider` | Custom provider (manual mode only) | |
| 171 | +| `disabled` | `bool` | Disable tracing | |
| 172 | + |
| 173 | +**Methods:** |
| 174 | + |
| 175 | +| Method | Description | |
| 176 | +|--------|-------------| |
| 177 | +| `capture_lambda_handler` | Decorator for Lambda handlers | |
| 178 | +| `capture_method` | Decorator for methods | |
| 179 | +| `add_span(name)` | Context manager for custom spans | |
| 180 | +| `get_current_span()` | Get the current active span | |
| 181 | + |
| 182 | +### Context propagation |
| 183 | + |
| 184 | +| Function | Description | |
| 185 | +|----------|-------------| |
| 186 | +| `inject_trace_context(carrier)` | Inject trace context into a dict | |
| 187 | +| `create_span_from_context(name, carrier)` | Create span from extracted context | |
0 commit comments