title | description |
---|---|
Tracer |
Core utility |
import Note from "../../src/components/Note"
Tracer is an opinionated thin wrapper for AWS X-Ray Python SDK.
Key features
- Capture cold start as annotation, and responses as well as full exceptions as metadata
- Run functions locally with SAM CLI without code change to disable tracing
- Explicitly disable tracing via env var
POWERTOOLS_TRACE_DISABLED="true"
- Support tracing async methods
- Auto patch supported modules, or a tuple of explicit modules supported by AWS X-Ray
Your AWS Lambda function must have permission to send traces to AWS X-Ray - Here is an example using AWS Serverless Application Model (SAM)
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
...
Runtime: python3.8
Tracing: Active # highlight-line
Environment:
Variables:
POWERTOOLS_SERVICE_NAME: example
You can either explicitly pass using service
param or via POWERTOOLS_SERVICE_NAME
environment variable. The service name is utilized for exceptions, metadata, and namespace data.
from aws_lambda_powertools import Tracer
# POWERTOOLS_SERVICE_NAME defined
tracer = Tracer() # highlight-line
# Explicit definition
tracer = Tracer(service="booking")
You can trace your Lambda function handler via capture_lambda_handler
.
When using this decorator, Tracer performs these additional tasks to ease operations:
- Creates a
ColdStart
annotation to easily filter traces that have had an initialization overhead - Adds any response, or full exceptions generated by the handler as metadata
from aws_lambda_powertools import Tracer
tracer = Tracer()
@tracer.capture_lambda_handler # highlight-line
def handler(event, context):
charge_id = event.get('charge_id')
payment = collect_payment(charge_id)
...
Annotations are key-values indexed by AWS X-Ray on a per trace basis. You can use them to filter traces as well as to create Trace Groups.
You can add annotations using put_annotation
method from Tracer.
from aws_lambda_powertools import Tracer
tracer = Tracer()
@tracer.capture_lambda_handler
def handler(event, context):
...
tracer.put_annotation(key="PaymentStatus", value="SUCCESS") # highlight-line
Metadata are non-indexed values that can add additional context for an operation.
You can add metadata using put_metadata
method from Tracer.
from aws_lambda_powertools import Tracer
tracer = Tracer()
@tracer.capture_lambda_handler
def handler(event, context):
...
ret = some_logic()
tracer.put_metadata(key="payment_response", value=ret) # highlight-line
You can trace a synchronous function using the capture_method
.
@tracer.capture_method
def collect_payment(charge_id):
ret = requests.post(PAYMENT_ENDPOINT) # logic
tracer.put_annotation("PAYMENT_STATUS", "SUCCESS") # custom annotation
return ret
...
You can trace an asynchronous function using the capture_method
. The decorator will detect whether your function is asynchronous, and adapt its behaviour accordingly.
import asyncio
from aws_lambda_powertools import Tracer
tracer = Tracer()
# highlight-start
@tracer.capture_method
async def collect_payment():
...
# highlight-end
@tracer.capture_lambda_handler
def handler(evt, ctx): # highlight-line
asyncio.run(collect_payment())
You can use aiohttp_trace_config
function to create a valid aiohttp trace_config object. This is necessary since X-Ray utilizes aiohttp trace hooks to capture requests end-to-end.
import asyncio
import aiohttp
from aws_lambda_powertools import Tracer
from aws_lambda_powertools.tracing import aiohttp_trace_config # highlight-line
tracer = Tracer()
async def aiohttp_task():
async with aiohttp.ClientSession(trace_configs=[aiohttp_trace_config()]) as session: # highlight-line
async with session.get("https://httpbin.org/json") as resp:
resp = await resp.json()
return resp
You can use tracer.provider
attribute to access all methods provided by AWS X-Ray xray_recorder
object.
This is useful when you need a feature available in X-Ray that is not available in the Tracer utility, for example thread-safe, or context managers.
As of now, X-Ray SDK will raise an exception when async functions are run and traced concurrently.A safe workaround mechanism is to use in_subsegment_async
available via Tracer escape hatch (tracer.provider
).
import asyncio
from aws_lambda_powertools import Tracer
tracer = Tracer()
async def another_async_task():
# highlight-start
async with tracer.provider.in_subsegment_async("## another_async_task") as subsegment:
subsegment.put_annotation(key="key", value="value")
subsegment.put_metadata(key="key", value="value", namespace="namespace")
...
# highlight-end
async def another_async_task_2():
...
@tracer.capture_method
async def collect_payment(charge_id):
asyncio.gather(another_async_task(), another_async_task_2()) # highlight-line
...
Tracer keeps a copy of its configuration after the first initialization. This is useful for scenarios where you want to use Tracer in more than one location across your code base.
When reusing Tracer in Lambda Layers, or in multiple modules, do not setauto_patch=False
, because import order matters.
This can result in the first Tracer config being inherited by new instances, and their modules not being patched.
# handler.py
from aws_lambda_powertools import Tracer
tracer = Tracer(service="payment")
@tracer.capture_lambda_handler
def handler(event, context):
charge_id = event.get('charge_id')
payment = collect_payment(charge_id)
...
from aws_lambda_powertools import Tracer
# highlight-start
# new instance using existing configuration
tracer = Tracer(service="payment")
# highlight-end
You can safely disable Tracer when unit testing your code using POWERTOOLS_TRACE_DISABLED
environment variable.
POWERTOOLS_TRACE_DISABLED=1 python -m pytest
- Use annotations on key operations to slice and dice traces, create unique views, and create metrics from it via Trace Groups
- Use a namespace when adding metadata to group data more easily
- Annotations and metadata are added to the current subsegment opened. If you want them in a specific subsegment, use a context manager via the escape hatch mechanism