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
16 changes: 16 additions & 0 deletions integration_tests/container/cjs/callback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Callback-style handler — (event, context, callback) instead of async —
// manually wrapped with datadog(). The migration spike broke exactly this
// seam: the new host's tracePromise wrapper replaced promisifiedHandler's
// call site, so callback handlers returned null to API Gateway. handler.spec
// pins the unit behavior; this case pins the same path end to end through
// the RIE invoke. The setTimeout makes the completion genuinely asynchronous
// so the wrapper cannot mistake it for a sync return.
const { datadog } = require("datadog-lambda-js");

function handle(event, context, callback) {
setTimeout(() => {
callback(null, { message: "hello, dog!" });
}, 10);
}

module.exports.handle = datadog(handle);
35 changes: 35 additions & 0 deletions integration_tests/container/cjs/fetch-requests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// fetch variant of http-requests.js. On Node 18+ the global fetch is
// undici, which dd-trace instruments through its undici plugin — a different
// injection path than the http/https plugin that patches axios in
// http-requests.js. Both paths must keep injecting the x-datadog-* trace
// context; this case pins the fetch one.
//
// Like http-requests.js this entry point is UNWRAPPED and runs through the
// npm redirect entry (dist/handler.handler) in the cjs-fetch-requests case,
// so dd-trace initializes before the user handler loads and the tracer's
// undici plugin does the injection. The mock echoes the request headers and
// this handler logs them, so the golden shows the injected downstream trace
// context (x-datadog-trace-id / x-datadog-parent-id, normalized to XXXX).
const { sendDistributionMetric } = require("datadog-lambda-js");

const urls = (process.env.MOCK_HTTP_URLS ||
"https://ip-ranges.datadoghq.com,https://ip-ranges.datadoghq.eu"
).split(",");

async function handle(event, context) {
const responsePayload = { message: "hello, dog!" };

sendDistributionMetric("serverless.integration_test.execution", 1, "function:fetch-request");

for (let index = 0; index < urls.length; index++) {
const response = await fetch(urls[index]);
const body = await response.json();
console.log(`mock-http saw headers for ${urls[index]}: ${JSON.stringify(body.headers)}`);
}

console.log(`Snapshot test fetch requests successfully made to URLs: ${urls}`);

return responsePayload;
}

module.exports.handle = handle;
17 changes: 17 additions & 0 deletions integration_tests_local/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ The case names are:
| `manual-status-500` | manual wrap with userland `dd-trace` init returning a 500 API Gateway response (`DD_TRACE_ENABLED=true`); error span tag + enhanced error metrics |
| `manual-send-metrics` | manual wrap calling `sendDistributionMetric` inside and outside the handler; per-event return values |
| `manual-process-input` | manual wrap with userland `dd-trace` init reading the active span; per-event return values |
| `manual-callback` | manual wrap of a callback-style `(event, context, callback)` handler; pins the `promisifiedHandler` seam end to end (the migration spike broke exactly this) |
| `manual-metrics-only` | `DD_TRACE_ENABLED=false` (metrics-only customers): enhanced + custom metrics still flush, no `aws.lambda` span, no trace JSON, no `dd.trace_id` log correlation |
| `cjs-capture-payload` | `DD_CAPTURE_LAMBDA_PAYLOAD=true` in redirect mode; span meta gains `function.request` / `function.response` with the captured payloads |
| `cjs-http-requests` | downstream HTTP calls against a hermetic mock server in redirect mode; asserts injected `x-datadog-*`/`traceparent` headers and log injection via dd-trace's http plugin |
| `manual-http-requests` | same handler, manual wrap without userland dd-trace init; exercises the library's own `patchHttp` fallback (request wrapping + per-request logging + exact header set via mock echo) |
| `cjs-fetch-requests` | fetch variant of `cjs-http-requests`: the global fetch (undici) is instrumented by a different dd-trace plugin than http/https; mock echo pins the injected headers on that path |
| `cjs-custom-extractor` | `DD_TRACE_EXTRACTOR=extractor.extract`; asserts `_dd.parent_source: event` on the inferred span |
| `cjs-proactive-init` | eager-init managed-instances RIE path with a 15 s init→invoke gap; asserts proactive-initialization markers on the raw logs |

Expand Down Expand Up @@ -281,3 +285,16 @@ endpoints). Do not diff one suite's output against the other's snapshots.
- The layer fixture installs into a plain `/opt/nodejs/node_modules`
directory rather than a real published layer zip, so layer-version
metadata (e.g. an exact layer ARN in tags) cannot be reproduced locally.

Deliberately not covered locally (each has an assigned owner — do not re-add
here without closing that owner first):

- response streaming and `time_to_first_byte` — RIE cannot stream
invocations; owned by the `serverless-e2e-tests` lambda-features suite.
- direct-API and KMS/Secrets Manager metric key paths — need real AWS;
unit specs plus an L3 spot-check.
- aws-sdk v2/v3 client spans in the lambda context (parenting under
`aws.lambda`, flush before invocation end) — need real AWS services;
owned by L3.
- durable-execution checkpoint extraction — owned by
`serverless-e2e-tests/durable-functions`.
51 changes: 51 additions & 0 deletions integration_tests_local/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@
# manual-status-500 | cjs | status-code-500s.handle | manual wrap; API GW 500 -> span error + enhanced error metric
# manual-send-metrics | cjs | send-metrics.handle | manual wrap; sendDistributionMetric via DD_FLUSH_TO_LOG
# manual-process-input | cjs | process-input.handle | manual wrap; dd-trace child spans via tracer.wrap
# manual-callback | cjs | callback.handle | manual wrap; callback-style (event, context, callback) handler — the spike's proven break seam
# cjs-http-requests | cjs | node_modules/datadog-lambda-js/dist/handler.handler | npm redirect; downstream HTTP header injection via dd-trace's http plugin (hermetic mock server)
# manual-http-requests | cjs | http-requests-manual.handle | manual wrap; patchHttp fallback wrapping + per-request logging (hermetic mock)
# cjs-fetch-requests | cjs | node_modules/datadog-lambda-js/dist/handler.handler | npm redirect; header injection on global fetch via dd-trace's undici plugin (hermetic mock)
# cjs-custom-extractor | cjs | node_modules/datadog-lambda-js/dist/handler.handler | DD_TRACE_EXTRACTOR custom extractor + _dd.parent_source
# cjs-proactive-init | cjs | node_modules/datadog-lambda-js/dist/handler.handler | proactive-initialization markers (raw-log assertions)
# manual-metrics-only | cjs | send-metrics.handle | DD_TRACE_ENABLED=false: metrics flush, no spans, no log correlation
# cjs-capture-payload | cjs | node_modules/datadog-lambda-js/dist/handler.handler | DD_CAPTURE_LAMBDA_PAYLOAD=true: function.request/response span tags
#
# Usage (from repo root or this directory):
# ./integration_tests_local/run.sh # all runtimes, all cases
Expand Down Expand Up @@ -111,10 +115,14 @@ ALL_CASES=(
"manual-status-500"
"manual-send-metrics"
"manual-process-input"
"manual-callback"
"cjs-http-requests"
"manual-http-requests"
"cjs-fetch-requests"
"cjs-custom-extractor"
"cjs-proactive-init"
"manual-metrics-only"
"cjs-capture-payload"
)

function configure_case() {
Expand Down Expand Up @@ -184,6 +192,37 @@ function configure_case() {
case_entry_handler="process-input.handle"
case_return_mode=per-event
;;
manual-callback)
# Callback-style (event, context, callback) handler under manual
# wrap — the seam the migration spike broke (the tracePromise
# wrapper replaced promisifiedHandler's call site, so callback
# handlers returned null to API Gateway). handler.spec.ts pins
# the unit behavior; this case pins the same path end to end
# through the RIE invoke.
case_image=cjs
case_entry_handler="callback.handle"
;;
manual-metrics-only)
# DD_TRACE_ENABLED=false — metrics-only customers. The golden pins
# that enhanced + custom metrics still flush (via DD_FLUSH_TO_LOG)
# while no aws.lambda span, no trace JSON and no dd.trace_id log
# correlation appear. Same handler and per-event payloads as
# manual-send-metrics; the diff between the two goldens is exactly
# the tracing surface.
case_image=cjs
case_entry_handler="send-metrics.handle"
case_extra_env=(-e DD_TRACE_ENABLED=false)
case_return_mode=per-event
;;
cjs-capture-payload)
# DD_CAPTURE_LAMBDA_PAYLOAD=true — the aws.lambda span meta gains
# function.request / function.response holding the captured
# payloads (event JSON is static, so the captured tags are
# deterministic).
case_image=cjs
case_entry_handler="node_modules/datadog-lambda-js/dist/handler.handler"
case_extra_env=(-e DD_LAMBDA_HANDLER=handler.handle -e DD_CAPTURE_LAMBDA_PAYLOAD=true)
;;
cjs-http-requests)
# Redirect mode, not manual wrap: redirect mode initializes
# dd-trace before the user handler loads, so the tracer's http
Expand Down Expand Up @@ -219,6 +258,18 @@ function configure_case() {
case_needs_mock=true
case_extra_env=(-e "MOCK_HTTP_URLS=http://mock-http:8080/ip-ranges-us,http://mock-http:8080/ip-ranges-eu")
;;
cjs-fetch-requests)
# fetch/undici variant of cjs-http-requests: on Node 18+ the
# global fetch is undici, instrumented by dd-trace's undici
# plugin — a different injection path than the http/https plugin
# that patches axios. Redirect mode, so dd-trace initializes
# before the user handler loads and the plugin does the
# injection; the mock echo pins the injected headers.
case_image=cjs
case_entry_handler="node_modules/datadog-lambda-js/dist/handler.handler"
case_needs_mock=true
case_extra_env=(-e DD_LAMBDA_HANDLER=fetch-requests.handle -e "MOCK_HTTP_URLS=http://mock-http:8080/ip-ranges-us,http://mock-http:8080/ip-ranges-eu")
;;
cjs-custom-extractor)
case_image=cjs
case_entry_handler="node_modules/datadog-lambda-js/dist/handler.handler"
Expand Down
Loading
Loading