use super::JsonVisitor;
use crate::JsonExtension;
use chrono::Local;
use serde_json::{json, Value};
use std::{collections::BTreeMap, process};
use tracing::{Event, Metadata};
use tracing_subscriber::registry::{LookupSpan, SpanRef};
pub fn json<S: for<'l> LookupSpan<'l>>(event: &Event, metadata: &Metadata, spans: Vec<SpanRef<'_, S>>) -> String {
let now = Local::now();
let thread = std::thread::current();
let pid = process::id();
let mut tree = BTreeMap::new();
let mut visitor = JsonVisitor(&mut tree);
event.record(&mut visitor);
let message = tree
.remove("message")
.unwrap_or(Value::String(String::from("<none provided>")));
let mut spans_as_json: Vec<Value> = vec![];
for span in spans.iter() {
let ext = span.extensions();
let storage = ext.get::<JsonExtension>().unwrap();
let data = &storage.0;
spans_as_json.push(json!({
"fields": match data.is_empty() {
true => None,
false => Some(data)
},
"target": span.metadata().target(),
"level": metadata.level().as_str().to_lowercase(),
"name": span.metadata().name(),
"meta": json!({
"module": span.metadata().module_path(),
"file": span.metadata().file(),
"line": span.metadata().line(),
})
}));
}
serde_json::to_string(&json!({
"@timestamp": now.to_rfc3339(),
"message": message,
"metadata.module": metadata.module_path(),
"metadata.file": metadata.file(),
"metadata.line": metadata.line(),
"thread.name": thread.name().unwrap_or("main"),
"process.id": pid,
"spans": spans_as_json,
"fields": match tree.is_empty() {
true => None,
false => Some(tree),
}
}))
.unwrap()
}