@@ -9,7 +9,12 @@ import type {
9
9
import type { Context , Handler } from 'aws-lambda' ;
10
10
import merge from 'lodash.merge' ;
11
11
import { EnvironmentVariablesService } from './config/EnvironmentVariablesService.js' ;
12
- import { LogJsonIndent , LogLevelThreshold , ReservedKeys } from './constants.js' ;
12
+ import {
13
+ LogJsonIndent ,
14
+ LogLevelThreshold ,
15
+ ReservedKeys ,
16
+ UncaughtErrorLogMessage ,
17
+ } from './constants.js' ;
13
18
import type { LogFormatter } from './formatter/LogFormatter.js' ;
14
19
import type { LogItem } from './formatter/LogItem.js' ;
15
20
import { PowertoolsLogFormatter } from './formatter/PowertoolsLogFormatter.js' ;
@@ -39,6 +44,7 @@ import type {
39
44
* * Capture key fields from AWS Lambda context, cold start, and structure log output as JSON
40
45
* * Append additional keys to one or all log items
41
46
* * Switch log level to `DEBUG` based on a sample rate value for a percentage of invocations
47
+ * * Ability to buffer logs in memory and flush them when there's an error
42
48
*
43
49
* After initializing the Logger class, you can use the methods to log messages at different levels.
44
50
*
@@ -54,7 +60,7 @@ import type {
54
60
* };
55
61
* ```
56
62
*
57
- * To enrich the log items with information from the Lambda context, you can use the {@link Logger.addContext | addContext()} method.
63
+ * To enrich the log items with information from the Lambda context, you can use the {@link Logger.addContext | ` addContext()` } method.
58
64
*
59
65
* @example
60
66
* ```typescript
@@ -69,7 +75,7 @@ import type {
69
75
* };
70
76
* ```
71
77
*
72
- * You can also add additional attributes to all log items using the {@link Logger.appendKeys | appendKeys()} method.
78
+ * You can also add additional attributes to all log items using the {@link Logger.appendKeys | ` appendKeys()` } method.
73
79
*
74
80
* @example
75
81
* ```typescript
@@ -82,10 +88,10 @@ import type {
82
88
* };
83
89
*```
84
90
*
85
- * If you write your functions as classes and use TypeScript, you can use the {@link Logger.injectLambdaContext} class method decorator
91
+ * If you write your functions as classes and use TypeScript, you can use the {@link Logger.injectLambdaContext | `injectLambdaContext()` } class method decorator
86
92
* to automatically add context to your logs and clear the state after the invocation.
87
93
*
88
- * If instead you use Middy.js middlewares, you use the {@link "middleware/middy".injectLambdaContext | injectLambdaContext()} middleware.
94
+ * If instead you use Middy.js middlewares, you use the {@link "middleware/middy".injectLambdaContext | ` injectLambdaContext()` } middleware.
89
95
*
90
96
* @see https://docs.powertools.aws.dev/lambda/typescript/latest/core/logger/
91
97
*/
@@ -97,7 +103,7 @@ class Logger extends Utility implements LoggerInterface {
97
103
* full control over the output of the logs. In testing environments, we use the
98
104
* default console instance.
99
105
*
100
- * This property is initialized in the constructor in setOptions().
106
+ * This property is initialized in the constructor in ` setOptions()` .
101
107
*/
102
108
private console ! : Console ;
103
109
/**
@@ -191,7 +197,7 @@ class Logger extends Utility implements LoggerInterface {
191
197
#maxBufferBytesSize = 20480 ;
192
198
193
199
/**
194
- * Contains buffered logs, grouped by _X_AMZN_TRACE_ID, each group with a max size of `maxBufferBytesSize`
200
+ * Contains buffered logs, grouped by ` _X_AMZN_TRACE_ID` , each group with a max size of `maxBufferBytesSize`
195
201
*/
196
202
#buffer?: CircularMap < string > ;
197
203
@@ -379,8 +385,8 @@ class Logger extends Utility implements LoggerInterface {
379
385
* Class method decorator that adds the current Lambda function context as extra
380
386
* information in all log items.
381
387
*
382
- * This decorator is useful when you want to add the Lambda context to all log items
383
- * and it works only when decorating a class method that is a Lambda function handler .
388
+ * This decorator is useful when you want to enrich your logs with information
389
+ * from the function context, such as the function name, version, and request ID, and more .
384
390
*
385
391
* @example
386
392
* ```typescript
@@ -401,7 +407,18 @@ class Logger extends Utility implements LoggerInterface {
401
407
* export const handler = handlerClass.handler.bind(handlerClass);
402
408
* ```
403
409
*
410
+ * The decorator can also be used to log the Lambda invocation event; this can be configured both via
411
+ * the `logEvent` parameter and the `POWERTOOLS_LOGGER_LOG_EVENT` environment variable. When both
412
+ * are set, the `logEvent` parameter takes precedence.
413
+ *
414
+ * Additionally, the decorator can be used to reset the temporary keys added with the `appendKeys()` method
415
+ * after the invocation, or to flush the buffer when an uncaught error is thrown in the handler.
416
+ *
404
417
* @see https://www.typescriptlang.org/docs/handbook/decorators.html#method-decorators
418
+ *
419
+ * @param options.logEvent - When `true` the logger will log the event.
420
+ * @param options.resetKeys - When `true` the logger will clear temporary keys added with {@link Logger.appendKeys() `appendKeys()`} method.
421
+ * @param options.flushBufferOnUncaughtError - When `true` the logger will flush the buffer when an uncaught error is thrown in the handler.
405
422
*/
406
423
public injectLambdaContext (
407
424
options ?: InjectLambdaContextOptions
@@ -420,16 +437,24 @@ class Logger extends Utility implements LoggerInterface {
420
437
callback
421
438
) {
422
439
loggerRef . refreshSampleRateCalculation ( ) ;
423
- Logger . injectLambdaContextBefore ( loggerRef , event , context , options ) ;
440
+ loggerRef . addContext ( context ) ;
441
+ loggerRef . logEventIfEnabled ( event , options ?. logEvent ) ;
424
442
425
- let result : unknown ;
426
443
try {
427
- result = await originalMethod . apply ( this , [ event , context , callback ] ) ;
444
+ return await originalMethod . apply ( this , [ event , context , callback ] ) ;
445
+ } catch ( error ) {
446
+ if ( options ?. flushBufferOnUncaughtError ) {
447
+ loggerRef . flushBuffer ( ) ;
448
+ loggerRef . error ( {
449
+ message : UncaughtErrorLogMessage ,
450
+ error,
451
+ } ) ;
452
+ }
453
+ throw error ;
454
+ /* v8 ignore next */
428
455
} finally {
429
456
if ( options ?. clearState || options ?. resetKeys ) loggerRef . resetKeys ( ) ;
430
457
}
431
-
432
- return result ;
433
458
} ;
434
459
} ;
435
460
}
@@ -450,7 +475,7 @@ class Logger extends Utility implements LoggerInterface {
450
475
/**
451
476
* @deprecated - This method is deprecated and will be removed in the next major version.
452
477
*/
453
- public static injectLambdaContextBefore (
478
+ /* v8 ignore start */ public static injectLambdaContextBefore (
454
479
logger : Logger ,
455
480
event : unknown ,
456
481
context : Context ,
@@ -463,7 +488,7 @@ class Logger extends Utility implements LoggerInterface {
463
488
shouldLogEvent = options . logEvent ;
464
489
}
465
490
logger . logEventIfEnabled ( event , shouldLogEvent ) ;
466
- }
491
+ } /* v8 ignore stop */
467
492
468
493
/**
469
494
* Log the AWS Lambda event payload for the current invocation if the environment variable `POWERTOOLS_LOGGER_LOG_EVENT` is set to `true`.
@@ -1239,6 +1264,11 @@ class Logger extends Utility implements LoggerInterface {
1239
1264
persistentKeys && this . appendPersistentKeys ( persistentKeys ) ;
1240
1265
}
1241
1266
1267
+ /**
1268
+ * Configure the buffer settings for the Logger instance.
1269
+ *
1270
+ * @param options - Options to configure the Logger instance
1271
+ */
1242
1272
#setLogBuffering(
1243
1273
options : NonNullable < ConstructorOptions [ 'logBufferOptions' ] >
1244
1274
) {
@@ -1269,30 +1299,34 @@ class Logger extends Utility implements LoggerInterface {
1269
1299
}
1270
1300
1271
1301
/**
1272
- * Add a log to the buffer
1273
- * @param xrayTraceId - _X_AMZN_TRACE_ID of the request
1302
+ * Add a log to the buffer.
1303
+ *
1304
+ * @param xrayTraceId - `_X_AMZN_TRACE_ID` of the request
1274
1305
* @param log - Log to be buffered
1275
- * @param logLevel - level of log to be buffered
1306
+ * @param logLevel - The level of log to be buffered
1276
1307
*/
1277
1308
protected bufferLogItem (
1278
1309
xrayTraceId : string ,
1279
1310
log : LogItem ,
1280
1311
logLevel : number
1281
1312
) : void {
1282
1313
log . prepareForPrint ( ) ;
1283
-
1284
- const stringified = JSON . stringify (
1285
- log . getAttributes ( ) ,
1286
- this . getJsonReplacer ( ) ,
1287
- this . logIndentation
1314
+ this . #buffer?. setItem (
1315
+ xrayTraceId ,
1316
+ JSON . stringify (
1317
+ log . getAttributes ( ) ,
1318
+ this . getJsonReplacer ( ) ,
1319
+ this . logIndentation
1320
+ ) ,
1321
+ logLevel
1288
1322
) ;
1289
-
1290
- this . #buffer?. setItem ( xrayTraceId , stringified , logLevel ) ;
1291
1323
}
1292
1324
1293
1325
/**
1294
- * Flushes all items of the respective _X_AMZN_TRACE_ID within
1295
- * the buffer.
1326
+ * Flush all logs in the request buffer.
1327
+ *
1328
+ * This is called automatically when you use the {@link injectLambdaContext | `@logger.injectLambdaContext()`} decorator and
1329
+ * your function throws an error.
1296
1330
*/
1297
1331
public flushBuffer ( ) : void {
1298
1332
const traceId = this . envVarsService . getXrayTraceId ( ) ;
@@ -1328,9 +1362,10 @@ class Logger extends Utility implements LoggerInterface {
1328
1362
this . #buffer?. delete ( traceId ) ;
1329
1363
}
1330
1364
/**
1331
- * Tests if the log meets the criteria to be buffered
1332
- * @param traceId - _X_AMZN_TRACE_ID of the request
1333
- * @param logLevel - The level of the log being considered
1365
+ * Test if the log meets the criteria to be buffered.
1366
+ *
1367
+ * @param traceId - `_X_AMZN_TRACE_ID` of the request
1368
+ * @param logLevel - The level of the log being considered
1334
1369
*/
1335
1370
protected shouldBufferLog (
1336
1371
traceId : string | undefined ,
0 commit comments