diff --git a/examples/cdk/lib/example-function.MyFunction.ts b/examples/cdk/lib/example-function.MyFunction.ts index 9d00fa2b3d..1cad15a5af 100644 --- a/examples/cdk/lib/example-function.MyFunction.ts +++ b/examples/cdk/lib/example-function.MyFunction.ts @@ -6,19 +6,24 @@ import { Tracer } from '@aws-lambda-powertools/tracer'; const namespace = 'CDKExample'; const serviceName = 'MyFunctionWithStandardHandler'; -const metrics = new Metrics({ namespace: namespace, service: serviceName }); +const metrics = new Metrics({ namespace: namespace, serviceName: serviceName }); const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName }); const tracer = new Tracer({ serviceName: serviceName }); -export const handler = async (_event: unknown, context: Context): Promise => { +export const handler = async (event: unknown, context: Context): Promise => { // Since we are in manual mode we need to create the handler segment (the 4 lines below would be done for you by decorator/middleware) // we do it at the beginning because we want to trace the whole duration of the handler - const segment = tracer.getSegment(); // This is the facade segment (the one that is created by Lambda & that can't be manipulated) - const handlerSegment = segment.addNewSubsegment(`## ${context.functionName}`); - // TODO: expose tracer.annotateColdStart() - tracer.putAnnotation('ColdStart', Tracer.coldStart); + 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 handlerSegment = segment.addNewSubsegment(`## ${process.env._HANDLER}`); + tracer.setSegment(handlerSegment); - // ### Experiment logger + // Annotate the subsegment with the cold start & serviceName + tracer.annotateColdStart(); + tracer.addServiceNameAnnotation(); + + // ### Experiment with Logger + logger.addContext(context); logger.addPersistentLogAttributes({ testKey: 'testValue', }); @@ -27,7 +32,7 @@ export const handler = async (_event: unknown, context: Context): Promise logger.warn('This is an WARN log'); logger.error('This is an ERROR log'); - // ### Experiment metrics + // ### Experiment with Metrics metrics.captureColdStartMetric(); metrics.raiseOnEmptyMetrics(); metrics.setDefaultDimensions({ environment: 'example', type: 'standardFunction' }); @@ -38,24 +43,31 @@ export const handler = async (_event: unknown, context: Context): Promise metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50); metrics.publishStoredMetrics(); - metrics.raiseOnEmptyMetrics(); - - // ### Experiment tracer + metrics.throwOnEmptyMetrics(); - tracer.putAnnotation('Myannotation', 'My annotation\'s value'); + // ### Experiment with Tracer + // This annotation & metadata will be added to the handlerSegment subsegment (## index.handler) + tracer.putAnnotation('awsRequestId', context.awsRequestId); + tracer.putMetadata('eventPayload', event); - // Create subsegment & set it as active - const subsegment = handlerSegment.addNewSubsegment('MySubSegment'); + // Create another subsegment & set it as active + const subsegment = handlerSegment.addNewSubsegment('### MySubSegment'); + tracer.setSegment(subsegment); + let res; try { - throw new Error('test'); - // Add the response as metadata + res = { foo: 'bar' }; + tracer.addResponseAsMetadata(res, process.env._HANDLER); } catch (err) { // Add the error as metadata subsegment.addError(err as Error, false); + throw err; + } finally { + // Close subsegments (the AWS Lambda one is closed automatically) + subsegment.close(); // (### MySubSegment) + handlerSegment.close(); // (## index.handler) + // Set the facade segment as active again (the one created by AWS Lambda) + tracer.setSegment(segment); } - // Close subsegment - subsegment.close(); - handlerSegment.close(); }; diff --git a/examples/cdk/lib/example-function.MyFunctionWithDecorator.ts b/examples/cdk/lib/example-function.MyFunctionWithDecorator.ts index 9715539f74..a12c3892a9 100644 --- a/examples/cdk/lib/example-function.MyFunctionWithDecorator.ts +++ b/examples/cdk/lib/example-function.MyFunctionWithDecorator.ts @@ -1,24 +1,26 @@ import { Tracer } from '@aws-lambda-powertools/tracer'; -import { Callback, Context } from 'aws-lambda'; +import { Context } from 'aws-lambda'; +import { Events, LambdaInterface } from '@aws-lambda-powertools/commons'; import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; import { Logger } from '@aws-lambda-powertools/logger'; const namespace = 'CDKExample'; const serviceName = 'MyFunctionWithDecorator'; -const metrics = new Metrics({ namespace: namespace, service: serviceName }); +const metrics = new Metrics({ namespace: namespace, serviceName: serviceName }); const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName }); const tracer = new Tracer({ serviceName: serviceName }); -export class MyFunctionWithDecorator { - @tracer.captureLambdaHanlder() +export class MyFunctionWithDecorator implements LambdaInterface { + // We decorate the handler with the various decorators + @tracer.captureLambdaHandler() @logger.injectLambdaContext() @metrics.logMetrics({ captureColdStartMetric: true, - raiseOnEmptyMetrics: true, + throwOnEmptyMetrics: true, defaultDimensions: { environment: 'example', type: 'withDecorator' }, }) - public handler(_event: unknown, _context: Context, _callback: Callback): void | Promise { + public async handler(event: typeof Events.Custom.CustomEvent, context: Context): Promise { // ### Experiment logger logger.addPersistentLogAttributes({ testKey: 'testValue', @@ -36,28 +38,34 @@ export class MyFunctionWithDecorator { metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50); // ### Experiment tracer - tracer.putAnnotation('Myannotation', 'My annotation\'s value'); - // Create subsegment & set it as active - const segment = tracer.getSegment(); // This is the facade segment (the one that is created by Lambda & that can't be manipulated) - const subsegment = segment.addNewSubsegment('MySubSegment'); + // Service & Cold Start annotations will be added for you by the decorator/middleware + // These traces will be added to the main segment (## index.handler) + tracer.putAnnotation('awsRequestId', context.awsRequestId); + tracer.putMetadata('eventPayload', event); + + // Create another subsegment & set it as active + const handlerSegment = tracer.getSegment(); // This is the custom segment created by Tracer for you (## index.handler) + const subsegment = handlerSegment.addNewSubsegment('### MySubSegment'); tracer.setSegment(subsegment); - // TODO: Add the ColdStart annotation !!! NOT POSSIBLE - // tracer.putAnnotation('ColdStart', tracer); + let res; try { - throw new Error('test'); - // Add the response as metadata + res = { foo: 'bar' }; } catch (err) { - // Add the error as metadata - subsegment.addError(err as Error, false); + throw err; + } finally { + // Close the subsegment you created (### MySubSegment) + subsegment.close(); + // Set back the original segment as active (## index.handler) + tracer.setSegment(handlerSegment); + // The main segment (facade) will be closed for you at the end by the decorator/middleware } - - // Close subsegment - subsegment.close(); + + return res; } } -export const handlerClass = new MyFunctionWithDecorator(); -export const handler = handlerClass.handler; +export const myFunction = new MyFunctionWithDecorator(); +export const handler = myFunction.handler; diff --git a/examples/cdk/lib/example-function.MyFunctionWithMiddy.ts b/examples/cdk/lib/example-function.MyFunctionWithMiddy.ts index 297f5bbda3..14e139fcfa 100644 --- a/examples/cdk/lib/example-function.MyFunctionWithMiddy.ts +++ b/examples/cdk/lib/example-function.MyFunctionWithMiddy.ts @@ -1,43 +1,73 @@ import middy from '@middy/core'; -import { Callback, Context } from 'aws-lambda'; -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Context } from 'aws-lambda'; +import { Events } from '@aws-lambda-powertools/commons'; +import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; +import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; +import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger'; -const metrics = new Metrics({ namespace: 'CDKExample', service: 'withMiddy' }); // Sets metric namespace, and service as a metric dimension +const namespace = 'CDKExample'; +const serviceName = 'MyFunctionWithMiddyMiddleware'; -type CustomEvent = { - throw: boolean -}; +const metrics = new Metrics({ namespace: namespace, serviceName: serviceName }); +const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName }); +const tracer = new Tracer({ serviceName: serviceName }); -class MyFunctionWithDecorator { +const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => { + // ### Experiment with Logger + // AWS Lambda context is automatically injected by the middleware - @metrics.logMetrics({ captureColdStartMetric: true }) - public handler(_event: CustomEvent, _context: Context, _callback: Callback): void | Promise { - metrics.addMetric('test-metric', MetricUnits.Count, 10); - if (_event.throw) { - throw new Error('Test error'); - } - } -} + logger.addPersistentLogAttributes({ + testKey: 'testValue', + }); + logger.debug('This is an DEBUG log'); // Won't show because we pass logLevel: 'INFO' in the constructor. + logger.info('This is an INFO log'); + logger.warn('This is an WARN log'); + logger.error('This is an ERROR log'); -const handler = middy(async (_event, _context) => { + // ### Experiment with Metrics + // Default metrics, cold start, and throwOnEmptyMetrics are enabled by the middleware - const handlerClass = new MyFunctionWithDecorator(); + metrics.addMetric('test-metric', MetricUnits.Count, 10); - return handlerClass.handler(_event, _context, () => console.log('Lambda invoked!')); -}); + const metricWithItsOwnDimensions = metrics.singleMetric(); + metricWithItsOwnDimensions.addDimension('InnerDimension', 'true'); + metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50); + + // ### Experiment with Tracer -handler.before(async (_request) => { - metrics.addMetric('beforeHandlerCalled', MetricUnits.Count, 1); -}); + // Service & Cold Start annotations will be added for you by the decorator/middleware -handler.after(async (_request) => { - // Won't be flushed since happens after - metrics.addMetric('afterHandlerCalled', MetricUnits.Count, 1); + // These traces will be added to the main segment (## index.handler) + tracer.putAnnotation('awsRequestId', context.awsRequestId); + tracer.putMetadata('eventPayload', event); -}); + // Create another subsegment & set it as active + const handlerSegment = tracer.getSegment(); // This is the custom segment created by Tracer for you (## index.handler) + const subsegment = handlerSegment.addNewSubsegment('### MySubSegment'); + tracer.setSegment(subsegment); -handler.onError(async (_request) => { - metrics.addMetric('onErrorHandlerCalled', MetricUnits.Count, 1); -}); + let res; + try { + res = { foo: 'bar' }; + } catch (err) { + throw err; + } finally { + // Close the subsegment you created (### MySubSegment) + subsegment.close(); + // Set back the original segment as active (## index.handler) + tracer.setSegment(handlerSegment); + // The main segment (facade) will be closed for you at the end by the decorator/middleware + } + + return res; +} -module.exports = { handler }; \ No newline at end of file +// We instrument the handler with the various Middy middlewares +export const handler = middy(lambdaHandler) + .use(captureLambdaHandler(tracer)) + .use(logMetrics(metrics, { + captureColdStartMetric: true, + throwOnEmptyMetrics: true, + defaultDimensions: { environment: 'example', type: 'withDecorator' }, + })) + .use(injectLambdaContext(logger)); \ No newline at end of file diff --git a/examples/cdk/lib/example-function.Tracer.CaptureErrorDisabled.ts b/examples/cdk/lib/example-function.Tracer.CaptureErrorDisabled.ts index 4ef338b716..6bdea71da0 100644 --- a/examples/cdk/lib/example-function.Tracer.CaptureErrorDisabled.ts +++ b/examples/cdk/lib/example-function.Tracer.CaptureErrorDisabled.ts @@ -3,11 +3,11 @@ import { Context } from 'aws-lambda'; import { Events } from '@aws-lambda-powertools/commons'; import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer'; -// Set environment variable to disable capture response +// Set environment variable to disable capture response - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html process.env.POWERTOOLS_TRACER_ERROR_RESPONSE = 'false'; const tracer = new Tracer({ serviceName: 'tracerCaptureErrorDisabledFn' }); -// In this example we are using the middleware pattern but you could use also the captureLambdaHandler decorator +// In this example we are using the Middy middleware pattern but you can instrument your functions also with the captureLambdaHandler decorator & manual instrumentation export const handler = middy(async (event: typeof Events.Custom.CustomEvent, context: Context) => { tracer.putAnnotation('awsRequestId', context.awsRequestId); tracer.putMetadata('eventPayload', event); diff --git a/examples/cdk/lib/example-function.Tracer.CaptureResponseDisabled.ts b/examples/cdk/lib/example-function.Tracer.CaptureResponseDisabled.ts index 7d36290cc8..9dab5ffb1e 100644 --- a/examples/cdk/lib/example-function.Tracer.CaptureResponseDisabled.ts +++ b/examples/cdk/lib/example-function.Tracer.CaptureResponseDisabled.ts @@ -3,7 +3,7 @@ import { Context } from 'aws-lambda'; import { Events } from '@aws-lambda-powertools/commons'; import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer'; -// Set environment variable to disable capture response +// Set environment variable to disable capture response - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html process.env.POWERTOOLS_TRACER_CAPTURE_RESPONSE = 'false'; const tracer = new Tracer({ serviceName: 'tracerCaptureResponseDisabledFn' }); diff --git a/examples/cdk/lib/example-function.Tracer.Decorator.ts b/examples/cdk/lib/example-function.Tracer.Decorator.ts index d1c7f203b5..1294c2adf9 100644 --- a/examples/cdk/lib/example-function.Tracer.Decorator.ts +++ b/examples/cdk/lib/example-function.Tracer.Decorator.ts @@ -2,8 +2,9 @@ import { Callback, Context } from 'aws-lambda'; import { Events } from '@aws-lambda-powertools/commons'; import { Tracer } from '@aws-lambda-powertools/tracer'; -// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor const tracer = new Tracer({ serviceName: 'tracerDecoratorFn' }); +// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable +// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html export class MyFunctionWithDecorator { // We instrument the handler with the decorator and the tracer will automatically create a subsegment and capture relevant annotations and metadata diff --git a/examples/cdk/lib/example-function.Tracer.Disabled.ts b/examples/cdk/lib/example-function.Tracer.Disabled.ts index 15cd3e8e31..866b3a73b7 100644 --- a/examples/cdk/lib/example-function.Tracer.Disabled.ts +++ b/examples/cdk/lib/example-function.Tracer.Disabled.ts @@ -3,15 +3,15 @@ import { Context } from 'aws-lambda'; import { Events } from '@aws-lambda-powertools/commons'; import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer'; -// process.env.POWERTOOLS_TRACE_ENABLED = 'false'; // Alternative to disabling tracing in the constructor +// Disable Tracer by setting POWERTOOLS_TRACE_ENABLED = 'false' in the function environment variables - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html const tracer = new Tracer({ serviceName: 'tracerDisabledFn', enabled: false }); -// In this example we are using the middleware pattern but you could use also the captureLambdaHandler decorator or the manual mode -export const handler = middy(async (event: typeof Events.Custom.CustomEvent, context: Context) => { +// In this example we are using the middleware pattern but the same applies also the captureLambdaHandler decorator or to manual instrumentation +const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => { // No tracing will be done and the commands will be ignored, this is useful for testing tracer.putAnnotation('awsRequestId', context.awsRequestId); tracer.putMetadata('eventPayload', event); - + let res; try { res = { foo: 'bar' }; @@ -20,4 +20,6 @@ export const handler = middy(async (event: typeof Events.Custom.CustomEvent, con } return res; -}).use(captureLambdaHandler(tracer)); \ No newline at end of file +} + +export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer)); \ No newline at end of file diff --git a/examples/cdk/lib/example-function.Tracer.Manual.ts b/examples/cdk/lib/example-function.Tracer.Manual.ts index 99bad242cb..036bb990fa 100644 --- a/examples/cdk/lib/example-function.Tracer.Manual.ts +++ b/examples/cdk/lib/example-function.Tracer.Manual.ts @@ -2,8 +2,9 @@ import { Context } from 'aws-lambda'; import { Events } from '@aws-lambda-powertools/commons'; import { Tracer } from '@aws-lambda-powertools/tracer'; -// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor const tracer = new Tracer({ serviceName: 'tracerManualFn' }); +// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable +// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html export const handler = async (event: typeof Events.Custom.CustomEvent, context: Context): Promise => { const segment = tracer.getSegment(); // This is the facade segment (the one that is created by AWS Lambda) diff --git a/examples/cdk/lib/example-function.Tracer.Middleware.ts b/examples/cdk/lib/example-function.Tracer.Middleware.ts index 77ad9deb2c..810c285ca8 100644 --- a/examples/cdk/lib/example-function.Tracer.Middleware.ts +++ b/examples/cdk/lib/example-function.Tracer.Middleware.ts @@ -3,15 +3,15 @@ import { Context } from 'aws-lambda'; import { Events } from '@aws-lambda-powertools/commons'; import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer'; -// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor const tracer = new Tracer({ serviceName: 'tracerMiddlewareFn' }); +// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable +// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html -// We instrument the handler with the middy middleware and the tracer will automatically create a subsegment and capture relevant annotations and metadata -export const handler = middy(async (event: typeof Events.Custom.CustomEvent, context: Context) => { +const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => { // Add custom annotation & metadata tracer.putAnnotation('awsRequestId', context.awsRequestId); tracer.putMetadata('eventPayload', event); - + let res; try { res = { foo: 'bar' }; @@ -20,4 +20,11 @@ export const handler = middy(async (event: typeof Events.Custom.CustomEvent, con } return res; -}).use(captureLambdaHandler(tracer)); \ No newline at end of file +} + +// We instrument the handler with the Middy middleware and the Tracer will automatically: +// * handle the lifecycle of the subsegment +// * create a ColdStart annotation to easily filter traces that have had an initialization overhead +// * create 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 +export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer)); \ No newline at end of file diff --git a/examples/cdk/lib/example-function.Tracer.PatchAWSSDKv2.ts b/examples/cdk/lib/example-function.Tracer.PatchAWSSDKv2.ts index a105d52c4a..08eab6c55c 100644 --- a/examples/cdk/lib/example-function.Tracer.PatchAWSSDKv2.ts +++ b/examples/cdk/lib/example-function.Tracer.PatchAWSSDKv2.ts @@ -3,11 +3,15 @@ import { Events } from '@aws-lambda-powertools/commons'; import { Tracer } from '@aws-lambda-powertools/tracer'; import { STS } from 'aws-sdk'; -// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor const tracer = new Tracer({ serviceName: 'tracerPatchAWSSDKv2Fn' }); -// To patch a specific AWS SDK Client, we pass it to the Tracer that will return an instrumented version of it +// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable +// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html + +// To patch a specific AWS SDK v2 Client, we pass it to the Tracer that will return an instrumented version of it const sts = tracer.captureAWSClient(new STS()); +// Here we are showing an example with manual instrumentation but you can do the same also with the captureLambdaHandler Middy Middleware and Class decorator +// See: https://awslabs.github.io/aws-lambda-powertools-typescript/latest/core/tracer/#lambda-handler export const handler = async (_event: typeof Events.Custom.CustomEvent, _context: Context): 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 @@ -18,16 +22,18 @@ export const handler = async (_event: typeof Events.Custom.CustomEvent, _context try { // Tracer will create a subsegment for the AWS SDK call and capture relevant annotations and metadata res = await sts.getCallerIdentity({}).promise(); - // Add custom metadata with the response object - tracer.putMetadata('awsResponse', res); + // Add the response as metadata + tracer.addResponseAsMetadata(res, process.env._HANDLER); } catch (err) { + // Add error as metadata to the current subsegment + 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); } - // Close subsegment (the AWS Lambda one is closed automatically) - subsegment.close(); - // Set the facade segment as active again - tracer.setSegment(segment); - return res; }; \ No newline at end of file diff --git a/examples/cdk/lib/example-function.Tracer.PatchAWSSDKv3.ts b/examples/cdk/lib/example-function.Tracer.PatchAWSSDKv3.ts index 1a9517a3a7..c53150f05a 100644 --- a/examples/cdk/lib/example-function.Tracer.PatchAWSSDKv3.ts +++ b/examples/cdk/lib/example-function.Tracer.PatchAWSSDKv3.ts @@ -3,11 +3,15 @@ import { Events } from '@aws-lambda-powertools/commons'; import { Tracer } from '@aws-lambda-powertools/tracer'; import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts'; -// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor const tracer = new Tracer({ serviceName: 'tracerManualFn' }); +// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable +// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html + // To patch a specific AWS SDK v3 Client, we need to pass it to the Tracer that will return an instrumented version of it const sts = tracer.captureAWSv3Client(new STSClient({})); +// Here we are showing an example with manual instrumentation but you can do the same also with the captureLambdaHandler Middy Middleware and Class decorator +// See: https://awslabs.github.io/aws-lambda-powertools-typescript/latest/core/tracer/#lambda-handler export const handler = async (_event: typeof Events.Custom.CustomEvent, _context: Context): 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 @@ -18,16 +22,18 @@ export const handler = async (_event: typeof Events.Custom.CustomEvent, _context try { // Tracer will create a subsegment for the AWS SDK call and capture relevant annotations and metadata res = await sts.send(new GetCallerIdentityCommand({})); - // Add custom metadata with the response object - tracer.putMetadata('awsResponse', res); + // Add the response as metadata + tracer.addResponseAsMetadata(res, process.env._HANDLER); } catch (err) { + // Add error as metadata to the current subsegment + 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); } - // Close subsegment (the AWS Lambda one is closed automatically) - subsegment.close(); - // Set the facade segment as active again - tracer.setSegment(segment); - return res; }; \ No newline at end of file diff --git a/examples/cdk/lib/example-function.Tracer.PatchAllAWSSDK.ts b/examples/cdk/lib/example-function.Tracer.PatchAllAWSSDK.ts index d6fa8f6665..55fa5ba534 100644 --- a/examples/cdk/lib/example-function.Tracer.PatchAllAWSSDK.ts +++ b/examples/cdk/lib/example-function.Tracer.PatchAllAWSSDK.ts @@ -2,14 +2,18 @@ import { Context } from 'aws-lambda'; import { Events } from '@aws-lambda-powertools/commons'; import { Tracer } from '@aws-lambda-powertools/tracer'; -// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor const tracer = new Tracer({ serviceName: 'tracerPatchAllAWSSDKFn' }); -// To patch all AWS SDKs, we need to import aws-sdk and pass it to the Tracer +// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable +// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html + +// To patch all AWS SDKs v2, we need to import aws-sdk and pass it to the Tracer // eslint-disable-next-line @typescript-eslint/no-var-requires const AWS = tracer.captureAWS(require('aws-sdk')); // Then we can use the AWS SDK as usual const sts = new AWS.STS(); +// Here we are showing an example with manual instrumentation but you can do the same also with the captureLambdaHandler Middy Middleware and Class decorator +// See: https://awslabs.github.io/aws-lambda-powertools-typescript/latest/core/tracer/#lambda-handler export const handler = async (_event: typeof Events.Custom.CustomEvent, _context: Context): 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 @@ -20,16 +24,18 @@ export const handler = async (_event: typeof Events.Custom.CustomEvent, _context try { // Tracer will create a subsegment for the AWS SDK call and capture relevant annotations and metadata res = await sts.getCallerIdentity({}).promise(); - // Add custom metadata with the response object - tracer.putMetadata('awsResponse', res); + // Add the response as metadata + tracer.addResponseAsMetadata(res, process.env._HANDLER); } catch (err) { + // Add error as metadata to the current subsegment + 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); } - // Close subsegment (the AWS Lambda one is closed automatically) - subsegment.close(); - // Set the facade segment as active again - tracer.setSegment(segment); - return res; }; \ No newline at end of file