Skip to content
Closed
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
18 changes: 10 additions & 8 deletions packages/logger/src/formatter/PowertoolLogFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { PowertoolLog } from '../types/formats';

/**
* This class is used to transform a set of log key-value pairs
* in the AWS Lambda Powertools' default structure log format.
* in the AWS Lambda Powertools' default structure log format. It orders
* attribute keys in a way that should be useful when visually scanning logs in
* a UI such as the Cloudwatch console.
*
* @class
* @extends {LogFormatter}
Expand All @@ -18,17 +20,17 @@ class PowertoolLogFormatter extends LogFormatter {
*/
public formatAttributes(attributes: UnformattedAttributes): PowertoolLog {
return {
cold_start: attributes.lambdaContext?.coldStart,
function_arn: attributes.lambdaContext?.invokedFunctionArn,
function_memory_size: attributes.lambdaContext?.memoryLimitInMB,
function_name: attributes.lambdaContext?.functionName,
function_request_id: attributes.lambdaContext?.awsRequestId,
level: attributes.logLevel,
message: attributes.message,
sampling_rate: attributes.sampleRateValue,
function_request_id: attributes.lambdaContext?.awsRequestId,
xray_trace_id: attributes.xRayTraceId,
cold_start: attributes.lambdaContext?.coldStart,
function_memory_size: attributes.lambdaContext?.memoryLimitInMB,
service: attributes.serviceName,
sampling_rate: attributes.sampleRateValue,
function_arn: attributes.lambdaContext?.invokedFunctionArn,
function_name: attributes.lambdaContext?.functionName,
timestamp: this.formatTimestamp(attributes.timestamp),
xray_trace_id: attributes.xRayTraceId,
};
}
}
Expand Down
59 changes: 59 additions & 0 deletions packages/logger/tests/unit/formatter/PowertoolLogFormatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,65 @@ describe('Class: PowertoolLogFormatter', () => {
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
});
});

test('it returns an object whose properties serialize in a useful order for viewing in Cloudwatch console', () => {
// Prepare
const formatter = new PowertoolLogFormatter();
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',
},
};

// Act
const value = formatter.formatAttributes(unformattedAttributes);
const serializedValue = JSON.stringify(value);

// Assess
const orderOf = (key: string): number => serializedValue.indexOf(key);
// These are execution specific properties where order matters most
expect(orderOf('level')).toBeLessThan(orderOf('message'));
expect(orderOf('message')).toBeLessThan(orderOf('function_request_id'));
expect(orderOf('function_request_id')).toBeLessThan(
orderOf('xray_trace_id')
);
expect(orderOf('xray_trace_id')).toBeLessThan(orderOf('cold_start'));
expect(orderOf('cold_start')).toBeLessThan(
orderOf('function_memory_size')
);
// For all other properties, we just need to check that they come after
// the ones above. Timestamp is technicially execution specific, but log
// entries in Cloudwatch already have timestamps anyway, so it is less
// important for at-a-glance viewing.
expect(orderOf('function_memory_size')).toBeLessThan(orderOf('service'));
expect(orderOf('function_memory_size')).toBeLessThan(
orderOf('sampling_rate')
);
expect(orderOf('function_memory_size')).toBeLessThan(
orderOf('function_arn')
);
expect(orderOf('function_memory_size')).toBeLessThan(
orderOf('function_name')
);
expect(orderOf('function_memory_size')).toBeLessThan(
orderOf('timestamp')
);
});
});

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