Skip to content

Commit e106e5e

Browse files
committed
refactor(logger): add context enabled variable
1 parent 7f4463b commit e106e5e

17 files changed

+227
-251
lines changed

packages/logger/examples/child-logger.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
process.env._X_AMZN_TRACE_ID = 'abcdef123456abcdef123456abcdef123456';
2-
process.env.AWS_LAMBDA_FUNCTION_NAME = 'my-lambda-function';
3-
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '128';
4-
process.env.AWS_REGION = 'eu-central-1';
1+
import { populateEnvironmentVariables } from '../tests/helpers';
2+
3+
// Populate runtime
4+
populateEnvironmentVariables();
5+
// Additional runtime variables
56
process.env.LOG_LEVEL = 'INFO';
6-
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';
77

88
import * as dummyEvent from '../../../tests/resources/events/custom/hello-world.json';
99
import { context as dummyContext } from '../../../tests/resources/contexts/hello-world';
Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
process.env._X_AMZN_TRACE_ID = 'abcdef123456abcdef123456abcdef123456';
2-
process.env.AWS_LAMBDA_FUNCTION_NAME = 'my-lambda-function';
3-
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '128';
4-
process.env.AWS_REGION = 'eu-central-1';
1+
import { populateEnvironmentVariables } from '../tests/helpers';
2+
3+
// Populate runtime
4+
populateEnvironmentVariables();
5+
// Additional runtime variables
56
process.env.CUSTOM_ENV = 'prod';
7+
process.env.POWERTOOLS_CONTEXT_ENABLED = 'TRUE';
68

79
import * as dummyEvent from '../../../tests/resources/events/custom/hello-world.json';
810
import * as powertool from '../../../package.json';
@@ -41,36 +43,4 @@ const lambdaHandler: Handler = async (event, context) => {
4143

4244
};
4345

44-
lambdaHandler(dummyEvent, dummyContext, () => {});
45-
46-
/**
47-
* Sample output:
48-
*
49-
* {
50-
* message: 'This is an ERROR log',
51-
* service: 'foo-bar',
52-
* environment: 'prod',
53-
* awsRegion: 'eu-central-1',
54-
* correlationIds: {
55-
* awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e8deadbeef',
56-
* xRayTraceId: 'abcdef123456abcdef123456abcdef123456',
57-
* myCustomCorrelationId: 'foo-bar-baz'
58-
* },
59-
* lambdaFunction: {
60-
* name: 'foo-bar-function',
61-
* arn: 'arn:aws:lambda:eu-central-1:123456789012:function:Example',
62-
* memoryLimitInMB: 128,
63-
* version: '$LATEST',
64-
* coldStart: undefined
65-
* },
66-
* logLevel: 'ERROR',
67-
* timestamp: '2021-03-10T18:47:04.724Z',
68-
* logger: {
69-
* name: '@aws-lambda-powertools/logger',
70-
* version: '0.0.0',
71-
* level: 'ERROR',
72-
* sampleRateValue: 0.00001
73-
* }
74-
* }
75-
*
76-
**/
46+
lambdaHandler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));

packages/logger/examples/formatters/CustomLogFormatter.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ class CustomLogFormatter extends LogFormatter {
1212
environment: attributes.environment,
1313
awsRegion: attributes.awsRegion,
1414
correlationIds: {
15-
awsRequestId: attributes.awsRequestId,
15+
awsRequestId: attributes.lambdaContext?.awsRequestId,
1616
xRayTraceId: attributes.xRayTraceId
1717
},
1818
lambdaFunction: {
19-
name: attributes.functionName,
20-
arn: attributes.invokedFunctionArn,
21-
memoryLimitInMB: Number(attributes.memoryLimitInMB),
22-
version: attributes.functionVersion,
23-
coldStart: attributes.coldStart,
19+
name: attributes.lambdaContext?.name,
20+
arn: attributes.lambdaContext?.arn,
21+
memoryLimitInMB: attributes.lambdaContext?.memoryLimitInMB,
22+
version: attributes.lambdaContext?.version,
23+
coldStart: attributes.lambdaContext?.coldStart,
2424
},
2525
logLevel: attributes.logLevel,
2626
timestamp: this.formatTimestamp(attributes.timestamp),
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { populateEnvironmentVariables } from '../tests/helpers';
2+
3+
// Populate runtime
4+
populateEnvironmentVariables();
5+
// Additional runtime variables
6+
process.env.LOG_LEVEL = 'WARN';
7+
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';
8+
process.env.POWERTOOLS_CONTEXT_ENABLED = 'TRUE';
9+
10+
import * as dummyEvent from '../../../tests/resources/events/custom/hello-world.json';
11+
import { context as dummyContext } from '../../../tests/resources/contexts/hello-world';
12+
import { Handler } from 'aws-lambda';
13+
import { Logger } from '../src';
14+
15+
const logger = new Logger();
16+
17+
const lambdaHandler: Handler = async (event, context) => {
18+
logger.addContext(context);
19+
20+
logger.debug('This is a DEBUG log', { bar: 'baz' });
21+
logger.info('This is an INFO log', { bar: 'baz' });
22+
logger.warn('This is a WARN log', { bar: 'baz' });
23+
logger.error('This is an ERROR log', { bar: 'baz' });
24+
25+
return {
26+
foo: 'bar'
27+
};
28+
29+
};
30+
31+
lambdaHandler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
Lines changed: 7 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import { populateEnvironmentVariables } from '../tests/helpers';
2+
3+
// Populate runtime
4+
populateEnvironmentVariables();
5+
// Additional runtime variables
16
process.env.LOG_LEVEL = 'WARN';
27
process.env.POWERTOOLS_SERVICE_NAME = 'hello-world';
38

@@ -8,8 +13,7 @@ import { Logger } from '../src';
813

914
const logger = new Logger();
1015

11-
const lambdaHandler: Handler = async (event, context) => {
12-
logger.addContext(context);
16+
const lambdaHandler: Handler = async () => {
1317

1418
logger.debug('This is a DEBUG log', { bar: 'baz' });
1519
logger.info('This is an INFO log', { bar: 'baz' });
@@ -22,66 +26,4 @@ const lambdaHandler: Handler = async (event, context) => {
2226

2327
};
2428

25-
lambdaHandler(dummyEvent, dummyContext, () => {});
26-
27-
/**
28-
* Logs output:
29-
*
30-
* {
31-
* sampling_rate: 1,
32-
* service: 'hello-world',
33-
* xray_trace_id: 'abcdef123456abcdef123456abcdef123456',
34-
* cold_start: true,
35-
* lambda_function_arn: 'arn:aws:lambda:eu-central-1:123456789012:function:Example',
36-
* lambda_function_memory_size: 128,
37-
* lambda_function_name: 'foo-bar-function',
38-
* aws_request_id: 'c6af9ac6-7b61-11e6-9a41-93e8deadbeef',
39-
* message: 'This is a DEBUG log',
40-
* timestamp: '2021-03-10T01:42:42.664Z',
41-
* level: 'DEBUG',
42-
* bar: 'baz'
43-
* }
44-
* {
45-
* sampling_rate: 1,
46-
* service: 'hello-world',
47-
* xray_trace_id: 'abcdef123456abcdef123456abcdef123456',
48-
* cold_start: true,
49-
* lambda_function_arn: 'arn:aws:lambda:eu-central-1:123456789012:function:Example',
50-
* lambda_function_memory_size: 128,
51-
* lambda_function_name: 'foo-bar-function',
52-
* aws_request_id: 'c6af9ac6-7b61-11e6-9a41-93e8deadbeef',
53-
* message: 'This is an INFO log',
54-
* timestamp: '2021-03-10T01:42:42.667Z',
55-
* level: 'INFO',
56-
* bar: 'baz'
57-
* }
58-
* {
59-
* sampling_rate: 1,
60-
* service: 'hello-world',
61-
* xray_trace_id: 'abcdef123456abcdef123456abcdef123456',
62-
* cold_start: true,
63-
* lambda_function_arn: 'arn:aws:lambda:eu-central-1:123456789012:function:Example',
64-
* lambda_function_memory_size: 128,
65-
* lambda_function_name: 'foo-bar-function',
66-
* aws_request_id: 'c6af9ac6-7b61-11e6-9a41-93e8deadbeef',
67-
* message: 'This is a WARN log',
68-
* timestamp: '2021-03-10T01:42:42.667Z',
69-
* level: 'WARN',
70-
* bar: 'baz'
71-
* }
72-
* {
73-
* sampling_rate: 1,
74-
* service: 'hello-world',
75-
* xray_trace_id: 'abcdef123456abcdef123456abcdef123456',
76-
* cold_start: true,
77-
* lambda_function_arn: 'arn:aws:lambda:eu-central-1:123456789012:function:Example',
78-
* lambda_function_memory_size: 128,
79-
* lambda_function_name: 'foo-bar-function',
80-
* aws_request_id: 'c6af9ac6-7b61-11e6-9a41-93e8deadbeef',
81-
* message: 'This is an ERROR log',
82-
* timestamp: '2021-03-10T01:42:42.667Z',
83-
* level: 'ERROR',
84-
* bar: 'baz'
85-
* }
86-
*
87-
**/
29+
lambdaHandler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));

packages/logger/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"version": "npm run format && git add -A src",
2020
"postversion": "git push && git push --tags",
2121
"example:hello-world": "ts-node examples/hello-world.ts",
22+
"example:hello-world-with-context": "ts-node examples/hello-world-with-context.ts",
2223
"example:custom-logger-options": "ts-node examples/custom-logger-options.ts",
2324
"example:child-logger": "ts-node examples/child-logger.ts"
2425
},

packages/logger/src/Logger.ts

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import { LogItem } from './log';
55
import { cloneDeep, merge } from 'lodash/fp';
66
import { ConfigServiceInterface, EnvironmentVariablesService } from './config';
77
import {
8-
DefaultLoggerAttributes,
98
Environment,
9+
LoggerData,
1010
LogAttributes,
1111
LoggerOptions,
1212
LogLevel,
13-
LogLevelThresholds, UnformattedAttributes,
13+
LogLevelThresholds,
14+
UnformattedAttributes, LambdaFunctionContext,
1415
} from '../types';
1516
import { LogFormatterInterface, PowertoolLogFormatter } from './formatter';
1617

@@ -20,10 +21,10 @@ class Logger implements LoggerInterface {
2021

2122
private customConfigService?: ConfigServiceInterface;
2223

23-
private defaultLoggerAttributes: DefaultLoggerAttributes = {};
24-
2524
private static readonly defaultLogLevel: LogLevel = 'INFO';
2625

26+
private static readonly defaultSampleRate: number = 1;
27+
2728
private envVarsService?: EnvironmentVariablesService;
2829

2930
private logFormatter?: LogFormatterInterface;
@@ -37,14 +38,30 @@ class Logger implements LoggerInterface {
3738
'ERROR': 20
3839
};
3940

40-
private sampleRateValue?: number;
41+
private loggerData: LoggerData = <LoggerData>{};
4142

4243
public constructor(options: LoggerOptions = {}) {
4344
this.applyOptions(options);
4445
}
4546

4647
public addContext(context: Context): void {
47-
this.addToDefaultLoggerAttributes(context, { isColdStart: Logger.isColdStart() });
48+
if (!this.isContextEnabled()) {
49+
return;
50+
}
51+
52+
const lambdaContext: LambdaFunctionContext = {
53+
arn: context.invokedFunctionArn,
54+
awsRequestId: context.awsRequestId,
55+
coldStart: Logger.isColdStart(),
56+
memoryLimitInMB: Number(context.memoryLimitInMB),
57+
name: context.functionName,
58+
version: context.functionVersion,
59+
};
60+
61+
this.addToLoggerData({
62+
lambdaContext
63+
});
64+
4865
}
4966

5067
public createChild(options: LoggerOptions = {}): Logger {
@@ -77,9 +94,9 @@ class Logger implements LoggerInterface {
7794
this.printLog('WARN', this.createLogItem('WARN', message, attributes).getAttributes());
7895
}
7996

80-
private addToDefaultLoggerAttributes(...attributesArray: Array<DefaultLoggerAttributes>): void {
81-
attributesArray.forEach((attributes: DefaultLoggerAttributes) => {
82-
this.defaultLoggerAttributes = merge(this.getDefaultLoggerAttributes(), attributes);
97+
private addToLoggerData(...attributesArray: Array<Partial<LoggerData>>): void {
98+
attributesArray.forEach((attributes: Partial<LoggerData>) => {
99+
this.loggerData = merge(this.getLoggerData(), attributes);
83100
});
84101
}
85102

@@ -99,26 +116,23 @@ class Logger implements LoggerInterface {
99116
this.setLogLevel(logLevel);
100117
this.setSampleRateValue(sampleRateValue);
101118
this.setLogFormatter(logFormatter);
102-
this.populateDefaultLoggerAttributes(serviceName, environment, customAttributes);
119+
this.populateLoggerData(serviceName, environment, customAttributes);
103120

104121
return this;
105122
}
106123

107124
private createLogItem(logLevel: LogLevel, message: string, customAttributes: LogAttributes = {}): LogItem {
108-
this.addToDefaultLoggerAttributes({ logLevel, message, timestamp: new Date() });
125+
const unformattedAttributes: UnformattedAttributes = merge({ logLevel, message, timestamp: new Date() }, this.getLoggerData());
109126

110-
return new LogItem().addAttributes(this.getLogFormatter().format(this.getDefaultLoggerAttributes() as UnformattedAttributes))
127+
return new LogItem()
128+
.addAttributes(this.getLogFormatter().format(unformattedAttributes))
111129
.addAttributes(customAttributes);
112130
}
113131

114132
private getCustomConfigService(): ConfigServiceInterface | undefined {
115133
return this.customConfigService;
116134
}
117135

118-
private getDefaultLoggerAttributes(): DefaultLoggerAttributes {
119-
return this.defaultLoggerAttributes;
120-
}
121-
122136
private getEnvVarsService(): EnvironmentVariablesService {
123137
if (!this.envVarsService) {
124138
this.setEnvVarsService();
@@ -136,25 +150,45 @@ class Logger implements LoggerInterface {
136150
}
137151

138152
private getLogLevel(): LogLevel {
139-
if (!this.logLevel) {
153+
if (this.loggerData?.logLevel) {
140154
this.setLogLevel();
141155
}
142156

143157
return <LogLevel> this.logLevel;
144158
}
145159

146-
private getSampleRateValue(): number | undefined {
147-
return this.sampleRateValue;
160+
private getLoggerData(): LoggerData {
161+
return this.loggerData;
148162
}
149163

150-
private populateDefaultLoggerAttributes(serviceName?: string, environment?: Environment, customAttributes: LogAttributes = {}): void {
151-
this.addToDefaultLoggerAttributes({
164+
private getSampleRateValue(): number {
165+
if (!this.loggerData?.sampleRateValue) {
166+
this.setSampleRateValue();
167+
}
168+
169+
return <number> this.loggerData?.sampleRateValue;
170+
}
171+
172+
private isContextEnabled(): boolean {
173+
return this.getCustomConfigService()?.getIsContextEnabled() === true || this.getEnvVarsService().getIsContextEnabled() === true;
174+
}
175+
176+
private populateLoggerData(serviceName?: string, environment?: Environment, customAttributes: LogAttributes = {}): void {
177+
178+
if (this.isContextEnabled()) {
179+
this.addToLoggerData( {
180+
lambdaContext: {
181+
coldStart: Logger.isColdStart(),
182+
memoryLimitInMB: this.getEnvVarsService().getFunctionMemory(),
183+
name: this.getEnvVarsService().getFunctionName(),
184+
version:this.getEnvVarsService().getFunctionVersion(),
185+
}
186+
});
187+
}
188+
189+
this.addToLoggerData({
152190
awsRegion: this.getEnvVarsService().getAwsRegion(),
153191
environment: environment || this.getCustomConfigService()?.getCurrentEnvironment() || this.getEnvVarsService().getCurrentEnvironment(),
154-
functionName: this.getEnvVarsService().getFunctionName(),
155-
functionVersion: this.getEnvVarsService().getFunctionVersion(),
156-
logLevel: this.getLogLevel(),
157-
memoryLimitInMB: this.getEnvVarsService().getFunctionMemory(),
158192
sampleRateValue: this.getSampleRateValue(),
159193
serviceName: serviceName || this.getCustomConfigService()?.getServiceName() || this.getEnvVarsService().getServiceName(),
160194
xRayTraceId: this.getEnvVarsService().getXrayTraceId(),
@@ -184,11 +218,13 @@ class Logger implements LoggerInterface {
184218
}
185219

186220
private setLogLevel(logLevel?: LogLevel): void {
187-
this.logLevel = (logLevel || this.getCustomConfigService()?.getLogLevel() || this.getEnvVarsService().getLogLevel() || Logger.defaultLogLevel) as LogLevel;
221+
this.logLevel = (logLevel || this.getCustomConfigService()?.getLogLevel() || this.getEnvVarsService().getLogLevel()
222+
|| Logger.defaultLogLevel) as LogLevel;
188223
}
189224

190225
private setSampleRateValue(sampleRateValue?: number): void {
191-
this.sampleRateValue = sampleRateValue || this.getCustomConfigService()?.getSampleRateValue() || this.getEnvVarsService().getSampleRateValue();
226+
this.loggerData.sampleRateValue = sampleRateValue || this.getCustomConfigService()?.getSampleRateValue()
227+
|| this.getEnvVarsService().getSampleRateValue() || Logger.defaultSampleRate;
192228
}
193229

194230
private shouldPrint(logLevel: LogLevel): boolean {

0 commit comments

Comments
 (0)