Skip to content

Commit a02a46d

Browse files
ci(integration): stabilize Lambda log snapshots (#824)
* ci(integration): stabilize Lambda log snapshots A successful log fetch could still contain fewer completions than were invoked, and AWS proactive initialization changes cold-start fields without a library behavior change. Both cases made the snapshots depend on platform timing. The AWS snapshots now wait for every completion and ignore only scheduler-owned fields. RIE and focused telemetry tests retain cold-start and proactive-initialization coverage. * ci(integration): fix runner helper resolution 1. A relative runner invocation leaves its helper directory relative, so later directory changes make every log normalization call miss the executable. 2. Successful Serverless diagnostics entered the log payload and could produce false snapshot mismatches. * ci(integration): normalize historical snapshot padding The former `INIT_START` substitution left an empty line in stored zip snapshots, so current output that deletes the whole line failed every zip-handler comparison. * ci(integration): fix normalizer references and formatting --------- Co-authored-by: Joey Zhao <5253430+joeyzhao2018@users.noreply.github.com>
1 parent 60b335a commit a02a46d

9 files changed

Lines changed: 625 additions & 206 deletions

File tree

‎integration_tests_local/README.md‎

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ manual-wrap handlers, plus targeted feature cases (HTTP header injection,
66
custom trace extractors, proactive initialization) — inside Docker against the
77
[AWS Lambda Runtime Interface Emulator (RIE)](https://github.com/aws/aws-lambda-runtime-interface-emulator),
88
invokes them with the same input events as the AWS-based suite, captures
9-
logs from `docker logs`, normalizes them with `./normalize.sh` — the AWS
10-
suite's filter chain plus documented RIE-specific handling, not an identical
11-
copy — and diffs them against **local** snapshots in `./snapshots/`.
9+
logs from `docker logs`, normalizes them with the `rie` mode of
10+
`../scripts/normalize_integration_logs.sh`, and diffs them against **local**
11+
snapshots in `./snapshots/`.
1212

1313
The case set is deliberately at least as wide as the AWS-based suite
1414
(`integration_tests/serverless.yml`): every behavior the old suite pinned
@@ -224,16 +224,15 @@ genuinely diverges (error stack frames, warning emission) it carries
224224

225225
When AWS publishes the bare Node 26 GA image, swap the pinned tag and re-run.
226226
If GA output diverges further, add `*_node26` overrides captured from the
227-
pinned pre-migration ref rather than absorbing the difference into
228-
`normalize.sh` — the oracle is tied to the implementation under test, and a
229-
base-image change must be reviewed, not hidden by normalization.
227+
pinned pre-migration ref. Do not absorb the difference into the shared
228+
integration-log normalizer because the oracle is tied to the implementation
229+
under test. A base-image change must be reviewed, not hidden by normalization.
230230

231231
## Files
232232

233233
- `run.sh` — the runner (build images, run under RIE, invoke, diff snapshots)
234-
- `normalize.sh` — the local log-normalization pipeline, based on the AWS
235-
suite's filters with documented RIE-specific handling. Reads stdin, writes
236-
stdout; honors `RUN_ID` for optional per-run ID stripping.
234+
- `../scripts/normalize_integration_logs.sh` — the shared AWS/RIE log normalizer.
235+
Reads stdin, writes stdout; honors `RUN_ID` for optional per-run ID stripping.
237236
- `prepare-layer.js` — assembles the layer fixture's build context from the
238237
repo build, mirroring the release Dockerfile's `/opt` layout
239238
- `bin/` — downloaded RIE binary (gitignored)

‎integration_tests_local/normalize.sh‎

Lines changed: 0 additions & 110 deletions
This file was deleted.

‎integration_tests_local/run.sh‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# Runs the test cases below against the AWS Runtime Interface Emulator (RIE)
66
# — no AWS account needed. Logs are captured from `docker logs`, normalized
7-
# with ./normalize.sh, and diffed against LOCAL snapshots in ./snapshots/
7+
# with the `rie` mode of scripts/normalize_integration_logs.sh, and diffed against LOCAL snapshots in ./snapshots/
88
# (not integration_tests/snapshots/).
99
#
1010
# The case set is deliberately at least as wide as the AWS-based suite in
@@ -483,7 +483,7 @@ function compare_snapshot() {
483483
local diff_status
484484

485485
if [ "$sort_lines" = true ]; then
486-
# Preserve normalized whitespace; normalize.sh removes RIE's REPORT tab.
486+
# Preserve normalized whitespace; the shared normalizer removes RIE's REPORT tab.
487487
diff_output=$(printf '%s\n' "$actual" | LC_ALL=C sort | diff - <(LC_ALL=C sort "$snapshot_path"))
488488
else
489489
diff_output=$(printf '%s\n' "$actual" | diff - "$snapshot_path")
@@ -775,7 +775,7 @@ for node_version in "${RUNTIMES[@]}"; do
775775
continue
776776
fi
777777

778-
# Proactive initialization is platform scheduling, so normalize.sh
778+
# Proactive initialization is platform scheduling, so the shared normalizer
779779
# drops the markers. For the dedicated case we assert them against the
780780
# raw log before normalization, which keeps the coverage without
781781
# weakening the shared pipeline.
@@ -790,7 +790,7 @@ for node_version in "${RUNTIMES[@]}"; do
790790
done
791791
fi
792792

793-
logs=$(printf '%s\n' "$raw_logs" | "$local_dir/normalize.sh")
793+
logs=$(printf '%s\n' "$raw_logs" | "$repo_dir/scripts/normalize_integration_logs.sh" rie)
794794

795795
# `runtime:nodejsNN.x` is the only genuinely runtime-specific line in
796796
# the whole log — everything else is identical across 18/20/22/24/26.
@@ -813,7 +813,7 @@ for node_version in "${RUNTIMES[@]}"; do
813813

814814
# Same assert-then-collapse for the dd_lambda_layer tag (emitted by the
815815
# manual-wrap cases): the node major in the tag must match the runtime
816-
# under test. normalize.sh already collapses minor/patch to XX.X;
816+
# under test. The shared normalizer already collapses minor/patch to XX.X;
817817
# after this guard passes, the major collapses to XX as well, so the
818818
# shared golden reads datadog-nodevXX.XX.X.
819819
layer_majors=$(printf '%s\n' "$logs" | grep -o 'dd_lambda_layer:datadog-nodev[0-9]*' | sed 's/.*datadog-nodev//' | sort -u || true)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/bin/bash
2+
3+
set -eo pipefail
4+
5+
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
6+
echo "Usage: $0 <aws|rie> [raw|formatted]" >&2
7+
exit 2
8+
fi
9+
10+
platform=$1
11+
case "$platform" in
12+
aws)
13+
cold_start_filter="s/(\"cold_start\":[[:space:]]*)\"(?:true|false)\"/\$1\"XXXX\"/g"
14+
cold_start_filter+="; s/cold_start:(?:true|false)/cold_start:XXXX/g"
15+
leading_blank_filter='/./,$!d'
16+
;;
17+
rie)
18+
cold_start_filter=''
19+
leading_blank_filter=''
20+
;;
21+
*)
22+
echo "Unsupported integration-test platform: $platform" >&2
23+
exit 2
24+
;;
25+
esac
26+
27+
input_format=${2:-raw}
28+
case "$input_format" in
29+
raw|formatted) ;;
30+
*)
31+
echo "Unsupported integration-test log format: $input_format" >&2
32+
exit 2
33+
;;
34+
esac
35+
36+
timestamp_filter="s/[0-9]{4}\\-[0-9]{2}\\-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]+"
37+
timestamp_filter+="( \\(\\-?\\+?[0-9:]+\\))?/XXXX-XX-XX XX:XX:XX.XXX/"
38+
volatile_value_filter="s/\"(span_id|apiid|runtime-id|record_ids|parent_id|trace_id|start|duration"
39+
volatile_value_filter+="|tcp\\.local\\.address|tcp\\.local\\.port|dns\\.address|request_id|function_arn"
40+
volatile_value_filter+="|x-datadog-trace-id|x-datadog-parent-id|datadog_lambda|dd_trace|process_id)\""
41+
volatile_value_filter+=": (\"?)[a-zA-Z0-9\\.:\\-]+(\"?)/\"\$1\":\$2XXXX\$3/g"
42+
43+
script_path=${BASH_SOURCE[0]}
44+
scripts_dir=$(dirname "$script_path")
45+
repo_dir=$(dirname "$scripts_dir")
46+
47+
if [ "$input_format" = formatted ]; then
48+
cat
49+
else
50+
node "$repo_dir/integration_tests/parse-json.js"
51+
fi |
52+
sed '/Serverless: Recoverable error occurred/d' |
53+
perl -p -e 's/(RequestId|TraceId|init|SegmentId|Duration|Memory Used|"e"):( )?[a-z0-9\.\-]+/\1:\2XXXX/g' |
54+
sed '/preview runtime version and should not be used for production workloads/d' |
55+
sed '/^INIT_REPORT /d' |
56+
sed '/DEP0205.*module\.register()/d' |
57+
sed '/node --trace-deprecation.*where the warning was created/d' |
58+
perl -p -e 's/(x-datadog-parent-id:|x-datadog-trace-id:|account_id:)[0-9]+/$1XXXX/g' |
59+
perl -p -e 's/"(x-datadog-trace-id|x-datadog-parent-id)":"[0-9]+"/"$1":"XXXX"/g' |
60+
perl -p -e 's/"traceparent":"[0-9a-f-]+"/"traceparent":"XXXX"/g' |
61+
perl -p -e 's/"tracestate":"[^"]*"/"tracestate":"XXXX"/g' |
62+
perl -p -e "s/(api_key=|'api_key': ')[a-z0-9\.\-]+/\1XXXX/g" |
63+
perl -p -e "$timestamp_filter" |
64+
perl -p -e 's/[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]+Z/XXXX-XX-XXTXX:XX:XX.XXXZ/' |
65+
perl -p -e 's/"requestId": "[0-9a-f-]+"/"requestId": "XXXX"/g' |
66+
perl -p -e 's/"requestId":"[0-9a-f-]+"/"requestId":"XXXX"/g' |
67+
perl -p -e 's/TimeoutOverflowWarning: [0-9]+/TimeoutOverflowWarning: XXXX/g' |
68+
perl -p -e 's/\\n\(Use `node --trace-warnings \.\.\.` to show where the warning was created\)//g' |
69+
sed '/^(Use `node --trace-warnings \.\.\.` to show where the warning was created)$/d' |
70+
perl -p -e 's/\(node:[0-9]+\)/(node:XX)/g' |
71+
perl -p -e 's/(dd\.trace_id=)[0-9]+ (dd\.span_id=)[0-9]+/$1XXXX $2XXXX/' |
72+
perl -p -e $'s/[0-9a-z]+\-[0-9a-z]+\-[0-9a-z]+\-[0-9a-z]+\-[0-9a-z]+\t/XXXX-XXXX-XXXX-XXXX-XXXX\t/' |
73+
perl -p -e 's/(dd_lambda_layer:datadog-nodev[0-9]+\.)[0-9]+\.[0-9]+/$1XX.X/g' |
74+
perl -p -e "$volatile_value_filter" |
75+
perl -p -e 's/"dns\.addresses": "[^"]*"/"dns.addresses": "XXXX"/g' |
76+
RUN_ID="${RUN_ID:-}" perl -p -e 's/\Q$ENV{RUN_ID}\E/XXXX/g if length $ENV{RUN_ID}' |
77+
perl -p -e 's/(.js:)[0-9]*:[0-9]*/$1XXX:XXX/g' |
78+
perl -p -e 's/(datadog_lambda:v)[0-9\.]+/$1X.X.X/g' |
79+
perl -p -e 's/("resource":"169.)[0-9\.]+/$1X.X.X/g' |
80+
perl -p -e 's/User-Agent:axios\/\d+\.\d+\.\d+/User-Agent:axios\/X.X.X/g' |
81+
sed '/INIT_START Runtime Version:/d' |
82+
sed "$leading_blank_filter" |
83+
sed -E '/^[[:space:]]*"proactive_initialization(" *:|:true")/d' |
84+
perl -p -e "$cold_start_filter" |
85+
perl -p -e 's/ \(init: [^)]*\)//g' |
86+
perl -p -e 's/^[0-9]{2} \w{3} [0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3} (\[INFO\] \(rapid\))/XXXX $1/' |
87+
perl -p -e 's/(LocalProcessSupervisor\.Exec pid=)[0-9]+/$1XX/g' |
88+
perl -p -e 's/(requestId: )[0-9a-f-]+/$1XXXX/g' |
89+
perl -p -e 's/(duration(Ms)?: )[0-9.]+/$1XXXX/g' |
90+
sed -E 's/(tracestate\:)([A-Za-z0-9\-\=\:\;].+)/\1XXX/g' |
91+
sed -E 's/("_dd.p.tid"\: ")[a-z0-9\.\-]+/\1XXXX/g' |
92+
sed -E 's/(_dd.p.tid=)[a-z0-9\.\-]+/\1XXXX/g' |
93+
sed -E '/^REPORT RequestId:/s/[[:blank:]]+$//'

0 commit comments

Comments
 (0)