From 7b5b76eadf0aa59e2482bd0f971fd8f2c8b32703 Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Tue, 5 Apr 2022 14:09:37 -0700 Subject: [PATCH 1/2] docs(tracer): extract code examples --- docs/core/tracer.md | 200 ++---------------- docs/examples/core/tracer/annotations.ts | 7 + docs/examples/core/tracer/escapeHatch.ts | 7 + docs/examples/core/tracer/handler.ts | 7 + docs/examples/core/tracer/handlerDecorator.ts | 15 ++ docs/examples/core/tracer/handlerManual.ts | 32 +++ .../core/tracer/handlerMiddyMiddleware.ts | 13 ++ docs/examples/core/tracer/metadata.ts | 8 + docs/examples/core/tracer/methodsDecorator.ts | 20 ++ docs/examples/core/tracer/methodsManual.ts | 34 +++ docs/examples/core/tracer/patchingAWS.ts | 4 + .../examples/core/tracer/patchingAWSClient.ts | 5 + .../core/tracer/patchingAWSv3Client.ts | 5 + .../examples/core/tracer/samExampleHandler.ts | 9 + docs/examples/core/tracer/template.yml | 14 ++ .../core/tracer/tracingHTTPSRequests.ts | 8 + 16 files changed, 204 insertions(+), 184 deletions(-) create mode 100644 docs/examples/core/tracer/annotations.ts create mode 100644 docs/examples/core/tracer/escapeHatch.ts create mode 100644 docs/examples/core/tracer/handler.ts create mode 100644 docs/examples/core/tracer/handlerDecorator.ts create mode 100644 docs/examples/core/tracer/handlerManual.ts create mode 100644 docs/examples/core/tracer/handlerMiddyMiddleware.ts create mode 100644 docs/examples/core/tracer/metadata.ts create mode 100644 docs/examples/core/tracer/methodsDecorator.ts create mode 100644 docs/examples/core/tracer/methodsManual.ts create mode 100644 docs/examples/core/tracer/patchingAWS.ts create mode 100644 docs/examples/core/tracer/patchingAWSClient.ts create mode 100644 docs/examples/core/tracer/patchingAWSv3Client.ts create mode 100644 docs/examples/core/tracer/samExampleHandler.ts create mode 100644 docs/examples/core/tracer/template.yml create mode 100644 docs/examples/core/tracer/tracingHTTPSRequests.ts diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 8f24399847..69d2624c26 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -39,13 +39,7 @@ The `Tracer` utility must always be instantiated outside of the Lambda handler. === "handler.ts" ```typescript hl_lines="1 3" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - export const handler = async (_event, _context): Promise => { - // ... - }; + --8<-- "docs/examples/core/tracer/handler.ts" ``` ### Utility settings @@ -70,29 +64,13 @@ The `Tracer` utility is instantiated outside of the Lambda handler. In doing thi === "handler.ts" ```typescript hl_lines="1 4" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - // Tracer parameter fetched from the environment variables (see template.yaml tab) - const tracer = new Tracer(); - - // You can also pass the parameter in the constructor - // const tracer = new Tracer({ - // serviceName: "serverlessAirline" - // }); + --8<-- "docs/examples/core/tracer/samExampleHandler.ts" ``` === "template.yml" - ```yaml hl_lines="6 9" - Resources: - HelloWorldFunction: - Type: AWS::Serverless::Function - Properties: - Runtime: nodejs14.x - Tracing: Active - Environment: - Variables: - POWERTOOLS_SERVICE_NAME: serverlessAirline + ```yaml hl_lines="11 14" + --8<-- "docs/examples/core/tracer/template.yml" ``` ### Lambda handler @@ -102,56 +80,13 @@ You can quickly start by importing the `Tracer` class, initialize it outside the === "Manual" ```typescript hl_lines="6 8-9 12-13 19 22 26 28" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - export const handler = async (_event: any, context: any): Promise => { - const segment = tracer.getSegment(); // This is the facade segment (the one that is created by AWS Lambda) - // Create subsegment for the function & set it as active - const subsegment = segment.addNewSubsegment(`## ${process.env._HANDLER}`); - tracer.setSegment(subsegment); - - // Annotate the subsegment with the cold start & serviceName - tracer.annotateColdStart(); - tracer.addServiceNameAnnotation(); - - let res; - try { - /* ... */ - // Add the response as metadata - tracer.addResponseAsMetadata(res, process.env._HANDLER); - } catch (err) { - // Add the error as metadata - tracer.addErrorAsMetadata(err as Error); - throw err; - } finally { - // Close subsegment (the AWS Lambda one is closed automatically) - subsegment.close(); - // Set back the facade segment as active again - tracer.setSegment(segment); - } - - return res; - }; + --8<-- "docs/examples/core/tracer/handlerManual.ts" ``` === "Middy Middleware" ```typescript hl_lines="1-2 11 13" - import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; - import middy from '@middy/core'; // (1) - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - const lambdaHandler = async (_event: any, _context: any): Promise => { - /* ... */ - }; - - // Wrap the handler with middy - export const handler = middy(lambdaHandler) - // Use the middleware by passing the Tracer instance as a parameter - .use(captureLambdaHandler(tracer)); + --8<-- "docs/examples/core/tracer/handlerMiddyMiddleware.ts" ``` 1. Using Middy for the first time? You can install Middy by running `npm i @middy/core`. @@ -164,21 +99,7 @@ You can quickly start by importing the `Tracer` class, initialize it outside the See the [official TypeScript documentation](https://www.typescriptlang.org/docs/handbook/decorators.html) for more details. ```typescript hl_lines="8" - import { Tracer } from '@aws-lambda-powertools/tracer'; - import { LambdaInterface } from '@aws-lambda-powertools/commons'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - class Lambda implements LambdaInterface { - // Decorate your handler class method - @tracer.captureLambdaHandler() - public async handler(_event: any, _context: any): Promise { - /* ... */ - } - } - - export const handlerClass = new Lambda(); - export const handler = handlerClass.handler; + --8<-- "docs/examples/core/tracer/handlerDecorator.ts" ``` When using the `captureLambdaHandler` decorator or middleware, Tracer performs these additional tasks to ease operations: @@ -198,26 +119,13 @@ When using the `captureLambdaHandler` decorator or middleware, Tracer performs t You can add annotations using `putAnnotation` method. ```typescript hl_lines="6" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - export const handler = async (_event: any, _context: any): Promise => { - tracer.putAnnotation('successfulBooking', true); - }; + --8<-- "docs/examples/core/tracer/annotations.ts" ``` === "Metadata" You can add metadata using `putMetadata` method. ```typescript hl_lines="7" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - export const handler = async (_event: any, _context: any): Promise => { - const res; /* ... */ - tracer.putMetadata('paymentResponse', res); - }; + --8<-- "docs/examples/core/tracer/metadata.ts" ``` ### Methods @@ -227,65 +135,13 @@ You can trace other Class methods using the `captureMethod` decorator or any arb === "Manual" ```typescript hl_lines="6 8-9 15 18 23 25" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - const getChargeId = async (): Promise => { - const parentSubsegment = tracer.getSegment(); // This is the subsegment currently active - // Create subsegment for the function & set it as active - const subsegment = parentSubsegment.addNewSubsegment(`### chargeId`); - tracer.setSegment(subsegment); - - let res; - try { - /* ... */ - // Add the response as metadata - tracer.addResponseAsMetadata(res, 'chargeId'); - } catch (err) { - // Add the error as metadata - tracer.addErrorAsMetadata(err as Error); - throw err; - } - - // Close subsegment (the AWS Lambda one is closed automatically) - subsegment.close(); - // Set the facade segment as active again - tracer.setSegment(parentSubsegment); - - return res; - }; - - export const handler = async (_event: any, _context: any): Promise => { - const chargeId = getChargeId(); - const payment = collectPayment(chargeId); - /* ... */ - }; + --8<-- "docs/examples/core/tracer/methodsManual.ts" ``` === "Decorator" ```typescript hl_lines="8" - import { Tracer } from '@aws-lambda-powertools/tracer'; - import { LambdaInterface } from '@aws-lambda-powertools/commons'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - class Lambda implements LambdaInterface { - // Decorate your class method - @tracer.captureMethod() - public getChargeId(): string { - /* ... */ - return 'foo bar'; - } - - public async handler(_event: any, _context: any): Promise { - /* ... */ - } - } - - export const myFunction = new Lambda(); - export const handler = myFunction.handler; + --8<-- "docs/examples/core/tracer/methodsDecorator.ts" ``` ### Patching AWS SDK clients @@ -300,11 +156,7 @@ You can patch any AWS SDK clients by calling the `captureAWSv3Client` method: === "index.ts" ```typescript hl_lines="5" - import { S3Client } from '@aws-sdk/client-s3'; - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - const client = tracer.captureAWSv3Client(new S3Client({})); + --8<-- "docs/examples/core/tracer/patchingAWSv3Client.ts" ``` !!! info @@ -315,10 +167,7 @@ You can patch all AWS SDK v2 clients by calling the `captureAWS` method: === "index.ts" ```typescript hl_lines="4" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - const AWS = tracer.captureAWS(require('aws-sdk')); + --8<-- "docs/examples/core/tracer/patchingAWS.ts" ``` 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`: @@ -326,11 +175,7 @@ If you're looking to shave a few microseconds, or milliseconds depending on your === "index.ts" ```typescript hl_lines="5" - import { S3 } from 'aws-sdk'; - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - const s3 = tracer.captureAWSClient(new S3()); + --8<-- "docs/examples/core/tracer/patchingAWSClient.ts" ``` ### Tracing HTTP requests @@ -346,14 +191,7 @@ You can opt-out from this feature by setting the **`POWERTOOLS_TRACER_CAPTURE_HT === "index.ts" ```typescript hl_lines="2 7" - import { Tracer } from '@aws-lambda-powertools/tracer'; - import axios from 'axios'; // (1) - - const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - - export const handler = async (event: unknown, context: Context): Promise => { - await axios.get('https://httpbin.org/status/200'); - }; + --8<-- "docs/examples/core/tracer/tracingHTTPSRequests.ts" ``` 1. You can install the [axios](https://www.npmjs.com/package/axios) package using `npm i axios` @@ -416,13 +254,7 @@ This is useful when you need a feature available in X-Ray that is not available === "index.ts" ```typescript hl_lines="7" - import { Logger } from '@aws-lambda-powertools/logger'; - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const serviceName = 'serverlessAirline'; - const logger = new Logger({ serviceName: serviceName }); - const tracer = new Tracer({ serviceName: serviceName }); - tracer.provider.setLogger(logger); + --8<-- "docs/examples/core/tracer/escapeHatch.ts" ``` ## Testing your code diff --git a/docs/examples/core/tracer/annotations.ts b/docs/examples/core/tracer/annotations.ts new file mode 100644 index 0000000000..c95e1d83c2 --- /dev/null +++ b/docs/examples/core/tracer/annotations.ts @@ -0,0 +1,7 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +export const handler = async (_event: any, _context: any): Promise => { + tracer.putAnnotation('successfulBooking', true); +}; diff --git a/docs/examples/core/tracer/escapeHatch.ts b/docs/examples/core/tracer/escapeHatch.ts new file mode 100644 index 0000000000..b4b169cdec --- /dev/null +++ b/docs/examples/core/tracer/escapeHatch.ts @@ -0,0 +1,7 @@ +import { Logger } from '@aws-lambda-powertools/logger'; +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const serviceName = 'serverlessAirline'; +const logger = new Logger({ serviceName: serviceName }); +const tracer = new Tracer({ serviceName: serviceName }); +tracer.provider.setLogger(logger); diff --git a/docs/examples/core/tracer/handler.ts b/docs/examples/core/tracer/handler.ts new file mode 100644 index 0000000000..b0f3491fb1 --- /dev/null +++ b/docs/examples/core/tracer/handler.ts @@ -0,0 +1,7 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +export const handler = async (_event, _context): Promise => { + // ... +}; diff --git a/docs/examples/core/tracer/handlerDecorator.ts b/docs/examples/core/tracer/handlerDecorator.ts new file mode 100644 index 0000000000..eb39fbcfa4 --- /dev/null +++ b/docs/examples/core/tracer/handlerDecorator.ts @@ -0,0 +1,15 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; +import { LambdaInterface } from '@aws-lambda-powertools/commons'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +class Lambda implements LambdaInterface { + // Decorate your handler class method + @tracer.captureLambdaHandler() + public async handler(_event: any, _context: any): Promise { + /* ... */ + } +} + +export const handlerClass = new Lambda(); +export const handler = handlerClass.handler; diff --git a/docs/examples/core/tracer/handlerManual.ts b/docs/examples/core/tracer/handlerManual.ts new file mode 100644 index 0000000000..9169dff321 --- /dev/null +++ b/docs/examples/core/tracer/handlerManual.ts @@ -0,0 +1,32 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +export const handler = async (_event: any, context: any): Promise => { + const segment = tracer.getSegment(); // This is the facade segment (the one that is created by AWS Lambda) + // Create subsegment for the function & set it as active + const subsegment = segment.addNewSubsegment(`## ${process.env._HANDLER}`); + tracer.setSegment(subsegment); + + // Annotate the subsegment with the cold start & serviceName + tracer.annotateColdStart(); + tracer.addServiceNameAnnotation(); + + let res; + try { + /* ... */ + // Add the response as metadata + tracer.addResponseAsMetadata(res, process.env._HANDLER); + } catch (err) { + // Add the error as metadata + tracer.addErrorAsMetadata(err as Error); + throw err; + } finally { + // Close subsegment (the AWS Lambda one is closed automatically) + subsegment.close(); + // Set back the facade segment as active again + tracer.setSegment(segment); + } + + return res; +}; diff --git a/docs/examples/core/tracer/handlerMiddyMiddleware.ts b/docs/examples/core/tracer/handlerMiddyMiddleware.ts new file mode 100644 index 0000000000..e2d61b09f0 --- /dev/null +++ b/docs/examples/core/tracer/handlerMiddyMiddleware.ts @@ -0,0 +1,13 @@ +import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; +import middy from '@middy/core'; // (1) + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +const lambdaHandler = async (_event: any, _context: any): Promise => { + /* ... */ +}; + +// Wrap the handler with middy +export const handler = middy(lambdaHandler) + // Use the middleware by passing the Tracer instance as a parameter + .use(captureLambdaHandler(tracer)); diff --git a/docs/examples/core/tracer/metadata.ts b/docs/examples/core/tracer/metadata.ts new file mode 100644 index 0000000000..11dc1fe813 --- /dev/null +++ b/docs/examples/core/tracer/metadata.ts @@ -0,0 +1,8 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +export const handler = async (_event: any, _context: any): Promise => { + const res; /* ... */ + tracer.putMetadata('paymentResponse', res); +}; diff --git a/docs/examples/core/tracer/methodsDecorator.ts b/docs/examples/core/tracer/methodsDecorator.ts new file mode 100644 index 0000000000..fcbe304988 --- /dev/null +++ b/docs/examples/core/tracer/methodsDecorator.ts @@ -0,0 +1,20 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; +import { LambdaInterface } from '@aws-lambda-powertools/commons'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +class Lambda implements LambdaInterface { + // Decorate your class method + @tracer.captureMethod() + public getChargeId(): string { + /* ... */ + return 'foo bar'; + } + + public async handler(_event: any, _context: any): Promise { + /* ... */ + } +} + +export const myFunction = new Lambda(); +export const handler = myFunction.handler; diff --git a/docs/examples/core/tracer/methodsManual.ts b/docs/examples/core/tracer/methodsManual.ts new file mode 100644 index 0000000000..552dbfd479 --- /dev/null +++ b/docs/examples/core/tracer/methodsManual.ts @@ -0,0 +1,34 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +const getChargeId = async (): Promise => { + const parentSubsegment = tracer.getSegment(); // This is the subsegment currently active + // Create subsegment for the function & set it as active + const subsegment = parentSubsegment.addNewSubsegment(`### chargeId`); + tracer.setSegment(subsegment); + + let res; + try { + /* ... */ + // Add the response as metadata + tracer.addResponseAsMetadata(res, 'chargeId'); + } catch (err) { + // Add the error as metadata + tracer.addErrorAsMetadata(err as Error); + throw err; + } + + // Close subsegment (the AWS Lambda one is closed automatically) + subsegment.close(); + // Set the facade segment as active again + tracer.setSegment(parentSubsegment); + + return res; +}; + +export const handler = async (_event: any, _context: any): Promise => { + const chargeId = getChargeId(); + const payment = collectPayment(chargeId); + /* ... */ +}; diff --git a/docs/examples/core/tracer/patchingAWS.ts b/docs/examples/core/tracer/patchingAWS.ts new file mode 100644 index 0000000000..a0506cb579 --- /dev/null +++ b/docs/examples/core/tracer/patchingAWS.ts @@ -0,0 +1,4 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); +const AWS = tracer.captureAWS(require('aws-sdk')); diff --git a/docs/examples/core/tracer/patchingAWSClient.ts b/docs/examples/core/tracer/patchingAWSClient.ts new file mode 100644 index 0000000000..f8f4d1a29f --- /dev/null +++ b/docs/examples/core/tracer/patchingAWSClient.ts @@ -0,0 +1,5 @@ +import { S3 } from 'aws-sdk'; +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); +const s3 = tracer.captureAWSClient(new S3()); diff --git a/docs/examples/core/tracer/patchingAWSv3Client.ts b/docs/examples/core/tracer/patchingAWSv3Client.ts new file mode 100644 index 0000000000..96856789e4 --- /dev/null +++ b/docs/examples/core/tracer/patchingAWSv3Client.ts @@ -0,0 +1,5 @@ +import { S3Client } from '@aws-sdk/client-s3'; +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); +const client = tracer.captureAWSv3Client(new S3Client({})); diff --git a/docs/examples/core/tracer/samExampleHandler.ts b/docs/examples/core/tracer/samExampleHandler.ts new file mode 100644 index 0000000000..5fa4f251c0 --- /dev/null +++ b/docs/examples/core/tracer/samExampleHandler.ts @@ -0,0 +1,9 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; + +// Tracer parameter fetched from the environment variables (see template.yaml tab) +const tracer = new Tracer(); + +// You can also pass the parameter in the constructor +// const tracer = new Tracer({ +// serviceName: "serverlessAirline" +// }); diff --git a/docs/examples/core/tracer/template.yml b/docs/examples/core/tracer/template.yml new file mode 100644 index 0000000000..28ce32ac1f --- /dev/null +++ b/docs/examples/core/tracer/template.yml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 + +Resources: + HelloWorldFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: src + Handler: index.lambda_handler + Runtime: nodejs14.x + Tracing: Active + Environment: + Variables: + POWERTOOLS_SERVICE_NAME: serverlessAirline diff --git a/docs/examples/core/tracer/tracingHTTPSRequests.ts b/docs/examples/core/tracer/tracingHTTPSRequests.ts new file mode 100644 index 0000000000..de80e8a15d --- /dev/null +++ b/docs/examples/core/tracer/tracingHTTPSRequests.ts @@ -0,0 +1,8 @@ +import { Tracer } from '@aws-lambda-powertools/tracer'; +import axios from 'axios'; // (1) + +const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + +export const handler = async (event: unknown, context: Context): Promise => { + await axios.get('https://httpbin.org/status/200'); +}; From 9db13dbdae7718dd0f8817456511748405a7dfa4 Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Wed, 6 Apr 2022 15:04:12 -0700 Subject: [PATCH 2/2] fix(docs): add missing import of Context --- docs/examples/core/tracer/tracingHTTPSRequests.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/examples/core/tracer/tracingHTTPSRequests.ts b/docs/examples/core/tracer/tracingHTTPSRequests.ts index de80e8a15d..b6d0f74b6c 100644 --- a/docs/examples/core/tracer/tracingHTTPSRequests.ts +++ b/docs/examples/core/tracer/tracingHTTPSRequests.ts @@ -1,4 +1,5 @@ import { Tracer } from '@aws-lambda-powertools/tracer'; +import { Context } from 'aws-lambda'; import axios from 'axios'; // (1) const tracer = new Tracer({ serviceName: 'serverlessAirline' });