[APMSVLS-501] feat(bottlecap): add bottlecap-test-mode binary#1216
Draft
lucaspimentel wants to merge 1 commit intolpimentel/bottlecap-test-modefrom
Draft
[APMSVLS-501] feat(bottlecap): add bottlecap-test-mode binary#1216lucaspimentel wants to merge 1 commit intolpimentel/bottlecap-test-modefrom
lucaspimentel wants to merge 1 commit intolpimentel/bottlecap-test-modefrom
Conversation
A second [[bin]] target that runs the APM trace-processing surface as a long-lived HTTP server with no Lambda lifecycle. Listens on 127.0.0.1:8126 and exposes the standard tracer endpoints (/v0.4/traces, /v0.5/traces, /v0.6/stats, /info) plus POST /flush for deterministic harness-driven flushing. Configured by the same DD_* env vars the Lambda binary reads. Optional periodic flushing via DD_SERVERLESS_FLUSH_STRATEGY (decoupled from managed-instance mode). Gated behind the `test-mode` cargo feature (required-features), so it is not built in default or fips builds. Build with `cargo build --bin bottlecap-test-mode --features test-mode`. Intended for the cross-agent parity harness (APMSVLS-496) and for local dev workflows that need a tracer endpoint without standing up a Lambda. APMSVLS-501 🤖 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.
Stacked on #1201. Review #1201 first; this PR's diff is purely additive once that lands.
Overview
Adds a second
[[bin]]target,bottlecap-test-mode, that runs the APM trace-processing surface as a long-lived HTTP server with no AWS Lambda Extension lifecycle. ReusesTraceAgent,FlushingService, and the trace/stats/proxy flushers built bybottlecap::startup::build_trace_agent(introduced in #1201); the only Lambda-binary code it duplicates isinit_ustrandenable_logging_subsystem(~20 lines, called out in the design doc).Endpoints on
127.0.0.1:8126:/v0.4/traces,/v0.5/traces,/v0.6/stats,/info— unchanged from the Lambda binary'sTraceAgentrouter.POST /flush— new, registered by aFlushRouterExtensionimpl attached viaTraceAgent::with_router_extension(...)(the seam from [APMSVLS-501] refactor(bottlecap): preparatory work for "test-mode" binary #1201). CallsFlushingService::flush_blocking_final()and returns204 No Contentfor deterministic harness-driven flushing.Configuration: same
DD_*env vars as the Lambda binary. Notable inputs:DD_APM_DD_URL— redirects trace intake (the parity harness points this at the fake-intake from [APMSVLS-497][APMSVLS-498] test: add fake-intake for APM payload-level tests #1194).DD_SERVERLESS_FLUSH_STRATEGY— opt-in periodic flush ticker, decoupled from managed-instance mode.DD_TESTMODE_FUNCTION_ARN— overrides the stub ARN used for tag generation (defaults toarn:aws:lambda:us-east-1:000000000000:function:testmode).API key is hardcoded to
"stub-key"(no secrets resolver path); the parity harness fake-intake ignores auth.Feature gating
Gated behind the
test-modecargo feature viarequired-features = ["test-mode"], the same feature that gatesInvocationProcessorHandle::noop()(added in #1201). The binary is therefore not built indefaultorfipsbuilds, including bycargo build --workspace. Build/run with:CI will need a clippy/build step that passes
--features test-modeto keep this binary green going forward; happy to add that as a follow-up if reviewers prefer.Shutdown ordering
signal::ctrl_c()cancels the shutdown token first (drives axum'sgraceful_shutdownso any in-flight/v0.4/tracesrequest drains through the trace aggregator), then runsflush_blocking_final(). The periodic flush task selects on the same token so it doesn't leak when the listener stops.Why a second binary
The overlap between Lambda-mode and test-mode is small (~20 lines:
init_ustr, logging, config load), and the rest is intentionally different (no telemetry listener, no LWA, no logs agent, no proxy, no DogStatsD UDP, no event-bus-driven lifecycle). A second[[bin]]makes the test-mode surface explicit and structural, enforced by the compiler instead of by a runtime branch. Rejected alternatives (env-var branch, auto-detect, CLI flag, single binary with mode gating) are in the design doc.Design doc:
lucas-pimentel/docs/bottlecap-test-mode.md(local; happy to land it in-repo if reviewers prefer).Testing
cargo check --bin bottlecap-test-mode --features test-modecargo clippy --workspace --all-targets --features default -- -D warnings(existing surface unchanged)cargo clippy --workspace --all-targets --features default,test-mode -- -D warningscargo fmt --all -- --check:8200:POST /v0.4/traces(real msgpack span) → 200, buffered, periodic flush fired at 2s, intake receivedPOST /api/v0.2/traces(485 bytes,DD-API-KEY: stub-key).POST /flush→ 204.POST /v0.5/traces(malformed) → 500 (correct rejection from the existing v0.5 deserializer).GET /info→ 200 with the standard endpoints list.TRACE_AGENT | Shutdown signal received, shutting down→Aggregator service stopped→ clean exit.No new unit tests in this PR. The seam (
RouterExtension) and the no-op handle (InvocationProcessorHandle::noop()) are both covered by tests added in #1201; end-to-end coverage for test-mode lands as part of the parity harness (#1194 and the futureapm-agent-parity-rsrepo).🤖 Generated with Claude Code