use crate::model::{LogValue, LogEvent};
use std::collections::HashMap;
use tracing::field::{Field, Visit};
pub(crate) struct LogEventFieldVisitor<'a> {
fields: &'a mut HashMap<String, LogValue>,
message: &'a mut Option<String>,
message_field_count: u32,
}
impl<'a> LogEventFieldVisitor<'a> {
pub(crate) fn new(event: &'a mut LogEvent) -> Self {
Self {
fields: &mut event.fields,
message: &mut event.message,
message_field_count: 0,
}
}
fn record_potential_message(&mut self, field_name: &str, value_str: String) {
if field_name == "message" {
if self.message.is_none() {
*self.message = Some(value_str);
} else {
self.message_field_count += 1;
let disambiguated_key = format!("message.{}", self.message_field_count);
self.fields.insert(disambiguated_key, LogValue::String(value_str));
}
} else {
self.fields.insert(field_name.to_string(), LogValue::String(value_str));
}
}
}
impl<'a> Visit for LogEventFieldVisitor<'a> {
fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) {
let value_str = format!("{:?}", value);
if field.name() == "message" {
if self.message.is_none() {
*self.message = Some(value_str);
} else {
self.message_field_count += 1;
let disambiguated_key = format!("message.{}", self.message_field_count);
self.fields.insert(disambiguated_key, LogValue::Debug(value_str));
}
} else {
self.fields.insert(field.name().to_string(), LogValue::Debug(value_str));
}
}
fn record_str(&mut self, field: &Field, value: &str) {
self.record_potential_message(field.name(), value.to_string());
}
fn record_i64(&mut self, field: &Field, value: i64) {
self.fields.insert(field.name().to_string(), LogValue::Int(value));
}
fn record_u64(&mut self, field: &Field, value: u64) {
if value <= i64::MAX as u64 {
self.fields.insert(field.name().to_string(), LogValue::Int(value as i64));
} else {
self.fields.insert(field.name().to_string(), LogValue::String(value.to_string()));
}
}
fn record_f64(&mut self, field: &Field, value: f64) {
self.fields.insert(field.name().to_string(), LogValue::Float(value));
}
fn record_bool(&mut self, field: &Field, value: bool) {
self.fields.insert(field.name().to_string(), LogValue::Bool(value));
}
}