Skip to content

Commit

Permalink
feat(logger): Support for external observability providers (#1511)
Browse files Browse the repository at this point in the history
* Updated formatAttributes for additional parameters and LogItem return type

* Updated the unit tests to pass with new formatter

* Updated Powertool named objects to Powertools

* Updated tests to match new naming consistency

* Updated for tests for new naming consistency

* Updated formatter for new design decisions

* Update Logger for ephemeral attributes

* Update bringYourOwnFormatter documentation to match new formatter

---------

Co-authored-by: erikayao93 <[email protected]>
  • Loading branch information
2 people authored and dreamorosi committed Sep 18, 2023
1 parent 6a470cf commit f95b4e3
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 99 deletions.
13 changes: 11 additions & 2 deletions docs/snippets/logger/bringYourOwnFormatterClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import {
LogAttributes,
UnformattedAttributes,
} from '@aws-lambda-powertools/logger/lib/types';
import { LogItem } from '@aws-lambda-powertools/logger/lib/log';

// Replace this line with your own type
type MyCompanyLog = LogAttributes;

class MyCompanyLogFormatter extends LogFormatter {
public formatAttributes(attributes: UnformattedAttributes): MyCompanyLog {
return {
public formatAttributes(
attributes: UnformattedAttributes,
additionalLogAttributes: LogAttributes
): LogItem {
const baseAttributes: MyCompanyLog = {
message: attributes.message,
service: attributes.serviceName,
environment: attributes.environment,
Expand All @@ -31,6 +35,11 @@ class MyCompanyLogFormatter extends LogFormatter {
sampleRateValue: attributes.sampleRateValue,
},
};

const logItem = new LogItem({ attributes: baseAttributes });
logItem.addAttributes(additionalLogAttributes); // add any attributes not explicitly defined

return logItem;
}
}

Expand Down
26 changes: 14 additions & 12 deletions packages/logger/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { randomInt } from 'node:crypto';
import { Console } from 'node:console';
import type { Context, Handler } from 'aws-lambda';
import { Utility } from '@aws-lambda-powertools/commons';
import { LogFormatterInterface, PowertoolLogFormatter } from './formatter';
import { LogFormatterInterface, PowertoolsLogFormatter } from './formatter';
import { LogItem } from './log';
import merge from 'lodash.merge';
import { ConfigServiceInterface, EnvironmentVariablesService } from './config';
Expand Down Expand Up @@ -627,16 +627,13 @@ class Logger extends Utility implements ClassThatLogs {
this.getPowertoolLogData()
);

const logItem = new LogItem({
baseAttributes: this.getLogFormatter().formatAttributes(
unformattedBaseAttributes
),
persistentAttributes: this.getPersistentLogAttributes(),
});

// Add ephemeral attributes
let additionalLogAttributes: LogAttributes = {};
additionalLogAttributes = merge(
additionalLogAttributes,
this.getPersistentLogAttributes()
);
if (typeof input !== 'string') {
logItem.addAttributes(input);
additionalLogAttributes = merge(additionalLogAttributes, input);
}
extraInput.forEach((item: Error | LogAttributes | string) => {
const attributes: LogAttributes =
Expand All @@ -646,9 +643,14 @@ class Logger extends Utility implements ClassThatLogs {
? { extra: item }
: item;

logItem.addAttributes(attributes);
additionalLogAttributes = merge(additionalLogAttributes, attributes);
});

const logItem = this.getLogFormatter().formatAttributes(
unformattedBaseAttributes,
additionalLogAttributes
);

return logItem;
}

Expand Down Expand Up @@ -925,7 +927,7 @@ class Logger extends Utility implements ClassThatLogs {
* @returns {void}
*/
private setLogFormatter(logFormatter?: LogFormatterInterface): void {
this.logFormatter = logFormatter || new PowertoolLogFormatter();
this.logFormatter = logFormatter || new PowertoolsLogFormatter();
}

/**
Expand Down
9 changes: 6 additions & 3 deletions packages/logger/src/formatter/LogFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LogFormatterInterface } from '.';
import { LogAttributes, UnformattedAttributes } from '../types';
import { LogItem } from '../log';

/**
* Typeguard to monkey patch Error to add a cause property.
Expand Down Expand Up @@ -30,11 +31,13 @@ abstract class LogFormatter implements LogFormatterInterface {
* It formats key-value pairs of log attributes.
*
* @param {UnformattedAttributes} attributes
* @returns {LogAttributes}
* @param {LogAttributes} additionalLogAttributes
* @returns {LogItem}
*/
public abstract formatAttributes(
attributes: UnformattedAttributes
): LogAttributes;
attributes: UnformattedAttributes,
additionalLogAttributes: LogAttributes
): LogItem;

/**
* It formats a given Error parameter.
Expand Down
9 changes: 7 additions & 2 deletions packages/logger/src/formatter/LogFormatterInterface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LogAttributes, UnformattedAttributes } from '../types';
import { LogItem } from '../log';

/**
* @interface
Expand All @@ -8,9 +9,13 @@ interface LogFormatterInterface {
* It formats key-value pairs of log attributes.
*
* @param {UnformattedAttributes} attributes
* @returns {PowertoolLog}
* @param {LogAttributes} additionalLogAttributes
* @returns {LogItem}
*/
formatAttributes(attributes: UnformattedAttributes): LogAttributes;
formatAttributes(
attributes: UnformattedAttributes,
additionalLogAttributes: LogAttributes
): LogItem;

/**
* It formats a given Error parameter.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { LogFormatter } from '.';
import { UnformattedAttributes } from '../types';
import { PowertoolLog } from '../types/formats';
import { LogAttributes, UnformattedAttributes } from '../types';
import { PowertoolsLog } from '../types/formats';
import { LogItem } from '../log';

/**
* This class is used to transform a set of log key-value pairs
Expand All @@ -9,15 +10,19 @@ import { PowertoolLog } from '../types/formats';
* @class
* @extends {LogFormatter}
*/
class PowertoolLogFormatter extends LogFormatter {
class PowertoolsLogFormatter extends LogFormatter {
/**
* It formats key-value pairs of log attributes.
*
* @param {UnformattedAttributes} attributes
* @returns {PowertoolLog}
* @param {LogAttributes} additionalLogAttributes
* @returns {PowertoolsLog}
*/
public formatAttributes(attributes: UnformattedAttributes): PowertoolLog {
return {
public formatAttributes(
attributes: UnformattedAttributes,
additionalLogAttributes: LogAttributes
): LogItem {
const baseAttributes: PowertoolsLog = {
cold_start: attributes.lambdaContext?.coldStart,
function_arn: attributes.lambdaContext?.invokedFunctionArn,
function_memory_size: attributes.lambdaContext?.memoryLimitInMB,
Expand All @@ -30,7 +35,13 @@ class PowertoolLogFormatter extends LogFormatter {
timestamp: this.formatTimestamp(attributes.timestamp),
xray_trace_id: attributes.xRayTraceId,
};

const powertoolLogItem = new LogItem({ attributes: baseAttributes });

powertoolLogItem.addAttributes(additionalLogAttributes);

return powertoolLogItem;
}
}

export { PowertoolLogFormatter };
export { PowertoolsLogFormatter };
2 changes: 1 addition & 1 deletion packages/logger/src/formatter/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './LogFormatter';
export * from './LogFormatterInterface';
export * from './PowertoolLogFormatter';
export * from './PowertoolsLogFormatter';
10 changes: 3 additions & 7 deletions packages/logger/src/log/LogItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@ import { LogAttributes } from '../types';
class LogItem implements LogItemInterface {
private attributes: LogAttributes = {};

public constructor(params: {
baseAttributes: LogAttributes;
persistentAttributes: LogAttributes;
}) {
public constructor(params: { attributes: LogAttributes }) {
// Add attributes in the log item in this order:
// - Base attributes supported by the Powertool by default
// - Persistent attributes provided by developer, not formatted
// - Persistent attributes provided by developer, not formatted (done later)
// - Ephemeral attributes provided as parameters for a single log item (done later)
this.addAttributes(params.baseAttributes);
this.addAttributes(params.persistentAttributes);
this.addAttributes(params.attributes);
}

public addAttributes(attributes: LogAttributes): LogItem {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { LogAttributes, LogLevel } from '..';

type PowertoolLog = LogAttributes & {
type PowertoolsLog = LogAttributes & {
/**
* timestamp
*
Expand Down Expand Up @@ -90,4 +90,4 @@ type PowertoolLog = LogAttributes & {
lambda_request_id?: string;
};

export type { PowertoolLog };
export type { PowertoolsLog };
2 changes: 1 addition & 1 deletion packages/logger/src/types/formats/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './PowertoolLog';
export * from './PowertoolsLog';
34 changes: 17 additions & 17 deletions packages/logger/tests/unit/Logger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '@aws-lambda-powertools/commons';
import { createLogger, Logger } from '../../src';
import { EnvironmentVariablesService } from '../../src/config';
import { PowertoolLogFormatter } from '../../src/formatter';
import { PowertoolsLogFormatter } from '../../src/formatter';
import {
ClassThatLogs,
LogJsonIndent,
Expand Down Expand Up @@ -798,7 +798,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: 0,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand Down Expand Up @@ -1601,7 +1601,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand All @@ -1624,7 +1624,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand All @@ -1647,7 +1647,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand Down Expand Up @@ -1713,7 +1713,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand All @@ -1736,7 +1736,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand All @@ -1762,7 +1762,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand All @@ -1785,7 +1785,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 20,
logLevelThresholds: {
...logLevelThresholds,
Expand Down Expand Up @@ -1829,7 +1829,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand All @@ -1852,7 +1852,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand Down Expand Up @@ -1882,7 +1882,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: INDENTATION,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand Down Expand Up @@ -1923,7 +1923,7 @@ describe('Class: Logger', () => {
envVarsService: expect.any(EnvironmentVariablesService),
logEvent: false,
logIndentation: 0,
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
logLevel: 8,
logLevelThresholds: {
...logLevelThresholds,
Expand All @@ -1950,7 +1950,7 @@ describe('Class: Logger', () => {

test('child logger should have the same logFormatter as its parent', () => {
// Prepare
class MyCustomLogFormatter extends PowertoolLogFormatter {}
class MyCustomLogFormatter extends PowertoolsLogFormatter {}
const parentLogger = new Logger({
logFormatter: new MyCustomLogFormatter(),
});
Expand All @@ -1968,7 +1968,7 @@ describe('Class: Logger', () => {

test('child logger with custom logFormatter in options should have provided logFormatter', () => {
// Prepare
class MyCustomLogFormatter extends PowertoolLogFormatter {}
class MyCustomLogFormatter extends PowertoolsLogFormatter {}
const parentLogger = new Logger();

// Act
Expand All @@ -1979,7 +1979,7 @@ describe('Class: Logger', () => {
// Assess
expect(parentLogger).toEqual(
expect.objectContaining({
logFormatter: expect.any(PowertoolLogFormatter),
logFormatter: expect.any(PowertoolsLogFormatter),
})
);

Expand All @@ -1992,7 +1992,7 @@ describe('Class: Logger', () => {

test('child logger should have exact same attributes as the parent logger created with all non-default options', () => {
// Prepare
class MyCustomLogFormatter extends PowertoolLogFormatter {}
class MyCustomLogFormatter extends PowertoolsLogFormatter {}
class MyCustomEnvironmentVariablesService extends EnvironmentVariablesService {}

const options: ConstructorOptions = {
Expand Down
Loading

0 comments on commit f95b4e3

Please sign in to comment.