synapse_pingora/waf/
trace.rs1use serde::Serialize;
4
5#[derive(Debug, Clone, Serialize)]
7#[serde(tag = "type", rename_all = "snake_case")]
8pub enum TraceEvent {
9 EvaluationStarted {
10 method: String,
11 uri: String,
12 candidate_rules: usize,
13 },
14 RuleStart {
15 rule_id: u32,
16 },
17 ConditionEvaluated {
18 rule_id: u32,
19 kind: String,
20 field: Option<String>,
21 op: Option<String>,
22 name: Option<String>,
23 matched: bool,
24 },
25 RuleEnd {
26 rule_id: u32,
27 matched: bool,
28 risk: f64,
29 blocking: bool,
30 },
31 EvaluationFinished {
32 verdict: String,
33 risk_score: u16,
34 matched_rules: Vec<u32>,
35 timed_out: bool,
36 rules_evaluated: Option<u32>,
37 detection_time_us: u64,
38 },
39 Truncated {
40 limit: usize,
41 },
42}
43
44pub trait TraceSink: Send {
46 fn record(&mut self, event: TraceEvent);
47}
48
49pub struct TraceState<'a> {
51 sink: Option<&'a mut dyn TraceSink>,
52}
53
54impl<'a> TraceState<'a> {
55 pub fn enabled(sink: &'a mut dyn TraceSink) -> Self {
56 Self { sink: Some(sink) }
57 }
58
59 pub fn disabled() -> Self {
60 Self { sink: None }
61 }
62
63 pub fn is_enabled(&self) -> bool {
64 self.sink.is_some()
65 }
66
67 pub fn emit(&mut self, event: TraceEvent) {
68 if let Some(sink) = self.sink.as_mut() {
69 sink.record(event);
70 }
71 }
72}