Skip to content

Commit

Permalink
feat(tracer): add support for capturing DynamoDB DocumentClient (#450)
Browse files Browse the repository at this point in the history
* feat: add support for capturing DynamoDB DocumentClient

* removed unused error ref

* chore: rebase

* chore: added e2e tests with DynamoDB Table
  • Loading branch information
dreamorosi authored Jan 25, 2022
1 parent 900aba9 commit 621ae50
Show file tree
Hide file tree
Showing 10 changed files with 1,865 additions and 708 deletions.
2,342 changes: 1,714 additions & 628 deletions packages/tracing/package-lock.json

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions packages/tracing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"devDependencies": {
"@aws-cdk/aws-lambda-nodejs": "^1.137.0",
"@aws-cdk/core": "^1.137.0",
"@aws-sdk/client-sts": "^3.45.0",
"@aws-cdk/aws-dynamodb": "^1.139.0",
"@aws-cdk/aws-lambda-nodejs": "^1.139.0",
"@aws-cdk/core": "^1.139.0",
"@aws-sdk/client-dynamodb": "^3.47.0",
"@types/aws-lambda": "^8.10.72",
"@types/jest": "^27.0.0",
"@types/node": "^17.0.8",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"aws-cdk": "^1.137.0",
"aws-cdk": "^1.139.0",
"aws-sdk": "^2.1048.0",
"esbuild": "^0.14.10",
"eslint": "^8.3.0",
Expand Down
10 changes: 9 additions & 1 deletion packages/tracing/src/Tracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,15 @@ class Tracer implements TracerInterface {
public captureAWSClient<T>(service: T): T {
if (!this.isTracingEnabled()) return service;

return this.provider.captureAWSClient(service);
try {
return this.provider.captureAWSClient(service);
} catch (error) {
try {
return this.provider.captureAWSClient((service as unknown as T & { service: T }).service);
} catch {
throw error;
}
}
}

/**
Expand Down
17 changes: 9 additions & 8 deletions packages/tracing/tests/e2e/tracer.test.Decorator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Tracer } from '../../src';
import { Callback, Context } from 'aws-lambda';
import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts';
import { DynamoDBClient, ScanCommand } from '@aws-sdk/client-dynamodb';
// eslint-disable-next-line @typescript-eslint/no-var-requires
let AWS = require('aws-sdk');

Expand All @@ -11,6 +11,7 @@ const customMetadataKey = process.env.EXPECTED_CUSTOM_METADATA_KEY ?? 'myMetadat
const customMetadataValue = JSON.parse(process.env.EXPECTED_CUSTOM_METADATA_VALUE) ?? { bar: 'baz' };
const customResponseValue = JSON.parse(process.env.EXPECTED_CUSTOM_RESPONSE_VALUE) ?? { foo: 'bar' };
const customErrorMessage = process.env.EXPECTED_CUSTOM_ERROR_MESSAGE ?? 'An error has occurred';
const testTableName = process.env.TEST_TABLE_NAME ?? 'TestTable';

interface CustomEvent {
throw: boolean
Expand All @@ -31,7 +32,7 @@ const refreshAWSSDKImport = (): void => {
};

const tracer = new Tracer({ serviceName: serviceName });
const stsv3 = tracer.captureAWSv3Client(new STSClient({}));
const dynamoDBv3 = tracer.captureAWSv3Client(new DynamoDBClient({}));

export class MyFunctionWithDecorator {
@tracer.captureLambdaHandler()
Expand All @@ -41,18 +42,18 @@ export class MyFunctionWithDecorator {
tracer.putAnnotation(customAnnotationKey, customAnnotationValue);
tracer.putMetadata(customMetadataKey, customMetadataValue);

let stsv2;
let dynamoDBv2;
refreshAWSSDKImport();
if (event.sdkV2 === 'client') {
stsv2 = tracer.captureAWSClient(new AWS.STS());
dynamoDBv2 = tracer.captureAWSClient(new AWS.DynamoDB.DocumentClient());
} else if (event.sdkV2 === 'all') {
AWS = tracer.captureAWS(AWS);
stsv2 = new AWS.STS();
dynamoDBv2 = new AWS.DynamoDB.DocumentClient();
}

return Promise.all([
stsv2.getCallerIdentity().promise(),
stsv3.send(new GetCallerIdentityCommand({})),
dynamoDBv2.scan({ TableName: testTableName }).promise(),
dynamoDBv3.send(new ScanCommand({ TableName: testTableName })),
new Promise((resolve, reject) => {
setTimeout(() => {
const res = this.myMethod();
Expand All @@ -64,7 +65,7 @@ export class MyFunctionWithDecorator {
}, 2000); // We need to wait for to make sure previous calls are finished
})
])
.then(([ _stsv2Res, _stsv3Res, promiseRes ]) => promiseRes)
.then(([ _dynamoDBv2Res, _dynamoDBv3Res, promiseRes ]) => promiseRes)
.catch((err) => {
throw err;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Tracer } from '../../src';
import { Context } from 'aws-lambda';
import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts';
import { DynamoDBClient, ScanCommand } from '@aws-sdk/client-dynamodb';
// eslint-disable-next-line @typescript-eslint/no-var-requires
let AWS = require('aws-sdk');

Expand All @@ -11,6 +11,7 @@ const customMetadataKey = process.env.EXPECTED_CUSTOM_METADATA_KEY ?? 'myMetadat
const customMetadataValue = JSON.parse(process.env.EXPECTED_CUSTOM_METADATA_VALUE) ?? { bar: 'baz' };
const customResponseValue = JSON.parse(process.env.EXPECTED_CUSTOM_RESPONSE_VALUE) ?? { foo: 'bar' };
const customErrorMessage = process.env.EXPECTED_CUSTOM_ERROR_MESSAGE ?? 'An error has occurred';
const testTableName = process.env.TEST_TABLE_NAME ?? 'TestTable';

interface CustomEvent {
throw: boolean
Expand All @@ -31,7 +32,7 @@ const refreshAWSSDKImport = (): void => {
};

const tracer = new Tracer({ serviceName: serviceName });
const stsv3 = tracer.captureAWSv3Client(new STSClient({}));
const dynamoDBv3 = tracer.captureAWSv3Client(new DynamoDBClient({}));

export class MyFunctionWithDecorator {
@tracer.captureLambdaHandler()
Expand All @@ -41,23 +42,23 @@ export class MyFunctionWithDecorator {
tracer.putAnnotation(customAnnotationKey, customAnnotationValue);
tracer.putMetadata(customMetadataKey, customMetadataValue);

let stsv2;
let dynamoDBv2;
refreshAWSSDKImport();
if (event.sdkV2 === 'client') {
stsv2 = tracer.captureAWSClient(new AWS.STS());
dynamoDBv2 = tracer.captureAWSClient(new AWS.DynamoDB.DocumentClient());
} else if (event.sdkV2 === 'all') {
AWS = tracer.captureAWS(AWS);
stsv2 = new AWS.STS();
dynamoDBv2 = new AWS.DynamoDB.DocumentClient();
}

try {
await stsv2.getCallerIdentity().promise();
await dynamoDBv2.scan({ TableName: testTableName }).promise();
} catch (err) {
console.error(err);
}

try {
await stsv3.send(new GetCallerIdentityCommand({}));
await dynamoDBv3.send(new ScanCommand({ TableName: testTableName }));
} catch (err) {
console.error(err);
}
Expand Down
15 changes: 8 additions & 7 deletions packages/tracing/tests/e2e/tracer.test.Manual.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Tracer } from '../../src';
import { Context } from 'aws-lambda';
import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts';
import { DynamoDBClient, ScanCommand } from '@aws-sdk/client-dynamodb';
// eslint-disable-next-line @typescript-eslint/no-var-requires
let AWS = require('aws-sdk');

Expand All @@ -11,6 +11,7 @@ const customMetadataKey = process.env.EXPECTED_CUSTOM_METADATA_KEY ?? 'myMetadat
const customMetadataValue = JSON.parse(process.env.EXPECTED_CUSTOM_METADATA_VALUE) ?? { bar: 'baz' };
const customResponseValue = JSON.parse(process.env.EXPECTED_CUSTOM_RESPONSE_VALUE) ?? { foo: 'bar' };
const customErrorMessage = process.env.EXPECTED_CUSTOM_ERROR_MESSAGE ?? 'An error has occurred';
const testTableName = process.env.TEST_TABLE_NAME ?? 'TestTable';

interface CustomEvent {
throw: boolean
Expand All @@ -31,7 +32,7 @@ const refreshAWSSDKImport = (): void => {
};

const tracer = new Tracer({ serviceName: serviceName });
const stsv3 = tracer.captureAWSv3Client(new STSClient({}));
const dynamoDBv3 = tracer.captureAWSv3Client(new DynamoDBClient({}));

export const handler = async (event: CustomEvent, _context: Context): Promise<void> => {
const segment = tracer.getSegment();
Expand All @@ -45,22 +46,22 @@ export const handler = async (event: CustomEvent, _context: Context): Promise<vo
tracer.putAnnotation(customAnnotationKey, customAnnotationValue);
tracer.putMetadata(customMetadataKey, customMetadataValue);

let stsv2;
let dynamoDBv2;
refreshAWSSDKImport();
if (event.sdkV2 === 'client') {
stsv2 = tracer.captureAWSClient(new AWS.STS());
dynamoDBv2 = tracer.captureAWSClient(new AWS.DynamoDB.DocumentClient());
} else if (event.sdkV2 === 'all') {
AWS = tracer.captureAWS(AWS);
stsv2 = new AWS.STS();
dynamoDBv2 = new AWS.DynamoDB.DocumentClient();
}
try {
await stsv2.getCallerIdentity().promise();
await dynamoDBv2.scan({ TableName: testTableName }).promise();
} catch (err) {
console.error(err);
}

try {
await stsv3.send(new GetCallerIdentityCommand({}));
await dynamoDBv3.send(new ScanCommand({ TableName: testTableName }));
} catch (err) {
console.error(err);
}
Expand Down
15 changes: 8 additions & 7 deletions packages/tracing/tests/e2e/tracer.test.Middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import middy from '@middy/core';
import { captureLambdaHandler, Tracer } from '../../src';
import { Context } from 'aws-lambda';
import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts';
import { DynamoDBClient, ScanCommand } from '@aws-sdk/client-dynamodb';
// eslint-disable-next-line @typescript-eslint/no-var-requires
let AWS = require('aws-sdk');

Expand All @@ -12,6 +12,7 @@ const customMetadataKey = process.env.EXPECTED_CUSTOM_METADATA_KEY ?? 'myMetadat
const customMetadataValue = JSON.parse(process.env.EXPECTED_CUSTOM_METADATA_VALUE) ?? { bar: 'baz' };
const customResponseValue = JSON.parse(process.env.EXPECTED_CUSTOM_RESPONSE_VALUE) ?? { foo: 'bar' };
const customErrorMessage = process.env.EXPECTED_CUSTOM_ERROR_MESSAGE ?? 'An error has occurred';
const testTableName = process.env.TEST_TABLE_NAME ?? 'TestTable';

interface CustomEvent {
throw: boolean
Expand All @@ -32,29 +33,29 @@ const refreshAWSSDKImport = (): void => {
};

const tracer = new Tracer({ serviceName: serviceName });
const stsv3 = tracer.captureAWSv3Client(new STSClient({}));
const dynamoDBv3 = tracer.captureAWSv3Client(new DynamoDBClient({}));

export const handler = middy(async (event: CustomEvent, _context: Context): Promise<void> => {
tracer.putAnnotation('invocation', event.invocation);
tracer.putAnnotation(customAnnotationKey, customAnnotationValue);
tracer.putMetadata(customMetadataKey, customMetadataValue);

let stsv2;
let dynamoDBv2;
refreshAWSSDKImport();
if (event.sdkV2 === 'client') {
stsv2 = tracer.captureAWSClient(new AWS.STS());
dynamoDBv2 = tracer.captureAWSClient(new AWS.DynamoDB.DocumentClient());
} else if (event.sdkV2 === 'all') {
AWS = tracer.captureAWS(AWS);
stsv2 = new AWS.STS();
dynamoDBv2 = new AWS.DynamoDB.DocumentClient();
}
try {
await stsv2.getCallerIdentity().promise();
await dynamoDBv2.scan({ TableName: testTableName }).promise();
} catch (err) {
console.error(err);
}

try {
await stsv3.send(new GetCallerIdentityCommand({}));
await dynamoDBv3.send(new ScanCommand({ TableName: testTableName }));
} catch (err) {
console.error(err);
}
Expand Down
Loading

0 comments on commit 621ae50

Please sign in to comment.