Skip to content

Commit cb4de92

Browse files
committed
test: add decorator e2e
1 parent dd42e52 commit cb4de92

File tree

2 files changed

+117
-4
lines changed

2 files changed

+117
-4
lines changed

Diff for: packages/tracer/tests/e2e/allFeatures.decorator.test.functionCode.ts

+37-4
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@ const refreshAWSSDKImport = (): void => {
3535
const tracer = new Tracer({ serviceName: serviceName });
3636
const dynamoDBv3 = tracer.captureAWSv3Client(new DynamoDBClient({}));
3737

38-
export class MyFunctionWithDecorator {
38+
export class MyFunctionBase {
3939
private readonly returnValue: string;
4040

4141
public constructor() {
4242
this.returnValue = customResponseValue;
4343
}
4444

45-
@tracer.captureLambdaHandler()
4645
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
4746
// @ts-ignore
4847
public handler(event: CustomEvent, _context: Context, _callback: Callback<unknown>): void | Promise<unknown> {
@@ -79,13 +78,47 @@ export class MyFunctionWithDecorator {
7978
});
8079
}
8180

82-
@tracer.captureMethod()
8381
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
8482
// @ts-ignore
8583
public myMethod(): string {
8684
return this.returnValue;
8785
}
8886
}
8987

88+
class MyFunctionWithDecorator extends MyFunctionBase {
89+
@tracer.captureLambdaHandler()
90+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
91+
// @ts-ignore
92+
public handler(event: CustomEvent, _context: Context, _callback: Callback<unknown>): void | Promise<unknown> {
93+
return super.handler(event, _context, _callback);
94+
}
95+
96+
@tracer.captureMethod()
97+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
98+
// @ts-ignore
99+
public myMethod(): string {
100+
return super.myMethod();
101+
}
102+
}
103+
90104
const handlerClass = new MyFunctionWithDecorator();
91-
export const handler = handlerClass.handler.bind(handlerClass);
105+
export const handler = handlerClass.handler.bind(handlerClass);
106+
107+
class MyFunctionWithDecoratorCaptureResponseFalse extends MyFunctionBase {
108+
@tracer.captureLambdaHandler({ captureResponse: false })
109+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
110+
// @ts-ignore
111+
public handler(event: CustomEvent, _context: Context, _callback: Callback<unknown>): void | Promise<unknown> {
112+
return super.handler(event, _context, _callback);
113+
}
114+
115+
@tracer.captureMethod({ captureResponse: false })
116+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
117+
// @ts-ignore
118+
public myMethod(): string {
119+
return super.myMethod();
120+
}
121+
}
122+
123+
const handlerWithCaptureResponseFalseClass = new MyFunctionWithDecoratorCaptureResponseFalse();
124+
export const handlerWithCaptureResponseFalse = handlerClass.handler.bind(handlerWithCaptureResponseFalseClass);

Diff for: packages/tracer/tests/e2e/allFeatures.decorator.test.ts

+80
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ const uuidFunction3 = v4();
7878
const functionNameWithTracerDisabled = generateUniqueName(RESOURCE_NAME_PREFIX, uuidFunction3, runtime, 'AllFeatures-Decorator-TracerDisabled');
7979
const serviceNameWithTracerDisabled = functionNameWithNoCaptureErrorOrResponse;
8080

81+
/**
82+
* Function #4 disables tracer
83+
*/
84+
const uuidFunction4 = v4();
85+
const functionNameWithCaptureResponseFalse = generateUniqueName(RESOURCE_NAME_PREFIX, uuidFunction4, runtime, 'AllFeatures-Decorator-CaptureResponseFalse');
86+
const serviceNameWithCaptureResponseFalse = functionNameWithCaptureResponseFalse;
87+
8188
const xray = new AWS.XRay();
8289
const invocations = 3;
8390

@@ -149,13 +156,30 @@ describe(`Tracer E2E tests, all features with decorator instantiation for runtim
149156
});
150157
ddbTable.grantWriteData(functionWithTracerDisabled);
151158

159+
const functionWithCaptureResponseFalse = createTracerTestFunction({
160+
stack,
161+
functionName: functionNameWithCaptureResponseFalse,
162+
handler: 'handlerWithCaptureResponseFalse',
163+
entry,
164+
expectedServiceName: serviceNameWithCaptureResponseFalse,
165+
environmentParams: {
166+
TEST_TABLE_NAME: ddbTableName,
167+
POWERTOOLS_TRACER_CAPTURE_RESPONSE: 'true',
168+
POWERTOOLS_TRACER_CAPTURE_ERROR: 'true',
169+
POWERTOOLS_TRACE_ENABLED: 'true',
170+
},
171+
runtime
172+
});
173+
ddbTable.grantWriteData(functionWithCaptureResponseFalse);
174+
152175
await deployStack(integTestApp, stack);
153176

154177
// Act
155178
await Promise.all([
156179
invokeAllTestCases(functionNameWithAllFlagsEnabled),
157180
invokeAllTestCases(functionNameWithNoCaptureErrorOrResponse),
158181
invokeAllTestCases(functionNameWithTracerDisabled),
182+
invokeAllTestCases(functionNameWithCaptureResponseFalse),
159183
]);
160184

161185
}, SETUP_TIMEOUT);
@@ -303,6 +327,62 @@ describe(`Tracer E2E tests, all features with decorator instantiation for runtim
303327

304328
}, TEST_CASE_TIMEOUT);
305329

330+
it('should not capture response when the decorator\'s captureResponse is set to false', async () => {
331+
332+
const tracesWithCaptureResponseFalse = await getTraces(xray, startTime, await getFunctionArn(functionNameWithCaptureResponseFalse), invocations, 5);
333+
334+
expect(tracesWithCaptureResponseFalse.length).toBe(invocations);
335+
336+
// Assess
337+
for (let i = 0; i < invocations; i++) {
338+
const trace = tracesWithCaptureResponseFalse[i];
339+
340+
/**
341+
* Expect the trace to have 5 segments:
342+
* 1. Lambda Context (AWS::Lambda)
343+
* 2. Lambda Function (AWS::Lambda::Function)
344+
* 3. DynamoDB (AWS::DynamoDB)
345+
* 4. DynamoDB Table (AWS::DynamoDB::Table)
346+
* 5. Remote call (httpbin.org)
347+
*/
348+
expect(trace.Segments.length).toBe(5);
349+
const invocationSubsegment = getInvocationSubsegment(trace);
350+
351+
/**
352+
* Invocation subsegment should have a subsegment '## index.handler' (default behavior for PowerTool tracer)
353+
* '## index.handler' subsegment should have 4 subsegments
354+
* 1. DynamoDB (PutItem on the table)
355+
* 2. DynamoDB (PutItem overhead)
356+
* 3. httpbin.org (Remote call)
357+
* 4. '### myMethod' (method decorator)
358+
*/
359+
const handlerSubsegment = getFirstSubsegment(invocationSubsegment);
360+
expect(handlerSubsegment.name).toBe('## index.handlerWithCaptureResponseFalse');
361+
expect(handlerSubsegment?.subsegments).toHaveLength(4);
362+
363+
if (!handlerSubsegment.subsegments) {
364+
fail('"## index.handlerWithCaptureResponseFalse" subsegment should have subsegments');
365+
}
366+
const subsegments = splitSegmentsByName(handlerSubsegment.subsegments, [ 'DynamoDB', 'httpbin.org', '### myMethod' ]);
367+
expect(subsegments.get('DynamoDB')?.length).toBe(2);
368+
expect(subsegments.get('httpbin.org')?.length).toBe(1);
369+
expect(subsegments.get('### myMethod')?.length).toBe(1);
370+
expect(subsegments.get('other')?.length).toBe(0);
371+
372+
// No metadata because capturing the response was disabled and that's
373+
// the only metadata that could be in the subsegment for the test.
374+
const myMethodSegment = subsegments.get('### myMethod')?.[0];
375+
expect(myMethodSegment).toBeDefined();
376+
expect(myMethodSegment).not.toHaveProperty('metadata');
377+
378+
const shouldThrowAnError = (i === (invocations - 1));
379+
if (shouldThrowAnError) {
380+
assertErrorAndFault(invocationSubsegment, expectedCustomErrorMessage);
381+
}
382+
}
383+
384+
}, TEST_CASE_TIMEOUT);
385+
306386
it('should not capture any custom traces when disabled', async () => {
307387
const expectedNoOfTraces = 2;
308388
const tracesWithTracerDisabled = await getTraces(xray, startTime, await getFunctionArn(functionNameWithTracerDisabled), invocations, expectedNoOfTraces);

0 commit comments

Comments
 (0)