Skip to content

Commit 12c60c5

Browse files
committed
chore: consistent keys merging
1 parent edbbc4d commit 12c60c5

File tree

2 files changed

+70
-16
lines changed

2 files changed

+70
-16
lines changed

packages/logger/src/Logger.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ class Logger extends Utility implements LoggerInterface {
187187
* Flag used to determine if the logger is initialized.
188188
*/
189189
#isInitialized = false;
190+
/**
191+
* Map used to hold the list of keys and their type.
192+
*
193+
* Because keys of different types can be overwritten, we keep a list of keys that were added and their last
194+
* type. We then use this map at log preparation time to pick the last one.
195+
*/
196+
#keys: Map<string, 'temp' | 'persistent'> = new Map();
190197

191198
/**
192199
* Log level used by the current instance of Logger.
@@ -255,7 +262,10 @@ class Logger extends Utility implements LoggerInterface {
255262
* @param {LogAttributes} attributes
256263
* @returns {void}
257264
*/
258-
public appendKeys(attributes?: LogAttributes): void {
265+
public appendKeys(attributes: LogAttributes): void {
266+
for (const attributeKey of Object.keys(attributes)) {
267+
this.#keys.set(attributeKey, 'temp');
268+
}
259269
merge(this.temporaryLogAttributes, attributes);
260270
}
261271

@@ -265,6 +275,9 @@ class Logger extends Utility implements LoggerInterface {
265275
* @param attributes - The attributes to add to all log items.
266276
*/
267277
public appendPersistentKeys(attributes: LogAttributes): void {
278+
for (const attributeKey of Object.keys(attributes)) {
279+
this.#keys.set(attributeKey, 'persistent');
280+
}
268281
merge(this.persistentLogAttributes, attributes);
269282
}
270283

@@ -508,8 +521,12 @@ class Logger extends Utility implements LoggerInterface {
508521
*/
509522
public removeKeys(keys: string[]): void {
510523
for (const key of keys) {
511-
if (this.temporaryLogAttributes && key in this.temporaryLogAttributes) {
512-
delete this.temporaryLogAttributes[key];
524+
this.temporaryLogAttributes[key] = undefined;
525+
526+
if (this.persistentLogAttributes[key]) {
527+
this.#keys.set(key, 'persistent');
528+
} else {
529+
this.#keys.delete(key);
513530
}
514531
}
515532
}
@@ -522,18 +539,27 @@ class Logger extends Utility implements LoggerInterface {
522539
*/
523540
public removePersistentLogAttributes(keys: string[]): void {
524541
for (const key of keys) {
525-
if (this.persistentLogAttributes && key in this.persistentLogAttributes) {
526-
delete this.persistentLogAttributes[key];
542+
this.persistentLogAttributes[key] = undefined;
543+
544+
if (this.temporaryLogAttributes[key]) {
545+
this.#keys.set(key, 'temp');
546+
} else {
547+
this.#keys.delete(key);
527548
}
528549
}
529550
}
530551

531552
/**
532553
* It resets the state, by removing all temporary log attributes added with `appendKeys()` method.
533-
*
534-
* @returns {void}
535554
*/
536555
public resetState(): void {
556+
for (const key of Object.keys(this.temporaryLogAttributes)) {
557+
if (this.persistentLogAttributes[key]) {
558+
this.#keys.set(key, 'persistent');
559+
} else {
560+
this.#keys.delete(key);
561+
}
562+
}
537563
this.temporaryLogAttributes = {};
538564
}
539565

@@ -688,13 +714,18 @@ class Logger extends Utility implements LoggerInterface {
688714
...this.getPowertoolsLogData(),
689715
};
690716

691-
// gradually merge additional attributes starting from customer-provided persistent & temporary attributes
692-
let additionalLogAttributes = {
693-
...this.temporaryLogAttributes,
694-
...this.getPersistentLogAttributes(),
695-
};
717+
const additionalAttributes: LogAttributes = {};
718+
// gradually add additional attributes picking only the last added for each key
719+
for (const [key, type] of this.#keys) {
720+
if (type === 'persistent') {
721+
additionalAttributes[key] = this.persistentLogAttributes[key];
722+
} else {
723+
additionalAttributes[key] = this.temporaryLogAttributes[key];
724+
}
725+
}
726+
696727
// if the main input is not a string, then it's an object with additional attributes, so we merge it
697-
additionalLogAttributes = merge(additionalLogAttributes, otherInput);
728+
merge(additionalAttributes, otherInput);
698729
// then we merge the extra input attributes (if any)
699730
for (const item of extraInput) {
700731
const attributes: LogAttributes =
@@ -704,12 +735,12 @@ class Logger extends Utility implements LoggerInterface {
704735
? { extra: item }
705736
: item;
706737

707-
additionalLogAttributes = merge(additionalLogAttributes, attributes);
738+
merge(additionalAttributes, attributes);
708739
}
709740

710741
return this.getLogFormatter().formatAttributes(
711742
unformattedBaseAttributes,
712-
additionalLogAttributes
743+
additionalAttributes
713744
);
714745
}
715746

@@ -1106,7 +1137,7 @@ class Logger extends Utility implements LoggerInterface {
11061137
this.getEnvVarsService().getServiceName() ||
11071138
this.getDefaultServiceName(),
11081139
});
1109-
this.addPersistentLogAttributes(persistentLogAttributes);
1140+
this.appendPersistentKeys(persistentLogAttributes);
11101141
}
11111142
}
11121143

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,29 @@ describe('Class: Logger', () => {
17191719
})
17201720
);
17211721
});
1722+
1723+
it('preserves persistent keys that were previously overwritten', () => {
1724+
// Prepare
1725+
const logger = new Logger({
1726+
persistentKeys: {
1727+
aws_region: 'eu-west-1',
1728+
},
1729+
});
1730+
const debugSpy = jest.spyOn(logger['console'], 'info');
1731+
logger.appendKeys({
1732+
aws_region: 'us-east-1',
1733+
});
1734+
1735+
// Act
1736+
logger.resetState();
1737+
logger.info('foo');
1738+
1739+
// Assess
1740+
const log = JSON.parse(debugSpy.mock.calls[0][0]);
1741+
expect(log).toStrictEqual(
1742+
expect.objectContaining({ aws_region: 'eu-west-1' })
1743+
);
1744+
});
17221745
});
17231746

17241747
describe('method: setPersistentLogAttributes (deprecated)', () => {

0 commit comments

Comments
 (0)