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): add removeKeys functionality #901

Merged
merged 9 commits into from
May 30, 2022
15 changes: 12 additions & 3 deletions docs/core/logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,12 @@ You can append additional persistent keys and values in the logs generated durin
* Via the Logger's `appendKeys` method, for all log items generated after calling this method
* Passing them in the Logger's constructor

To remove the keys you added, you can use the `removeKeys` method.


=== "handler.ts"

```typescript hl_lines="5-12 16-23"
```typescript hl_lines="5-13 17-25 30"
import { Logger } from '@aws-lambda-powertools/logger';

// Add persistent log keys via the constructor
Expand All @@ -213,7 +216,8 @@ You can append additional persistent keys and values in the logs generated durin
logger: {
name: '@aws-lambda-powertools/logger',
version: '0.0.1',
}
},
extra_key: "some-value"
}
});

Expand All @@ -224,10 +228,14 @@ You can append additional persistent keys and values in the logs generated durin
// logger: {
// name: '@aws-lambda-powertools/logger',
// version: '0.0.1',
// }
// },
// extra_key: "some-value"
// });

export const handler = async (_event: any, _context: any): Promise<unknown> => {

// If you don't want to log the "extra_key" attribute in your logs, you can remove it
logger.removeKeys(["extra_key"])

// This info log will print all extra custom attributes added above
// Extra attributes: logger object with name and version of the logger library, awsAccountId, awsRegion
Expand Down Expand Up @@ -271,6 +279,7 @@ You can append additional persistent keys and values in the logs generated durin
}
```


!!! tip "Logger will automatically ignore any key with an `undefined` value"

### Appending additional data to a single log item
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"test": "npm run lerna-test",
"commit": "commit",
"package": "npm run package",
"setup-local": "npm ci --foreground-scripts && cd examples/cdk && npm ci && cd ../.. && cd examples/sam && npm ci && cd ../..",
saragerion marked this conversation as resolved.
Show resolved Hide resolved
"lerna-test": "lerna exec -- npm run test",
"lerna-test:unit": "lerna exec -- npm run test:unit",
"lerna-test:e2e": "lerna exec -- npm run test:e2e",
Expand Down
24 changes: 24 additions & 0 deletions packages/logger/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,30 @@ class Logger extends Utility implements ClassThatLogs {
this.setLogsSampled();
}

/**
* Alias for removePersistentLogAttributes.
*
* @param {string[]} keys
* @returns {void}
*/
public removeKeys(keys: string[]): void {
this.removePersistentLogAttributes(keys);
}

/**
* It removes attributes based on provided keys to all log items generated by this Logger instance.
*
* @param {string[]} keys
* @returns {void}
*/
public removePersistentLogAttributes(keys: string[]): void {
keys.forEach((key) => {
if (this.persistentLogAttributes && key in this.persistentLogAttributes) {
delete this.persistentLogAttributes[key];
}
});
}

/**
* It sets the user-provided sample rate value.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import middy from '@middy/core';

const PERSISTENT_KEY = process.env.PERSISTENT_KEY;
const PERSISTENT_VALUE = process.env.PERSISTENT_VALUE;
const REMOVABLE_KEY = process.env.REMOVABLE_KEY;
const REMOVABLE_VALUE = process.env.REMOVABLE_VALUE;
const ERROR_MSG = process.env.ERROR_MSG || 'error';
const SINGLE_LOG_ITEM_KEY = process.env.SINGLE_LOG_ITEM_KEY;
const SINGLE_LOG_ITEM_VALUE = process.env.SINGLE_LOG_ITEM_VALUE;
Expand All @@ -13,14 +15,16 @@ const ARBITRARY_OBJECT_DATA = process.env.ARBITRARY_OBJECT_DATA;
const logger = new Logger({
persistentLogAttributes: {
[PERSISTENT_KEY]: PERSISTENT_VALUE,
[REMOVABLE_KEY]: REMOVABLE_VALUE,
},
});

const testFunction = async (event: APIGatewayProxyEvent, context: Context): Promise<{requestId: string}> => {
// Test feature 1: Log level filtering
// Test feature 2: Context data
// Test feature 3: Persistent additional log keys and value
// Test feature 3: Add and remove persistent additional log keys and value
// Test feature 4: X-Ray Trace ID injection
logger.removeKeys([REMOVABLE_KEY]);
logger.debug('##### This should not appear');
logger.info('This is an INFO log with context and persistent key');

Expand Down
12 changes: 12 additions & 0 deletions packages/logger/tests/e2e/basicFeatures.middy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const lambdaFunctionCodeFile = 'basicFeatures.middy.test.FunctionCode.ts';
// Text to be used by Logger in the Lambda function
const PERSISTENT_KEY = 'persistentKey';
const PERSISTENT_VALUE = `a persistent value that will be put in every log ${uuid}`;
const REMOVABLE_KEY = 'removableKey';
const REMOVABLE_VALUE = 'a persistent value that will be removed and not displayed in any log ${uuid}';
const SINGLE_LOG_ITEM_KEY = `keyForSingleLogItem${uuid}`;
const SINGLE_LOG_ITEM_VALUE = `a value for a single log item${uuid}`;
const ERROR_MSG = `error-${uuid}`;
Expand Down Expand Up @@ -72,6 +74,8 @@ describe(`logger E2E tests basic functionalities (middy) for runtime: ${runtime}
// Text to be used by Logger in the Lambda function
PERSISTENT_KEY,
PERSISTENT_VALUE,
REMOVABLE_KEY,
REMOVABLE_VALUE,
SINGLE_LOG_ITEM_KEY,
SINGLE_LOG_ITEM_VALUE,
ERROR_MSG,
Expand Down Expand Up @@ -147,6 +151,14 @@ describe(`logger E2E tests basic functionalities (middy) for runtime: ${runtime}
expect(message).toContain(`"${PERSISTENT_KEY}":"${PERSISTENT_VALUE}"`);
}
}, TEST_CASE_TIMEOUT);

it('should not contain persistent keys that were removed on runtime', async () => {
const logMessages = invocationLogs[0].getFunctionLogs();

for (const message of logMessages) {
expect(message).not.toContain(`"${REMOVABLE_KEY}":"${REMOVABLE_VALUE}"`);
}
}, TEST_CASE_TIMEOUT);
});

describe('X-Ray Trace ID injection', () => {
Expand Down
93 changes: 92 additions & 1 deletion packages/logger/tests/unit/Logger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ describe('Class: Logger', () => {

describe('Method: appendKeys', () => {

test('when called, populates the logger\'s propriety persistentLogAttributes ', () => {
test('when called, it populates the logger\'s propriety persistentLogAttributes ', () => {
saragerion marked this conversation as resolved.
Show resolved Hide resolved

// Prepare
const logger = new Logger();
Expand Down Expand Up @@ -704,6 +704,97 @@ describe('Class: Logger', () => {
});
});

describe('Method: removeKeys', () => {

test('when called, it removes keys from the logger\'s propriety persistentLogAttributes', () => {
saragerion marked this conversation as resolved.
Show resolved Hide resolved

// Prepare
const logger = new Logger();
logger.appendKeys({
aws_account_id: '123456789012',
aws_region: 'eu-west-1',
logger: {
name: 'aws-lambda-powertool-typescript',
version: '0.2.4',
},
});

// Act
logger.removeKeys([ 'aws_account_id', 'aws_region' ]);

// Assess
expect(logger).toEqual(expect.objectContaining({
persistentLogAttributes: {
logger: {
name: 'aws-lambda-powertool-typescript',
version: '0.2.4',
},
},
}));
});

test('when called with non-existing keys, the logger\'s propriety persistentLogAttributes is not mutated and it does not throw an error', () => {

// Prepare
const logger = new Logger();
logger.appendKeys({
aws_account_id: '123456789012',
aws_region: 'eu-west-1',
logger: {
name: 'aws-lambda-powertool-typescript',
version: '0.2.4',
},
});
const loggerBeforeKeysAreRemoved = { ...logger };

// Act
logger.removeKeys(['not_existing_key']);

// Assess
expect(logger).toEqual(loggerBeforeKeysAreRemoved);
expect(logger).toEqual(expect.objectContaining({
persistentLogAttributes: {
aws_account_id: '123456789012',
aws_region: 'eu-west-1',
logger: {
name: 'aws-lambda-powertool-typescript',
version: '0.2.4',
},
},
}));
});

});

test('when called multiple times with the same keys, the outcome is the same', () => {

// Prepare
const logger = new Logger();
logger.appendKeys({
aws_account_id: '123456789012',
aws_region: 'eu-west-1',
logger: {
name: 'aws-lambda-powertool-typescript',
version: '0.2.4',
},
});

// Act
logger.removeKeys([ 'aws_account_id', 'aws_region' ]);
logger.removeKeys([ 'aws_account_id', 'aws_region' ]);

// Assess
expect(logger).toEqual(expect.objectContaining({
persistentLogAttributes: {
logger: {
name: 'aws-lambda-powertool-typescript',
version: '0.2.4',
},
},
}));

});

describe('Method: injectLambdaContext', () => {

beforeEach(() => {
Expand Down