mz_tracing/
lib.rs
1use proptest::arbitrary::Arbitrary;
13use proptest::prelude::{BoxedStrategy, Strategy};
14use serde::{Deserialize, Serializer, de};
15use std::fmt::Formatter;
16use std::str::FromStr;
17use tracing_subscriber::EnvFilter;
18
19pub mod params;
20
21#[derive(Debug, Clone)]
22struct ValidatedEnvFilterString(String);
23
24pub struct CloneableEnvFilter {
26 filter: EnvFilter,
27 validated: ValidatedEnvFilterString,
28}
29
30impl AsRef<EnvFilter> for CloneableEnvFilter {
31 fn as_ref(&self) -> &EnvFilter {
32 &self.filter
33 }
34}
35
36impl From<CloneableEnvFilter> for EnvFilter {
37 fn from(value: CloneableEnvFilter) -> Self {
38 value.filter
39 }
40}
41
42impl PartialEq for CloneableEnvFilter {
43 fn eq(&self, other: &Self) -> bool {
44 format!("{}", self) == format!("{}", other)
45 }
46}
47
48impl Eq for CloneableEnvFilter {}
49
50impl Clone for CloneableEnvFilter {
51 fn clone(&self) -> Self {
52 Self {
54 filter: EnvFilter::from_str(&self.validated.0).expect("validated"),
58 validated: self.validated.clone(),
59 }
60 }
61}
62
63impl FromStr for CloneableEnvFilter {
64 type Err = tracing_subscriber::filter::ParseError;
65
66 fn from_str(s: &str) -> Result<Self, Self::Err> {
67 let filter: EnvFilter = s.parse()?;
68 Ok(CloneableEnvFilter {
69 filter,
70 validated: ValidatedEnvFilterString(s.to_string()),
71 })
72 }
73}
74
75impl std::fmt::Display for CloneableEnvFilter {
76 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
77 write!(f, "{}", self.filter)
78 }
79}
80
81impl std::fmt::Debug for CloneableEnvFilter {
82 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
83 write!(f, "{}", self.filter)
84 }
85}
86
87impl Arbitrary for CloneableEnvFilter {
88 type Strategy = BoxedStrategy<Self>;
89 type Parameters = ();
90
91 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
92 proptest::sample::select(vec!["info", "debug", "warn", "error", "off"])
95 .prop_map(|x| CloneableEnvFilter::from_str(x).expect("valid EnvFilter"))
96 .boxed()
97 }
98}
99
100impl serde::Serialize for CloneableEnvFilter {
101 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
102 where
103 S: Serializer,
104 {
105 serializer.serialize_str(&format!("{}", self))
106 }
107}
108
109impl<'de> Deserialize<'de> for CloneableEnvFilter {
110 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
111 where
112 D: serde::Deserializer<'de>,
113 {
114 let s = String::deserialize(deserializer)?;
115 Self::from_str(s.as_str()).map_err(|x| de::Error::custom(x.to_string()))
116 }
117}
118use tracing_subscriber::filter::Directive;
119
120#[derive(PartialEq, Eq, Clone, Debug)]
122pub struct SerializableDirective(Directive);
123
124impl From<SerializableDirective> for Directive {
125 fn from(value: SerializableDirective) -> Self {
126 value.0
127 }
128}
129
130impl From<Directive> for SerializableDirective {
131 fn from(value: Directive) -> Self {
132 SerializableDirective(value)
133 }
134}
135
136impl FromStr for SerializableDirective {
137 type Err = tracing_subscriber::filter::ParseError;
138
139 fn from_str(s: &str) -> Result<Self, Self::Err> {
140 let dir: Directive = s.parse()?;
141 Ok(SerializableDirective(dir))
142 }
143}
144
145impl std::fmt::Display for SerializableDirective {
146 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
147 write!(f, "{}", self.0)
148 }
149}
150
151impl Arbitrary for SerializableDirective {
152 type Strategy = BoxedStrategy<Self>;
153 type Parameters = ();
154
155 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
156 proptest::sample::select(vec!["info", "debug", "warn", "error", "off"])
159 .prop_map(|x| SerializableDirective::from_str(x).expect("valid Directive"))
160 .boxed()
161 }
162}
163
164impl serde::Serialize for SerializableDirective {
165 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
166 where
167 S: Serializer,
168 {
169 serializer.serialize_str(&format!("{}", self))
170 }
171}
172
173impl<'de> Deserialize<'de> for SerializableDirective {
174 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
175 where
176 D: serde::Deserializer<'de>,
177 {
178 let s = String::deserialize(deserializer)?;
179 Self::from_str(s.as_str()).map_err(|x| de::Error::custom(x.to_string()))
180 }
181}
182
183#[cfg(test)]
184mod test {
185 use crate::{CloneableEnvFilter, SerializableDirective};
186 use std::str::FromStr;
187
188 #[mz_ore::test]
192 fn roundtrips() {
193 let filter = CloneableEnvFilter::from_str(
194 "abc=debug,def=trace,[123],foo,baz[bar{a=b}]=debug,[{13=37}]=trace,info",
195 )
196 .expect("valid");
197 assert_eq!(
198 format!("{}", filter),
199 format!(
200 "{}",
201 CloneableEnvFilter::from_str(&format!("{}", filter)).expect("valid")
202 )
203 );
204 }
205
206 #[mz_ore::test]
207 fn roundtrips_directive() {
208 let dir = SerializableDirective::from_str("abc=debug").expect("valid");
209 assert_eq!(
210 format!("{}", dir),
211 format!(
212 "{}",
213 SerializableDirective::from_str(&format!("{}", dir)).expect("valid")
214 )
215 );
216 }
217}