Assert on events in tests¶
MemorySink keeps every event in a Vec you can inspect. It is available
without any Cargo feature, so telemetry assertions do not drag the remote
sink stack into your test build.
Capture what your code records¶
use std::sync::Arc;
use rtb_telemetry::{CollectionPolicy, MemorySink, TelemetryContext};
#[tokio::test]
async fn records_the_command_invocation() {
let sink = Arc::new(MemorySink::new());
let telemetry = TelemetryContext::builder()
.tool("mytool")
.tool_version("1.0.0")
.salt("mytool-test-salt")
.sink(sink.clone())
.policy(CollectionPolicy::Enabled)
.build();
run_my_command(&telemetry).await.unwrap();
let events = sink.snapshot();
assert_eq!(events.len(), 1);
assert_eq!(events[0].name, "command.invoke");
assert_eq!(events[0].attrs.get("outcome").map(String::as_str), Some("ok"));
}
Clone the Arc into the builder and keep the original: cloning shares the
backing vector, so the handle you kept sees everything the context
recorded. snapshot() returns events in emit order; len() and
is_empty() are there for the common assertions.
Prove that opting out really collects nothing¶
The test worth having is the negative one:
#[tokio::test]
async fn disabled_policy_records_nothing() {
let sink = Arc::new(MemorySink::new());
let telemetry = TelemetryContext::builder()
.tool("mytool")
.tool_version("1.0.0")
// no salt needed — a Disabled context never derives an identity
.sink(sink.clone())
.build(); // policy defaults to Disabled
run_my_command(&telemetry).await.unwrap();
assert!(sink.is_empty());
}
Leaving .policy(…) off is deliberate here: it asserts the default
behaviour, so the test fails if someone ever changes which way the default
points.
Use a distinct salt in tests¶
Any string works — nothing validates it — but use a test-specific one. A test that reuses your production salt writes your real machine identity into test output and CI logs.
Do not assert redaction against MemorySink¶
MemorySink stores the event exactly as the caller built it, without
calling redacted(). That is the right behaviour for asserting what your
code passed, and the wrong tool for proving a secret was scrubbed. For
that, either assert on event.redacted() directly or write through a
FileSink into a tempfile::tempdir() and read the line back.
Testing an HTTP sink without a network¶
HttpSink refuses non-HTTPS endpoints unless allow_insecure_endpoint is
set, which is what that flag is for: point it at a
wiremock server on http://127.0.0.1:… in
tests and leave the flag off everywhere else.
Beware a machine with no machine ID in CI¶
An Enabled context derives a machine ID at build(). On a host where
that cannot be read — a stripped container image is the usual culprit —
every derivation returns a different random value, so a test asserting
that two derivations match will fail there and pass on your laptop. Seed a
stable /etc/machine-id in the CI image, as this repository's own pipeline
does, or do not assert on identity stability.