diff --git a/src/trace/listener.ts b/src/trace/listener.ts index fdaa0d92..21fa5479 100644 --- a/src/trace/listener.ts +++ b/src/trace/listener.ts @@ -5,7 +5,12 @@ import { patchHttp, unpatchHttp } from "./patch-http"; import { extractTriggerTags, extractHTTPStatusCodeTag, parseEventSource } from "./trigger"; import { ColdStartTracerConfig, ColdStartTracer } from "./cold-start-tracer"; import { logDebug, tagObject } from "../utils"; -import { didFunctionColdStart, isProactiveInitialization, isManagedInstancesMode } from "../utils/cold-start"; +import { + didFunctionColdStart, + isProactiveInitialization, + isManagedInstancesMode, + isProvisionedConcurrency, +} from "../utils/cold-start"; import { datadogLambdaVersion } from "../constants"; import { ddtraceVersion, parentSpanFinishTimeHeader, DD_SERVICE_ENV_VAR } from "./constants"; import { patchConsole } from "./patch-console"; @@ -182,11 +187,10 @@ export class TraceListener { } const coldStartNodes = getTraceTree(); if (coldStartNodes.length > 0) { - // Skip creating cold start spans in managed instances mode - // since the gap between the sandbox init and the function - // invocation might be too large to provide a useful trace and - // experience - if (!isManagedInstancesMode()) { + // Skip creating cold start spans in managed instances mode or provisioned concurrency + // since the gap between the sandbox init and the function invocation might be very + // large (minutes or hours), making the spans misleading and not useful + if (!isManagedInstancesMode() && !isProvisionedConcurrency()) { const coldStartConfig: ColdStartTracerConfig = { tracerWrapper: this.tracerWrapper, parentSpan: diff --git a/src/utils/cold-start.spec.ts b/src/utils/cold-start.spec.ts index 479659ad..36d33db2 100644 --- a/src/utils/cold-start.spec.ts +++ b/src/utils/cold-start.spec.ts @@ -4,6 +4,7 @@ import { setSandboxInit, isProactiveInitialization, isManagedInstancesMode, + isProvisionedConcurrency, } from "./cold-start"; beforeEach(_resetColdStart); @@ -78,4 +79,31 @@ describe("cold-start", () => { process.env.AWS_LAMBDA_INITIALIZATION_TYPE = originalValue; }); + + it("identifies provisioned concurrency when AWS_LAMBDA_INITIALIZATION_TYPE is set", () => { + const originalValue = process.env.AWS_LAMBDA_INITIALIZATION_TYPE; + + process.env.AWS_LAMBDA_INITIALIZATION_TYPE = "provisioned-concurrency"; + expect(isProvisionedConcurrency()).toEqual(true); + + process.env.AWS_LAMBDA_INITIALIZATION_TYPE = originalValue; + }); + + it("identifies non-provisioned concurrency when AWS_LAMBDA_INITIALIZATION_TYPE is not set", () => { + const originalValue = process.env.AWS_LAMBDA_INITIALIZATION_TYPE; + + delete process.env.AWS_LAMBDA_INITIALIZATION_TYPE; + expect(isProvisionedConcurrency()).toEqual(false); + + process.env.AWS_LAMBDA_INITIALIZATION_TYPE = originalValue; + }); + + it("identifies non-provisioned concurrency when AWS_LAMBDA_INITIALIZATION_TYPE has different value", () => { + const originalValue = process.env.AWS_LAMBDA_INITIALIZATION_TYPE; + + process.env.AWS_LAMBDA_INITIALIZATION_TYPE = "on-demand"; + expect(isProvisionedConcurrency()).toEqual(false); + + process.env.AWS_LAMBDA_INITIALIZATION_TYPE = originalValue; + }); }); diff --git a/src/utils/cold-start.ts b/src/utils/cold-start.ts index 720d6eba..dfbaf57f 100644 --- a/src/utils/cold-start.ts +++ b/src/utils/cold-start.ts @@ -47,6 +47,18 @@ export function isManagedInstancesMode(): boolean { return process.env.AWS_LAMBDA_INITIALIZATION_TYPE === "lambda-managed-instances"; } +/** + * Checks if the Lambda function is running with provisioned concurrency. + * With provisioned concurrency, containers are pre-warmed before invocations, + * so the gap between initialization and invocation can be very large (minutes or hours). + * Cold start spans created from pre-warm module load times would have inflated durations + * and are not useful in the context of the actual invocation. + * @returns true if running with provisioned concurrency, false otherwise + */ +export function isProvisionedConcurrency(): boolean { + return process.env.AWS_LAMBDA_INITIALIZATION_TYPE === "provisioned-concurrency"; +} + // For testing, reset the globals to their original values export function _resetColdStart() { functionDidColdStart = true; diff --git a/src/utils/index.ts b/src/utils/index.ts index 45bc2bd8..55052795 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -4,6 +4,7 @@ export { setSandboxInit, isProactiveInitialization, isManagedInstancesMode, + isProvisionedConcurrency, } from "./cold-start"; export { promisifiedHandler } from "./handler"; export { Timer } from "./timer";