Skip to content

Commit 4cdaaea

Browse files
dreamorosiijemmy
andauthored
fix: updated CDK examples to remove old references & improve comments (#439)
* fix: updated CDK examples to correct errors & improved comments/structure * fix: updated comment * fix: Update examples/cdk/lib/example-function.Tracer.CaptureErrorDisabled.ts Co-authored-by: ijemmy <[email protected]> * fix: Update examples/cdk/lib/example-function.MyFunctionWithMiddy.ts Co-authored-by: ijemmy <[email protected]> * fix: added missing throw error statement Co-authored-by: ijemmy <[email protected]>
1 parent cf43568 commit 4cdaaea

12 files changed

+189
-110
lines changed

Diff for: examples/cdk/lib/example-function.MyFunction.ts

+31-19
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,24 @@ import { Tracer } from '@aws-lambda-powertools/tracer';
66
const namespace = 'CDKExample';
77
const serviceName = 'MyFunctionWithStandardHandler';
88

9-
const metrics = new Metrics({ namespace: namespace, service: serviceName });
9+
const metrics = new Metrics({ namespace: namespace, serviceName: serviceName });
1010
const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName });
1111
const tracer = new Tracer({ serviceName: serviceName });
1212

13-
export const handler = async (_event: unknown, context: Context): Promise<void> => {
13+
export const handler = async (event: unknown, context: Context): Promise<void> => {
1414
// 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)
1515
// we do it at the beginning because we want to trace the whole duration of the handler
16-
const segment = tracer.getSegment(); // This is the facade segment (the one that is created by Lambda & that can't be manipulated)
17-
const handlerSegment = segment.addNewSubsegment(`## ${context.functionName}`);
18-
// TODO: expose tracer.annotateColdStart()
19-
tracer.putAnnotation('ColdStart', Tracer.coldStart);
16+
const segment = tracer.getSegment(); // This is the facade segment (the one that is created by AWS Lambda)
17+
// Create subsegment for the function & set it as active
18+
const handlerSegment = segment.addNewSubsegment(`## ${process.env._HANDLER}`);
19+
tracer.setSegment(handlerSegment);
2020

21-
// ### Experiment logger
21+
// Annotate the subsegment with the cold start & serviceName
22+
tracer.annotateColdStart();
23+
tracer.addServiceNameAnnotation();
24+
25+
// ### Experiment with Logger
26+
logger.addContext(context);
2227
logger.addPersistentLogAttributes({
2328
testKey: 'testValue',
2429
});
@@ -27,7 +32,7 @@ export const handler = async (_event: unknown, context: Context): Promise<void>
2732
logger.warn('This is an WARN log');
2833
logger.error('This is an ERROR log');
2934

30-
// ### Experiment metrics
35+
// ### Experiment with Metrics
3136
metrics.captureColdStartMetric();
3237
metrics.throwOnEmptyMetrics();
3338
metrics.setDefaultDimensions({ environment: 'example', type: 'standardFunction' });
@@ -38,24 +43,31 @@ export const handler = async (_event: unknown, context: Context): Promise<void>
3843
metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50);
3944

4045
metrics.publishStoredMetrics();
41-
metrics.raiseOnEmptyMetrics();
42-
43-
// ### Experiment tracer
46+
metrics.throwOnEmptyMetrics();
4447

45-
tracer.putAnnotation('Myannotation', 'My annotation\'s value');
48+
// ### Experiment with Tracer
49+
// This annotation & metadata will be added to the handlerSegment subsegment (## index.handler)
50+
tracer.putAnnotation('awsRequestId', context.awsRequestId);
51+
tracer.putMetadata('eventPayload', event);
4652

47-
// Create subsegment & set it as active
48-
const subsegment = handlerSegment.addNewSubsegment('MySubSegment');
53+
// Create another subsegment & set it as active
54+
const subsegment = handlerSegment.addNewSubsegment('### MySubSegment');
55+
tracer.setSegment(subsegment);
4956

57+
let res;
5058
try {
51-
throw new Error('test');
52-
// Add the response as metadata
59+
res = { foo: 'bar' };
60+
tracer.addResponseAsMetadata(res, process.env._HANDLER);
5361
} catch (err) {
5462
// Add the error as metadata
5563
subsegment.addError(err as Error, false);
64+
throw err;
65+
} finally {
66+
// Close subsegments (the AWS Lambda one is closed automatically)
67+
subsegment.close(); // (### MySubSegment)
68+
handlerSegment.close(); // (## index.handler)
69+
// Set the facade segment as active again (the one created by AWS Lambda)
70+
tracer.setSegment(segment);
5671
}
5772

58-
// Close subsegment
59-
subsegment.close();
60-
handlerSegment.close();
6173
};
+28-20
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
import { Tracer } from '@aws-lambda-powertools/tracer';
2-
import { Callback, Context } from 'aws-lambda';
2+
import { Context } from 'aws-lambda';
3+
import { Events, LambdaInterface } from '@aws-lambda-powertools/commons';
34
import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics';
45
import { Logger } from '@aws-lambda-powertools/logger';
56

67
const namespace = 'CDKExample';
78
const serviceName = 'MyFunctionWithDecorator';
89

9-
const metrics = new Metrics({ namespace: namespace, service: serviceName });
10+
const metrics = new Metrics({ namespace: namespace, serviceName: serviceName });
1011
const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName });
1112
const tracer = new Tracer({ serviceName: serviceName });
1213

13-
export class MyFunctionWithDecorator {
14-
@tracer.captureLambdaHanlder()
14+
export class MyFunctionWithDecorator implements LambdaInterface {
15+
// We decorate the handler with the various decorators
16+
@tracer.captureLambdaHandler()
1517
@logger.injectLambdaContext()
1618
@metrics.logMetrics({
1719
captureColdStartMetric: true,
1820
throwOnEmptyMetrics: true,
1921
defaultDimensions: { environment: 'example', type: 'withDecorator' },
2022
})
21-
public handler(_event: unknown, _context: Context, _callback: Callback<unknown>): void | Promise<unknown> {
23+
public async handler(event: typeof Events.Custom.CustomEvent, context: Context): Promise<unknown> {
2224
// ### Experiment logger
2325
logger.addPersistentLogAttributes({
2426
testKey: 'testValue',
@@ -36,28 +38,34 @@ export class MyFunctionWithDecorator {
3638
metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50);
3739

3840
// ### Experiment tracer
39-
tracer.putAnnotation('Myannotation', 'My annotation\'s value');
4041

41-
// Create subsegment & set it as active
42-
const segment = tracer.getSegment(); // This is the facade segment (the one that is created by Lambda & that can't be manipulated)
43-
const subsegment = segment.addNewSubsegment('MySubSegment');
42+
// Service & Cold Start annotations will be added for you by the decorator/middleware
4443

44+
// These traces will be added to the main segment (## index.handler)
45+
tracer.putAnnotation('awsRequestId', context.awsRequestId);
46+
tracer.putMetadata('eventPayload', event);
47+
48+
// Create another subsegment & set it as active
49+
const handlerSegment = tracer.getSegment(); // This is the custom segment created by Tracer for you (## index.handler)
50+
const subsegment = handlerSegment.addNewSubsegment('### MySubSegment');
4551
tracer.setSegment(subsegment);
46-
// TODO: Add the ColdStart annotation !!! NOT POSSIBLE
47-
// tracer.putAnnotation('ColdStart', tracer);
4852

53+
let res;
4954
try {
50-
throw new Error('test');
51-
// Add the response as metadata
55+
res = { foo: 'bar' };
5256
} catch (err) {
53-
// Add the error as metadata
54-
subsegment.addError(err as Error, false);
57+
throw err;
58+
} finally {
59+
// Close the subsegment you created (### MySubSegment)
60+
subsegment.close();
61+
// Set back the original segment as active (## index.handler)
62+
tracer.setSegment(handlerSegment);
63+
// The main segment (facade) will be closed for you at the end by the decorator/middleware
5564
}
56-
57-
// Close subsegment
58-
subsegment.close();
65+
66+
return res;
5967
}
6068
}
6169

62-
export const handlerClass = new MyFunctionWithDecorator();
63-
export const handler = handlerClass.handler;
70+
export const myFunction = new MyFunctionWithDecorator();
71+
export const handler = myFunction.handler;
+60-30
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,73 @@
11
import middy from '@middy/core';
2-
import { Callback, Context } from 'aws-lambda';
3-
import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics';
2+
import { Context } from 'aws-lambda';
3+
import { Events } from '@aws-lambda-powertools/commons';
4+
import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics';
5+
import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer';
6+
import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger';
47

5-
const metrics = new Metrics({ namespace: 'CDKExample', service: 'withMiddy' }); // Sets metric namespace, and service as a metric dimension
8+
const namespace = 'CDKExample';
9+
const serviceName = 'MyFunctionWithMiddyMiddleware';
610

7-
type CustomEvent = {
8-
throw: boolean
9-
};
11+
const metrics = new Metrics({ namespace: namespace, serviceName: serviceName });
12+
const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName });
13+
const tracer = new Tracer({ serviceName: serviceName });
1014

11-
class MyFunctionWithDecorator {
15+
const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => {
16+
// ### Experiment with Logger
17+
// AWS Lambda context is automatically injected by the middleware
1218

13-
@metrics.logMetrics({ captureColdStartMetric: true })
14-
public handler(_event: CustomEvent, _context: Context, _callback: Callback<unknown>): void | Promise<unknown> {
15-
metrics.addMetric('test-metric', MetricUnits.Count, 10);
16-
if (_event.throw) {
17-
throw new Error('Test error');
18-
}
19-
}
20-
}
19+
logger.addPersistentLogAttributes({
20+
testKey: 'testValue',
21+
});
22+
logger.debug('This is an DEBUG log'); // Won't show because we pass logLevel: 'INFO' in the constructor.
23+
logger.info('This is an INFO log');
24+
logger.warn('This is an WARN log');
25+
logger.error('This is an ERROR log');
2126

22-
const handler = middy(async (_event, _context) => {
27+
// ### Experiment with Metrics
28+
// Default metrics, cold start, and throwOnEmptyMetrics are enabled by the middleware
2329

24-
const handlerClass = new MyFunctionWithDecorator();
30+
metrics.addMetric('test-metric', MetricUnits.Count, 10);
2531

26-
return handlerClass.handler(_event, _context, () => console.log('Lambda invoked!'));
27-
});
32+
const metricWithItsOwnDimensions = metrics.singleMetric();
33+
metricWithItsOwnDimensions.addDimension('InnerDimension', 'true');
34+
metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50);
35+
36+
// ### Experiment with Tracer
2837

29-
handler.before(async (_request) => {
30-
metrics.addMetric('beforeHandlerCalled', MetricUnits.Count, 1);
31-
});
38+
// Service & Cold Start annotations will be added for you by the decorator/middleware
3239

33-
handler.after(async (_request) => {
34-
// Won't be flushed since happens after
35-
metrics.addMetric('afterHandlerCalled', MetricUnits.Count, 1);
40+
// These traces will be added to the main segment (## index.handler)
41+
tracer.putAnnotation('awsRequestId', context.awsRequestId);
42+
tracer.putMetadata('eventPayload', event);
3643

37-
});
44+
// Create another subsegment & set it as active
45+
const handlerSegment = tracer.getSegment(); // This is the custom segment created by Tracer for you (## index.handler)
46+
const subsegment = handlerSegment.addNewSubsegment('### MySubSegment');
47+
tracer.setSegment(subsegment);
3848

39-
handler.onError(async (_request) => {
40-
metrics.addMetric('onErrorHandlerCalled', MetricUnits.Count, 1);
41-
});
49+
let res;
50+
try {
51+
res = { foo: 'bar' };
52+
} catch (err) {
53+
throw err;
54+
} finally {
55+
// Close the subsegment you created (### MySubSegment)
56+
subsegment.close();
57+
// Set back the original segment as active (## index.handler)
58+
tracer.setSegment(handlerSegment);
59+
// The main segment (facade) will be closed for you at the end by the decorator/middleware
60+
}
61+
62+
return res;
63+
}
4264

43-
module.exports = { handler };
65+
// We instrument the handler with the various Middy middlewares
66+
export const handler = middy(lambdaHandler)
67+
.use(captureLambdaHandler(tracer))
68+
.use(logMetrics(metrics, {
69+
captureColdStartMetric: true,
70+
throwOnEmptyMetrics: true,
71+
defaultDimensions: { environment: 'example', type: 'withDecorator' },
72+
}))
73+
.use(injectLambdaContext(logger));

Diff for: examples/cdk/lib/example-function.Tracer.CaptureErrorDisabled.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import { Context } from 'aws-lambda';
33
import { Events } from '@aws-lambda-powertools/commons';
44
import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer';
55

6-
// Set environment variable to disable capture response
6+
// Set environment variable to disable capture response - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
77
process.env.POWERTOOLS_TRACER_ERROR_RESPONSE = 'false';
88
const tracer = new Tracer({ serviceName: 'tracerCaptureErrorDisabledFn' });
99

10-
// In this example we are using the middleware pattern but you could use also the captureLambdaHandler decorator
10+
// In this example we are using the Middy middleware pattern but you can instrument your functions also with the captureLambdaHandler decorator & manual instrumentation
1111
export const handler = middy(async (event: typeof Events.Custom.CustomEvent, context: Context) => {
1212
tracer.putAnnotation('awsRequestId', context.awsRequestId);
1313
tracer.putMetadata('eventPayload', event);

Diff for: examples/cdk/lib/example-function.Tracer.CaptureResponseDisabled.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Context } from 'aws-lambda';
33
import { Events } from '@aws-lambda-powertools/commons';
44
import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer';
55

6-
// Set environment variable to disable capture response
6+
// Set environment variable to disable capture response - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
77
process.env.POWERTOOLS_TRACER_CAPTURE_RESPONSE = 'false';
88
const tracer = new Tracer({ serviceName: 'tracerCaptureResponseDisabledFn' });
99

Diff for: examples/cdk/lib/example-function.Tracer.Decorator.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { Callback, Context } from 'aws-lambda';
22
import { Events } from '@aws-lambda-powertools/commons';
33
import { Tracer } from '@aws-lambda-powertools/tracer';
44

5-
// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor
65
const tracer = new Tracer({ serviceName: 'tracerDecoratorFn' });
6+
// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable
7+
// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
78

89
export class MyFunctionWithDecorator {
910
// We instrument the handler with the decorator and the tracer will automatically create a subsegment and capture relevant annotations and metadata

Diff for: examples/cdk/lib/example-function.Tracer.Disabled.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import { Context } from 'aws-lambda';
33
import { Events } from '@aws-lambda-powertools/commons';
44
import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer';
55

6-
// process.env.POWERTOOLS_TRACE_ENABLED = 'false'; // Alternative to disabling tracing in the constructor
6+
// Disable Tracer by setting POWERTOOLS_TRACE_ENABLED = 'false' in the function environment variables - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
77
const tracer = new Tracer({ serviceName: 'tracerDisabledFn', enabled: false });
88

9-
// In this example we are using the middleware pattern but you could use also the captureLambdaHandler decorator or the manual mode
10-
export const handler = middy(async (event: typeof Events.Custom.CustomEvent, context: Context) => {
9+
// In this example we are using the middleware pattern but the same applies also the captureLambdaHandler decorator or to manual instrumentation
10+
const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => {
1111
// No tracing will be done and the commands will be ignored, this is useful for testing
1212
tracer.putAnnotation('awsRequestId', context.awsRequestId);
1313
tracer.putMetadata('eventPayload', event);
14-
14+
1515
let res;
1616
try {
1717
res = { foo: 'bar' };
@@ -20,4 +20,6 @@ export const handler = middy(async (event: typeof Events.Custom.CustomEvent, con
2020
}
2121

2222
return res;
23-
}).use(captureLambdaHandler(tracer));
23+
}
24+
25+
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));

Diff for: examples/cdk/lib/example-function.Tracer.Manual.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { Context } from 'aws-lambda';
22
import { Events } from '@aws-lambda-powertools/commons';
33
import { Tracer } from '@aws-lambda-powertools/tracer';
44

5-
// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor
65
const tracer = new Tracer({ serviceName: 'tracerManualFn' });
6+
// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable
7+
// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
78

89
export const handler = async (event: typeof Events.Custom.CustomEvent, context: Context): Promise<unknown> => {
910
const segment = tracer.getSegment(); // This is the facade segment (the one that is created by AWS Lambda)

Diff for: examples/cdk/lib/example-function.Tracer.Middleware.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import { Context } from 'aws-lambda';
33
import { Events } from '@aws-lambda-powertools/commons';
44
import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer';
55

6-
// process.env.POWERTOOLS_SERVICE_NAME = 'tracerManualFn'; // Alternative to setting the service name in the constructor
76
const tracer = new Tracer({ serviceName: 'tracerMiddlewareFn' });
7+
// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable
8+
// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
89

9-
// We instrument the handler with the middy middleware and the tracer will automatically create a subsegment and capture relevant annotations and metadata
10-
export const handler = middy(async (event: typeof Events.Custom.CustomEvent, context: Context) => {
10+
const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => {
1111
// Add custom annotation & metadata
1212
tracer.putAnnotation('awsRequestId', context.awsRequestId);
1313
tracer.putMetadata('eventPayload', event);
14-
14+
1515
let res;
1616
try {
1717
res = { foo: 'bar' };
@@ -20,4 +20,11 @@ export const handler = middy(async (event: typeof Events.Custom.CustomEvent, con
2020
}
2121

2222
return res;
23-
}).use(captureLambdaHandler(tracer));
23+
}
24+
25+
// We instrument the handler with the Middy middleware and the Tracer will automatically:
26+
// * handle the lifecycle of the subsegment
27+
// * create a ColdStart annotation to easily filter traces that have had an initialization overhead
28+
// * create a Service annotation to easily filter traces that have a specific service name
29+
// * captures any response, or full exceptions generated by the handler, and include them as tracing metadata
30+
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));

0 commit comments

Comments
 (0)