diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 25e87a12f9..90921e6df3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -78,11 +78,7 @@ First, [fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) the ```console git clone https://github.com/{your-account}/aws-lambda-powertools-typescript.git cd aws-lambda-powertools-typescript -npm ci --foreground-scripts; -cd examples/cdk; npm ci -cd ../.. -cd examples/sam; npm ci -npm run init-environment +npm run setup-local ``` We recommend that you use [Visual Studio Code](https://code.visualstudio.com/) to work on the repo. diff --git a/docs/core/logger.md b/docs/core/logger.md index 01a47148f7..f4ae99ca9c 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -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 @@ -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" } }); @@ -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 => { + + // 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 @@ -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 diff --git a/package.json b/package.json index 84e18f2c9e..2e7676dfad 100644 --- a/package.json +++ b/package.json @@ -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 ../.. && npm run init-environment", "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", diff --git a/packages/logger/src/Logger.ts b/packages/logger/src/Logger.ts index 8d6a936645..e26fdfac27 100644 --- a/packages/logger/src/Logger.ts +++ b/packages/logger/src/Logger.ts @@ -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. * diff --git a/packages/logger/tests/e2e/basicFeatures.middy.test.FunctionCode.ts b/packages/logger/tests/e2e/basicFeatures.middy.test.FunctionCode.ts index 3270b40830..8a80ed8985 100644 --- a/packages/logger/tests/e2e/basicFeatures.middy.test.FunctionCode.ts +++ b/packages/logger/tests/e2e/basicFeatures.middy.test.FunctionCode.ts @@ -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; @@ -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'); diff --git a/packages/logger/tests/e2e/basicFeatures.middy.test.ts b/packages/logger/tests/e2e/basicFeatures.middy.test.ts index 04d964efcb..ab36645acd 100644 --- a/packages/logger/tests/e2e/basicFeatures.middy.test.ts +++ b/packages/logger/tests/e2e/basicFeatures.middy.test.ts @@ -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}`; @@ -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, @@ -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', () => { diff --git a/packages/logger/tests/unit/Logger.test.ts b/packages/logger/tests/unit/Logger.test.ts index a167ef5d1a..6a9757e0cb 100644 --- a/packages/logger/tests/unit/Logger.test.ts +++ b/packages/logger/tests/unit/Logger.test.ts @@ -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 persistentLogAttributes property', () => { // Prepare const logger = new Logger(); @@ -704,6 +704,97 @@ describe('Class: Logger', () => { }); }); + describe('Method: removeKeys', () => { + + test('when called, it removes keys from the logger\'s persistentLogAttributes property', () => { + + // 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 property 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(() => {