#[derive(Clone, Debug)]
pub enum FieldValue {
Bool(bool),
I64(i64),
U64(u64),
String(String),
Debug(String),
Error(String),
}
impl std::fmt::Display for FieldValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Bool(value) => write!(f, "{value}"),
Self::I64(value) => write!(f, "{value}"),
Self::U64(value) => write!(f, "{value}"),
Self::String(value) | Self::Debug(value) | Self::Error(value) => write!(f, "{value}"),
}
}
}
#[derive(Default)]
pub struct EventVisitor {
message: Option<String>,
fields: Vec<(&'static str, FieldValue)>,
}
impl EventVisitor {
pub fn into_message_and_fields(self) -> (String, Vec<(&'static str, FieldValue)>) {
let Self { message, fields } = self;
let message = message.unwrap_or_default();
(message, fields)
}
#[cfg(not(target_arch = "wasm32"))] pub fn format_as_string(self) -> String {
let (message, fields) = self.into_message_and_fields();
let fields = fields
.iter()
.map(|(key, value)| format!("{key}={value}"))
.collect::<Vec<_>>();
match (message.is_empty(), fields.is_empty()) {
(_, true) => message,
(true, false) => fields.join(" "),
(false, false) => format!("{message} {}", fields.join(" ")),
}
}
}
impl tracing::field::Visit for EventVisitor {
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
if field.name() == "message" {
self.message = Some(format!("{value:?}"));
} else {
self.fields
.push((field.name(), FieldValue::Debug(format!("{value:?}"))));
}
}
fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
if field.name() == "message" {
self.message = Some(value.to_owned());
} else {
self.fields
.push((field.name(), FieldValue::String(value.to_owned())));
}
}
fn record_i64(&mut self, field: &tracing::field::Field, value: i64) {
if field.name() == "message" {
self.message = Some(value.to_string());
} else {
self.fields.push((field.name(), FieldValue::I64(value)));
}
}
fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
if field.name() == "message" {
self.message = Some(value.to_string());
} else {
self.fields.push((field.name(), FieldValue::U64(value)));
}
}
fn record_bool(&mut self, field: &tracing::field::Field, value: bool) {
if field.name() == "message" {
self.message = Some(value.to_string());
} else {
self.fields.push((field.name(), FieldValue::Bool(value)));
}
}
fn record_error(
&mut self,
field: &tracing::field::Field,
value: &(dyn std::error::Error + 'static),
) {
if field.name() == "message" {
self.message = Some(value.to_string());
} else {
self.fields
.push((field.name(), FieldValue::Error(value.to_string())));
}
}
}