Skip to main content

systemprompt_logging/services/
format.rs

1//! Console formatter that filters system fields and renders structured values.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use std::fmt::{self, Write};
7use tracing::field::{Field, Visit};
8use tracing_subscriber::field::{MakeVisitor, VisitFmt, VisitOutput};
9use tracing_subscriber::fmt::format::Writer;
10
11use crate::layer::InstanceLabel;
12use crate::sanitize::{REDACTION_PLACEHOLDER, escape_control, is_redacted, is_system_sentinel};
13
14#[derive(Debug, Clone, Default)]
15pub struct FilterSystemFields {
16    instance: InstanceLabel,
17}
18
19impl FilterSystemFields {
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    pub(crate) const fn labelled(instance: InstanceLabel) -> Self {
25        Self { instance }
26    }
27}
28
29#[derive(Debug)]
30pub struct FilteringVisitor<'a> {
31    writer: Writer<'a>,
32    instance: InstanceLabel,
33    is_first: bool,
34    result: fmt::Result,
35}
36
37impl<'a> FilteringVisitor<'a> {
38    const fn new(writer: Writer<'a>, instance: InstanceLabel) -> Self {
39        Self {
40            writer,
41            instance,
42            is_first: true,
43            result: Ok(()),
44        }
45    }
46
47    fn record_filtered(&mut self, field: &Field, value: &dyn fmt::Debug) {
48        if self.result.is_err() {
49            return;
50        }
51
52        let debug_str = format!("{:?}", value);
53        if is_system_sentinel(&debug_str) {
54            return;
55        }
56
57        self.write_value(field.name(), &debug_str);
58    }
59
60    fn write_scalar(&mut self, field: &Field, value: impl fmt::Display) {
61        if self.result.is_err() {
62            return;
63        }
64        self.result = self.write_field(field.name(), &value.to_string());
65    }
66
67    fn write_value(&mut self, name: &str, rendered: &str) {
68        let safe = if is_redacted(name) {
69            REDACTION_PLACEHOLDER.to_owned()
70        } else {
71            escape_control(rendered)
72        };
73        self.result = self.write_field(name, &safe);
74    }
75
76    fn write_field(&mut self, name: &str, value: &str) -> fmt::Result {
77        if self.is_first {
78            self.is_first = false;
79        } else {
80            self.writer.write_char(' ')?;
81        }
82        write!(self.writer, "{}={}", name, value)
83    }
84}
85
86impl Visit for FilteringVisitor<'_> {
87    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
88        self.record_filtered(field, value);
89    }
90
91    fn record_str(&mut self, field: &Field, value: &str) {
92        if self.result.is_err() {
93            return;
94        }
95        if is_system_sentinel(value) {
96            return;
97        }
98        self.write_value(field.name(), &format!("{:?}", value));
99    }
100
101    fn record_i64(&mut self, field: &Field, value: i64) {
102        self.write_scalar(field, value);
103    }
104
105    fn record_u64(&mut self, field: &Field, value: u64) {
106        self.write_scalar(field, value);
107    }
108
109    fn record_i128(&mut self, field: &Field, value: i128) {
110        self.write_scalar(field, value);
111    }
112
113    fn record_u128(&mut self, field: &Field, value: u128) {
114        self.write_scalar(field, value);
115    }
116
117    fn record_f64(&mut self, field: &Field, value: f64) {
118        self.write_scalar(field, value);
119    }
120
121    fn record_bool(&mut self, field: &Field, value: bool) {
122        self.write_scalar(field, value);
123    }
124}
125
126impl VisitOutput<fmt::Result> for FilteringVisitor<'_> {
127    fn finish(mut self) -> fmt::Result {
128        self.result?;
129        if let Some(instance_id) = self.instance.get().cloned() {
130            self.write_field("instance", instance_id.as_str())?;
131        }
132        Ok(())
133    }
134}
135
136impl VisitFmt for FilteringVisitor<'_> {
137    fn writer(&mut self) -> &mut dyn Write {
138        &mut self.writer
139    }
140}
141
142impl<'a> MakeVisitor<Writer<'a>> for FilterSystemFields {
143    type Visitor = FilteringVisitor<'a>;
144
145    fn make_visitor(&self, target: Writer<'a>) -> Self::Visitor {
146        FilteringVisitor::new(target, self.instance.clone())
147    }
148}