Skip to content
Merged
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
1 change: 1 addition & 0 deletions packages/logger/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ class Logger extends Utility implements LoggerInterface {
memoryLimitInMB: context.memoryLimitInMB,
functionName: context.functionName,
functionVersion: context.functionVersion,
tenantId: context.tenantId,
},
});
}
Expand Down
1 change: 1 addition & 0 deletions packages/logger/src/formatter/PowertoolsLogFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class PowertoolsLogFormatter extends LogFormatter {
function_request_id: attributes.lambdaContext?.awsRequestId,
sampling_rate: attributes.sampleRateValue,
xray_trace_id: attributes.xRayTraceId,
tenant_id: attributes.lambdaContext?.tenantId,
};

// If logRecordOrder is not set, return the log item with the attributes in the order they were added
Expand Down
7 changes: 7 additions & 0 deletions packages/logger/src/types/logKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ type PowertoolsLambdaContextKeys = {
* @example "899856cb-83d1-40d7-8611-9e78f15f32f4"
*/
function_request_id: string;
/**
* The tenant ID from AWS Lambda Tenant Isolation feature.
*
* @example "cff02b3a-0e12-4be2-b3e0-758b49c4cd9b"
*/
tenant_id?: string;
};

/**
Expand All @@ -159,6 +165,7 @@ type LambdaFunctionContext = Pick<
| 'functionVersion'
| 'invokedFunctionArn'
| 'awsRequestId'
| 'tenantId'
> & {
coldStart: boolean;
};
Expand Down
7 changes: 7 additions & 0 deletions packages/logger/tests/unit/formatters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const unformattedAttributes: UnformattedAttributes = {
invokedFunctionArn:
'arn:aws:lambda:eu-west-1:123456789012:function:Example',
awsRequestId: 'abcdefg123456789',
tenantId: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b',
},
};

Expand Down Expand Up @@ -155,6 +156,7 @@ describe('Formatters', () => {
service: 'hello-world',
timestamp: '2016-06-20T12:08:10.000Z',
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
tenant_id: undefined,
});
expect(value).toBeInstanceOf(LogItem);
});
Expand Down Expand Up @@ -184,6 +186,7 @@ describe('Formatters', () => {
service: 'hello-world',
timestamp: '2016-06-20T12:08:10.000Z',
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
tenant_id: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b',
});
});

Expand Down Expand Up @@ -215,6 +218,7 @@ describe('Formatters', () => {
function_request_id: 'abcdefg123456789',
sampling_rate: 0.25,
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
tenant_id: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b',
});
});

Expand Down Expand Up @@ -256,6 +260,7 @@ describe('Formatters', () => {
function_request_id: 'abcdefg123456789',
sampling_rate: 0.25,
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
tenant_id: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b',
another_key: 'another_value',
});
});
Expand Down Expand Up @@ -297,6 +302,7 @@ describe('Formatters', () => {
function_request_id: 'abcdefg123456789',
sampling_rate: 0.25,
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
tenant_id: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b',
});
});

Expand Down Expand Up @@ -328,6 +334,7 @@ describe('Formatters', () => {
function_request_id: 'abcdefg123456789',
sampling_rate: 0.25,
xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793',
tenant_id: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b',
additional_key: 'additional_value',
});
});
Expand Down
58 changes: 58 additions & 0 deletions packages/logger/tests/unit/injectLambdaContext.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const getContextLogEntries = (overrides?: Record<string, unknown>) => ({
function_memory_size: context.memoryLimitInMB,
function_name: context.functionName,
function_request_id: context.awsRequestId,
tenant_id: context.tenantId,
cold_start: true,
...overrides,
});
Expand Down Expand Up @@ -76,6 +77,39 @@ describe('Inject Lambda Context', () => {
);
});

it('does not include tenant_id when context does not have tenantId', () => {
// Prepare
const logger = new Logger();
const contextWithoutTenantId = {
...context,
tenantId: undefined,
};

// Act
logger.addContext(contextWithoutTenantId);
logger.info('Hello, world!');

// Assess
expect(console.info).toHaveBeenCalledTimes(1);
expect(console.info).toHaveLoggedNth(
1,
expect.objectContaining({
message: 'Hello, world!',
function_arn: context.invokedFunctionArn,
function_memory_size: context.memoryLimitInMB,
function_name: context.functionName,
function_request_id: context.awsRequestId,
cold_start: true,
})
);
expect(console.info).not.toHaveLoggedNth(
1,
expect.objectContaining({
tenant_id: expect.anything(),
})
);
});

it('adds the context to log messages when the feature is enabled in the Middy.js middleware', async () => {
// Prepare
const logger = new Logger();
Expand All @@ -97,6 +131,30 @@ describe('Inject Lambda Context', () => {
);
});

it('does not include tenant_id when using Middy.js middleware without tenantId in context', async () => {
// Prepare
const logger = new Logger();
const contextWithoutTenantId = {
...context,
tenantId: undefined,
};
const handler = middy(() => {
logger.info('Hello, world!');
}).use(injectLambdaContext(logger));

// Act
await handler(event, contextWithoutTenantId);

// Assess
expect(console.info).toHaveBeenCalledTimes(1);
expect(console.info).not.toHaveLoggedNth(
1,
expect.objectContaining({
tenant_id: expect.anything(),
})
);
});

it('adds the context to the messages of each logger instance', async () => {
// Prepare
const logger1 = new Logger({ serviceName: 'parent' });
Expand Down
2 changes: 2 additions & 0 deletions packages/logger/tests/unit/logEvent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ describe('Log event', () => {
function_memory_size: '128',
function_name: 'foo-bar-function',
function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678',
tenant_id: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b'
})
);
});
Expand Down Expand Up @@ -107,6 +108,7 @@ describe('Log event', () => {
function_memory_size: '128',
function_name: 'foo-bar-function',
function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678',
tenant_id: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b'
})
);
});
Expand Down
6 changes: 3 additions & 3 deletions packages/testing/src/TestInvocationLogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class TestInvocationLogs {
* The first element is START, and the last two elements are END, and REPORT.
* [
* 'START RequestId: c6af9ac6-7b61-11e6-9a41-93e812345678 Version: $LATEST',
* '{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","level":"INFO","message":"This is an INFO log with some context and persistent key","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works"}',
* '{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","level":"INFO","message":"This is an INFO log with some context","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","additionalKey":"additionalValue"}',
* '{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","level":"ERROR","message":"There was an error","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","error":{"name":"Error","location":"/var/task/index.js:2778","message":"you cannot prevent this","stack":"Error: you cannot prevent this\\n at testFunction (/var/task/index.js:2778:11)\\n at runRequest (/var/task/index.js:2314:36)"}}',
* '{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","tenant_id":"cff02b3a-0e12-4be2-b3e0-758b49c4cd9b","level":"INFO","message":"This is an INFO log with some context and persistent key","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works"}',
* '{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","tenant_id":"cff02b3a-0e12-4be2-b3e0-758b49c4cd9b","level":"INFO","message":"This is an INFO log with some context","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","additionalKey":"additionalValue"}',
* '{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","tenant_id":"cff02b3a-0e12-4be2-b3e0-758b49c4cd9b","level":"ERROR","message":"There was an error","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","error":{"name":"Error","location":"/var/task/index.js:2778","message":"you cannot prevent this","stack":"Error: you cannot prevent this\\n at testFunction (/var/task/index.js:2778:11)\\n at runRequest (/var/task/index.js:2314:36)"}}',
* 'END RequestId: c6af9ac6-7b61-11e6-9a41-93e812345678',
* 'REPORT RequestId: c6af9ac6-7b61-11e6-9a41-93e812345678\tDuration: 2.16 ms\tBilled Duration: 3 ms\tMemory Size: 128 MB\tMax Memory Used: 57 MB\t',
* ]
Expand Down
1 change: 1 addition & 0 deletions packages/testing/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default {
invokedFunctionArn:
'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function',
awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e812345678',
tenantId: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b',
getRemainingTimeInMillis: () => 1234,
done: () => console.log('Done!'),
fail: () => console.log('Failed!'),
Expand Down
11 changes: 6 additions & 5 deletions packages/testing/tests/unit/TestInvocationLogs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { beforeEach, describe, expect, it } from 'vitest';
import { TestInvocationLogs } from '../../src/TestInvocationLogs.js';

const exampleLogs = `START RequestId: c6af9ac6-7b61-11e6-9a41-93e812345678 Version: $LATEST
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","level":"DEBUG","message":"This is a DEBUG log but contains the word INFO some context and persistent key","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works"}
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","level":"INFO","message":"This is an INFO log with some context","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","additionalKey":"additionalValue"}
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","level":"INFO","message":"This is a second INFO log with some context","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","additionalKey":"additionalValue"}
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","level":"ERROR","message":"There was an error","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","error":{"name":"Error","location":"/var/task/index.js:2778","message":"you cannot prevent this","stack":"Error: you cannot prevent this\\n at testFunction (/var/task/index.js:2778:11)\\n at runRequest (/var/task/index.js:2314:36)"}}
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","tenant_id":"cff02b3a-0e12-4be2-b3e0-758b49c4cd9b","level":"DEBUG","message":"This is a DEBUG log but contains the word INFO some context and persistent key","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works"}
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","tenant_id":"cff02b3a-0e12-4be2-b3e0-758b49c4cd9b","level":"INFO","message":"This is an INFO log with some context","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","additionalKey":"additionalValue"}
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","tenant_id":"cff02b3a-0e12-4be2-b3e0-758b49c4cd9b","level":"INFO","message":"This is a second INFO log with some context","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","additionalKey":"additionalValue"}
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","tenant_id":"cff02b3a-0e12-4be2-b3e0-758b49c4cd9b","level":"ERROR","message":"There was an error","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works","error":{"name":"Error","location":"/var/task/index.js:2778","message":"you cannot prevent this","stack":"Error: you cannot prevent this\\n at testFunction (/var/task/index.js:2778:11)\\n at runRequest (/var/task/index.js:2314:36)"}}
END RequestId: c6af9ac6-7b61-11e6-9a41-93e812345678
REPORT RequestId: c6af9ac6-7b61-11e6-9a41-93e812345678\tDuration: 2.16 ms\tBilled Duration: 3 ms\tMemory Size: 128 MB\tMax Memory Used: 57 MB\t`;

Expand Down Expand Up @@ -121,7 +121,7 @@ describe('getFunctionLogs()', () => {
describe('parseFunctionLog()', () => {
it('returns an object with the correct values based on the given log', () => {
const rawLogStr =
'{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","level":"DEBUG","message":"This is a DEBUG log but contains the word INFO some context and persistent key","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works"}';
'{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:561912387782:function:loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_memory_size":128,"function_name":"loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c","function_request_id":"7f586697-238a-4c3b-9250-a5f057c1119c","tenant_id":"cff02b3a-0e12-4be2-b3e0-758b49c4cd9b","level":"DEBUG","message":"This is a DEBUG log but contains the word INFO some context and persistent key","service":"logger-e2e-testing","timestamp":"2022-01-27T16:04:39.323Z","persistentKey":"works"}';

const logObj = TestInvocationLogs.parseFunctionLog(rawLogStr);
expect(logObj).toStrictEqual({
Expand All @@ -132,6 +132,7 @@ describe('parseFunctionLog()', () => {
function_name:
'loggerMiddyStandardFeatures-c555a2ec-1121-4586-9c04-185ab36ea34c',
function_request_id: '7f586697-238a-4c3b-9250-a5f057c1119c',
tenant_id: 'cff02b3a-0e12-4be2-b3e0-758b49c4cd9b',
level: 'DEBUG',
message:
'This is a DEBUG log but contains the word INFO some context and persistent key',
Expand Down