Skip to content

Commit 1e330b3

Browse files
authored
fix(logger): warn only once on ALC log level mismatch (#3816)
1 parent 8a072c1 commit 1e330b3

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

packages/logger/src/Logger.ts

+23-3
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ class Logger extends Utility implements LoggerInterface {
236236
refreshedTimes: 0,
237237
};
238238

239+
/**
240+
* Map used to store the warning messages that have already been logged.
241+
*/
242+
readonly #warnOnceMap = new Map<string, boolean>();
243+
239244
/**
240245
* Log level used by the current instance of Logger.
241246
*
@@ -714,6 +719,17 @@ class Logger extends Utility implements LoggerInterface {
714719
this.processLogItem(LogLevelThreshold.WARN, input, extraInput);
715720
}
716721

722+
/**
723+
* Log a warning message once per unique message.
724+
*
725+
* @param message - The log message.
726+
*/
727+
#warnOnce(message: string): void {
728+
if (this.#warnOnceMap.has(message)) return;
729+
this.#warnOnceMap.set(message, true);
730+
this.warn(message);
731+
}
732+
717733
/**
718734
* Factory method for instantiating logger instances. Used by `createChild` method.
719735
* Important for customization and subclassing. It allows subclasses, like `MyOwnLogger`,
@@ -811,7 +827,7 @@ class Logger extends Utility implements LoggerInterface {
811827
this.isValidLogLevel(selectedLogLevel) &&
812828
this.logLevel > LogLevelThreshold[selectedLogLevel]
813829
) {
814-
this.warn(
830+
this.#warnOnce(
815831
`Current log level (${selectedLogLevel}) does not match AWS Lambda Advanced Logging Controls minimum log level (${awsLogLevel}). This can lead to data loss, consider adjusting them.`
816832
);
817833
}
@@ -1153,7 +1169,10 @@ class Logger extends Utility implements LoggerInterface {
11531169
private setInitialLogLevel(logLevel?: ConstructorOptions['logLevel']): void {
11541170
const constructorLogLevel = logLevel?.toUpperCase();
11551171

1156-
if (this.awsLogLevelShortCircuit(constructorLogLevel)) return;
1172+
if (this.awsLogLevelShortCircuit(constructorLogLevel)) {
1173+
this.#initialLogLevel = this.logLevel;
1174+
return;
1175+
}
11571176

11581177
if (this.isValidLogLevel(constructorLogLevel)) {
11591178
this.logLevel = LogLevelThreshold[constructorLogLevel];
@@ -1469,6 +1488,7 @@ class Logger extends Utility implements LoggerInterface {
14691488
* logger.setCorrelationId('my-correlation-id'); // sets the correlation ID directly with the first argument as value
14701489
* ```
14711490
*
1491+
* @example
14721492
* ```typescript
14731493
* import { Logger } from '@aws-lambda-powertools/logger';
14741494
* import { search } from '@aws-lambda-powertools/logger/correlationId';
@@ -1483,7 +1503,7 @@ class Logger extends Utility implements LoggerInterface {
14831503
public setCorrelationId(value: unknown, correlationIdPath?: string): void {
14841504
if (typeof correlationIdPath === 'string') {
14851505
if (!this.#correlationIdSearchFn) {
1486-
this.warn(
1506+
this.#warnOnce(
14871507
'correlationIdPath is set but no search function was provided. The correlation ID will not be added to the log attributes.'
14881508
);
14891509
return;

packages/logger/tests/unit/injectLambdaContext.test.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ describe('Inject Lambda Context', () => {
297297
expect(logger.getCorrelationId()).toBe('12345-test-id');
298298
});
299299

300-
it('warns when correlationIdPath is provided but no search function is available', async () => {
300+
it('warns once when correlationIdPath is provided but no search function is available', async () => {
301301
// Prepare
302302
const logger = new Logger(); // No search function provided
303303
const warnSpy = vi.spyOn(logger, 'warn');
@@ -306,7 +306,7 @@ describe('Inject Lambda Context', () => {
306306
'x-correlation-id': '12345-test-id',
307307
},
308308
};
309-
// Act - Use middleware which will internally call setCorrelationIdFromPath
309+
// Act
310310
const handler = middy(async () => {
311311
logger.info('Hello, world!');
312312
}).use(
@@ -315,12 +315,14 @@ describe('Inject Lambda Context', () => {
315315
})
316316
);
317317

318+
await handler(testEvent, context);
318319
await handler(testEvent, context);
319320

320321
// Assess
321322
expect(warnSpy).toHaveBeenCalledWith(
322323
'correlationIdPath is set but no search function was provided. The correlation ID will not be added to the log attributes.'
323324
);
325+
expect(warnSpy).toHaveBeenCalledTimes(1);
324326
});
325327

326328
it('does not set correlation ID when search function returns falsy value', async () => {

0 commit comments

Comments
 (0)