From ddec5d00a4b9f07d2d4c8caaa267f42886ec0ff0 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Thu, 19 Dec 2019 10:42:38 -0500 Subject: [PATCH] WIP json --- examples/examples/futures-spawn.rs | 1 + tracing-subscriber/Cargo.toml | 2 +- tracing-subscriber/src/fmt/format/json.rs | 77 ++++++++++++++--------- 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/examples/examples/futures-spawn.rs b/examples/examples/futures-spawn.rs index 1261f471..40844ff2 100644 --- a/examples/examples/futures-spawn.rs +++ b/examples/examples/futures-spawn.rs @@ -35,6 +35,7 @@ fn main() { use tracing_subscriber::fmt; let subscriber = fmt::Subscriber::builder() .with_max_level(Level::TRACE) + .json() .finish(); let _ = tracing::subscriber::set_global_default(subscriber); tokio::run(parent_task(10)); diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index 807477fd..ee8513cf 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -42,7 +42,7 @@ chrono = { version = "0.4", optional = true } # only required by the json feature serde_json = { version = "1.0", optional = true } -serde = { version = "1.0", optional = true } +serde = { version = "1.0", optional = true, features = ["derive"] } tracing-serde = { version = "0.1.0", optional = true } # opt-in deps diff --git a/tracing-subscriber/src/fmt/format/json.rs b/tracing-subscriber/src/fmt/format/json.rs index f3a61f33..9b82a8d6 100644 --- a/tracing-subscriber/src/fmt/format/json.rs +++ b/tracing-subscriber/src/fmt/format/json.rs @@ -5,8 +5,11 @@ use crate::{ fmt::fmt_layer::FormattedFields, registry::{LookupMetadata, LookupSpan}, }; -use serde::ser::{SerializeMap, Serializer as _}; -use serde_json::Serializer; +use serde::{ + ser::{SerializeMap, Serializer as _}, + Serialize, +}; +use serde_json::{Serializer, Value}; use std::{ collections::BTreeMap, fmt::{self, Write}, @@ -16,7 +19,7 @@ use tracing_core::{ field::{self, Field}, Event, Subscriber, }; -use tracing_serde::AsSerde; +use tracing_serde::fields::SerializeFieldMap; #[cfg(feature = "tracing-log")] use tracing_log::NormalizeEvent; @@ -27,6 +30,15 @@ use tracing_log::NormalizeEvent; #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] pub struct Json; +#[derive(Serialize, Default)] +struct SerializedEvent<'a> { + timestamp: Option<&'a str>, + level: Option, + target: Option<&'a str>, + fields: Option<&'a SerializeFieldMap<'a, Event<'a>>>, + parent_spans: Vec, +} + impl FormatEvent for Format where S: Subscriber + for<'lookup> LookupSpan<'lookup> + LookupMetadata, @@ -42,7 +54,7 @@ where where S: Subscriber + for<'a> LookupSpan<'a> + LookupMetadata, { - use serde_json::{json, Value}; + use serde_json::json; use tracing_serde::fields::AsMap; let mut timestamp = String::new(); self.timer.format_time(&mut timestamp)?; @@ -55,40 +67,45 @@ where let meta = event.metadata(); let mut visit = || { - let mut serializer = Serializer::new(WriteAdaptor::new(writer)); - let mut serializer = serializer.serialize_map(None)?; + let ctx = &ctx.ctx; - serializer.serialize_entry("timestamp", ×tamp)?; - serializer.serialize_entry("level", &meta.level().as_serde())?; + let mut serialized_event = SerializedEvent::default(); - let id = ctx.ctx.current_span(); - let id = id.id(); - if let Some(id) = id { - if let Some(span) = ctx.ctx.span(id) { - let ext = span.extensions(); - let data = ext - .get::>() - .expect("Unable to find FormattedFields in extensions; this is a bug"); - // TODO: let's _not_ do this, but this resolves - // https://github.com/tokio-rs/tracing/issues/391. - // We should probably rework this to use a `serde_json::Value` or something - // similar in a JSON-specific layer, but I'd (david) - // rather have a uglier fix now rather than shipping broken JSON. - let mut fields: Value = serde_json::from_str(&data)?; - fields["name"] = json!(span.metadata().name()); - serializer.serialize_entry("span", &fields).unwrap_or(()); - } + for span in ctx.scope() { + let id = span.id(); + let span = ctx + .span(&id) + .expect(&format!("Missing span for id: {:?}", id)); + + let ext = span.extensions(); + let data = ext + .get::>() + .expect("Unable to find FormattedFields in extensions; this is a bug"); + // TODO: let's _not_ do this, but this resolves + // https://github.com/tokio-rs/tracing/issues/391. + // We should probably rework this to use a `serde_json::Value` or something + // similar in a JSON-specific layer, but I'd (david) + // rather have a uglier fix now rather than shipping broken JSON. + let mut fields: Value = match serde_json::from_str(&data) { + Ok(fields) => fields, + Err(_) => return, + }; + fields["name"] = json!(span.metadata().name()); + serialized_event.parent_spans.push(fields); } + serialized_event.timestamp = Some(×tamp); + serialized_event.level = Some(meta.level().to_string()); if self.display_target { - serializer.serialize_entry("target", meta.target())?; + serialized_event.target = Some(meta.target()); } - serializer.serialize_entry("fields", &event.field_map())?; - serializer.end() + let map = &event.field_map(); + serialized_event.fields = Some(map); + serde_json::to_writer(WriteAdaptor::new(writer), &serialized_event).unwrap(); }; - visit().map_err(|_| fmt::Error)?; + visit(); writeln!(writer) } } @@ -174,7 +191,7 @@ impl<'a> crate::field::VisitOutput for JsonVisitor<'a> { ser_map.serialize_entry(k, &v)?; } - ser_map.end() + SerializeMap::end(ser_map) }; if inner().is_err() {