Skip to content

Commit 3bc2be6

Browse files
authored
refactor!: diagnostic visit is now fallible (#121)
Signed-off-by: tison <[email protected]>
1 parent 78da7c2 commit 3bc2be6

File tree

11 files changed

+49
-38
lines changed

11 files changed

+49
-38
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
88

99
* `Diagnostic` is now a trait. `Visitor`'s method signature is simplified.
1010
* `Append::flush` is now fallible.
11+
* `Diagnostic`'s and `Visitor`'s `visit` methods are fallible.
1112

1213
## [0.23.1] 2025-03-23
1314

src/append/fastrace.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl Append for FastraceEvent {
4444
let mut collector = KvCollector { kv: Vec::new() };
4545
record.key_values().visit(&mut collector)?;
4646
for d in diagnostics {
47-
d.visit(&mut collector);
47+
d.visit(&mut collector)?;
4848
}
4949

5050
fastrace::local::LocalSpan::add_event(fastrace::Event::new(message).with_properties(
@@ -88,9 +88,8 @@ impl<'kvs> log::kv::VisitSource<'kvs> for KvCollector {
8888
}
8989

9090
impl Visitor for KvCollector {
91-
fn visit(&mut self, key: Cow<str>, value: Cow<str>) {
92-
let key = key.into_owned();
93-
let value = value.into_owned();
94-
self.kv.push((key, value));
91+
fn visit(&mut self, key: Cow<str>, value: Cow<str>) -> anyhow::Result<()> {
92+
self.kv.push((key.into_owned(), value.into_owned()));
93+
Ok(())
9594
}
9695
}

src/append/journald/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,11 @@ impl<'kvs> log::kv::VisitSource<'kvs> for WriteKeyValues<'_> {
247247
}
248248

249249
impl Visitor for WriteKeyValues<'_> {
250-
fn visit(&mut self, key: Cow<str>, value: Cow<str>) {
250+
fn visit(&mut self, key: Cow<str>, value: Cow<str>) -> anyhow::Result<()> {
251251
let key = key.as_ref();
252252
let value = value.as_bytes();
253253
field::put_field_length_encoded(self.0, field::FieldName::WriteEscaped(key), value);
254+
Ok(())
254255
}
255256
}
256257

@@ -310,7 +311,7 @@ impl Append for Journald {
310311
let mut visitor = WriteKeyValues(&mut buffer);
311312
record.key_values().visit(&mut visitor)?;
312313
for d in diagnostics {
313-
d.visit(&mut visitor);
314+
d.visit(&mut visitor)?;
314315
}
315316
// Put all extra fields of the appender
316317
buffer.extend_from_slice(&self.extra_fields);

src/append/opentelemetry.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ impl Append for OpentelemetryLog {
259259
};
260260
record.key_values().visit(&mut extractor)?;
261261
for d in diagnostics {
262-
d.visit(&mut extractor);
262+
d.visit(&mut extractor)?;
263263
}
264264

265265
self.logger.emit(log_record);
@@ -300,9 +300,10 @@ impl<'kvs> log::kv::VisitSource<'kvs> for KvExtractor<'_> {
300300
}
301301

302302
impl Visitor for KvExtractor<'_> {
303-
fn visit(&mut self, key: Cow<str>, value: Cow<str>) {
303+
fn visit(&mut self, key: Cow<str>, value: Cow<str>) -> anyhow::Result<()> {
304304
let key = key.into_owned();
305305
let value = value.into_owned();
306306
self.record.add_attribute(key, value);
307+
Ok(())
307308
}
308309
}

src/diagnostic/fastrace.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ use crate::Diagnostic;
4040
pub struct FastraceDiagnostic {}
4141

4242
impl Diagnostic for FastraceDiagnostic {
43-
fn visit(&self, visitor: &mut dyn Visitor) {
43+
fn visit(&self, visitor: &mut dyn Visitor) -> anyhow::Result<()> {
4444
if let Some(span) = fastrace::collector::SpanContext::current_local_parent() {
4545
let trace_id = format!("{:016x}", span.trace_id.0);
46-
visitor.visit("trace_id".into(), trace_id.into());
46+
visitor.visit("trace_id".into(), trace_id.into())?;
4747
}
48+
49+
Ok(())
4850
}
4951
}

src/diagnostic/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ mod thread_local;
3131
/// A visitor to walk through diagnostic key-value pairs.
3232
pub trait Visitor {
3333
/// Visits a key-value pair.
34-
fn visit(&mut self, key: Cow<str>, value: Cow<str>);
34+
fn visit(&mut self, key: Cow<str>, value: Cow<str>) -> anyhow::Result<()>;
3535
}
3636

3737
/// A trait representing a Mapped Diagnostic Context (MDC) that provides diagnostic key-values.
3838
pub trait Diagnostic: fmt::Debug + Send + Sync + 'static {
39-
fn visit(&self, visitor: &mut dyn Visitor);
39+
fn visit(&self, visitor: &mut dyn Visitor) -> anyhow::Result<()>;
4040
}
4141

4242
impl<T: Diagnostic> From<T> for Box<dyn Diagnostic> {

src/diagnostic/static_global.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ impl StaticDiagnostic {
5252
}
5353

5454
impl Diagnostic for StaticDiagnostic {
55-
fn visit(&self, visitor: &mut dyn Visitor) {
55+
fn visit(&self, visitor: &mut dyn Visitor) -> anyhow::Result<()> {
5656
for (key, value) in self.kvs.iter() {
57-
visitor.visit(key.into(), value.into());
57+
visitor.visit(key.into(), value.into())?;
5858
}
59+
60+
Ok(())
5961
}
6062
}

src/diagnostic/thread_local.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,13 @@ impl ThreadLocalDiagnostic {
5454
}
5555

5656
impl Diagnostic for ThreadLocalDiagnostic {
57-
fn visit(&self, visitor: &mut dyn Visitor) {
57+
fn visit(&self, visitor: &mut dyn Visitor) -> anyhow::Result<()> {
5858
CONTEXT.with(|map| {
5959
let map = map.borrow();
6060
for (key, value) in map.iter() {
61-
visitor.visit(key.into(), value.into());
61+
visitor.visit(key.into(), value.into())?;
6262
}
63+
Ok(())
6364
})
6465
}
6566
}

src/layout/json.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,11 @@ impl<'kvs> log::kv::VisitSource<'kvs> for KvCollector<'_> {
8686
}
8787

8888
impl Visitor for KvCollector<'_> {
89-
fn visit(&mut self, key: Cow<str>, value: Cow<str>) {
89+
fn visit(&mut self, key: Cow<str>, value: Cow<str>) -> anyhow::Result<()> {
9090
let key = key.into_owned();
9191
let value = value.into_owned();
9292
self.kvs.insert(key, value.into());
93+
Ok(())
9394
}
9495
}
9596

@@ -130,7 +131,7 @@ impl Layout for JsonLayout {
130131
let mut visitor = KvCollector { kvs: &mut kvs };
131132
record.key_values().visit(&mut visitor)?;
132133
for d in diagnostics {
133-
d.visit(&mut visitor);
134+
d.visit(&mut visitor)?;
134135
}
135136

136137
let record_line = RecordLine {

src/layout/logfmt.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,21 @@ impl LogfmtLayout {
7070
}
7171

7272
// The encode logic is copied from https://github.com/go-logfmt/logfmt/blob/76262ea7/encode.go.
73-
fn encode_key_value(result: &mut String, key: &str, value: &str) {
73+
fn encode_key_value(result: &mut String, key: &str, value: &str) -> anyhow::Result<()> {
7474
use std::fmt::Write;
7575

7676
if key.contains([' ', '=', '"']) {
7777
// omit keys contain special chars
78-
return;
78+
anyhow::bail!("key contains special chars: {key}");
7979
}
8080

81-
// SAFETY: extend a string is always possible
8281
if value.contains([' ', '=', '"']) {
83-
write!(result, " {key}=\"{}\"", value.escape_debug()).unwrap();
82+
write!(result, " {key}=\"{}\"", value.escape_debug())?;
8483
} else {
85-
write!(result, " {key}={value}").unwrap();
84+
write!(result, " {key}={value}")?;
8685
}
86+
87+
Ok(())
8788
}
8889

8990
struct KvFormatter {
@@ -96,14 +97,17 @@ impl<'kvs> log::kv::VisitSource<'kvs> for KvFormatter {
9697
key: log::kv::Key<'kvs>,
9798
value: log::kv::Value<'kvs>,
9899
) -> Result<(), log::kv::Error> {
99-
encode_key_value(&mut self.text, key.as_str(), value.to_string().as_str());
100-
Ok(())
100+
match encode_key_value(&mut self.text, key.as_str(), value.to_string().as_str()) {
101+
Ok(()) => Ok(()),
102+
Err(err) => Err(log::kv::Error::boxed(err)),
103+
}
101104
}
102105
}
103106

104107
impl Visitor for KvFormatter {
105-
fn visit(&mut self, key: Cow<str>, value: Cow<str>) {
106-
encode_key_value(&mut self.text, key.as_ref(), value.as_ref());
108+
fn visit(&mut self, key: Cow<str>, value: Cow<str>) -> anyhow::Result<()> {
109+
encode_key_value(&mut self.text, key.as_ref(), value.as_ref())?;
110+
Ok(())
107111
}
108112
}
109113

@@ -127,17 +131,17 @@ impl Layout for LogfmtLayout {
127131
text: format!("timestamp={time:.6}"),
128132
};
129133

130-
visitor.visit(Cow::Borrowed("level"), level.into());
131-
visitor.visit(Cow::Borrowed("module"), target.into());
134+
visitor.visit(Cow::Borrowed("level"), level.into())?;
135+
visitor.visit(Cow::Borrowed("module"), target.into())?;
132136
visitor.visit(
133137
Cow::Borrowed("position"),
134138
format!("{}:{}", file, line).into(),
135-
);
136-
visitor.visit(Cow::Borrowed("message"), message.to_string().into());
139+
)?;
140+
visitor.visit(Cow::Borrowed("message"), message.to_string().into())?;
137141

138142
record.key_values().visit(&mut visitor)?;
139143
for d in diagnostics {
140-
d.visit(&mut visitor);
144+
d.visit(&mut visitor)?;
141145
}
142146

143147
Ok(visitor.text.into_bytes())

src/layout/text.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,11 @@ impl<'kvs> log::kv::VisitSource<'kvs> for KvWriter {
171171
}
172172

173173
impl Visitor for KvWriter {
174-
fn visit(&mut self, key: Cow<str>, value: Cow<str>) {
174+
fn visit(&mut self, key: Cow<str>, value: Cow<str>) -> anyhow::Result<()> {
175175
use std::fmt::Write;
176176

177-
// SAFETY: no more than an allocate-less version
178-
// self.text.push_str(&format!(" {key}={value}"))
179-
write!(&mut self.text, " {key}={value}").unwrap();
177+
write!(&mut self.text, " {key}={value}")?;
178+
Ok(())
180179
}
181180
}
182181

@@ -201,7 +200,7 @@ impl Layout for TextLayout {
201200
};
202201
record.key_values().visit(&mut visitor)?;
203202
for d in diagnostics {
204-
d.visit(&mut visitor);
203+
d.visit(&mut visitor)?;
205204
}
206205

207206
Ok(visitor.text.into_bytes())

0 commit comments

Comments
 (0)