diff --git a/packages/commons/src/Utility.ts b/packages/commons/src/Utility.ts index 2932785e0d..89f1dbd03d 100644 --- a/packages/commons/src/Utility.ts +++ b/packages/commons/src/Utility.ts @@ -51,15 +51,46 @@ * ``` */ export class Utility { + readonly #initializationType: + | 'unknown' + | 'on-demand' + | 'provisioned-concurrency'; protected coldStart = true; protected readonly defaultServiceName: string = 'service_undefined'; + public constructor() { + this.#initializationType = this.getInitializationType(); + if (this.#initializationType !== 'on-demand') { + this.coldStart = false; + } + } + + /** + * Get the value of the `AWS_LAMBDA_INITIALIZATION_TYPE` environment variable. + */ + protected getInitializationType(): + | 'unknown' + | 'on-demand' + | 'provisioned-concurrency' { + const envVarValue = process.env.AWS_LAMBDA_INITIALIZATION_TYPE?.trim(); + if (envVarValue === 'on-demand') { + return 'on-demand'; + } + if (envVarValue === 'provisioned-concurrency') { + return 'provisioned-concurrency'; + } + return 'unknown'; + } + /** * Get the cold start status of the current execution environment. * * The method also flips the cold start status to `false` after the first invocation. */ protected getColdStart(): boolean { + if (this.#initializationType !== 'on-demand') { + return false; + } if (this.coldStart) { this.coldStart = false; diff --git a/packages/commons/tests/unit/Utility.test.ts b/packages/commons/tests/unit/Utility.test.ts index 16f88c3f38..15b3309538 100644 --- a/packages/commons/tests/unit/Utility.test.ts +++ b/packages/commons/tests/unit/Utility.test.ts @@ -15,6 +15,12 @@ describe('Class: Utility', () => { public validateServiceName(serviceName: string): boolean { return this.isValidServiceName(serviceName); } + public getInitializationType(): + | 'unknown' + | 'on-demand' + | 'provisioned-concurrency' { + return super.getInitializationType(); + } } it('returns the correct cold start value', () => { @@ -27,6 +33,15 @@ describe('Class: Utility', () => { expect(utility.dummyMethod()).toBe(false); }); + it('returns the correct cold start value when provisioned concurrency is used', () => { + // Prepare + process.env.AWS_LAMBDA_INITIALIZATION_TYPE = 'provisioned-concurrency'; + const utility = new TestUtility(); + + // Act & Assess + expect(utility.dummyMethod()).toBe(false); + }); + it('flips the cold start value', () => { // Prepare const utility = new TestUtility(); @@ -54,4 +69,23 @@ describe('Class: Utility', () => { expect(utility.validateServiceName('serverlessAirline')).toBe(true); expect(utility.validateServiceName('')).toBe(false); }); + + it.each([ + { value: 'on-demand', expected: 'on-demand' }, + { value: 'provisioned-concurrency', expected: 'provisioned-concurrency' }, + { value: '', expected: 'unknown' }, + ])( + 'returns the correct initialization type ($value)', + ({ value, expected }) => { + // Prepare + process.env.AWS_LAMBDA_INITIALIZATION_TYPE = value; + const utility = new TestUtility(); + + // Act + const initializationType = utility.getInitializationType(); + + // Assess + expect(initializationType).toBe(expected); + } + ); }); diff --git a/packages/commons/tests/unit/awsSdkUtils.test.ts b/packages/commons/tests/unit/awsSdkUtils.test.ts index c8f233e355..7af7af9d3a 100644 --- a/packages/commons/tests/unit/awsSdkUtils.test.ts +++ b/packages/commons/tests/unit/awsSdkUtils.test.ts @@ -6,6 +6,10 @@ import { PT_VERSION as version, } from '../../src/index.js'; +vi.hoisted(() => { + process.env.AWS_EXECUTION_ENV = ''; +}); + describe('Helpers: awsSdk', () => { describe('Function: userAgentMiddleware', () => { beforeAll(() => { diff --git a/packages/commons/vitest.config.ts b/packages/commons/vitest.config.ts index d5aa737c68..9f1196ef1f 100644 --- a/packages/commons/vitest.config.ts +++ b/packages/commons/vitest.config.ts @@ -3,5 +3,6 @@ import { defineProject } from 'vitest/config'; export default defineProject({ test: { environment: 'node', + setupFiles: ['../testing/src/setupEnv.ts'], }, }); diff --git a/packages/logger/tests/e2e/advancedUses.test.ts b/packages/logger/tests/e2e/advancedUses.test.ts index c41aaec409..6682042226 100644 --- a/packages/logger/tests/e2e/advancedUses.test.ts +++ b/packages/logger/tests/e2e/advancedUses.test.ts @@ -12,6 +12,7 @@ import { RESOURCE_NAME_PREFIX, STACK_OUTPUT_LOG_GROUP } from './constants.js'; * In this e2e test for Logger, we test a number of advanced use cases: * - Log buffering enabled with flush on error (both manually on logger.error and automatically on uncaught error) * - Correlation ID injection (both manually and automatically) + * - Cold start detection for provisioned concurrency (always false) * * The test is split into three cases: * - Manual instrumentation @@ -127,6 +128,7 @@ describe('Logger E2E - Advanced uses', () => { expect.objectContaining({ level: 'INFO', message: 'an info log', + cold_start: false, correlation_id: correlationId, }) ); @@ -136,6 +138,7 @@ describe('Logger E2E - Advanced uses', () => { expect.objectContaining({ level: 'DEBUG', message: 'a buffered debug log', + cold_start: false, correlation_id: correlationId, }) ); @@ -145,6 +148,7 @@ describe('Logger E2E - Advanced uses', () => { expect.objectContaining({ level: 'ERROR', message: 'Uncaught error detected, flushing log buffer before exit', + cold_start: false, correlation_id: correlationId, error: expect.objectContaining({ name: 'Error',