Skip to content

Commit 1c59e21

Browse files
committed
Add examples
1 parent a0b9c6d commit 1c59e21

15 files changed

+36743
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ node_modules
1818
# Build output
1919
dist
2020
lib
21+
!examples/cdk/lib
2122

2223
# Coverage directory
2324
coverage

examples/cdk/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.js
2+
!jest.config.js
3+
*.d.ts
4+
node_modules
5+
6+
# CDK asset staging directory
7+
.cdk.staging
8+
cdk.out

examples/cdk/.npmignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.ts
2+
!*.d.ts
3+
4+
# CDK asset staging directory
5+
.cdk.staging
6+
cdk.out

examples/cdk/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Welcome to your CDK TypeScript project!
2+
3+
This is a blank project for TypeScript development with CDK.
4+
5+
The `cdk.json` file tells the CDK Toolkit how to execute your app.
6+
7+
## Useful commands
8+
9+
* `npm run build` compile typescript to js
10+
* `npm run watch` watch for changes and compile
11+
* `npm run test` perform the jest unit tests
12+
* `cdk deploy` deploy this stack to your default AWS account/region
13+
* `cdk diff` compare deployed stack with current state
14+
* `cdk synth` emits the synthesized CloudFormation template

examples/cdk/bin/cdk-app.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env node
2+
import 'source-map-support/register';
3+
import * as cdk from 'aws-cdk-lib';
4+
import { CdkAppStack } from '../lib/example-stack';
5+
6+
const app = new cdk.App();
7+
new CdkAppStack(app, 'CdkAppStack', {
8+
/* If you don't specify 'env', this stack will be environment-agnostic.
9+
* Account/Region-dependent features and context lookups will not work,
10+
* but a single synthesized template can be deployed anywhere. */
11+
12+
/* Uncomment the next line to specialize this stack for the AWS Account
13+
* and Region that are implied by the current CLI configuration. */
14+
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
15+
16+
/* Uncomment the next line if you know exactly what Account and Region you
17+
* want to deploy the stack to. */
18+
// env: { account: '123456789012', region: 'us-east-1' },
19+
20+
/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
21+
});

examples/cdk/cdk.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"app": "npx ts-node --prefer-ts-exts bin/cdk-app.ts",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"**/*.d.ts",
11+
"**/*.js",
12+
"tsconfig.json",
13+
"package*.json",
14+
"yarn.lock",
15+
"node_modules",
16+
"test"
17+
]
18+
},
19+
"context": {
20+
"@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
21+
"@aws-cdk/core:stackRelativeExports": true,
22+
"@aws-cdk/aws-rds:lowercaseDbIdentifier": true,
23+
"@aws-cdk/aws-lambda:recognizeVersionProps": true,
24+
"@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true
25+
}
26+
}

examples/cdk/jest.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
testEnvironment: 'node',
3+
roots: ['<rootDir>/test'],
4+
testMatch: ['**/*.test.ts'],
5+
transform: {
6+
'^.+\\.tsx?$': 'ts-jest'
7+
}
8+
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {Metrics, MetricUnits} from '@aws-lambda-powertools/metrics';
2+
import {Logger} from '@aws-lambda-powertools/logger';
3+
import {Tracer} from '@aws-lambda-powertools/tracer';
4+
import { Subsegment } from 'aws-xray-sdk-core';
5+
6+
7+
8+
const namespace = 'CDKExample';
9+
const serviceName = 'MyFunctionWithStandardHandler';
10+
11+
const metrics = new Metrics({ namespace: namespace, service: serviceName });
12+
const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName });
13+
const tracer = new Tracer({ serviceName: serviceName });
14+
15+
export const handler = async (event: any, context: any) => {
16+
// ### Experiment logger
17+
logger.addPersistentLogAttributes({
18+
testKey: 'testValue',
19+
});
20+
logger.debug('This is an DEBUG log'); // Won't show by default
21+
logger.info('This is an INFO log');
22+
logger.warn('This is an WARN log');
23+
logger.error('This is an ERROR log');
24+
25+
// ### Experiment metrics
26+
metrics.captureColdStartMetric();
27+
metrics.raiseOnEmptyMetrics();
28+
metrics.setDefaultDimensions({ environment: 'example', type: 'standardFunction' });
29+
metrics.addMetric('test-metric', MetricUnits.Count, 10);
30+
31+
const metricWithItsOwnDimensions = metrics.singleMetric();
32+
metricWithItsOwnDimensions.addDimension('InnerDimension', 'true');
33+
metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50);
34+
35+
metrics.purgeStoredMetrics();
36+
metrics.raiseOnEmptyMetrics();
37+
38+
// ### Experiment tracer
39+
tracer.putAnnotation('Myannotation', 'My annotation\'s value');
40+
41+
// Create subsegment & set it as active
42+
const subsegment = new Subsegment('MySubSegment');
43+
tracer.setSegment(subsegment);
44+
// TODO: Add the ColdStart annotation !!! NOT POSSIBLE
45+
// tracer.putAnnotation('ColdStart', tracer);
46+
47+
try {
48+
throw new Error('test');
49+
// Add the response as metadata
50+
} catch (err) {
51+
// Add the error as metadata
52+
subsegment.addError(err as Error, false);
53+
}
54+
55+
// Close subsegment
56+
subsegment.close();
57+
};
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics';
2+
import { Logger, createLogger } from '@aws-lambda-powertools/logger';
3+
import { Tracer } from '@aws-lambda-powertools/tracer';
4+
import { Subsegment } from 'aws-xray-sdk-core';
5+
import { Callback, Context } from 'aws-lambda';
6+
7+
const namespace = 'CDKExample';
8+
const serviceName = 'MyFunctionWithDecorator';
9+
10+
const metrics = new Metrics({ namespace: namespace, service: serviceName });
11+
const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName });
12+
const tracer = new Tracer({ serviceName: serviceName });
13+
14+
export class MyFunctionWithDecorator {
15+
@tracer.captureLambdaHanlder()
16+
@logger.injectLambdaContext()
17+
@metrics.logMetrics({
18+
captureColdStartMetric: true,
19+
raiseOnEmptyMetrics: true,
20+
defaultDimensions: { environment: 'example', type: 'withDecorator' },
21+
})
22+
public handler(_event: any, _context: Context, _callback: Callback<any>): void | Promise<any> {
23+
// ### Experiment logger
24+
logger.addPersistentLogAttributes({
25+
testKey: 'testValue',
26+
});
27+
logger.debug('This is an DEBUG log'); // Won't show by default
28+
logger.info('This is an INFO log');
29+
logger.warn('This is an WARN log');
30+
logger.error('This is an ERROR log');
31+
32+
// ### Experiment metrics
33+
metrics.addMetric('test-metric', MetricUnits.Count, 10);
34+
35+
const metricWithItsOwnDimensions = metrics.singleMetric();
36+
metricWithItsOwnDimensions.addDimension('InnerDimension', 'true');
37+
metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50);
38+
39+
// ### Experiment tracer
40+
tracer.putAnnotation('Myannotation', 'My annotation\'s value');
41+
42+
// Create subsegment & set it as active
43+
const subsegment = new Subsegment('MySubSegment');
44+
tracer.setSegment(subsegment);
45+
// TODO: Add the ColdStart annotation !!! NOT POSSIBLE
46+
// tracer.putAnnotation('ColdStart', tracer);
47+
48+
try {
49+
throw new Error('test');
50+
// Add the response as metadata
51+
} catch (err) {
52+
// Add the error as metadata
53+
subsegment.addError(err as Error, false);
54+
}
55+
56+
// Close subsegment
57+
subsegment.close();
58+
}
59+
}
60+
61+
export const handlerClass = new MyFunctionWithDecorator();
62+
export const handler = handlerClass.handler;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import middy from '@middy/core'
2+
import {Metrics, MetricUnits} from '@aws-lambda-powertools/metrics';
3+
import { Callback, Context } from 'aws-lambda';
4+
5+
6+
const metrics = new Metrics({namespace:"CDKExample", service:"withMiddy"}); // Sets metric namespace, and service as a metric dimension
7+
8+
class MyFunctionWithDecorator {
9+
10+
@metrics.logMetrics({captureColdStartMetric: true})
11+
public handler(_event: any, _context: Context, _callback: Callback<any>): void | Promise<any> {
12+
metrics.addMetric('test-metric', MetricUnits.Count, 10);
13+
if(_event.throw) {
14+
throw new Error('Test error');
15+
}
16+
}
17+
}
18+
19+
const handler = middy(async (_event, _context) => {
20+
21+
const handlerClass = new MyFunctionWithDecorator()
22+
return handlerClass.handler(_event, _context, () => {});
23+
})
24+
25+
handler.before(async (_request) => {
26+
metrics.addMetric('beforeHandlerCalled', MetricUnits.Count, 1);
27+
})
28+
29+
handler.after(async (_request) => {
30+
// Won't be flushed since happens after
31+
metrics.addMetric('afterHandlerCalled', MetricUnits.Count, 1);
32+
33+
})
34+
35+
handler.onError(async (_request) => {
36+
metrics.addMetric('onErrorHandlerCalled', MetricUnits.Count, 1);
37+
})
38+
39+
module.exports = { handler }

examples/cdk/lib/example-stack.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { Stack, StackProps, custom_resources, aws_iam } from 'aws-cdk-lib';
2+
import {Events} from '@aws-lambda-powertools/commons';
3+
import { Construct } from 'constructs';
4+
import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
5+
import { Tracing } from 'aws-cdk-lib/aws-lambda';
6+
7+
export class CdkAppStack extends Stack {
8+
constructor(scope: Construct, id: string, props?: StackProps) {
9+
super(scope, id, props);
10+
11+
const myFunctionWithStandardFunctions = new lambda.NodejsFunction(this, 'MyFunction', { tracing: Tracing.ACTIVE });
12+
const myFunctionWithDecorator = new lambda.NodejsFunction(this, 'MyFunctionWithDecorator', {
13+
tracing: Tracing.ACTIVE,
14+
});
15+
const myFunctionWithWithMiddleware = new lambda.NodejsFunction(this, 'MyFunctionWithMiddy', {
16+
tracing: Tracing.ACTIVE,
17+
});
18+
19+
// Invoke all functions twice
20+
for (let i = 0; i < 2; i++) {
21+
new custom_resources.AwsCustomResource(this, `Invoke-std-func-${i}`, {
22+
onUpdate: {
23+
service: 'Lambda',
24+
action: 'invoke',
25+
physicalResourceId: custom_resources.PhysicalResourceId.of(new Date().toISOString()),
26+
parameters: {
27+
FunctionName: myFunctionWithStandardFunctions.functionName,
28+
InvocationType: 'RequestResponse',
29+
Payload: JSON.stringify(Events.Custom.CustomEvent),
30+
}
31+
},
32+
policy: custom_resources.AwsCustomResourcePolicy.fromStatements([
33+
new aws_iam.PolicyStatement({
34+
effect: aws_iam.Effect.ALLOW,
35+
resources: [
36+
myFunctionWithStandardFunctions.functionArn,
37+
],
38+
actions: ['lambda:InvokeFunction'],
39+
}),
40+
]),
41+
});
42+
new custom_resources.AwsCustomResource(this, `Invoke-dec-func-${i}`, {
43+
onUpdate: {
44+
service: 'Lambda',
45+
action: 'invoke',
46+
physicalResourceId: custom_resources.PhysicalResourceId.of(new Date().toISOString()),
47+
parameters: {
48+
FunctionName: myFunctionWithDecorator.functionName,
49+
InvocationType: 'RequestResponse',
50+
Payload: JSON.stringify(Events.Custom.CustomEvent),
51+
}
52+
},
53+
policy: custom_resources.AwsCustomResourcePolicy.fromStatements([
54+
new aws_iam.PolicyStatement({
55+
effect: aws_iam.Effect.ALLOW,
56+
resources: [
57+
myFunctionWithDecorator.functionArn,
58+
],
59+
actions: ['lambda:InvokeFunction'],
60+
}),
61+
]),
62+
});
63+
new custom_resources.AwsCustomResource(this, `Invoke-middy-func-${i}`, {
64+
onUpdate: {
65+
service: 'Lambda',
66+
action: 'invoke',
67+
physicalResourceId: custom_resources.PhysicalResourceId.of(new Date().toISOString()),
68+
parameters: {
69+
FunctionName: myFunctionWithWithMiddleware.functionName,
70+
InvocationType: 'RequestResponse',
71+
Payload: JSON.stringify(Events.Custom.CustomEvent),
72+
}
73+
},
74+
policy: custom_resources.AwsCustomResourcePolicy.fromStatements([
75+
new aws_iam.PolicyStatement({
76+
effect: aws_iam.Effect.ALLOW,
77+
resources: [
78+
myFunctionWithWithMiddleware.functionArn,
79+
],
80+
actions: ['lambda:InvokeFunction'],
81+
}),
82+
]),
83+
});
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)