JSPM

  • Created
  • Published
  • Downloads 140876
  • Score
    100M100P100Q186445F
  • License MIT

The tracer package for the AWS Lambda powertools (TypeScript) library

Package Exports

  • @aws-lambda-powertools/tracer
  • @aws-lambda-powertools/tracer/lib/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@aws-lambda-powertools/tracer) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

tracer

Usage

npm run test

npm run example:hello-world
npm run example:capture-lambda-handler-response-decorator
npm run example:capture-lambda-handler-error-decorator

Getting started

// Import the library
import { Tracer } from "../src";
// When going public, it will be something like: import { Tracer } from '@aws-lambda-powertools/tracer';

// Environment variables set for the Lambda
process.env.POWERTOOLS_TRACE_ENABLED = "true";
process.env.POWERTOOLS_SERVICE_NAME = "hello-world";
process.env.POWERTOOLS_TRACER_CAPTURE_RESPONSE = "true";
process.env.POWERTOOLS_TRACER_CAPTURE_ERROR = "true";

// Instantiate the Tracer with default configuration
const tracer = new Tracer();

Capturing Lambda handler

// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {
    return new Promise((resolve, _reject) => resolve({
      foo: 'bar'
    } as unknown as TResult));
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the trace
{
    "Id": "abcdef123456abcdef123456abcdef123456",
    "Duration": 0.656,
    "LimitExceeded": false,
    "Segments": [
        {
            "Id": "1234567890abcdef0",
            "Document": {
                "id": "1234567890abcdef0",
                "name": "foo-bar-function",
                "start_time": 1638792392.764036,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638792392.957155,
                "parent_id": "abcdef01234567890",
                "aws": {
                    "account_id": "111122223333",
                    "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:foo-bar-function",
                    "resource_names": [
                        "foo-bar-function"
                    ]
                },
                "origin": "AWS::Lambda::Function",
                "subsegments": [
                    // Initialization subsegment (if any)
                    {
                        "id": "4be0933d48d5b52f",
                        "name": "Invocation",
                        "start_time": 1638792392.7642102,
                        "end_time": 1638792392.9384046,
                        "aws": {
                            "function_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
                        },
                        "subsegments": [
                            {
                                "id": "aae0c94a16d66abd",
                                "name": "## foo-bar-function",
                                "start_time": 1638792392.766,
                                "end_time": 1638792392.836,
                                "annotations": {
                                    "ColdStart": true
                                },
                                "metadata": {
                                    "hello-world": {
                                        "foo-bar-function response": {
                                            "foo": "bar"
                                        }
                                    }
                                }
                            }
                        ]
                    },
                    // Overhead subsegment (if any)
                ]
            }
        }
    ]
}

With Error

// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {
    // Some logic that throws an error
    throw Error('Some error occurred')
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the trace
{
    "Id": "abcdef123456abcdef123456abcdef123456",
    "Duration": 0.656,
    "LimitExceeded": false,
    "Segments": [
        {
            "Id": "1234567890abcdef0",
            "Document": {
                "id": "1234567890abcdef0",
                "name": "foo-bar-function",
                "start_time": 1638792392.764036,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638792392.957155,
                "parent_id": "abcdef01234567890",
                "aws": {
                    "account_id": "111122223333",
                    "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:foo-bar-function",
                    "resource_names": [
                        "foo-bar-function"
                    ]
                },
                "origin": "AWS::Lambda::Function",
                "subsegments": [
                    // Initialization subsegment (if any)
                    {
                        "id": "4be0933d48d5b52f",
                        "name": "Invocation",
                        "start_time": 1638792392.7642102,
                        "end_time": 1638792392.9384046,
                        "aws": {
                            "function_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
                        },
                        "subsegments": [
                            {
                                "id": "aae0c94a16d66abd",
                                "name": "## foo-bar-function",
                                "start_time": 1638792392.766,
                                "end_time": 1638792392.836,
                                "fault": true,
                                "cause": {
                                    "working_directory": "/var/task",
                                    "exceptions": [
                                        {
                                            "message": "Some error occurred",
                                            "type": "Error",
                                            "remote": false,
                                            "stack": [
                                                {
                                                    "path": "/var/task/index.js",
                                                    "line": 51489,
                                                    "label": "Tracer2.handler"
                                                },
                                                {
                                                    "path": "/var/task/index.js",
                                                    "line": 16372,
                                                    "label": "anonymous"
                                                },
                                                // Full stack trace
                                            ]
                                        }
                                    ]
                                }
                            }
                        ]
                    },
                    // Overhead subsegment (if any)
                ]
            }
        }
    ]
}

Adding annotation on subsegment

// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {

    tracer.putAnnotation("my-annotation", "my-value");

    return new Promise((resolve, _reject) => resolve({
      foo: 'bar'
    } as unknown as TResult));
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the trace
{
    "Id": "abcdef123456abcdef123456abcdef123456",
    "Duration": 0.656,
    "LimitExceeded": false,
    "Segments": [
        {
            "Id": "1234567890abcdef0",
            "Document": {
                "id": "1234567890abcdef0",
                "name": "foo-bar-function",
                "start_time": 1638792392.764036,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638792392.957155,
                "parent_id": "abcdef01234567890",
                "aws": {
                    "account_id": "111122223333",
                    "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:foo-bar-function",
                    "resource_names": [
                        "foo-bar-function"
                    ]
                },
                "origin": "AWS::Lambda::Function",
                "subsegments": [
                    // Initialization subsegment (if any)
                    {
                        "id": "4be0933d48d5b52f",
                        "name": "Invocation",
                        "start_time": 1638792392.7642102,
                        "end_time": 1638792392.9384046,
                        "aws": {
                            "function_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
                        },
                        "subsegments": [
                            {
                                "id": "aae0c94a16d66abd",
                                "name": "## foo-bar-function",
                                "start_time": 1638792392.766,
                                "end_time": 1638792392.836,
                                "annotations": {
                                    "ColdStart": true,
                                    "my-annotation": "my-value"
                                },
                                "metadata": {
                                    "hello-world": {
                                        "foo-bar-function response": {
                                            "foo": "bar"
                                        }
                                    }
                                }
                            }
                        ]
                    },
                    // Overhead subsegment (if any)
                ]
            }
        }
    ]
}

Adding metadata to subsegment

// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {

    tracer.putMetadata("my-metadata", 1234);
    tracer.putMetadata("my-scoped-metadata", 1234, "my-namespace");

    return new Promise((resolve, _reject) => resolve({
      foo: 'bar'
    } as unknown as TResult));
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the trace
{
    "Id": "abcdef123456abcdef123456abcdef123456",
    "Duration": 0.656,
    "LimitExceeded": false,
    "Segments": [
        {
            "Id": "1234567890abcdef0",
            "Document": {
                "id": "1234567890abcdef0",
                "name": "foo-bar-function",
                "start_time": 1638792392.764036,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638792392.957155,
                "parent_id": "abcdef01234567890",
                "aws": {
                    "account_id": "111122223333",
                    "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:foo-bar-function",
                    "resource_names": [
                        "foo-bar-function"
                    ]
                },
                "origin": "AWS::Lambda::Function",
                "subsegments": [
                    // Initialization subsegment (if any)
                    {
                        "id": "4be0933d48d5b52f",
                        "name": "Invocation",
                        "start_time": 1638792392.7642102,
                        "end_time": 1638792392.9384046,
                        "aws": {
                            "function_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
                        },
                        "subsegments": [
                            {
                                "id": "aae0c94a16d66abd",
                                "name": "## foo-bar-function",
                                "start_time": 1638792392.766,
                                "end_time": 1638792392.836,
                                "annotations": {
                                    "ColdStart": true
                                },
                                "metadata": {
                                    "hello-world": {
                                        "foo-bar-function response": {
                                            "foo": "bar"
                                        },
                                        "my-metadata": 1234
                                    },
                                    "my-namespace": {
                                        "my-scoped-metadata": 1234
                                    }
                                }
                            }
                        ]
                    },
                    // Overhead subsegment (if any)
                ]
            }
        }
    ]
}

Capturing other methods

// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();

class Lambda implements LambdaInterface {
  @tracer.captureMethod()
  public async dummyMethod(some: string): Promise<string> {
      // Some async logic
      return new Promise((resolve, _reject) => setTimeout(() => resolve(some), 3000));
  }

  public async handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): Promise<TResult> {
    const result = await this.dummyMethod('bar');
    
    return new Promise((resolve, _reject) => resolve({
      foo: result
    } as unknown as TResult));
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the trace
{
    "Id": "abcdef123456abcdef123456abcdef123456",
    "Duration": 0.656,
    "LimitExceeded": false,
    "Segments": [
        {
            "Id": "1234567890abcdef0",
            "Document": {
                "id": "1234567890abcdef0",
                "name": "foo-bar-function",
                "start_time": 1638792392.764036,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638792392.957155,
                "parent_id": "abcdef01234567890",
                "aws": {
                    "account_id": "111122223333",
                    "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:foo-bar-function",
                    "resource_names": [
                        "foo-bar-function"
                    ]
                },
                "origin": "AWS::Lambda::Function",
                "subsegments": [
                    // Initialization subsegment (if any)
                    {
                        "id": "4be0933d48d5b52f",
                        "name": "Invocation",
                        "start_time": 1638792392.7642102,
                        "end_time": 1638792392.9384046,
                        "aws": {
                            "function_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
                        },
                        "subsegments": [
                            {
                                "id": "aae0c94a16d66abd",
                                "name": "## foo-bar-function",
                                "start_time": 1638792392.766,
                                "end_time": 1638792392.836,
                                "annotations": {
                                    "ColdStart": true
                                },
                                "subsegments": [
                                    {
                                        "id": "b1ac78c231577476",
                                        "name": "### dummyMethod",
                                        "start_time": 1638845552.777,
                                        "end_time": 1638845553.459,
                                        "metadata": {
                                            "hello-world": {
                                                "dummyMethod response": "bar"
                                            }
                                            // Other metadata (if any)
                                        }
                                        // Annotations (if any)
                                        // Other subsegments (if any)
                                    }
                                ]
                            }
                        ]
                    },
                    // Overhead subsegment (if any)
                ]
            }
        }
    ]
}

Capturing AWS SDK clients

AWS SDK JS v3

// AWS SDK JS v3
import { S3Client, ListObjectsV2Command } from "@aws-sdk/client-s3";
// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();
const client = new S3Client({});
tracer.captureAWSv3Client(client);

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {

    const command = new ListObjectsV2Command({
      Bucket: process.env.BUCKET_NAME,
    });

    return client
      .send(command)
      .then((data) => {
        // Do something with data

        return {
          foo: "bar",
        } as unknown as TResult;
      })
      .catch((error) => {
        logger.error("Error from action", error);
      });
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));

AWS SDK JS v2 (specific client)

// AWS SDK JS v2
import { S3 } from "aws-sdk";
// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();
const client = tracer.captureAWSClient(new S3({ apiVersion: "2006-03-01" }));

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {

    return s3
      .listObjectsV2({
        Bucket: process.env.BUCKET_NAME || "",
      })
      .promise()
      .then((data) => {
        // Do something with data

        return {
          foo: "bar",
        } as unknown as TResult;
      })
      .catch((error) => {
        logger.error("Error from action", error);
      });
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));

AWS SDK JS v2 (all clients)

// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();
// Capture all AWS SDK clients
const AWS = tracer.captureAWS(require('aws-sdk'));
const s3 = new AWS.S3({ apiVersion: "2006-03-01" });

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {

    return s3
      .listObjectsV2({
        Bucket: process.env.BUCKET_NAME || "",
      })
      .promise()
      .then((data: unknown) => {
        // Do something with data

        return {
          foo: "bar",
        } as unknown as TResult;
      })
      .catch((error: Error) => {
        logger.error("Error from action", error);
      });
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the trace
{
    "Id": "abcdef123456abcdef123456abcdef123456",
    "Duration": 0.656,
    "LimitExceeded": false,
    "Segments": [
        {
            "Id": "1234567890abcdef0",
            "Document": {
                "id": "1234567890abcdef0",
                "name": "foo-bar-function",
                "start_time": 1638792392.764036,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638792392.957155,
                "parent_id": "abcdef01234567890",
                "aws": {
                    "account_id": "111122223333",
                    "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:foo-bar-function",
                    "resource_names": [
                        "foo-bar-function"
                    ]
                },
                "origin": "AWS::Lambda::Function",
                "subsegments": [
                    // Initialization subsegment (if any)
                    {
                        "id": "4be0933d48d5b52f",
                        "name": "Invocation",
                        "start_time": 1638792392.7642102,
                        "end_time": 1638792392.9384046,
                        "aws": {
                            "function_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
                        },
                        "metadata": {
                            // Handler segment metadata
                        },
                        "subsegments": [
                            {
                                "id": "aae0c94a16d66abd",
                                "name": "## foo-bar-function",
                                "start_time": 1638792392.766,
                                "end_time": 1638792392.836,
                                "http": {
                                    "response": {
                                        "status": 200
                                    }
                                },
                                "aws": {
                                    "retries": 1,
                                    "region": "eu-west-1",
                                    "operation": "ListObjectsV2",
                                    "id_2": "mmG8kljASOkl9t5TsBd4D//U5W7Dr1ZrLWEsajtNMqY+VGLFDp0OHpYLz670ETOBPWERFyYh2w0="
                                },
                                "namespace": "aws"
                            }
                        ]
                    },
                    // Overhead subsegment (if any)
                ]
            }
        },
        {
            "Id": "021345abcdef6789",
            "Document": {
                "id": "021345abcdef6789",
                "name": "foo-bar-function",
                "start_time": 1638800791.846,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638800793.349,
                "http": {
                    "response": {
                        "status": 200
                    }
                },
                "aws": {
                    "request_id": "27df07c5-1c35-42eb-ae6f-55193c404205"
                },
                "origin": "AWS::Lambda",
                "resource_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
            }
        },
        {
            "Id": "117e4d4e091318a3",
            "Document": {
                "id": "117e4d4e091318a3",
                "name": "S3",
                "start_time": 1638800792.61,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638800793.247,
                "parent_id": "1234567890abcdef0",
                "inferred": true,
                "http": {
                    "response": {
                        "status": 200
                    }
                },
                "aws": {
                    "retries": 1,
                    "region": "eu-west-1",
                    "operation": "ListObjectsV2",
                    "id_2": "mmG8kljASOkl9t5TsBd4D//U5W7Dr1ZrLWEsajtNMqY+VGLFDp0OHpYLz670ETOBPWERFyYh2w0="
                },
                "origin": "AWS::S3"
            }
        }
    ]
}

Disabling capture response body

// Environment variables set for the Lambda
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';
process.env.POWERTOOLS_TRACER_CAPTURE_RESPONSE = 'false';

const tracer = new Tracer();

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {

    return new Promise((resolve, _reject) => resolve({
      foo: 'bar'
    } as unknown as TResult));
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the trace
{
    "Id": "abcdef123456abcdef123456abcdef123456",
    "Duration": 0.656,
    "LimitExceeded": false,
    "Segments": [
        {
            "Id": "1234567890abcdef0",
            "Document": {
                "id": "1234567890abcdef0",
                "name": "foo-bar-function",
                "start_time": 1638792392.764036,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638792392.957155,
                "parent_id": "abcdef01234567890",
                "aws": {
                    "account_id": "111122223333",
                    "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:foo-bar-function",
                    "resource_names": [
                        "foo-bar-function"
                    ]
                },
                "origin": "AWS::Lambda::Function",
                "subsegments": [
                    // Initialization subsegment (if any)
                    {
                        "id": "4be0933d48d5b52f",
                        "name": "Invocation",
                        "start_time": 1638792392.7642102,
                        "end_time": 1638792392.9384046,
                        "aws": {
                            "function_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
                        }
                        // Annotations (if any)
                        // Other metadata (if any)
                    },
                    // Overhead subsegment (if any)
                ]
            }
        }
    ]
}

Disabling capture error

// Environment variables set for the Lambda
process.env.POWERTOOLS_TRACER_CAPTURE_ERROR = "false";
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';

const tracer = new Tracer();

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {
    // Some logic that throws an error
    throw Error('Some error occurred')
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the trace
{
    "Id": "abcdef123456abcdef123456abcdef123456",
    "Duration": 0.656,
    "LimitExceeded": false,
    "Segments": [
        {
            "Id": "1234567890abcdef0",
            "Document": {
                "id": "1234567890abcdef0",
                "name": "foo-bar-function",
                "start_time": 1638792392.764036,
                "trace_id": "abcdef123456abcdef123456abcdef123456",
                "end_time": 1638792392.957155,
                "parent_id": "abcdef01234567890",
                "aws": {
                    "account_id": "111122223333",
                    "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:foo-bar-function",
                    "resource_names": [
                        "foo-bar-function"
                    ]
                },
                "origin": "AWS::Lambda::Function",
                "subsegments": [
                    // Initialization subsegment (if any)
                    {
                        "id": "4be0933d48d5b52f",
                        "name": "Invocation",
                        "start_time": 1638792392.7642102,
                        "end_time": 1638792392.9384046,
                        "aws": {
                            "function_arn": "arn:aws:lambda:eu-west-1:111122223333:function:foo-bar-function"
                        },
                        "error": true,
                        // Annotations (if any)
                        // Other metadata (if any)
                    },
                    // Overhead subsegment (if any)
                ]
            }
        }
    ]
}

Constructor options

const tracer = new Tracer({
  enabled: true,
  serviceName: 'hello-world'
});

class Lambda implements LambdaInterface {

  @tracer.captureLambdaHanlder()
  public handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<TResult> {
    return new Promise((resolve, _reject) => resolve({
      foo: 'bar'
    } as unknown as TResult));
  }

}

new Lambda().handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Click to expand and see the logs outputs
{
  level: 'INFO',
  message: 'This is an INFO log',
  sampling_rate: 0.5,
  service: 'hello-world',
  timestamp: '2021-03-25T09:59:31.252Z',
  xray_trace_id: 'abcdef123456abcdef123456abcdef123456',
  awsAccountId: '123456789012',
  logger: { name: 'aws-lambda-powertools-typescript', version: '0.0.1' },
  correlationIds: { myCustomCorrelationId: 'foo-bar-baz' }
}