From 9256329067024979086a7102c4952611ce4a050c Mon Sep 17 00:00:00 2001 From: Ava Silver Date: Fri, 26 Jun 2026 17:23:09 -0400 Subject: [PATCH 1/5] chore: add e2e cdk lambda fixture --- e2e/app/app.ts | 90 +++++++++++++++++++++++++++++++++++++++ e2e/app/handler/index.mjs | 21 +++++++++ 2 files changed, 111 insertions(+) create mode 100644 e2e/app/app.ts create mode 100644 e2e/app/handler/index.mjs diff --git a/e2e/app/app.ts b/e2e/app/app.ts new file mode 100644 index 00000000..cfb9a26b --- /dev/null +++ b/e2e/app/app.ts @@ -0,0 +1,90 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed + * under the Apache License Version 2.0. + * + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2021 Datadog, Inc. + */ + +import * as path from "path"; +import { App, Stack, StackProps, Tags } from "aws-cdk-lib"; +import * as lambda from "aws-cdk-lib/aws-lambda"; +import { Construct } from "constructs"; +import { DatadogLambda } from "../../src/index"; +import { E2E_NODE_LAYER_VERSION, E2E_EXTENSION_LAYER_VERSION, E2E_RUNTIME } from "../helpers/versions"; +import { FRESHNESS_TAG_KEY, RUN_ID_TAG_KEY } from "../helpers/naming"; + +// The CDK construct is the instrumentation mechanism under test. This same stack +// is provisioned uninstrumented first (E2E_INSTRUMENT=false, no DatadogLambda), +// then APPLY re-deploys it with E2E_INSTRUMENT=true (DatadogLambda applied). REMOVE +// is `cdk destroy` of the stack -- the function is deleted, leaving a clean +// end-state -- so the uninstrumented path only serves the initial baseline. +const instrument = process.env.E2E_INSTRUMENT === "true"; +const serviceName = requireEnv("E2E_SERVICE_NAME"); +const runId = requireEnv("E2E_RUN_ID"); +const createdTs = requireEnv("E2E_CREATED_TS"); +const site = process.env.DD_SITE ?? "datadoghq.com"; +const env = process.env.E2E_ENV ?? "e2e"; +const version = process.env.E2E_VERSION ?? "1.0.0"; + +class WorkloadStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const fn = new lambda.Function(this, "Handler", { + functionName: serviceName, + runtime: E2E_RUNTIME, + handler: "index.handler", + // Resolved from cwd (the repo root, where cdk runs) so it survives bundling + // the app to a single .cjs whose __dirname is the build output dir. + code: lambda.Code.fromAsset(path.resolve(process.cwd(), "e2e/app/handler")), + }); + + // Freshness tag is set at creation on the uninstrumented baseline too, so the + // cross-repo sweeper can find and reap this function even if the run crashes + // before REMOVE's `cdk destroy` deletes it. + Tags.of(fn).add(FRESHNESS_TAG_KEY, createdTs); + + if (!instrument) { + return; + } + + const datadogLambda = new DatadogLambda(this, "Datadog", { + nodeLayerVersion: E2E_NODE_LAYER_VERSION, + extensionLayerVersion: E2E_EXTENSION_LAYER_VERSION, + enableDatadogTracing: true, + enableDatadogLogs: true, + injectLogContext: true, + sourceCodeIntegration: false, + // Only needed when instrumenting; the uninstrumented baseline carries no key. + apiKey: requireEnv("DD_API_KEY"), + site, + service: serviceName, + env, + version, + // Surfaces as a `one_e2e_run_id` resource tag *and* in DD_TAGS, so the run id + // rides along on every emitted span and log -- the dimension the telemetry + // checker filters on to prove identity. + tags: `${RUN_ID_TAG_KEY}:${runId}`, + }); + datadogLambda.addLambdaFunctions([fn]); + } +} + +function requireEnv(name: string): string { + const value = process.env[name]; + if (!value) { + throw new Error(`Missing required env var ${name}`); + } + + return value; +} + +const app = new App(); +new WorkloadStack(app, serviceName, { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION ?? process.env.AWS_REGION, + }, +}); +app.synth(); diff --git a/e2e/app/handler/index.mjs b/e2e/app/handler/index.mjs new file mode 100644 index 00000000..41d02f33 --- /dev/null +++ b/e2e/app/handler/index.mjs @@ -0,0 +1,21 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed + * under the Apache License Version 2.0. + * + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2021 Datadog, Inc. + */ + +// Minimal hello-world handler for the e2e workload, duplicated from +// serverless-self-monitoring (lambda-managed-instances/handlers/default/nodejs). +// It just emits a log line and returns 200 -- tracing is auto-injected and logs +// are auto-collected by the Datadog Lambda layer + extension, so no tracer setup +// is needed here. The DD_TAGS-provided run id appears on the resulting telemetry. +export const handler = async () => { + console.log(`hello from one-e2e cdk lambda workload (run ${process.env.E2E_RUN_ID ?? "unknown"})`); + + return { + statusCode: 200, + body: JSON.stringify({ message: "ok" }), + }; +}; From e0b5af4b00764998860120dacfa40a13707ff8ef Mon Sep 17 00:00:00 2001 From: Ava Silver Date: Thu, 6 Aug 2026 14:40:54 -0400 Subject: [PATCH 2/5] preserve e2e run identity --- e2e/app/app.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/e2e/app/app.ts b/e2e/app/app.ts index cfb9a26b..5fa5b6b5 100644 --- a/e2e/app/app.ts +++ b/e2e/app/app.ts @@ -40,10 +40,10 @@ class WorkloadStack extends Stack { code: lambda.Code.fromAsset(path.resolve(process.cwd(), "e2e/app/handler")), }); - // Freshness tag is set at creation on the uninstrumented baseline too, so the - // cross-repo sweeper can find and reap this function even if the run crashes - // before REMOVE's `cdk destroy` deletes it. + // Stamp cleanup and run identity at creation so leaked baseline resources remain + // attributable even if the run stops before instrumentation or teardown. Tags.of(fn).add(FRESHNESS_TAG_KEY, createdTs); + Tags.of(fn).add(RUN_ID_TAG_KEY, runId); if (!instrument) { return; @@ -62,9 +62,8 @@ class WorkloadStack extends Stack { service: serviceName, env, version, - // Surfaces as a `one_e2e_run_id` resource tag *and* in DD_TAGS, so the run id - // rides along on every emitted span and log -- the dimension the telemetry - // checker filters on to prove identity. + // Stamp the run id on emitted spans and logs so the telemetry checker can + // distinguish this run from concurrent suites. tags: `${RUN_ID_TAG_KEY}:${runId}`, }); datadogLambda.addLambdaFunctions([fn]); From 396e74aaa0bfd550ea58d69529babab3aeff4aa5 Mon Sep 17 00:00:00 2001 From: Ava Silver Date: Thu, 6 Aug 2026 14:44:15 -0400 Subject: [PATCH 3/5] align e2e imports --- e2e/app/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/app/app.ts b/e2e/app/app.ts index 5fa5b6b5..2e49996a 100644 --- a/e2e/app/app.ts +++ b/e2e/app/app.ts @@ -11,8 +11,8 @@ import { App, Stack, StackProps, Tags } from "aws-cdk-lib"; import * as lambda from "aws-cdk-lib/aws-lambda"; import { Construct } from "constructs"; import { DatadogLambda } from "../../src/index"; -import { E2E_NODE_LAYER_VERSION, E2E_EXTENSION_LAYER_VERSION, E2E_RUNTIME } from "../helpers/versions"; import { FRESHNESS_TAG_KEY, RUN_ID_TAG_KEY } from "../helpers/naming"; +import { E2E_NODE_LAYER_VERSION, E2E_EXTENSION_LAYER_VERSION, E2E_RUNTIME } from "../helpers/versions"; // The CDK construct is the instrumentation mechanism under test. This same stack // is provisioned uninstrumented first (E2E_INSTRUMENT=false, no DatadogLambda), From 2a134cf5f01597bb9555ac4339619d3a91919cf5 Mon Sep 17 00:00:00 2001 From: Ava Silver Date: Thu, 6 Aug 2026 14:56:07 -0400 Subject: [PATCH 4/5] own e2e resources --- e2e/app/app.ts | 21 +++++++++++++++------ e2e/app/versions.ts | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 e2e/app/versions.ts diff --git a/e2e/app/app.ts b/e2e/app/app.ts index 2e49996a..6caf1920 100644 --- a/e2e/app/app.ts +++ b/e2e/app/app.ts @@ -7,12 +7,13 @@ */ import * as path from "path"; -import { App, Stack, StackProps, Tags } from "aws-cdk-lib"; +import { App, RemovalPolicy, Stack, StackProps, Tags } from "aws-cdk-lib"; import * as lambda from "aws-cdk-lib/aws-lambda"; +import * as logs from "aws-cdk-lib/aws-logs"; import { Construct } from "constructs"; import { DatadogLambda } from "../../src/index"; import { FRESHNESS_TAG_KEY, RUN_ID_TAG_KEY } from "../helpers/naming"; -import { E2E_NODE_LAYER_VERSION, E2E_EXTENSION_LAYER_VERSION, E2E_RUNTIME } from "../helpers/versions"; +import { E2E_NODE_LAYER_VERSION, E2E_EXTENSION_LAYER_VERSION, E2E_RUNTIME } from "./versions"; // The CDK construct is the instrumentation mechanism under test. This same stack // is provisioned uninstrumented first (E2E_INSTRUMENT=false, no DatadogLambda), @@ -31,19 +32,27 @@ class WorkloadStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); + const logGroup = new logs.LogGroup(this, "HandlerLogGroup", { + logGroupName: `/aws/lambda/${serviceName}`, + removalPolicy: RemovalPolicy.DESTROY, + retention: logs.RetentionDays.ONE_DAY, + }); const fn = new lambda.Function(this, "Handler", { functionName: serviceName, runtime: E2E_RUNTIME, handler: "index.handler", + logGroup, // Resolved from cwd (the repo root, where cdk runs) so it survives bundling // the app to a single .cjs whose __dirname is the build output dir. code: lambda.Code.fromAsset(path.resolve(process.cwd(), "e2e/app/handler")), }); - // Stamp cleanup and run identity at creation so leaked baseline resources remain - // attributable even if the run stops before instrumentation or teardown. - Tags.of(fn).add(FRESHNESS_TAG_KEY, createdTs); - Tags.of(fn).add(RUN_ID_TAG_KEY, runId); + // Stamp cleanup and run identity at creation so leaked resources remain attributable + // even if the run stops before instrumentation or teardown. + for (const resource of [fn, logGroup]) { + Tags.of(resource).add(FRESHNESS_TAG_KEY, createdTs); + Tags.of(resource).add(RUN_ID_TAG_KEY, runId); + } if (!instrument) { return; diff --git a/e2e/app/versions.ts b/e2e/app/versions.ts new file mode 100644 index 00000000..6dbd830b --- /dev/null +++ b/e2e/app/versions.ts @@ -0,0 +1,14 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed + * under the Apache License Version 2.0. + * + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2021 Datadog, Inc. + */ + +import * as lambda from "aws-cdk-lib/aws-lambda"; + +// Pinned artifacts keep failures attributable to this construct's wiring. +export const E2E_RUNTIME = lambda.Runtime.NODEJS_22_X; +export const E2E_NODE_LAYER_VERSION = 130; +export const E2E_EXTENSION_LAYER_VERSION = 83; From eefe03a3be8cce4d123987dbb16c3cf492c4b007 Mon Sep 17 00:00:00 2001 From: Ava Silver Date: Thu, 6 Aug 2026 15:05:56 -0400 Subject: [PATCH 5/5] align fixture lint --- e2e/app/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/app/app.ts b/e2e/app/app.ts index 6caf1920..9a1f0751 100644 --- a/e2e/app/app.ts +++ b/e2e/app/app.ts @@ -11,9 +11,9 @@ import { App, RemovalPolicy, Stack, StackProps, Tags } from "aws-cdk-lib"; import * as lambda from "aws-cdk-lib/aws-lambda"; import * as logs from "aws-cdk-lib/aws-logs"; import { Construct } from "constructs"; +import { E2E_NODE_LAYER_VERSION, E2E_EXTENSION_LAYER_VERSION, E2E_RUNTIME } from "./versions"; import { DatadogLambda } from "../../src/index"; import { FRESHNESS_TAG_KEY, RUN_ID_TAG_KEY } from "../helpers/naming"; -import { E2E_NODE_LAYER_VERSION, E2E_EXTENSION_LAYER_VERSION, E2E_RUNTIME } from "./versions"; // The CDK construct is the instrumentation mechanism under test. This same stack // is provisioned uninstrumented first (E2E_INSTRUMENT=false, no DatadogLambda),