1
+ import { captureLambdaHandler } from '../../src/middleware/middy' ;
2
+ import middy from '@middy/core' ;
3
+ // import { EnvironmentVariablesService } from '../../../src/config';
4
+ import { Tracer } from './../../src' ;
5
+ import type { Context , Handler } from 'aws-lambda/handler' ;
6
+ import { Segment , setContextMissingStrategy , Subsegment } from 'aws-xray-sdk-core' ;
7
+
8
+ jest . spyOn ( console , 'debug' ) . mockImplementation ( ( ) => null ) ;
9
+ jest . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => null ) ;
10
+ jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) => null ) ;
11
+
12
+ describe ( 'Middy middlewares' , ( ) => {
13
+ const ENVIRONMENT_VARIABLES = process . env ;
14
+
15
+ const mockContext : Context = {
16
+ callbackWaitsForEmptyEventLoop : true ,
17
+ functionVersion : '$LATEST' ,
18
+ functionName : 'foo-bar-function' ,
19
+ memoryLimitInMB : '128' ,
20
+ logGroupName : '/aws/lambda/foo-bar-function-123456abcdef' ,
21
+ logStreamName : '2021/03/09/[$LATEST]abcdef123456abcdef123456abcdef123456' ,
22
+ invokedFunctionArn : 'arn:aws:lambda:eu-central-1:123456789012:function:Example' ,
23
+ awsRequestId : Math . floor ( Math . random ( ) * 1000000000 ) . toString ( ) ,
24
+ getRemainingTimeInMillis : ( ) => 1234 ,
25
+ done : ( ) => console . log ( 'Done!' ) ,
26
+ fail : ( ) => console . log ( 'Failed!' ) ,
27
+ succeed : ( ) => console . log ( 'Succeeded!' ) ,
28
+ } ;
29
+
30
+ beforeEach ( ( ) => {
31
+ Tracer . coldStart = true ;
32
+ jest . clearAllMocks ( ) ;
33
+ jest . resetModules ( ) ;
34
+ process . env = { ...ENVIRONMENT_VARIABLES } ;
35
+ } ) ;
36
+
37
+ afterAll ( ( ) => {
38
+ process . env = ENVIRONMENT_VARIABLES ;
39
+ } ) ;
40
+ describe ( 'Middleware: captureLambdaHandler' , ( ) => {
41
+
42
+ test ( 'when used while tracing is disabled, it does nothing' , async ( ) => {
43
+
44
+ // Prepare
45
+ const tracer : Tracer = new Tracer ( { enabled : false } ) ;
46
+ const setSegmentSpy = jest . spyOn ( tracer . provider , 'setSegment' ) . mockImplementation ( ) ;
47
+ const getSegmentSpy = jest . spyOn ( tracer . provider , 'getSegment' )
48
+ . mockImplementationOnce ( ( ) => new Segment ( 'facade' , process . env . _X_AMZN_TRACE_ID || null ) )
49
+ . mockImplementationOnce ( ( ) => new Subsegment ( '## foo-bar-function' ) ) ;
50
+ const lambdaHandler : Handler = async ( _event : unknown , _context : Context ) => ( {
51
+ foo : 'bar'
52
+ } ) ;
53
+ const handler = middy ( lambdaHandler ) . use ( captureLambdaHandler ( tracer ) ) ;
54
+ const context = Object . assign ( { } , mockContext ) ;
55
+
56
+ // Act
57
+ await handler ( { } , context , ( ) => console . log ( 'Lambda invoked!' ) ) ;
58
+
59
+ // Assess
60
+ expect ( setSegmentSpy ) . toHaveBeenCalledTimes ( 0 ) ;
61
+ expect ( getSegmentSpy ) . toHaveBeenCalledTimes ( 0 ) ;
62
+
63
+ } ) ;
64
+
65
+ test ( 'when used as decorator while POWERTOOLS_TRACER_CAPTURE_RESPONSE is set to false, it does not capture the response as metadata' , async ( ) => {
66
+
67
+ // Prepare
68
+ process . env . POWERTOOLS_TRACER_CAPTURE_RESPONSE = 'false' ;
69
+ const tracer : Tracer = new Tracer ( ) ;
70
+ const newSubsegment : Segment | Subsegment | undefined = new Subsegment ( '## foo-bar-function' ) ;
71
+ const setSegmentSpy = jest . spyOn ( tracer . provider , 'setSegment' ) . mockImplementation ( ) ;
72
+ jest . spyOn ( tracer . provider , 'getSegment' ) . mockImplementation ( ( ) => newSubsegment ) ;
73
+ setContextMissingStrategy ( ( ) => null ) ;
74
+ const lambdaHandler : Handler = async ( _event : unknown , _context : Context ) => ( {
75
+ foo : 'bar'
76
+ } ) ;
77
+ const handler = middy ( lambdaHandler ) . use ( captureLambdaHandler ( tracer ) ) ;
78
+ const context = Object . assign ( { } , mockContext ) ;
79
+
80
+ // Act
81
+ await handler ( { } , context , ( ) => console . log ( 'Lambda invoked!' ) ) ;
82
+
83
+ // Assess
84
+ expect ( setSegmentSpy ) . toHaveBeenCalledTimes ( 1 ) ;
85
+ expect ( 'metadata' in newSubsegment ) . toBe ( false ) ;
86
+ delete process . env . POWERTOOLS_TRACER_CAPTURE_RESPONSE ;
87
+
88
+ } ) ;
89
+
90
+ test ( 'when used as decorator and with standard config, it captures the response as metadata' , async ( ) => {
91
+
92
+ // Prepare
93
+ const tracer : Tracer = new Tracer ( ) ;
94
+ const newSubsegment : Segment | Subsegment | undefined = new Subsegment ( '## foo-bar-function' ) ;
95
+ const setSegmentSpy = jest . spyOn ( tracer . provider , 'setSegment' ) . mockImplementation ( ) ;
96
+ jest . spyOn ( tracer . provider , 'getSegment' ) . mockImplementation ( ( ) => newSubsegment ) ;
97
+ setContextMissingStrategy ( ( ) => null ) ;
98
+ const lambdaHandler : Handler = async ( _event : unknown , _context : Context ) => ( {
99
+ foo : 'bar'
100
+ } ) ;
101
+ const handler = middy ( lambdaHandler ) . use ( captureLambdaHandler ( tracer ) ) ;
102
+ const context = Object . assign ( { } , mockContext ) ;
103
+
104
+ // Act
105
+ await handler ( { } , context , ( ) => console . log ( 'Lambda invoked!' ) ) ;
106
+
107
+ // Assess
108
+ expect ( setSegmentSpy ) . toHaveBeenCalledTimes ( 1 ) ;
109
+ expect ( setSegmentSpy ) . toHaveBeenCalledWith ( expect . objectContaining ( {
110
+ name : '## foo-bar-function' ,
111
+ } ) ) ;
112
+ expect ( newSubsegment ) . toEqual ( expect . objectContaining ( {
113
+ name : '## foo-bar-function' ,
114
+ metadata : {
115
+ 'hello-world' : {
116
+ 'foo-bar-function response' : {
117
+ foo : 'bar' ,
118
+ } ,
119
+ } ,
120
+ }
121
+ } ) ) ;
122
+
123
+ } ) ;
124
+
125
+ test ( 'when used as decorator while POWERTOOLS_TRACER_CAPTURE_ERROR is set to false, it does not capture the exceptions' , async ( ) => {
126
+
127
+ // Prepare
128
+ process . env . POWERTOOLS_TRACER_CAPTURE_ERROR = 'false' ;
129
+ const tracer : Tracer = new Tracer ( ) ;
130
+ const newSubsegment : Segment | Subsegment | undefined = new Subsegment ( '## foo-bar-function' ) ;
131
+ const setSegmentSpy = jest . spyOn ( tracer . provider , 'setSegment' ) . mockImplementation ( ) ;
132
+ jest . spyOn ( tracer . provider , 'getSegment' ) . mockImplementation ( ( ) => newSubsegment ) ;
133
+ setContextMissingStrategy ( ( ) => null ) ;
134
+ const addErrorSpy = jest . spyOn ( newSubsegment , 'addError' ) ;
135
+ const addErrorFlagSpy = jest . spyOn ( newSubsegment , 'addErrorFlag' ) ;
136
+ const lambdaHandler : Handler = async ( _event : unknown , _context : Context ) => {
137
+ throw new Error ( 'Exception thrown!' ) ;
138
+ } ;
139
+ const handler = middy ( lambdaHandler ) . use ( captureLambdaHandler ( tracer ) ) ;
140
+ const context = Object . assign ( { } , mockContext ) ;
141
+
142
+ // Act
143
+ await handler ( { } , context , ( ) => console . log ( 'Lambda invoked!' ) ) ;
144
+
145
+ // Assess
146
+ expect ( setSegmentSpy ) . toHaveBeenCalledTimes ( 1 ) ;
147
+ expect ( setSegmentSpy ) . toHaveBeenCalledWith ( expect . objectContaining ( {
148
+ name : '## foo-bar-function' ,
149
+ } ) ) ;
150
+ expect ( 'cause' in newSubsegment ) . toBe ( false ) ;
151
+ expect ( addErrorFlagSpy ) . toHaveBeenCalledTimes ( 1 ) ;
152
+ expect ( addErrorSpy ) . toHaveBeenCalledTimes ( 0 ) ;
153
+
154
+ delete process . env . POWERTOOLS_TRACER_CAPTURE_ERROR ;
155
+
156
+ } ) ;
157
+
158
+ } ) ;
159
+
160
+ } ) ;
0 commit comments