[APMSVLS-497][APMSVLS-498] test: add fake-intake for APM payload-level tests#1194
Open
lucaspimentel wants to merge 14 commits intolpimentel/stats-flusher-url-paramfrom
Open
[APMSVLS-497][APMSVLS-498] test: add fake-intake for APM payload-level tests#1194lucaspimentel wants to merge 14 commits intolpimentel/stats-flusher-url-paramfrom
lucaspimentel wants to merge 14 commits intolpimentel/stats-flusher-url-paramfrom
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces an in-process “fake Datadog intake” test harness for Bottlecap APM payload-level integration testing, enabling assertions on decoded stats/traces payload fields rather than only verifying that an HTTP request occurred.
Changes:
- Add
FakeIntakeaxum server that accepts/api/v0.2/statsand/api/v0.2/traces, decodes bodies, and storespb::StatsPayload/pb::AgentPayloadfor tests. - Add new APM integration tests that exercise the stats and traces flush paths and assert on decoded payload fields.
- Make
StatsFlusher::newaccept an explicit stats intake URL so tests can redirect it to the fake intake; update the production call site accordingly.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| bottlecap/tests/common/mod.rs | Adds a shared tests/common module exposing fake_intake. |
| bottlecap/tests/common/fake_intake.rs | Implements the in-process fake intake server with decoding and captured payload storage. |
| bottlecap/tests/apm_integration_test.rs | Adds payload-level integration tests for stats and traces flush paths. |
| bottlecap/src/traces/stats_flusher.rs | Accepts stats_url in the constructor and logs the actual endpoint used. |
| bottlecap/src/bin/bottlecap/main.rs | Passes trace_stats_url(&config.site) into StatsFlusher::new. |
| bottlecap/Cargo.toml | Adds dev-dependencies for msgpack and gzip decoding used by the fake intake. |
| bottlecap/Cargo.lock | Updates lockfile for the new dev-dependencies. |
duncanista
reviewed
Apr 24, 2026
Contributor
duncanista
left a comment
There was a problem hiding this comment.
Seems like the stats URL change is different to what this PR claims, do we really need them together?
6 tasks
2b10774 to
2e77c12
Compare
Member
Author
I split that small refactor out into #1210 and stacked this PR on that one. |
8f52b41 to
6fbe14b
Compare
…tests Spawns an axum server on a random local port that accepts POSTs on /api/v0.2/stats (msgpack + gzip) and /api/v0.2/traces (protobuf, with zstd/gzip/identity decompression), decodes each body on arrival, and stores the decoded pb::StatsPayload / pb::AgentPayload for tests to query via typed methods. Two integration tests cover both flush paths: - stats_payload_roundtrip_through_fake_intake: drives StatsFlusher::send directly and asserts on decoded hit counts, span kind, peer tags, and HTTP metadata. - trace_payload_roundtrip_through_fake_intake: drives TraceFlusher::flush through the real aggregator and asserts on decoded trace/span IDs and service metadata. Tests redirect StatsFlusher at the fake-intake by passing FakeIntake::stats_url() to StatsFlusher::new, which was lifted to take the URL as a parameter in a prior commit. Prototype for APMSVLS-494 phase 1; extraction to a shared datadog/apm-agent-parity-rs crate is planned for phase 2. Co-Authored-By: Claude <noreply@anthropic.com>
service_source and span_derived_primary_tags were added in 2.0.0 (crates.io) but the workspace pins the git version (1.0.0). 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
- Return Result instead of panicking on bad decompression; axum converts handler panics to TCP aborts, not 500s, which produces opaque test failures - Warn on unrecognized Content-Encoding instead of silently treating as identity - Make base_url() private; stats_url()/traces_url() cover all uses 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
base_url() was private and never called; stats_url() and traces_url() accessed the field directly. Removing it also makes the blanket #![allow(dead_code)] in common/mod.rs unnecessary. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
2e77c12 to
027f404
Compare
fake_intake was re-exported from tests/common/mod.rs, causing it to be compiled into every test binary. logs_integration_test and metrics_integration_test never use it, so the compiler emitted dead-code errors under RUSTFLAGS=-D warnings. Remove the re-export from common/mod.rs and include the module directly in apm_integration_test via #[path]. Remove the now-unused `mod common;` declarations from logs and metrics test files. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
The Drop impl already sends the shutdown signal and aborts the task. The explicit shutdown() method was never called in any test. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Adds an in-process fake Datadog intake for bottlecap so APM flush paths can be asserted at the payload-field level, not just "a request was made".
Before this PR, no APM payload flushed by bottlecap was covered by integration tests. The existing
httpmock-based tests for logs and metrics only checkbody_contains(<substring>)on raw bytes, so they can't catch regressions in stats bucket structure, span attribution, peer tags, or any other decoded field.This PR implements phase 1 of the fake-intake work (APMSVLS-496), covering both sub-tickets:
StatsPayloadmsgpack decode + first stats integration test.AgentPayloadprotobuf decode + first trace-payload integration test.Changes:
bottlecap/tests/common/fake_intake.rs— axum server on a random local port accepting/api/v0.2/stats(msgpack + gzip) and/api/v0.2/traces(protobuf with zstd/gzip/identity decompression). Decodes each body on arrival and storespb::StatsPayload/pb::AgentPayloadfor tests to query. Decompression failures return HTTP 400; unknownContent-Encodingvalues are warned.bottlecap/tests/apm_integration_test.rs— two new integration tests:stats_payload_roundtrip_through_fake_intake: drivesStatsFlusher::sendand asserts on hit counts, span kind, peer tags, and HTTP metadata.trace_payload_roundtrip_through_fake_intake: drivesTraceFlusher::flushthrough the real aggregator and asserts on trace/span IDs and service metadata.bottlecap/Cargo.toml— addsrmp-serdeandflate2as dev-dependencies.Phase 2 will extract this module into a shared crate consumed by both bottlecap and SCL; the module is deliberately bottlecap-type-free to make that extraction mechanical.
Testing
cargo test --test apm_integration_test— both new tests pass locally and on Linux CIcargo test— full bottlecap test suite passes locally (522 unit tests + integration/doc tests), no regressionsRUSTFLAGS="-D warnings" cargo clippy --workspace --all-targets --features default— clean locally and on Linux CIcargo fmt --all -- --check— clean locally