feat(server): opt-in IO capture for replay (--capture-io-path)#148
Merged
Conversation
ordo-server can now record each execution's full input + output to a JSONL file
— the exact shape 'ordo replay' consumes — turning production traffic into a
replayable regression corpus. Disabled by default; when off, no input is ever
cloned on the hot path.
- config: --capture-io-path (ORDO_CAPTURE_IO_PATH) + --capture-io-sample-rate
(ORDO_CAPTURE_IO_SAMPLE_RATE, default 100)
- capture.rs: CaptureLogger mirroring AuditLogger (Arc, daily-rotated
capture-YYYY-MM-DD.jsonl, atomic sample rate, sync flush); should_capture()
is checked BEFORE the input clone so a disabled/unsampled request pays nothing
- api.rs execute_ruleset: snapshot input only when should_capture(); write the
{ts, rule_name, tenant, input, code, output, duration_us, source_ip} record in
the success arm beside the existing audit call
- threaded through AppState (+ the RPC-state + test constructions)
- docs: en/zh 'Traffic Capture & Replay' page (the capture -> replay ->
write-tests loop, PII/sampling caveats) + sidebar
Scope v1: HTTP single execute. Batch + gRPC capture are documented follow-ups
(their service state doesn't carry the config/handles yet). Verified end-to-end:
ran the server with --capture-io-path, executed two rules, confirmed the JSONL
lines, replayed them locally, and saw a rule change flip a captured decision.
An isolated, reproducible perf harness for CaptureLogger (excluded from CI via #[ignore]). Measures single-threaded per-call cost and the multi-threaded throughput ceiling of the write path, for small and ~4KB payloads. Confirms the mutex only guards the write (serialization happens outside the lock), so capture throughput scales with cores rather than serializing on the lock. Run: cargo test -p ordo-server --bin ordo-server capture_throughput -- --ignored --nocapture
Pama-Lee
added a commit
that referenced
this pull request
Jul 6, 2026
* feat(server): opt-in IO capture for replay (--capture-io-path)
ordo-server can now record each execution's full input + output to a JSONL file
— the exact shape 'ordo replay' consumes — turning production traffic into a
replayable regression corpus. Disabled by default; when off, no input is ever
cloned on the hot path.
- config: --capture-io-path (ORDO_CAPTURE_IO_PATH) + --capture-io-sample-rate
(ORDO_CAPTURE_IO_SAMPLE_RATE, default 100)
- capture.rs: CaptureLogger mirroring AuditLogger (Arc, daily-rotated
capture-YYYY-MM-DD.jsonl, atomic sample rate, sync flush); should_capture()
is checked BEFORE the input clone so a disabled/unsampled request pays nothing
- api.rs execute_ruleset: snapshot input only when should_capture(); write the
{ts, rule_name, tenant, input, code, output, duration_us, source_ip} record in
the success arm beside the existing audit call
- threaded through AppState (+ the RPC-state + test constructions)
- docs: en/zh 'Traffic Capture & Replay' page (the capture -> replay ->
write-tests loop, PII/sampling caveats) + sidebar
Scope v1: HTTP single execute. Batch + gRPC capture are documented follow-ups
(their service state doesn't carry the config/handles yet). Verified end-to-end:
ran the server with --capture-io-path, executed two rules, confirmed the JSONL
lines, replayed them locally, and saw a rule change flip a captured decision.
* test(server): add ignored capture throughput micro-benchmark
An isolated, reproducible perf harness for CaptureLogger (excluded from CI via
#[ignore]). Measures single-threaded per-call cost and the multi-threaded
throughput ceiling of the write path, for small and ~4KB payloads. Confirms the
mutex only guards the write (serialization happens outside the lock), so capture
throughput scales with cores rather than serializing on the lock.
Run: cargo test -p ordo-server --bin ordo-server capture_throughput -- --ignored --nocapture
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.
The production-traffic source for
ordo replay(#147). ordo-server can now record each execution's full input + output to a JSONL file — the exact shapeordo replayconsumes — turning production traffic into a replayable regression corpus.What
--capture-io-path <dir>(ORDO_CAPTURE_IO_PATH) — enable capture; each execution appends a line tocapture-YYYY-MM-DD.jsonl(daily rotation).--capture-io-sample-rate(ORDO_CAPTURE_IO_SAMPLE_RATE, default 100) bounds volume.capture.rs—CaptureLoggermirroringAuditLogger(Arc,Mutex<BufWriter>, atomic sample rate, sync flush). Record:{ts, rule_name, tenant, input, code, output, duration_us, source_ip}.api.rs execute_ruleset—should_capture()is checked before the input clone, so a disabled or unsampled request never clones theValueon the hot path; the record is written in the success arm beside the existing audit call.AppState(+ the RPC-state + the 3 test constructions).--write-testsloop, PII/sampling caveats) + sidebar.Design / scope
OrdoGrpcService, the batch per-item loop) doesn't carry the config/handle yet, so wiring them is a separate change.Verified end-to-end
Ran the server with
--capture-io-path, executed two rules over HTTP, confirmed two JSONL lines with full input/output/code, thenordo replay'd them against a local project — and watched a rule change (limit 10000 → 30000) flip a captured decisionREJECTED → APPROVED.cargo test -p ordo-servergreen (175);clippyclean; docs build clean.Part 2 of 2 — pairs with #147 (
ordo replay).