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