Skip to content

Commit 8d52660

Browse files
shdqdreamorosiijemmy
authored
feat(logger): pretty printing logs in local and non-prod environment (#1141)
* test(logger): add tests for POWERTOOLS_DEV env var and for pretty printing logs when var is set to truthy value * feat(logger): add POWERTOOLS_DEV env var and method to get its value * test(logger): fix tests adding method that gets value of POWERTOOLS_DEV env var * feat(logger): add pretty printing to logs if POWERTOOLS_DEV env var set to truthy value * refactor(review): add private class property for indent size, move evaluation of this property to setOptions() * test(logger): fix tests according to the changes in default logger config * docs(logger): update sections for pretty printing logs using POWERTOOLS_DEV env var * Update docs/core/logger.md * Update docs/core/logger.md Co-authored-by: ijemmy <[email protected]> * fix(docs): update default value for POWERTOOLS_DEV env var * feat(logger): add isValueTrue method that checks the string value for truthiness * test(logger): adjust tests for config interface * test(logger): add tests for isValueTrue method, remove redundunt tests Co-authored-by: Andrea Amorosi <[email protected]> Co-authored-by: ijemmy <[email protected]>
1 parent 8533abe commit 8d52660

File tree

10 files changed

+211
-38
lines changed

10 files changed

+211
-38
lines changed

Diff for: docs/core/logger.md

+3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ Your Logger will include the following keys to your structured logging (default
104104
| **xray_trace_id**: `string` | `1-5759e988-bd862e3fe1be46a994272793` | X-Ray Trace ID. This value is always presented in Lambda environment, whether [tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"} or not. Logger will always log this value. |
105105
| **error**: `Object` | `{ name: "Error", location: "/my-project/handler.ts:18", message: "Unexpected error #1", stack: "[stacktrace]"}` | Optional - An object containing information about the Error passed to the logger |
106106

107+
???+ info
108+
When `POWERTOOLS_DEV` environment variable is present and set to `"true"` or `"1"`, Logger will pretty-print log messages for easier readability. We recommend to use this setting only when debugging on local environments.
109+
107110
### Capturing Lambda context info
108111

109112
You can enrich your structured logs with key Lambda context information in multiple ways.

Diff for: docs/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ Core utilities such as Tracing, Logging, and Metrics will be available across al
293293
| **POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS** | Captures HTTP(s) requests as segments. | [Tracer](./core/tracer) | `true` |
294294
| **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logger](./core/logger) | `false` |
295295
| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logger](./core/logger) | `0` |
296+
| **POWERTOOLS_DEV** | Increase JSON indentation to ease debugging when running functions locally or in a non-production environment | [Logger](./core/logger) | `false` |
296297
| **LOG_LEVEL** | Sets logging level | [Logger](./core/logger) | `INFO` |
297298

298299
## Tenets

Diff for: packages/logger/src/Logger.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { LogItem } from './log';
66
import cloneDeep from 'lodash.clonedeep';
77
import merge from 'lodash.merge';
88
import { ConfigServiceInterface, EnvironmentVariablesService } from './config';
9+
import { LogJsonIndent } from './types';
910
import type {
1011
ClassThatLogs,
1112
Environment,
@@ -127,6 +128,8 @@ class Logger extends Utility implements ClassThatLogs {
127128

128129
private logFormatter?: LogFormatterInterface;
129130

131+
private logIndentation: number = LogJsonIndent.COMPACT;
132+
130133
private logLevel?: LogLevel;
131134

132135
private readonly logLevelThresholds: LogLevelThresholds = {
@@ -595,7 +598,7 @@ class Logger extends Utility implements ClassThatLogs {
595598

596599
const consoleMethod = logLevel.toLowerCase() as keyof ClassThatLogs;
597600

598-
this.console[consoleMethod](JSON.stringify(log.getAttributes(), this.removeCircularDependencies()));
601+
this.console[consoleMethod](JSON.stringify(log.getAttributes(), this.removeCircularDependencies(), this.logIndentation));
599602
}
600603

601604
/**
@@ -688,6 +691,19 @@ class Logger extends Utility implements ClassThatLogs {
688691
this.logFormatter = logFormatter || new PowertoolLogFormatter();
689692
}
690693

694+
/**
695+
* If the `POWERTOOLS_DEV' env variable is set,
696+
* it adds JSON indentation for pretty printing logs.
697+
*
698+
* @private
699+
* @returns {void}
700+
*/
701+
private setLogIndentation(): void {
702+
if (this.getEnvVarsService().getDevMode()) {
703+
this.logIndentation = LogJsonIndent.PRETTY;
704+
}
705+
}
706+
691707
/**
692708
* It sets the Logger's instance log level.
693709
*
@@ -757,6 +773,7 @@ class Logger extends Utility implements ClassThatLogs {
757773
this.setLogFormatter(logFormatter);
758774
this.setPowertoolLogData(serviceName, environment);
759775
this.setLogEvent();
776+
this.setLogIndentation();
760777

761778
this.addPersistentLogAttributes(persistentLogAttributes);
762779

Diff for: packages/logger/src/config/ConfigServiceInterface.ts

+15
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ interface ConfigServiceInterface {
2222
*/
2323
getCurrentEnvironment(): string
2424

25+
/**
26+
* It returns the value of the POWERTOOLS_DEV environment variable.
27+
*
28+
* @returns {boolean}
29+
*/
30+
getDevMode(): boolean
31+
2532
/**
2633
* It returns the value of the POWERTOOLS_LOGGER_LOG_EVENT environment variable.
2734
*
@@ -50,6 +57,14 @@ interface ConfigServiceInterface {
5057
*/
5158
getServiceName(): string
5259

60+
/**
61+
* It returns true if the string value represents a boolean true value.
62+
*
63+
* @param {string} value
64+
* @returns boolean
65+
*/
66+
isValueTrue(value: string): boolean
67+
5368
}
5469

5570
export {

Diff for: packages/logger/src/config/EnvironmentVariablesService.ts

+26-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class EnvironmentVariablesService extends CommonEnvironmentVariablesService impl
2020
// Reserved environment variables
2121
private awsRegionVariable = 'AWS_REGION';
2222
private currentEnvironmentVariable = 'ENVIRONMENT';
23+
private devModeVariable = 'POWERTOOLS_DEV';
2324
private functionNameVariable = 'AWS_LAMBDA_FUNCTION_NAME';
2425
private functionVersionVariable = 'AWS_LAMBDA_FUNCTION_VERSION';
2526
private logEventVariable = 'POWERTOOLS_LOGGER_LOG_EVENT';
@@ -45,6 +46,17 @@ class EnvironmentVariablesService extends CommonEnvironmentVariablesService impl
4546
return this.get(this.currentEnvironmentVariable);
4647
}
4748

49+
/**
50+
* It returns the value of the POWERTOOLS_DEV environment variable.
51+
*
52+
* @returns {boolean}
53+
*/
54+
public getDevMode(): boolean {
55+
const value = this.get(this.devModeVariable);
56+
57+
return this.isValueTrue(value);
58+
}
59+
4860
/**
4961
* It returns the value of the AWS_LAMBDA_FUNCTION_MEMORY_SIZE environment variable.
5062
*
@@ -81,8 +93,8 @@ class EnvironmentVariablesService extends CommonEnvironmentVariablesService impl
8193
*/
8294
public getLogEvent(): boolean {
8395
const value = this.get(this.logEventVariable);
84-
85-
return value.toLowerCase() === 'true' || value === '1';
96+
97+
return this.isValueTrue(value);
8698
}
8799

88100
/**
@@ -105,6 +117,18 @@ class EnvironmentVariablesService extends CommonEnvironmentVariablesService impl
105117
return (value && value.length > 0) ? Number(value) : undefined;
106118
}
107119

120+
/**
121+
* It returns true if the string value represents a boolean true value.
122+
*
123+
* @param {string} value
124+
* @returns boolean
125+
*/
126+
public isValueTrue(value: string): boolean {
127+
const truthyValues: string[] = [ '1', 'y', 'yes', 't', 'true', 'on' ];
128+
129+
return truthyValues.includes(value.toLowerCase());
130+
}
131+
108132
}
109133

110134
export {

Diff for: packages/logger/src/types/Logger.ts

+5
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,8 @@ export {
7474
ConstructorOptions,
7575
HandlerOptions
7676
};
77+
78+
export const enum LogJsonIndent {
79+
PRETTY = 4,
80+
COMPACT = 0,
81+
}

Diff for: packages/logger/tests/unit/Logger.test.ts

+51-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as dummyEvent from '../../../../tests/resources/events/custom/hello-wor
1111
import { createLogger, Logger } from '../../src';
1212
import { EnvironmentVariablesService } from '../../src/config';
1313
import { PowertoolLogFormatter } from '../../src/formatter';
14-
import { ClassThatLogs } from '../../src/types';
14+
import { ClassThatLogs, LogJsonIndent } from '../../src/types';
1515
import { Context, Handler } from 'aws-lambda';
1616
import { Console } from 'console';
1717

@@ -573,6 +573,7 @@ describe('Class: Logger', () => {
573573
customConfigService: undefined,
574574
envVarsService: expect.any(EnvironmentVariablesService),
575575
logEvent: false,
576+
logIndentation: 0,
576577
logFormatter: expect.any(PowertoolLogFormatter),
577578
logLevel: 'DEBUG',
578579
logLevelThresholds: {
@@ -1271,6 +1272,7 @@ describe('Class: Logger', () => {
12711272
customConfigService: undefined,
12721273
envVarsService: expect.any(EnvironmentVariablesService),
12731274
logEvent: false,
1275+
logIndentation: 0,
12741276
logFormatter: expect.any(PowertoolLogFormatter),
12751277
logLevel: 'DEBUG',
12761278
logLevelThresholds: {
@@ -1295,6 +1297,7 @@ describe('Class: Logger', () => {
12951297
customConfigService: undefined,
12961298
envVarsService: expect.any(EnvironmentVariablesService),
12971299
logEvent: false,
1300+
logIndentation: 0,
12981301
logFormatter: expect.any(PowertoolLogFormatter),
12991302
logLevel: 'DEBUG',
13001303
logLevelThresholds: {
@@ -1321,6 +1324,7 @@ describe('Class: Logger', () => {
13211324
customConfigService: undefined,
13221325
envVarsService: expect.any(EnvironmentVariablesService),
13231326
logEvent: false,
1327+
logIndentation: 0,
13241328
logFormatter: expect.any(PowertoolLogFormatter),
13251329
logLevel: 'DEBUG',
13261330
logLevelThresholds: {
@@ -1345,6 +1349,7 @@ describe('Class: Logger', () => {
13451349
customConfigService: undefined,
13461350
envVarsService: expect.any(EnvironmentVariablesService),
13471351
logEvent: false,
1352+
logIndentation: 0,
13481353
logFormatter: expect.any(PowertoolLogFormatter),
13491354
logLevel: 'ERROR',
13501355
logLevelThresholds: {
@@ -1411,4 +1416,49 @@ describe('Class: Logger', () => {
14111416
});
14121417
});
14131418

1419+
describe('Feature: Pretty indentation for a local or non-production environment', () => {
1420+
1421+
test('when the `POWERTOOLS_DEV` env var is SET it makes log output has multiple lines', () => {
1422+
1423+
// Prepare
1424+
process.env.POWERTOOLS_DEV = 'true';
1425+
const INDENTATION = LogJsonIndent.PRETTY;
1426+
const logger = new Logger();
1427+
const consoleSpy = jest.spyOn(logger['console'], 'info').mockImplementation();
1428+
1429+
// Act
1430+
logger.info('Message with pretty identation');
1431+
1432+
// Assess
1433+
expect(consoleSpy).toBeCalledTimes(1);
1434+
expect(consoleSpy).toHaveBeenNthCalledWith(1, JSON.stringify({
1435+
level: 'INFO',
1436+
message: 'Message with pretty identation',
1437+
service: 'hello-world',
1438+
timestamp: '2016-06-20T12:08:10.000Z',
1439+
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
1440+
}, null, INDENTATION));
1441+
});
1442+
1443+
test('when the `POWERTOOLS_DEV` env var is NOT SET it makes log output as one-liner', () => {
1444+
1445+
// Prepare
1446+
const logger = new Logger();
1447+
const consoleSpy = jest.spyOn(logger['console'], 'info').mockImplementation();
1448+
1449+
// Act
1450+
logger.info('Message without pretty identation');
1451+
1452+
// Assess
1453+
expect(consoleSpy).toBeCalledTimes(1);
1454+
expect(consoleSpy).toHaveBeenNthCalledWith(1, JSON.stringify({
1455+
level: 'INFO',
1456+
message: 'Message without pretty identation',
1457+
service: 'hello-world',
1458+
timestamp: '2016-06-20T12:08:10.000Z',
1459+
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
1460+
}));
1461+
});
1462+
});
1463+
14141464
});

0 commit comments

Comments
 (0)