Skip to content

test: shared fixture corpus for tests and benches - #1472

Open
duncanista wants to merge 3 commits into
jordan.gonzalez/cargo-machete/featurefrom
jordan.gonzalez/test-fixtures/feature
Open

duncanista wants to merge 3 commits into
jordan.gonzalez/cargo-machete/featurefrom
jordan.gonzalez/test-fixtures/feature

Conversation

@duncanista

@duncanista duncanista commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

TL;DR: One shared set of generated test inputs: Telemetry API batches, Lambda log lines, traces, DogStatsD packets and trigger events.

Why: The fault-injection harness (#1473) and the benchmarks (#1474) need the same realistic inputs. Today each test builds its own by hand. The extension does not change.

Overview

Jira: SVLS-9977

Stacked on #1471 (jordan.gonzalez/cargo-machete/feature). This PR does not need the CI PRs below it. It sits on this stack so that the bench PR can build on both.

Why this PR

We are adding test tools for the extension:

All of them need the same realistic inputs: Telemetry API batches, Lambda log lines, trace payloads, DogStatsD packets and trigger events. Today each test builds its own inputs by hand. This PR adds one small set of generators for those inputs, so every tool tests and measures the same shapes. Large inputs, such as a 220 KB SQS batch, are generated at test time instead of being checked into git.

On its own, this PR only adds test code. The extension does not change. The only non-test change is 9 lines that make the existing stitch module #[doc(hidden)] pub, so integration tests and benches can call it.

What to check here: that the generated shapes match what Lambda sends (for example the split-record format that the stitcher reassembles since #1415), and the self-test in tests/fixtures_corpus.rs.

What is in it

bottlecap/tests/fixtures/ generates the inputs that the benches, the fault-injection
harness and the Lambda simulator share, so no large blob is in git:

  • telemetry: Telemetry API batches (platform events, function logs in 3 formats, split
    records for the stitcher, runtimeDone with or without metrics, logsDropped, unknown
    events);
  • logs: Lambda text and JSON lines, one OOM line per runtime;
  • traces: synthetic traces and the 2000-span v0.4 msgpack payload, at a fixed base time;
  • dogstatsd: datagrams for 50 metric names x 100 endpoints;
  • events: the checked-in trigger payloads plus a 220 KB SQS and a 100-record DynamoDB event.

tests/fixtures_corpus.rs checks the generators (for example, a split record stitches back).
It needs extension::telemetry::stitch from the integration tests, so the module and
FragmentBuffer become #[doc(hidden)] pub. No behavior change.

Size: 13 core lines, 1058 lines in total.

Testing

  • applies on the previous PR of the stack: pass
  • cargo fmt --all -- --check: pass
  • cargo clippy --workspace --all-targets --features default -- -D warnings: pass
  • cargo clippy --workspace --all-targets --features default,test-mode -- -D warnings: pass
  • cargo nextest run --workspace: pass

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T00:48:44.483869Z e895b77 New commits
🔒 Security Review ✅ Completed 2026-10-29T00:43:07.087115Z e895b77 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa7a94d02a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread bottlecap/tests/fixtures/dogstatsd.rs Outdated
Comment thread bottlecap/tests/fixtures/traces.rs Outdated
Comment thread bottlecap/tests/fixtures/traces.rs
Comment thread bottlecap/tests/fixtures/events.rs Outdated
Comment thread bottlecap/tests/fixtures/telemetry.rs Outdated
Comment thread bottlecap/tests/fixtures/events.rs

@lym953 lym953 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain more context? It's hard for me to understand what this PR does without reading your other PRs.

@duncanista duncanista changed the title [SVLS-9977] test: shared fixture corpus for tests and benches test: shared fixture corpus for tests and benches Oct 28, 2026
@duncanista

Copy link
Copy Markdown
Contributor Author

@lym953 thanks, fair point. i added a "why this pr" section at the top of the description. short version: it only adds test inputs that the harness (#1473) and the benches (#1474) share, the extension itself does not change. happy to walk through it.

@duncanista
duncanista requested a review from lym953 October 28, 2026 21:15
- dogstatsd: advance the metric name every 100 lines so n lines give min(n, 5000) contexts
- traces: set BASE_NS to 2026-10-27T12:00:00Z and encode meta/metrics in key order
- events: pad the SQS body to the exact size and put the LWA deadline 60 s from now
- telemetry: emit extension logs in the logger::Formatter JSON shape

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e499bbbed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

("Datadog-Meta-Lang", "python"),
("Datadog-Meta-Lang-Version", "3.12"),
("Datadog-Meta-Tracer-Version", "2.10.0"),
("X-Datadog-Trace-Count", "100"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match the trace-count header to each generated payload

When TRACE_HEADERS is reused with traces/v04_100_spans.msgpack, the request advertises 100 traces even though write_corpus constructs that payload with make_traces(5, 20, true). This makes the shared headers inconsistent with one of the generated payloads and can skew consumers that validate or account for the declared trace count; derive this header from the trace collection or provide separate headers for each corpus payload.

Useful? React with 👍 / 👎.

"dataType": "String"
}
},
"md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Compute the checksum for the generated SQS body

When sqs_event is used as a realistic SQS invocation, every record carries this fixed checksum even though the body varies with body_bytes; for example, the 22,000-byte body generated by sqs_220kb() has MD5 7610aadcb8bbb0434939e3680b0db7ca, not the value here. Consumers that verify SQS message integrity will therefore reject the fixture as corrupted, so md5OfBody should be computed from the generated body.

Useful? React with 👍 / 👎.

Comment on lines +71 to +74
put(
&format!("telemetry/{name}"),
&telemetry::log_batch(kind, 1000),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep generated telemetry POSTs within the subscribed byte limit

When the corpus is written, the JSON-object and JSON-string variants each put 1,000 generated records into one POST, but each underlying JSON record is already about 1.2 KB before its telemetry envelope and string escaping, so these bodies exceed the extension's configured 1 MiB maxBytes. Lambda would flush these small records before reaching 1,000 items, meaning the generated files exercise a batch shape the configured subscription will not produce; split these variants by serialized byte size or lower their event count.

Useful? React with 👍 / 👎.

@datadog-prod-us1-4

This comment has been minimized.

- write_corpus: 600 events for the JSON shapes so each POST fits the 1 MiB maxBytes
- traces: TRACE_HEADERS matches the reference payload's 100 traces

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e895b770b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

.map(|(k, v)| (k.as_str(), v.as_str()))
.collect(),
metrics: s.metrics.iter().map(|(k, v)| (k.as_str(), *v)).collect(),
r#type: &s.r#type,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve optional span fields during encoding

When v04_msgpack receives a pb::Span with meta_struct, span_links, or span_events, this conversion silently omits those fields from the encoded payload. Because the helper is exposed as an encoder for caller-supplied traces, benchmarks or fault-injection cases targeting structured metadata, links, or events will not actually send the requested data; preserve these fields deterministically or explicitly restrict the helper to the generated spans.

Useful? React with 👍 / 👎.

"serverless",
vec![
("span.kind", "server"),
("request_id", "8f5a7e2c-1b2c-4d5e-9f00-0123456789ab"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reuse the corpus request ID in trace roots

When a simulator combines these traces with the telemetry and log fixtures, every trace root carries a different request ID from telemetry::REQUEST_ID, which the other corpus generators consistently use. Request-ID-keyed paths such as invocation-context enrichment therefore cannot associate the tracer span with the simulated invocation; use the shared constant or accept a request ID as an argument.

Useful? React with 👍 / 👎.

//! DogStatsD datagrams as a client library sends them to UDP 8125.

/// The tags bottlecap adds to every metric (`SortedTags::parse(ENRICH_TAGS)`).
pub const ENRICH_TAGS: &str = "function_arn:arn:aws:lambda:us-east-1:123456789012:function:my-checkout-fn,region:us-east-1,account_id:123456789012,aws_account:123456789012,functionname:my-checkout-fn,resource:my-checkout-fn,executedversion:$LATEST,memorysize:128,architecture:arm64,runtime:nodejs22.x,_dd.runtime_family:nodejs,env:prod,service:checkout,version:1.2.3,dd_extension_version:90,_dd.compute_stats:1";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the span-only directive from metric enrichment tags

When ENRICH_TAGS is used to construct the DogStatsD aggregator, it adds _dd.compute_stats:1 to every generated metric even though tags/lambda/tags.rs::tags_from_env explicitly keeps this directive out of function tags and stamps it only on trace spans. The benchmark corpus consequently measures and asserts a custom-metric tag shape that production never emits; remove this directive from the enrichment fixture.

Useful? React with 👍 / 👎.

"Keys": {"Id": {"N": "101"}},
"NewImage": Value::Object(img),
"SequenceNumber": format!("{i}00000000000000000"),
"SizeBytes": 26,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update SizeBytes for generated DynamoDB images

When attrs changes the generated NewImage size—most notably in the 30-attribute reference event—SizeBytes remains the 26-byte value copied from the small sample event. DynamoDbRecord::enrich_span propagates this value into the inferred span's size_bytes tag, so simulator and processing experiments record incorrect payload metadata; derive a matching size for the generated image.

Useful? React with 👍 / 👎.

"body": body,
"attributes": {
"ApproximateReceiveCount": "1",
"SentTimestamp": "1545082649183",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align generated trigger timestamps with the corpus epoch

When the generated SQS event is processed alongside the 2026 telemetry and trace fixtures, every record still has a 2018 SentTimestamp (and the generated DynamoDB records similarly use a 2015 creation time). The trigger processors use these fields as inferred-span start times, so simulator runs produce spans years outside the invocation and stats window; generate trigger timestamps from the shared fixture epoch.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants