Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions packages/logger/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,19 @@ class Logger extends Utility implements LoggerInterface {
* @param options - The options to initialize the child logger with.
*/
public createChild(options: ConstructorOptions = {}): Logger {
// Determine proper key to use when merging persistent options with
// parent. Preferring persistentKeys over persistentLogAttributes.
// NOTE: when both are passed in for options warning message in
// setOptions is still triggered
const persistentKeyName: keyof Pick<
// extra type safety since dealing with string values and merge does not care
ConstructorOptions,
'persistentKeys' | 'persistentLogAttributes'
> =
'persistentLogAttributes' in options && !('persistentKeys' in options)
? 'persistentLogAttributes'
: 'persistentKeys';

const childLogger = this.createLogger(
// Merge parent logger options with options passed to createChild,
// the latter having precedence.
Expand All @@ -335,8 +348,7 @@ class Logger extends Utility implements LoggerInterface {
logFormatter: this.getLogFormatter(),
customConfigService: this.getCustomConfigService(),
environment: this.powertoolsLogData.environment,
persistentLogAttributes:
this.#attributesStore.getPersistentAttributes(),
[persistentKeyName]: this.#attributesStore.getPersistentAttributes(),
jsonReplacerFn: this.#jsonReplacerFn,
correlationIdSearchFn: this.#correlationIdSearchFn,
...(this.#bufferConfig.enabled && {
Expand Down
82 changes: 82 additions & 0 deletions packages/logger/tests/unit/initializeLogger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,88 @@ describe('Log levels', () => {
);
});

it('overrides the service name when creating a child logger', () => {
// Prepare
vi.stubEnv('POWERTOOLS_SERVICE_NAME', 'hello-world');
const logger = new Logger();
const childLogger = logger.createChild({ serviceName: 'child-service' });

// Act
childLogger.info('Hello, world!');

// Assess
expect(console.info).toHaveBeenCalledTimes(1);
expect(console.info).toHaveLoggedNth(
1,
expect.objectContaining({ service: 'child-service' })
);
});

it('maintains persistentKeys when creating a child logger', () => {
// Prepare
const mockDate = new Date(1466424490000);
vi.useFakeTimers().setSystemTime(mockDate);
const logger = new Logger({
persistentKeys: {
foo: 'hello',
overridable: 1,
},
});

logger.appendKeys({
resettableKey: 'some-id',
});

logger.appendPersistentKeys({
dynamic: 'stays',
});

const childLogger = logger.createChild({
serviceName: 'child-service',
persistentKeys: {
bar: 'world',
overridable: 2,
},
});

// Act
childLogger.info('Hello, world!');
childLogger.resetKeys();
childLogger.info('Hello again!');

// Assess
expect(console.info).toHaveBeenCalledTimes(2);
expect(console.info).toHaveLoggedNth(
1,
expect.objectContaining({
service: 'child-service',
foo: 'hello',
bar: 'world',
dynamic: 'stays',
message: 'Hello, world!',
overridable: 2,
resettableKey: 'some-id',
})
);

expect(console.info).toHaveLoggedNth(
2,
// using direct match here to ensure removal of resetKeys
{
service: 'child-service',
foo: 'hello',
bar: 'world',
dynamic: 'stays',
message: 'Hello again!',
overridable: 2,
level: 'INFO',
sampling_rate: 0,
timestamp: '2016-06-20T12:08:10.000Z',
xray_trace_id: '1-abcdef12-3456abcdef123456abcdef12',
}
);
});

it('`logRecordOrder` should be passed down to child logger', () => {
// Prepare
const expectedKeys = [
Expand Down
209 changes: 207 additions & 2 deletions packages/logger/tests/unit/workingWithkeys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,11 +519,16 @@ describe('Working with keys', () => {
});

// Act
const childLogger = logger.createChild();
const childLogger = logger.createChild({
persistentKeys: {
bar: 'foo',
},
});

// Assess
expect(childLogger.getPersistentLogAttributes()).toEqual({
foo: 'bar',
bar: 'foo',
});
});

Expand Down Expand Up @@ -671,7 +676,11 @@ describe('Working with keys', () => {

it('should pass persistentKeys to child with no warning', () => {
// Prepare
const logger = new Logger();
const logger = new Logger({
persistentKeys: {
foo: 'bar',
},
});
logger.createChild({ persistentKeys: { abc: 'xyz' } });

// Assess
Expand Down Expand Up @@ -816,4 +825,200 @@ describe('Working with keys', () => {
);
}
);

describe('deprecated persistentLogAttributes usage', () => {
it('sets #attributesStore on the logger', () => {
// Prepare
const logger = new Logger({
persistentLogAttributes: {
foo: 'bar',
},
});

// Assess
expect(logger.getPersistentLogAttributes()).toEqual({
foo: 'bar',
});

expect(console.warn).not.toHaveLogged(
expect.objectContaining({
message:
'Both persistentLogAttributes and persistentKeys options were provided. Using persistentKeys as persistentLogAttributes is deprecated and will be removed in future releases',
})
);
});

it('gets overridden by persistentKeys usage', () => {
// Prepare
const logger = new Logger({
persistentKeys: {
foo: 'bar',
},
// @ts-expect-error
persistentLogAttributes: {
foo: 'not-bar',
},
});

// Assess
expect(logger.getPersistentLogAttributes()).toEqual({
foo: 'bar',
});

expect(console.warn).toHaveLogged(
expect.objectContaining({
message:
'Both persistentLogAttributes and persistentKeys options were provided. Using persistentKeys as persistentLogAttributes is deprecated and will be removed in future releases',
})
);
});

it('persists for child loggers', () => {
// Prepare
const logger = new Logger({
persistentLogAttributes: {
foo: 'bar',
},
});

// Act
const child = logger.createChild();

// Assess
expect(child.getPersistentLogAttributes()).toEqual({
foo: 'bar',
});

expect(console.warn).not.toHaveLogged(
expect.objectContaining({
message:
'Both persistentLogAttributes and persistentKeys options were provided. Using persistentKeys as persistentLogAttributes is deprecated and will be removed in future releases',
})
);
});

it('persists for child loggers using persistentLogAttributes', () => {
// Prepare
const logger = new Logger({
persistentLogAttributes: {
foo: 'bar',
},
});

// Act
const child = logger.createChild({
persistentLogAttributes: {
bar: 'foo',
},
});

// Assess
expect(child.getPersistentLogAttributes()).toEqual({
foo: 'bar',
bar: 'foo',
});

expect(console.warn).not.toHaveLogged(
expect.objectContaining({
message:
'Both persistentLogAttributes and persistentKeys options were provided. Using persistentKeys as persistentLogAttributes is deprecated and will be removed in future releases',
})
);
});

it('persists for child loggers using persistKeys', () => {
// Prepare
const logger = new Logger({
persistentLogAttributes: {
foo: 'bar',
},
});

// Act
const child = logger.createChild({
persistentKeys: {
bar: 'foo',
},
});

// Assess
expect(child.getPersistentLogAttributes()).toEqual({
foo: 'bar',
bar: 'foo',
});

expect(console.warn).not.toHaveLogged(
expect.objectContaining({
message:
'Both persistentLogAttributes and persistentKeys options were provided. Using persistentKeys as persistentLogAttributes is deprecated and will be removed in future releases',
})
);
});

it('persists for child loggers using persistentLogAttributes when parent used persistentLogAttributes', () => {
// Prepare
const logger = new Logger({
persistentLogAttributes: {
foo: 'bar',
},
});

// Act
const child = logger.createChild({
persistentKeys: {
bar: 'foo',
},
// @ts-expect-error
persistentLogAttributes: {
bar: 'not-foo',
},
});

// Assess
expect(child.getPersistentLogAttributes()).toEqual({
foo: 'bar',
bar: 'foo',
});

expect(console.warn).toHaveLogged(
expect.objectContaining({
message:
'Both persistentLogAttributes and persistentKeys options were provided. Using persistentKeys as persistentLogAttributes is deprecated and will be removed in future releases',
})
);
});

it('persists for child loggers using persistentLogAttributes when parent used persistentKeys', () => {
// Prepare
const logger = new Logger({
persistentKeys: {
foo: 'bar',
},
});

// Act
const child = logger.createChild({
persistentKeys: {
bar: 'foo',
},
// @ts-expect-error
persistentLogAttributes: {
bar: 'not-foo',
},
});

// Assess
expect(child.getPersistentLogAttributes()).toEqual({
foo: 'bar',
bar: 'foo',
});

expect(console.warn).toHaveLogged(
expect.objectContaining({
message:
'Both persistentLogAttributes and persistentKeys options were provided. Using persistentKeys as persistentLogAttributes is deprecated and will be removed in future releases',
})
);
});
});
});
Loading