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::sanitize::{REDACTION_PLACEHOLDER, escape_control, is_redacted, is_system_sentinel};
12
13#[derive(Debug, Clone, Copy, Default)]
14pub struct FilterSystemFields;
15
16impl FilterSystemFields {
17    pub const fn new() -> Self {
18        Self
19    }
20}
21
22#[derive(Debug)]
23pub struct FilteringVisitor<'a> {
24    writer: Writer<'a>,
25    is_first: bool,
26    result: fmt::Result,
27}
28
29impl<'a> FilteringVisitor<'a> {
30    const fn new(writer: Writer<'a>) -> Self {
31        Self {
32            writer,
33            is_first: true,
34            result: Ok(()),
35        }
36    }
37
38    fn record_filtered(&mut self, field: &Field, value: &dyn fmt::Debug) {
39        if self.result.is_err() {
40            return;
41        }
42
43        let debug_str = format!("{:?}", value);
44        if is_system_sentinel(&debug_str) {
45            return;
46        }
47
48        self.write_value(field.name(), &debug_str);
49    }
50
51    fn write_value(&mut self, name: &str, rendered: &str) {
52        let safe = if is_redacted(name) {
53            REDACTION_PLACEHOLDER.to_owned()
54        } else {
55            escape_control(rendered)
56        };
57        self.result = self.write_field(name, &safe);
58    }
59
60    fn write_field(&mut self, name: &str, value: &str) -> fmt::Result {
61        if self.is_first {
62            self.is_first = false;
63        } else {
64            self.writer.write_char(' ')?;
65        }
66        write!(self.writer, "{}={}", name, value)
67    }
68}
69
70impl Visit for FilteringVisitor<'_> {
71    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
72        self.record_filtered(field, value);
73    }
74
75    fn record_str(&mut self, field: &Field, value: &str) {
76        if self.result.is_err() {
77            return;
78        }
79        if is_system_sentinel(value) {
80            return;
81        }
82        self.write_value(field.name(), &format!("{:?}", value));
83    }
84}
85
86impl VisitOutput<fmt::Result> for FilteringVisitor<'_> {
87    fn finish(self) -> fmt::Result {
88        self.result
89    }
90}
91
92impl VisitFmt for FilteringVisitor<'_> {
93    fn writer(&mut self) -> &mut dyn Write {
94        &mut self.writer
95    }
96}
97
98impl<'a> MakeVisitor<Writer<'a>> for FilterSystemFields {
99    type Visitor = FilteringVisitor<'a>;
100
101    fn make_visitor(&self, target: Writer<'a>) -> Self::Visitor {
102        FilteringVisitor::new(target)
103    }
104}