Tracer
Tracer is an opinionated thin wrapper for AWS X-Ray SDK for Node.js.
Key features¶
- Auto-capturing cold start and service name as annotations, and responses or full exceptions as metadata.
- Automatically tracing HTTP(S) clients including
fetch
and generating segments for each request. - Supporting tracing functions via decorators, middleware, and manual instrumentation.
- Supporting tracing AWS SDK v2 and v3 via AWS X-Ray SDK for Node.js.
- Auto-disable tracing when not running in the Lambda environment.
Getting started¶
Tracer relies on AWS X-Ray SDK over OpenTelemetry Distro (ADOT) for optimal cold start (lower latency).
Installation¶
Install the library in your project:
1 |
|
Usage¶
The Tracer
utility must always be instantiated outside of the Lambda handler. In doing this, subsequent invocations processed by the same instance of your function can reuse these resources. This saves cost by reducing function run time. In addition, Tracer
can track cold start and annotate the traces accordingly.
1 2 3 4 5 6 7 |
|
Using with ESM?¶
Tracer relies on the AWS X-Ray SDK for Node.js, which is distributed as a CommonJS module and uses require
.
To use it in an ESM project, you can instruct your bundler to use the require
syntax for specific dependencies while using ESM for everything else. This is commonly known as polyfill.
Code snippets for AWS CDK and AWS SAM CLI with esbuild
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
esbuild
will include this arbitrary code at the top of your bundle to maximize CommonJS compatibility (require
keyword).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
esbuild
will include this arbitrary code at the top of your bundle to maximize CommonJS compatibility (require
keyword).
Utility settings¶
The library has three optional settings. You can set them as environment variables, or pass them in the constructor:
Setting | Description | Environment variable | Default | Allowed Values | Example | Constructor parameter |
---|---|---|---|---|---|---|
Service name | Sets an annotation with the name of the service across all traces | POWERTOOLS_SERVICE_NAME |
service_undefined |
Any string | serverlessAirline |
serviceName |
Tracing enabled | Enables or disables tracing. | POWERTOOLS_TRACE_ENABLED |
true |
true or false |
false |
enabled |
Capture HTTPs Requests | Defines whether HTTPs requests will be traced or not | POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS |
true |
true or false |
false |
captureHTTPsRequests |
Capture Response | Defines whether functions responses are serialized as metadata | POWERTOOLS_TRACER_CAPTURE_RESPONSE |
true |
true or false |
false |
captureResult |
Capture Errors | Defines whether functions errors are serialized as metadata | POWERTOOLS_TRACER_CAPTURE_ERROR |
true |
true or false |
false |
N/A |
Note
Before you use this utility, your AWS Lambda function must have Active Tracing enabled as well as have permissions to send traces to AWS X-Ray
Example using AWS Serverless Application Model (SAM)¶
The Tracer
utility is instantiated outside of the Lambda handler. In doing this, the same instance can be used across multiple invocations inside the same execution environment. This allows Tracer
to be aware of things like whether or not a given invocation had a cold start or not.
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 |
|
Lambda handler¶
You can quickly start by importing the Tracer
class, initialize it outside the Lambda handler, and instrument your function.
A note about Middy
We guarantee support for Middy.js v4.x
through v6.x
versions.
Check their docs to learn more about Middy and its middleware stack as well as best practices when working with Powertools.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Note
The class method decorators in this project follow the experimental implementation enabled via the experimentalDecorators
compiler option in TypeScript.
Additionally, they are implemented to decorate async methods. When decorating a synchronous one, the decorator replaces its implementation with an async one causing the caller to have to await
the now decorated method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
- Binding your handler method allows your handler to access
this
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
When using the captureLambdaHandler
decorator or middleware, Tracer performs these additional tasks to ease operations:
- Handles the lifecycle of the subsegment
- Creates a
ColdStart
annotation to easily filter traces that have had an initialization overhead - Creates a
Service
annotation to easily filter traces that have a specific service name - Captures any response, or full exceptions generated by the handler, and include them as tracing metadata
Annotations & Metadata¶
Annotations are key-values associated with traces and indexed by AWS X-Ray. You can use them to filter traces and to create Trace Groups to slice and dice your transactions.
Metadata are key-values also associated with traces but not indexed by AWS X-Ray. You can use them to add additional context for an operation using any native object.
You can add annotations using putAnnotation
method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
- When Lambda starts an invocation the X-Ray SDk creates a segment called
facade
. This segment cannot be annotated or modified by your code, so you need to create a new subsegment. This is done automatically by Tracer when using the decorator or middleware patterns - To correctly trace the current and subsequent invocations you need to restore the original segment, this is done automatically by Tracer when using the decorator or middleware patterns.
You can add metadata using putMetadata
method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
- When Lambda starts an invocation the X-Ray SDk creates a segment called
facade
. This segment cannot be modified by your code, so you need to create a new subsegment. This is done automatically by Tracer when using the decorator or middleware patterns - To correctly trace the current and subsequent invocations you need to restore the original segment, this is done automatically by Tracer when using the decorator or middleware patterns.
Methods¶
You can trace other class methods using the captureMethod
decorator or any arbitrary asynchronous function using manual instrumentation.
Note
The class method decorators in this project follow the experimental implementation enabled via the experimentalDecorators
compiler option in TypeScript.
Additionally, they are implemented to decorate async methods. When decorating a synchronous one, the decorator replaces its implementation with an async one causing the caller to have to await
the now decorated method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
- You can set a custom name for the subsegment by passing
subSegmentName
to the decorator, like:@tracer.captureMethod({ subSegmentName: '### myCustomMethod' })
. - Binding your handler method allows your handler to access
this
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
Patching AWS SDK clients¶
Tracer can patch any AWS SDK clients and create traces when your application makes calls to AWS services.
Info
The following snippet assumes you are using the AWS SDK v3 for JavaScript
You can patch any AWS SDK clients by calling the captureAWSv3Client
method:
1 2 3 4 5 6 7 8 |
|
Info
The following two snippets assume you are using the AWS SDK v2 for JavaScript
You can patch all AWS SDK v2 clients by calling the captureAWS
method:
1 2 3 4 5 6 7 8 9 10 11 |
|
If you're looking to shave a few microseconds, or milliseconds depending on your function memory configuration, you can patch only specific AWS SDK v2 clients using captureAWSClient
:
1 2 3 4 5 6 7 8 |
|
Tracing HTTP requests¶
When your function makes outgoing requests to APIs, Tracer automatically traces those calls and adds the API to the service graph as a downstream service.
You can opt-out from this feature by setting the POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS=false
environment variable or by passing the captureHTTPsRequests: false
option to the Tracer
constructor.
Info
The following snippet shows how to trace fetch
requests, but you can use any HTTP client library built on top it, or on http, and https.
Support to 3rd party HTTP clients is provided on a best effort basis.
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Advanced¶
Disabling response auto-capture¶
Use POWERTOOLS_TRACER_CAPTURE_RESPONSE=false
environment variable to instruct Tracer not to serialize function responses as metadata.
This is commonly useful in three scenarios
- You might return sensitive information you don't want it to be added to your traces
- You might manipulate streaming objects that can be read only once; this prevents subsequent calls from being empty
- You might return more than 64K of data e.g.,
message too long
error
Alternatively, use the captureResponse: false
option in both tracer.captureLambdaHandler()
and tracer.captureMethod()
decorators, or use the same option in the Middy captureLambdaHandler
middleware to instruct Tracer not to serialize function responses as metadata.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Disabling errors auto-capture¶
Use POWERTOOLS_TRACER_CAPTURE_ERROR=false
environment variable to instruct Tracer not to serialize errors as metadata.
Commonly useful in one scenario
- You might return sensitive information from errors, stack traces you might not control
Access AWS X-Ray Root Trace ID¶
Tracer exposes a getRootXrayTraceId()
method that allows you to retrieve the AWS X-Ray Root Trace ID corresponds to the current function execution.
This is commonly useful in two scenarios
- By including the root trace id in your response, consumers can use it to correlate requests
- You might want to surface the root trace id to your end users so that they can reference it while contacting customer service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Escape hatch mechanism¶
You can use tracer.provider
attribute to access a subset of the methods provided by the AWS X-Ray SDK.
This is useful when you need a feature available in X-Ray that is not available in the Tracer utility, for example SQL queries tracing, or a custom logger.
1 2 3 4 5 6 7 |
|
If you need to access a method that is not available you can import it directly from the AWS X-Ray SDK for Node.js. Compatibility with the Tracer utility is not guaranteed.
Testing your code¶
Tracer is disabled by default when not running in the AWS Lambda environment - This means no code changes or environment variables to be set.
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 currently open subsegment. If you want them in a specific subsegment, create one via the escape hatch mechanism