1
1
import context from '@aws-lambda-powertools/testing-utils/context' ;
2
2
import type { Context } from 'aws-lambda' ;
3
+ import middy from 'middy5' ;
3
4
import { type Mock , beforeEach , describe , expect , it , vi } from 'vitest' ;
4
5
import { Logger } from '../../src/Logger.js' ;
5
6
import { LogLevel , UncaughtErrorLogMessage } from '../../src/constants.js' ;
7
+ import { injectLambdaContext } from '../../src/middleware/middy.js' ;
6
8
import type { ConstructorOptions } from '../../src/types/Logger.js' ;
7
9
8
10
describe ( 'Buffer logs' , ( ) => {
@@ -195,6 +197,34 @@ describe('Buffer logs', () => {
195
197
) ;
196
198
} ) ;
197
199
200
+ it ( 'it safely short circuits when clearBuffer is called without a trace id' , ( ) => {
201
+ // Prepare
202
+ process . env . _X_AMZN_TRACE_ID = undefined ;
203
+ const logger = new Logger ( {
204
+ logLevel : LogLevel . ERROR ,
205
+ logBufferOptions : { enabled : true , bufferAtVerbosity : LogLevel . DEBUG } ,
206
+ } ) ;
207
+
208
+ // Assess
209
+ expect ( ( ) => logger . clearBuffer ( ) ) . not . toThrow ( ) ;
210
+ } ) ;
211
+
212
+ it ( 'it clears the buffer' , ( ) => {
213
+ // Prepare
214
+ const logger = new Logger ( {
215
+ logLevel : LogLevel . ERROR ,
216
+ logBufferOptions : { enabled : true , bufferAtVerbosity : LogLevel . DEBUG } ,
217
+ } ) ;
218
+
219
+ // Arrange
220
+ logger . debug ( 'This is a log message' ) ;
221
+ logger . clearBuffer ( ) ;
222
+
223
+ logger . flushBuffer ( ) ;
224
+
225
+ // Assess
226
+ expect ( console . debug ) . not . toBeCalled ;
227
+ } ) ;
198
228
it ( 'it flushes the buffer when an error in logged' , ( ) => {
199
229
// Prepare
200
230
const logger = new Logger ( {
@@ -213,39 +243,113 @@ describe('Buffer logs', () => {
213
243
expect ( console . error ) . toBeCalledTimes ( 1 ) ;
214
244
} ) ;
215
245
216
- it ( 'flushes the buffer when an uncaught error is thrown' , async ( ) => {
217
- // Prepare
218
- const logger = new Logger ( { logBufferOptions : { enabled : true } } ) ;
219
- class TestClass {
220
- @logger . injectLambdaContext ( { flushBufferOnUncaughtError : true } )
221
- async handler ( _event : unknown , _context : Context ) {
222
- logger . debug ( 'This is a log message' ) ;
223
- logger . info ( 'This is an info message' ) ;
224
- throw new Error ( 'This is an error' ) ;
225
- }
246
+ it . each ( [
247
+ {
248
+ handlerFactory : ( logger : Logger ) =>
249
+ middy ( )
250
+ . use (
251
+ injectLambdaContext ( logger , { flushBufferOnUncaughtError : true } )
252
+ )
253
+ . handler ( async ( ) => {
254
+ logger . debug ( 'This is a log message' ) ;
255
+ logger . info ( 'This is an info message' ) ;
256
+ throw new Error ( 'This is an error' ) ;
257
+ } ) ,
258
+ case : 'middleware' ,
259
+ } ,
260
+ {
261
+ handlerFactory : ( logger : Logger ) => {
262
+ class TestClass {
263
+ @logger . injectLambdaContext ( { flushBufferOnUncaughtError : true } )
264
+ async handler ( _event : unknown , _context : Context ) {
265
+ logger . debug ( 'This is a log message' ) ;
266
+ logger . info ( 'This is an info message' ) ;
267
+ throw new Error ( 'This is an error' ) ;
268
+ }
269
+ }
270
+ const lambda = new TestClass ( ) ;
271
+ return lambda . handler . bind ( lambda ) ;
272
+ } ,
273
+ case : 'decorator' ,
274
+ } ,
275
+ ] ) (
276
+ 'flushes the buffer when an uncaught error is thrown ($case)' ,
277
+ async ( { handlerFactory } ) => {
278
+ // Prepare
279
+ const logger = new Logger ( { logBufferOptions : { enabled : true } } ) ;
280
+ const handler = handlerFactory ( logger ) ;
281
+
282
+ // Act & Assess
283
+ await expect ( ( ) =>
284
+ handler (
285
+ {
286
+ foo : 'bar' ,
287
+ } ,
288
+ context
289
+ )
290
+ ) . rejects . toThrow ( new Error ( 'This is an error' ) ) ;
291
+ expect ( console . debug ) . toBeCalledTimes ( 1 ) ;
292
+ expect ( console . info ) . toBeCalledTimes ( 1 ) ;
293
+ expect ( console . error ) . toHaveLogged (
294
+ expect . objectContaining ( {
295
+ message : UncaughtErrorLogMessage ,
296
+ } )
297
+ ) ;
298
+ // If debug is called after info, it means it was buffered and then flushed
299
+ expect ( console . debug ) . toHaveBeenCalledAfter ( console . info as Mock ) ;
300
+ // If error is called after debug, it means the buffer was flushed before the error log
301
+ expect ( console . debug ) . toHaveBeenCalledBefore ( console . error as Mock ) ;
226
302
}
227
- const lambda = new TestClass ( ) ;
228
- const handler = lambda . handler . bind ( lambda ) ;
229
-
230
- // Act & Assess
231
- await expect ( ( ) =>
232
- handler (
233
- {
234
- foo : 'bar' ,
235
- } ,
236
- context
237
- )
238
- ) . rejects . toThrow ( new Error ( 'This is an error' ) ) ;
239
- expect ( console . debug ) . toBeCalledTimes ( 1 ) ;
240
- expect ( console . info ) . toBeCalledTimes ( 1 ) ;
241
- expect ( console . error ) . toHaveLogged (
242
- expect . objectContaining ( {
243
- message : UncaughtErrorLogMessage ,
244
- } )
245
- ) ;
246
- // If debug is called after info, it means it was buffered and then flushed
247
- expect ( console . debug ) . toHaveBeenCalledAfter ( console . info as Mock ) ;
248
- // If error is called after debug, it means the buffer was flushed before the error log
249
- expect ( console . debug ) . toHaveBeenCalledBefore ( console . error as Mock ) ;
250
- } ) ;
303
+ ) ;
304
+ it . each ( [
305
+ {
306
+ handlerFactory : ( logger : Logger ) =>
307
+ middy ( )
308
+ . use (
309
+ injectLambdaContext ( logger , { flushBufferOnUncaughtError : false } )
310
+ )
311
+ . handler ( async ( ) => {
312
+ logger . debug ( 'This is a log message' ) ;
313
+ logger . info ( 'This is an info message' ) ;
314
+ throw new Error ( 'This is an error' ) ;
315
+ } ) ,
316
+ case : 'middleware' ,
317
+ } ,
318
+ {
319
+ handlerFactory : ( logger : Logger ) => {
320
+ class TestClass {
321
+ @logger . injectLambdaContext ( { flushBufferOnUncaughtError : false } )
322
+ async handler ( _event : unknown , _context : Context ) {
323
+ logger . debug ( 'This is a log message' ) ;
324
+ logger . info ( 'This is an info message' ) ;
325
+ throw new Error ( 'This is an error' ) ;
326
+ }
327
+ }
328
+ const lambda = new TestClass ( ) ;
329
+ return lambda . handler . bind ( lambda ) ;
330
+ } ,
331
+ case : 'decorator' ,
332
+ } ,
333
+ ] ) (
334
+ 'clears the buffer when an uncaught error is thrown and flushBufferOnUncaughtError is false ($case)' ,
335
+ async ( { handlerFactory } ) => {
336
+ // Prepare
337
+ const logger = new Logger ( { logBufferOptions : { enabled : true } } ) ;
338
+ const handler = handlerFactory ( logger ) ;
339
+
340
+ // Act & Assess
341
+ await expect ( ( ) =>
342
+ handler (
343
+ {
344
+ foo : 'bar' ,
345
+ } ,
346
+ context
347
+ )
348
+ ) . rejects . toThrow ( new Error ( 'This is an error' ) ) ;
349
+
350
+ // Assess
351
+ expect ( console . debug ) . not . toBeCalled ;
352
+ expect ( console . info ) . not . toBeCalled ;
353
+ }
354
+ ) ;
251
355
} ) ;
0 commit comments