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

feat(logger): introduce log key reordering functionality #2736

Merged
merged 34 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3a78c9a
feat: define `logRecordOrder` option in Logger types
arnabrahman Jul 4, 2024
a8dde6b
feat: pass the `logRecordOrder` option to `LogFormatter`
arnabrahman Jul 4, 2024
4f3967f
feat: order attributes if logRecordOrder is available
arnabrahman Jul 4, 2024
c743eb0
feat: use `lodash.merge` for merging ordered & base order attributes
arnabrahman Jul 4, 2024
e1539ac
test: `logRecordOrder` option during formatting
arnabrahman Jul 4, 2024
6115983
Merge branch 'main' into 1568-log-message-ordering
dreamorosi Jul 8, 2024
94ed8fe
Merge branch 'main' into 1568-log-message-ordering
dreamorosi Jul 8, 2024
7a6a7f1
feat: merge with main
arnabrahman Sep 2, 2024
e7be7a2
refactor: `LogRecordOrder` type union of `UnformattedAttributes` & `…
arnabrahman Sep 2, 2024
22ab7b9
test: logRecordOrder option during formatting
arnabrahman Sep 2, 2024
94b647f
refactor: replace `lodash.merge` wih native JS
arnabrahman Sep 2, 2024
e8014f4
test: `logRecordOrder` takes `additionalLogAttributes` into considera…
arnabrahman Sep 2, 2024
80a2333
test: formatter when `logRecordOrder` is not set
arnabrahman Sep 2, 2024
2dd0cc5
feat: during formatting, apply ordering for `additionalLogAttributes`…
arnabrahman Sep 2, 2024
31efcec
test: `logRecordOrder` orders correctly when key doesn't even exist
arnabrahman Sep 2, 2024
85ec8aa
test: `logRecordOrder` should be passed down to child logger
arnabrahman Sep 2, 2024
986245c
doc: reordering log keys position
arnabrahman Sep 3, 2024
bd63350
doc: fix reorderLogKeys example highlight line
arnabrahman Sep 3, 2024
da1d0ee
feat: merge with main
arnabrahman Sep 3, 2024
f0ba54e
Merge branch '1568-log-message-ordering' of github.com:arnabrahman/aw…
arnabrahman Sep 3, 2024
e3bac06
doc: remove @returns
arnabrahman Sep 3, 2024
1c6b2f6
Update packages/logger/src/Logger.ts
arnabrahman Sep 7, 2024
07ba540
doc: update `setLogFormatter` function doc block
arnabrahman Sep 7, 2024
bfe9510
refactor: return early if `logRecordOrder` is not set
arnabrahman Sep 7, 2024
da62495
refactor: make `logRecordOrder` & `logFormatter` mutually exclusive
arnabrahman Sep 8, 2024
4ae836c
refactor: use `logRecordOrder` only inside `PowertoolsLogFormatter` c…
arnabrahman Sep 8, 2024
0a50ee5
test: refactor test to match the key orders
arnabrahman Sep 8, 2024
37b43b2
refactor: extract unformattedAttributes to the top level
arnabrahman Sep 8, 2024
ce2cb90
test: update test to add uncovered line
arnabrahman Sep 8, 2024
8f90b90
test: set `unformattedAttributes.timestamp` inside `beforeEach`
arnabrahman Sep 8, 2024
735c650
doc: add callout
arnabrahman Sep 8, 2024
62f0aef
style: doc block & afterAll cleanup for `unformattedAttributes`
arnabrahman Sep 8, 2024
74f614f
test: refactor `logRecordOrder` test for child logger
arnabrahman Sep 8, 2024
f4d4220
Merge branch 'main' into 1568-log-message-ordering
dreamorosi Sep 9, 2024
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
15 changes: 12 additions & 3 deletions packages/logger/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type {
LogItemMessage,
LoggerInterface,
PowertoolsLogData,
UnformattedAttributes,
} from './types/Logger.js';

/**
Expand Down Expand Up @@ -1080,12 +1081,19 @@ class Logger extends Utility implements LoggerInterface {
*
* @private
* @param {LogFormatterInterface} logFormatter
* @param {Array<keyof UnformattedAttributes>} logRecordOrder
* @returns {void}
*/
private setLogFormatter(logFormatter?: LogFormatterInterface): void {
private setLogFormatter(
logFormatter?: LogFormatterInterface,
logRecordOrder?: Array<keyof UnformattedAttributes>
): void {
this.logFormatter =
logFormatter ??
new PowertoolsLogFormatter({ envVarsService: this.getEnvVarsService() });
new PowertoolsLogFormatter({
envVarsService: this.getEnvVarsService(),
logRecordOrder,
});
}

/**
Expand Down Expand Up @@ -1119,6 +1127,7 @@ class Logger extends Utility implements LoggerInterface {
persistentKeys,
persistentLogAttributes, // deprecated in favor of persistentKeys
environment,
logRecordOrder,
} = options;

if (persistentLogAttributes && persistentKeys) {
Expand All @@ -1140,7 +1149,7 @@ class Logger extends Utility implements LoggerInterface {
this.setInitialSampleRate(sampleRateValue);

// configurations that affect how logs are printed
this.setLogFormatter(logFormatter);
this.setLogFormatter(logFormatter, logRecordOrder);
this.setConsole();
this.setLogIndentation();

Expand Down
6 changes: 6 additions & 0 deletions packages/logger/src/formatter/LogFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ abstract class LogFormatter implements LogFormatterInterface {
*/
protected envVarsService?: EnvironmentVariablesService;

/**
* An array of keys that defines the order of the log record.
*/
protected logRecordOrder?: Array<keyof UnformattedAttributes>;

public constructor(options?: LogFormatterOptions) {
this.envVarsService = options?.envVarsService;
this.logRecordOrder = options?.logRecordOrder;
arnabrahman marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
18 changes: 17 additions & 1 deletion packages/logger/src/formatter/PowertoolsLogFormatter.ts
arnabrahman marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import merge from 'lodash.merge';
import type { LogAttributes, PowertoolsLog } from '../types/Log.js';
import type { UnformattedAttributes } from '../types/Logger.js';
import { LogFormatter } from './LogFormatter.js';
Expand Down Expand Up @@ -35,7 +36,22 @@ class PowertoolsLogFormatter extends LogFormatter {
timestamp: this.formatTimestamp(attributes.timestamp),
xray_trace_id: attributes.xRayTraceId,
};
const powertoolsLogItem = new LogItem({ attributes: baseAttributes });

arnabrahman marked this conversation as resolved.
Show resolved Hide resolved
const orderedAttributes = {} as PowertoolsLog;

// If logRecordOrder is set, order the attributes in the log item
this.logRecordOrder?.forEach((key) => {
if (key in baseAttributes) {
orderedAttributes[key] = baseAttributes[key];
delete baseAttributes[key];
}
});

// Merge the ordered attributes with the rest of the attributes
const powertoolsLogItem = new LogItem({
attributes: merge(orderedAttributes, baseAttributes),
});

powertoolsLogItem.addAttributes(additionalLogAttributes);

return powertoolsLogItem;
Expand Down
2 changes: 2 additions & 0 deletions packages/logger/src/types/Log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ type LogFormatterOptions = {
* If set, it gives the LogFormatter access to environment variables.
*/
envVarsService?: EnvironmentVariablesService;

logRecordOrder?: Array<keyof UnformattedAttributes>;
};

/**
Expand Down
1 change: 1 addition & 0 deletions packages/logger/src/types/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type BaseConstructorOptions = {
logFormatter?: LogFormatterInterface;
customConfigService?: ConfigServiceInterface;
environment?: Environment;
logRecordOrder?: Array<keyof UnformattedAttributes>;
};

type PersistentKeysOption = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,60 @@ describe('Class: PowertoolsLogFormatter', () => {
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
});
});

test('when logRecordOrder is set, it orders the attributes in the log item', () => {
// Prepare
const formatter = new PowertoolsLogFormatter({
logRecordOrder: ['message', 'timestamp', 'serviceName', 'environment'],
});
const unformattedAttributes: UnformattedAttributes = {
sampleRateValue: 0.25,
awsRegion: 'eu-west-1',
environment: 'prod',
serviceName: 'hello-world',
xRayTraceId: '1-5759e988-bd862e3fe1be46a994272793',
logLevel: 'WARN',
timestamp: new Date(),
message: 'This is a WARN log',
error: new Error('Something happened!'),
lambdaContext: {
functionName: 'my-lambda-function',
memoryLimitInMB: '123',
functionVersion: '1.23.3',
coldStart: true,
invokedFunctionArn:
'arn:aws:lambda:eu-west-1:123456789012:function:Example',
awsRequestId: 'abcdefg123456789',
},
};
const additionalLogAttributes: LogAttributes = {};

// Act
const value = formatter.formatAttributes(
unformattedAttributes,
additionalLogAttributes
);

const response = value.getAttributes();

// Assess
expect(JSON.stringify(response)).toEqual(
JSON.stringify({
message: 'This is a WARN log',
timestamp: '2016-06-20T12:08:10.000Z',
cold_start: true,
function_arn:
'arn:aws:lambda:eu-west-1:123456789012:function:Example',
function_memory_size: '123',
function_name: 'my-lambda-function',
function_request_id: 'abcdefg123456789',
level: 'WARN',
sampling_rate: 0.25,
service: 'hello-world',
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
})
);
});
});

describe('Method: formatError', () => {
Expand Down