use std::time::Duration;
use sha2::{Digest, Sha256};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum IgnoreField {
Status,
Headers,
Body,
}
#[derive(Clone, Debug)]
pub struct ShadowConfig {
sample_rate: u32,
pub shadow_timeout: Duration,
pub ignore: Vec<IgnoreField>,
}
impl ShadowConfig {
pub fn full_sample() -> Self {
Self {
sample_rate: 100,
shadow_timeout: Duration::from_secs(2),
ignore: Vec::new(),
}
}
#[must_use]
pub fn sample_rate(mut self, percent: u32) -> Self {
self.sample_rate = percent.min(100);
self
}
#[must_use]
pub fn shadow_timeout(mut self, d: Duration) -> Self {
self.shadow_timeout = d;
self
}
#[must_use]
pub fn ignore(mut self, field: IgnoreField) -> Self {
self.ignore.push(field);
self
}
pub fn sample_rate_percent(&self) -> u32 {
self.sample_rate
}
pub fn should_shadow(&self, key: &[u8]) -> bool {
if self.sample_rate >= 100 {
return true;
}
if self.sample_rate == 0 {
return false;
}
let mut hasher = Sha256::new();
hasher.update(key);
let digest = hasher.finalize();
let bucket = u32::from_be_bytes([digest[0], digest[1], digest[2], digest[3]]) % 100;
bucket < self.sample_rate
}
}
impl Default for ShadowConfig {
fn default() -> Self {
Self::full_sample()
}
}