logforth_append_fastrace/
lib.rs1#![cfg_attr(docsrs, feature(doc_cfg))]
18#![deny(missing_docs)]
19
20use std::borrow::Cow;
21
22use jiff::Zoned;
23use logforth_core::Diagnostic;
24use logforth_core::Error;
25use logforth_core::append::Append;
26use logforth_core::kv::KeyView;
27use logforth_core::kv::ValueView;
28use logforth_core::kv::Visitor;
29use logforth_core::record::Record;
30
31#[derive(Default, Debug, Clone)]
47#[non_exhaustive]
48pub struct FastraceEvent {}
49
50impl Append for FastraceEvent {
51 fn append(&self, record: &Record, diags: &[Box<dyn Diagnostic>]) -> Result<(), Error> {
52 let message = if let Some(msg) = record.payload_static() {
53 Cow::Borrowed(msg)
54 } else {
55 Cow::Owned(record.payload().to_string())
56 };
57
58 let mut collector = KvCollector { kv: Vec::new() };
59 record.key_values().visit(&mut collector)?;
60 for d in diags {
61 d.visit(&mut collector)?;
62 }
63
64 fastrace::local::LocalSpan::add_event(fastrace::Event::new(message).with_properties(
65 || {
66 [
67 (Cow::from("level"), Cow::from(record.level().name())),
68 (Cow::from("timestamp"), Cow::from(Zoned::now().to_string())),
69 ]
70 .into_iter()
71 .chain(collector.kv)
72 },
73 ));
74
75 Ok(())
76 }
77
78 fn flush(&self) -> Result<(), Error> {
79 fastrace::flush();
80 Ok(())
81 }
82}
83
84struct KvCollector {
85 kv: Vec<(Cow<'static, str>, Cow<'static, str>)>,
86}
87
88impl Visitor for KvCollector {
89 fn visit(&mut self, key: KeyView, value: ValueView) -> Result<(), Error> {
90 let k = key.to_cow();
91 let v = if let Some(s) = value.to_static_str() {
92 Cow::Borrowed(s)
93 } else {
94 Cow::Owned(value.to_string())
95 };
96 self.kv.push((k, v));
97 Ok(())
98 }
99}