Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(logger): merge child logger options correctly #1178

7 changes: 4 additions & 3 deletions packages/logger/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { Context, Handler } from 'aws-lambda';
import { Utility } from '@aws-lambda-powertools/commons';
import { LogFormatterInterface, PowertoolLogFormatter } from './formatter';
import { LogItem } from './log';
import cloneDeep from 'lodash.clonedeep';
import merge from 'lodash.merge';
import { ConfigServiceInterface, EnvironmentVariablesService } from './config';
import { LogJsonIndent } from './types';
Expand Down Expand Up @@ -122,6 +121,8 @@ class Logger extends Utility implements ClassThatLogs {

// envVarsService is always initialized in the constructor in setOptions()
private envVarsService!: EnvironmentVariablesService;

private initOptions: ConstructorOptions;

private logEvent: boolean = false;

Expand Down Expand Up @@ -151,7 +152,7 @@ class Logger extends Utility implements ClassThatLogs {
*/
public constructor(options: ConstructorOptions = {}) {
super();

this.initOptions = options;
dreamorosi marked this conversation as resolved.
Show resolved Hide resolved
this.setOptions(options);
}

Expand Down Expand Up @@ -205,7 +206,7 @@ class Logger extends Utility implements ClassThatLogs {
* @returns {Logger}
*/
public createChild(options: ConstructorOptions = {}): Logger {
return cloneDeep(this).setOptions(options);
return new Logger(merge({}, this.initOptions, options));
dreamorosi marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
127 changes: 121 additions & 6 deletions packages/logger/tests/unit/Logger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ describe('Class: Logger', () => {
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: {},
logEvent: false,
logIndentation: 0,
logFormatter: expect.any(PowertoolLogFormatter),
Expand Down Expand Up @@ -1236,6 +1237,110 @@ describe('Class: Logger', () => {

describe('Method: createChild', () => {

test('Child and grandchild loggers should have all ancestor\'s options', () => {
// Prepare
const INDENTATION = LogJsonIndent.COMPACT;
const loggerOptions = {
serviceName: 'parent-service-name',
sampleRateValue: 0.01,
};
const parentLogger = new Logger(loggerOptions);

// Act
const childLoggerOptions = { sampleRateValue: 1 };
const childLogger = parentLogger.createChild(childLoggerOptions);

const grandchildLoggerOptions = { serviceName: 'grandchild-logger-name' };
const grandchildLogger = childLogger.createChild(grandchildLoggerOptions);

// Assess
expect(parentLogger === childLogger).toBe(false);
expect(childLogger === grandchildLogger).toBe(false);
expect(parentLogger === grandchildLogger).toBe(false);

expect(parentLogger).toEqual({
console: expect.any(Console),
coldStart: true,
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: loggerOptions,
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logLevel: 'DEBUG',
logLevelThresholds: {
DEBUG: 8,
ERROR: 20,
INFO: 12,
WARN: 16,
},
logsSampled: false,
persistentLogAttributes: {},
powertoolLogData: {
awsRegion: 'eu-west-1',
environment: '',
sampleRateValue: 0.01,
serviceName: 'parent-service-name',
},
});

expect(childLogger).toEqual({
console: expect.any(Console),
coldStart: true,
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: { ...loggerOptions, ...childLoggerOptions },
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logLevel: 'DEBUG',
logLevelThresholds: {
DEBUG: 8,
ERROR: 20,
INFO: 12,
WARN: 16,
},
logsSampled: true,
persistentLogAttributes: {},
powertoolLogData: {
awsRegion: 'eu-west-1',
environment: '',
sampleRateValue: 1,
serviceName: 'parent-service-name',
},
});

expect(grandchildLogger).toEqual({
console: expect.any(Console),
coldStart: true,
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: { ...childLoggerOptions ,...grandchildLoggerOptions },
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logLevel: 'DEBUG',
logLevelThresholds: {
DEBUG: 8,
ERROR: 20,
INFO: 12,
WARN: 16,
},
logsSampled: true,
persistentLogAttributes: {},
powertoolLogData: {
awsRegion: 'eu-west-1',
environment: '',
sampleRateValue: 1,
serviceName: 'grandchild-logger-name',
},
});

});

test('when called, it returns a DISTINCT clone of the logger instance', () => {

// Prepare
Expand All @@ -1244,17 +1349,23 @@ describe('Class: Logger', () => {

// Act
const childLogger = parentLogger.createChild();
const childLoggerWithPermanentAttributes = parentLogger.createChild({

const optionsWithPermanentAttributes = {
persistentLogAttributes: {
extra: 'This is an attribute that will be logged only by the child logger',
},
});
const childLoggerWithSampleRateEnabled = parentLogger.createChild({
};
const childLoggerWithPermanentAttributes = parentLogger.createChild(optionsWithPermanentAttributes);

const optionsWithSampleRateEnabled = {
sampleRateValue: 1, // 100% probability to make sure that the logs are sampled
});
const childLoggerWithErrorLogLevel = parentLogger.createChild({
};
const childLoggerWithSampleRateEnabled = parentLogger.createChild(optionsWithSampleRateEnabled);

const optionsWithErrorLogLevel = {
logLevel: 'ERROR',
});
};
const childLoggerWithErrorLogLevel = parentLogger.createChild(optionsWithErrorLogLevel);

// Assess
expect(parentLogger === childLogger).toBe(false);
Expand All @@ -1272,6 +1383,7 @@ describe('Class: Logger', () => {
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: {},
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
Expand All @@ -1298,6 +1410,7 @@ describe('Class: Logger', () => {
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: optionsWithPermanentAttributes,
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
Expand Down Expand Up @@ -1326,6 +1439,7 @@ describe('Class: Logger', () => {
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: optionsWithSampleRateEnabled,
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
Expand All @@ -1352,6 +1466,7 @@ describe('Class: Logger', () => {
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: optionsWithErrorLogLevel,
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
Expand Down
5 changes: 4 additions & 1 deletion packages/logger/tests/unit/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ describe('Helper: createLogger function', () => {
defaultServiceName: 'service_undefined',
customConfigService: expect.any(EnvironmentVariablesService),
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: loggerOptions,
logEvent: false,
logIndentation: 0,
logFormatter: expect.any(PowertoolLogFormatter),
Expand Down Expand Up @@ -120,6 +121,7 @@ describe('Helper: createLogger function', () => {
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: {},
logEvent: false,
logIndentation: 0,
logFormatter: expect.any(PowertoolLogFormatter),
Expand Down Expand Up @@ -230,7 +232,7 @@ describe('Helper: createLogger function', () => {
test('when no log level is set, returns a Logger instance with INFO level', () => {

// Prepare
const loggerOptions:ConstructorOptions = {};
const loggerOptions: ConstructorOptions = {};
delete process.env.LOG_LEVEL;

// Act
Expand All @@ -243,6 +245,7 @@ describe('Helper: createLogger function', () => {
customConfigService: undefined,
defaultServiceName: 'service_undefined',
envVarsService: expect.any(EnvironmentVariablesService),
initOptions: loggerOptions,
logEvent: false,
logIndentation: 0,
logFormatter: expect.any(PowertoolLogFormatter),
Expand Down