pub struct Shadow {
pub sample_rate: f64,
pub max_usd_per_day: f64,
}Expand description
Shadow scoring settings for a route (ADR 0009 D2).
Observe mode records what traffic looked like; it never runs the ladder, so it cannot answer the one question it exists for — what would Firstpass have served, and what would it have cost? Shadow answers that by scoring a sample of observed requests off the hot path.
It makes real model calls, so there is deliberately no default-on sample rate and a hard daily ceiling is required. A measurement that quietly runs up a bill is worse than no measurement.
Fields§
§sample_rate: f64Fraction of observed requests scored counterfactually, in [0, 1].
max_usd_per_day: f64Hard ceiling on shadow spend per UTC day, in USD. Shadow stops when exhausted, and the fact that it stopped is recorded — silently degrading a measurement is its own bug.
Implementations§
Source§impl Shadow
impl Shadow
Sourcepub fn validate(&self) -> Result<(), String>
pub fn validate(&self) -> Result<(), String>
Whether this shadow config is coherent.
§Errors
If sample_rate is outside [0, 1] or max_usd_per_day is negative or non-finite.
Sourcepub fn sampled(&self, salt: &str, key_value: &str) -> bool
pub fn sampled(&self, salt: &str, key_value: &str) -> bool
Whether this request is in the shadow sample.
Uses the same salted bucketing as rollout, under its own domain tag, so shadow sampling is deterministic and — critically — independent of the rollout arm. If the two shared a hash, the shadow sample would be a biased subset of one arm and the projection it produces would not describe the traffic an operator is about to enforce on.