/

Tracer

Core utility


Tracer is an opinionated thin wrapper for AWS X-Ray Python SDK.

Tracer showcase

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

Initialization

Your AWS Lambda function must have permission to send traces to AWS X-Ray - Here is an example using AWS Serverless Application Model (SAM)

template.yaml
Resources:
    HelloWorldFunction:
        Type: AWS::Serverless::Function
        Properties:
        ...
        Runtime: python3.8
        Tracing: Active        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.

app.py
from aws_lambda_powertools import Tracer
# POWERTOOLS_SERVICE_NAME defined
tracer = Tracer()
# Explicit definition
tracer = Tracer(service="booking")

Lambda handler

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
lambda_handler.py
from aws_lambda_powertools import Tracer
tracer = Tracer()

@tracer.capture_lambda_handlerdef handler(event, context):
    charge_id = event.get('charge_id')
    payment = collect_payment(charge_id)
    ...

Annotations

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.

app.py
from aws_lambda_powertools import Tracer
tracer = Tracer()

@tracer.capture_lambda_handler
def handler(event, context):
    ...
    tracer.put_annotation(key="PaymentStatus", value="SUCCESS")

Metadata

Metadata are non-indexed values that can add additional context for an operation.

You can add metadata using put_metadata method from Tracer.

app.py
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)

Synchronous functions

You can trace a synchronous function using the capture_method.

app.py
@tracer.capture_method
def collect_payment(charge_id):
    ret = requests.post(PAYMENT_ENDPOINT) # logic
    tracer.put_annotation("PAYMENT_STATUS", "SUCCESS") # custom annotation
    return ret
...

Asynchronous functions

We do not support async Lambda handler - Lambda handler itself must be synchronous

You can trace an asynchronous function using the capture_method. The decorator will detect whether your function is asynchronous, and adapt its behaviour accordingly.

lambda_handler_with_async_code.py
import asyncio
from aws_lambda_powertools import Tracer
tracer = Tracer()

@tracer.capture_methodasync def collect_payment():    ...
@tracer.capture_lambda_handler
def handler(evt, ctx):    asyncio.run(collect_payment())

Tracing aiohttp requests

This snippet assumes you have aiohttp as a dependency

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.

app.py
import asyncio
import aiohttp

from aws_lambda_powertools import Tracer
from aws_lambda_powertools.tracing import aiohttp_trace_configtracer = Tracer()

async def aiohttp_task():
    async with aiohttp.ClientSession(trace_configs=[aiohttp_trace_config()]) as session:        async with session.get("https://httpbin.org/json") as resp:
            resp = await resp.json()
            return resp

Escape hatch mechanism

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.

Concurrent asynchronous functions


A safe workaround mechanism is to use in_subsegment_async available via Tracer escape hatch (tracer.provider).

lambda_handler_with_concurret_async_code_workaround.py
import asyncio

from aws_lambda_powertools import Tracer
tracer = Tracer()

async def another_async_task():
    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")        ...
async def another_async_task_2():
    ...

@tracer.capture_method
async def collect_payment(charge_id):
    asyncio.gather(another_async_task(), another_async_task_2())    ...

Reusing Tracer across your code

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.

lambda_handler.py
# 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)
...
another_file.py
from aws_lambda_powertools import Tracer
# new instance using existing configuration with auto patching overridentracer = Tracer(auto_patch=False)

Testing your code

You can safely disable Tracer when unit testing your code using POWERTOOLS_TRACE_DISABLED environment variable.

pytest_disable_tracing.sh
POWERTOOLS_TRACE_DISABLED=1 python -m pytest

Tips

  • 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
Edit on GitHub