zen_engine/decision_graph/
tracer.rs1use crate::nodes::NodeResult;
2use ahash::HashMap;
3use serde::{Deserialize, Serialize};
4use std::sync::Arc;
5use zen_expression::variable::ToVariable;
6use zen_types::decision::{DecisionNode, DecisionNodeKind};
7use zen_types::variable::Variable;
8
9pub(crate) struct NodeTracer(Option<HashMap<Arc<str>, DecisionGraphTrace>>);
10
11impl NodeTracer {
12 pub fn new(enabled: bool) -> Self {
13 Self(enabled.then(|| HashMap::default()))
14 }
15
16 pub fn record_execution(
17 &mut self,
18 node: &DecisionNode,
19 input_trace: Variable,
20 result: &NodeResult,
21 duration: std::time::Duration,
22 ) {
23 let Some(traces) = &mut self.0 else {
24 return;
25 };
26
27 if matches!(node.kind, DecisionNodeKind::SwitchNode { .. }) {
28 return;
29 }
30
31 let input = match &node.kind {
32 DecisionNodeKind::InputNode { .. } => Variable::Null,
33 _ => input_trace,
34 };
35
36 let mut trace = DecisionGraphTrace {
37 id: node.id.clone(),
38 name: node.name.clone(),
39 input,
40 order: traces.len() as u32,
41 output: Variable::Null,
42 trace_data: None,
43 performance: Some(Arc::from(format!("{:.1?}", duration))),
44 };
45
46 match &result {
47 Ok(ok) => {
48 trace.trace_data = ok.trace_data.clone();
49 if !matches!(node.kind, DecisionNodeKind::OutputNode { .. }) {
50 trace.output = ok.output.clone();
51 }
52 }
53 Err(err) => {
54 trace.trace_data = err.trace.clone();
55 }
56 };
57
58 traces.insert(node.id.clone(), trace);
59 }
60
61 pub fn trace_callback(&mut self) -> Option<impl FnMut(DecisionGraphTrace) + '_> {
62 let Some(traces) = &mut self.0 else {
63 return None;
64 };
65
66 Some(|mut trace: DecisionGraphTrace| {
67 trace.order = traces.len() as u32;
68 traces.insert(trace.id.clone(), trace);
69 })
70 }
71
72 pub fn into_traces(self) -> Option<HashMap<Arc<str>, DecisionGraphTrace>> {
73 self.0
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, ToVariable)]
78#[serde(rename_all = "camelCase")]
79pub struct DecisionGraphTrace {
80 pub input: Variable,
81 pub output: Variable,
82 pub name: Arc<str>,
83 pub id: Arc<str>,
84 pub performance: Option<Arc<str>>,
85 pub trace_data: Option<Variable>,
86 pub order: u32,
87}