From 19b5314a8956410c409b651ebf3d20edd0b486cf Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Wed, 9 Oct 2019 17:54:34 +0200 Subject: [PATCH 01/30] WIP: JSON formatter --- tracing-subscriber/Cargo.toml | 3 + tracing-subscriber/src/fmt/format.rs | 117 ++++++++++++++++++++++++++- tracing-subscriber/src/fmt/mod.rs | 17 ++++ 3 files changed, 136 insertions(+), 1 deletion(-) diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index ff8591269f..e550018451 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -25,12 +25,14 @@ env-filter = ["matchers", "regex", "lazy_static"] fmt = ["owning_ref"] ansi = ["fmt", "ansi_term"] registry_unstable = [] +json = ["tracing-serde", "serde_json"] # Alias for `env-filter`; renamed in version 0.1.2, and will be removed in 0.2. filter = ["env-filter"] [dependencies] tracing-core = "0.1.2" +tracing-serde = { path = "../tracing-serde", optional = true } # only required by the filter feature matchers = { optional = true, version = "0.0.1" } @@ -43,6 +45,7 @@ tracing-log = { version = "0.1", optional = true, default-features = false } ansi_term = { version = "0.11", optional = true } owning_ref = { version = "0.4.0", optional = true } chrono = { version = "0.4", optional = true } +serde_json = { version = "1.0", optional = true } # opt-in deps parking_lot = { version = ">= 0.7, < 0.10", features = ["owning_ref"], optional = true } diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index 555b15dcfd..d5cf5590c5 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -2,18 +2,26 @@ use super::span; use super::time::{self, FormatTime, SystemTime}; use crate::field::{MakeOutput, MakeVisitor, RecordFields, VisitFmt, VisitOutput}; + use std::fmt::{self, Write}; use std::marker::PhantomData; use tracing_core::{ field::{self, Field, Visit}, Event, Level, }; + #[cfg(feature = "tracing-log")] use tracing_log::NormalizeEvent; +#[cfg(feature = "json")] +use tracing_serde::AsSerde; + #[cfg(feature = "ansi")] use ansi_term::{Colour, Style}; +#[cfg(feature = "json")] +use serde_json::{json, Value}; + /// A type that can format a tracing `Event` for a `fmt::Write`. /// /// `FormatEvent` is primarily used in the context of [`FmtSubscriber`]. Each time an event is @@ -102,6 +110,13 @@ pub struct Compact; #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] pub struct Full; +/// Marker for `Format` that indicates that the verbose json log format should be used. +/// +/// The full format includes fields from all entered spans. +#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] +#[cfg(feature = "json")] +pub struct Json; + /// A pre-configured event formatter. /// /// You will usually want to use this as the `FormatEvent` for a `FmtSubscriber`. @@ -141,6 +156,19 @@ impl Format { } } + /// Use the full JSON format. + /// + /// See [`Json`]. + #[cfg(feature = "json")] + pub fn json(self) -> Format { + Format { + format: PhantomData, + timer: self.timer, + ansi: self.ansi, + display_target: self.display_target, + } + } + /// Use the given [`timer`] for log message timestamps. /// /// See [`time`] for the provided timer implementations. @@ -290,8 +318,41 @@ where } } -// === impl FormatFields === +#[cfg(feature = "json")] +impl FormatEvent for Format +where + N: for<'writer> FormatFields<'writer>, + T: FormatTime, +{ + fn format_event( + &self, + ctx: &span::Context<'_, N>, + writer: &mut dyn fmt::Write, + event: &Event<'_>, + ) -> fmt::Result { + let mut timestamp = String::new(); + self.timer.format_time(&mut timestamp)?; + + let mut log_data = json!({ + "timestamp": timestamp.trim(), + "event": event.as_serde(), + }); + + { + let log_data = log_data.as_object_mut().unwrap(); + + ctx.with_current(|(_, span)| { + log_data.insert(String::from("span"), Value::from(span.name())); + log_data.insert(String::from("fields"), Value::from(span.fields())); + }); + } + + write!(writer, "{}", serde_json::to_string(&log_data).unwrap())?; + writeln!(writer) + } +} +// === impl FormatFields === impl<'writer, M> FormatFields<'writer> for M where M: MakeOutput<&'writer mut dyn fmt::Write, fmt::Result>, @@ -687,6 +748,9 @@ mod test { use std::fmt; use std::sync::Mutex; + #[cfg(feature = "json")] + use serde_json::{json, Value}; + struct MockTime; impl FormatTime for MockTime { fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result { @@ -741,6 +805,38 @@ mod test { assert_eq!(expected, actual.as_str()); } + #[cfg(feature = "json")] + #[test] + fn json() { + lazy_static! { + static ref BUF: Mutex> = Mutex::new(vec![]); + } + + let make_writer = || MockWriter::new(&BUF); + + let expected = json!({ + "event": { + "message": "some json test", + "metadata": { + "fields": [ + "message" + ], + "file": "tracing-subscriber/src/fmt/format.rs", + "is_event": true, + "is_span": false, + "level": "INFO", + "line": 861, + "module_path": "tracing_subscriber::fmt::format::test", + "name": "event tracing-subscriber/src/fmt/format.rs:861", + "target": "tracing_subscriber::fmt::format::test" + }, + }, + "timestamp": "fake time", + }); + + test_json(make_writer, &expected, &BUF); + } + #[cfg(feature = "ansi")] fn test_ansi(make_writer: T, expected: &str, is_ansi: bool, buf: &Mutex>) where @@ -759,4 +855,23 @@ mod test { let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap(); assert_eq!(expected, actual.as_str()); } + + #[cfg(feature = "json")] + fn test_json(make_writer: T, expected: &Value, buf: &Mutex>) + where + T: crate::fmt::MakeWriter + Send + Sync + 'static, + { + let subscriber = crate::fmt::Subscriber::builder() + .json() + .with_writer(make_writer) + .with_timer(MockTime) + .finish(); + + with_default(subscriber, || { + tracing::info!("some json test"); + }); + + let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap(); + assert_eq!(&format!("{}\n", expected), actual.as_str()); + } } diff --git a/tracing-subscriber/src/fmt/mod.rs b/tracing-subscriber/src/fmt/mod.rs index 5f84487e33..5aac66bcf6 100644 --- a/tracing-subscriber/src/fmt/mod.rs +++ b/tracing-subscriber/src/fmt/mod.rs @@ -744,6 +744,23 @@ impl Builder { } } + /// Sets the subscriber being built to use a JSON formatter. + /// + /// See [`format::Json`] + #[cfg(feature = "json")] + pub fn json(self) -> Builder, F, W> + where + N: for<'writer> FormatFields<'writer> + 'static, + { + Builder { + fmt_event: format::Format::default().json(), + filter: self.filter, + fmt_fields: self.fmt_fields, + settings: self.settings, + make_writer: self.make_writer, + } + } + /// Sets the function that the subscriber being built should use to format /// events that occur. pub fn on_event(self, fmt_event: E2) -> Builder From de8e9317769adb1acccdb08e2b04270ee8355aed Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 14:16:07 +0200 Subject: [PATCH 02/30] Implement JSON formatting using SerdeMapVisitor --- tracing-serde/src/lib.rs | 50 ++++++++++++--- tracing-subscriber/Cargo.toml | 3 +- tracing-subscriber/src/fmt/format.rs | 91 +++++++++++++++------------- 3 files changed, 94 insertions(+), 50 deletions(-) diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index d91b0cb738..6320f6cd87 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -1,7 +1,7 @@ extern crate serde; extern crate tracing_core; -use std::fmt; +use std::{fmt, io}; use serde::{ ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer}, @@ -15,6 +15,33 @@ use tracing_core::{ span::{Attributes, Id, Record}, }; +/// A bridge between `fmt::Write` and `io::Write`. +pub struct WriteAdaptor<'a> { + fmt_write: &'a mut dyn fmt::Write, +} + +impl<'a> WriteAdaptor<'a> { + pub fn new(fmt_write: &'a mut dyn fmt::Write) -> Self { + Self { fmt_write, } + } +} + +impl<'a> io::Write for WriteAdaptor<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + let s = String::from_utf8_lossy(buf); + + self.fmt_write.write_str(&s).map_err(|e| { + io::Error::new(io::ErrorKind::Other, e) + })?; + + Ok(s.as_bytes().len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + #[derive(Debug)] pub struct SerializeField(Field); @@ -156,20 +183,29 @@ impl<'a> Serialize for SerializeRecord<'a> { S: Serializer, { let serializer = serializer.serialize_map(None)?; - let mut visitor = SerdeMapVisitor { - serializer, - state: Ok(()), - }; + let mut visitor = SerdeMapVisitor::new(serializer, Ok(())); self.0.record(&mut visitor); visitor.finish() } } -struct SerdeMapVisitor { +pub struct SerdeMapVisitor { serializer: S, state: Result<(), S::Error>, } +impl SerdeMapVisitor +where + S: SerializeMap, +{ + pub fn new(serializer: S, state: Result<(), S::Error>) -> Self { + Self { + serializer, + state, + } + } +} + impl Visit for SerdeMapVisitor where S: SerializeMap, @@ -213,7 +249,7 @@ impl SerdeMapVisitor { /// Completes serializing the visited object, returning `Ok(())` if all /// fields were serialized correctly, or `Error(S::Error)` if a field could /// not be serialized. - fn finish(self) -> Result { + pub fn finish(self) -> Result { self.state?; self.serializer.end() } diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index e550018451..4f9f19765d 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -25,7 +25,7 @@ env-filter = ["matchers", "regex", "lazy_static"] fmt = ["owning_ref"] ansi = ["fmt", "ansi_term"] registry_unstable = [] -json = ["tracing-serde", "serde_json"] +json = ["tracing-serde", "serde", "serde_json"] # Alias for `env-filter`; renamed in version 0.1.2, and will be removed in 0.2. filter = ["env-filter"] @@ -46,6 +46,7 @@ ansi_term = { version = "0.11", optional = true } owning_ref = { version = "0.4.0", optional = true } chrono = { version = "0.4", optional = true } serde_json = { version = "1.0", optional = true } +serde = { version = "1.0", optional = true } # opt-in deps parking_lot = { version = ">= 0.7, < 0.10", features = ["owning_ref"], optional = true } diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index d5cf5590c5..dfc4c8ce16 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -13,14 +13,15 @@ use tracing_core::{ #[cfg(feature = "tracing-log")] use tracing_log::NormalizeEvent; -#[cfg(feature = "json")] -use tracing_serde::AsSerde; - #[cfg(feature = "ansi")] use ansi_term::{Colour, Style}; #[cfg(feature = "json")] -use serde_json::{json, Value}; +use tracing_serde::{WriteAdaptor, SerdeMapVisitor}; +#[cfg(feature = "json")] +use serde_json::Serializer; +#[cfg(feature = "json")] +use serde::ser::{Serializer as _, SerializeMap}; /// A type that can format a tracing `Event` for a `fmt::Write`. /// @@ -333,22 +334,48 @@ where let mut timestamp = String::new(); self.timer.format_time(&mut timestamp)?; - let mut log_data = json!({ - "timestamp": timestamp.trim(), - "event": event.as_serde(), - }); + #[cfg(feature = "tracing-log")] + let normalized_meta = event.normalized_metadata(); + #[cfg(feature = "tracing-log")] + let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); + #[cfg(not(feature = "tracing-log"))] + let meta = event.metadata(); + + let fmt_ctx = { + #[cfg(feature = "ansi")] + { + FmtCtx::new(&ctx, false) + } + #[cfg(not(feature = "ansi"))] + { + FmtCtx::new(&ctx) + } + }; - { - let log_data = log_data.as_object_mut().unwrap(); + let mut serializer = Serializer::new(WriteAdaptor::new(writer)); - ctx.with_current(|(_, span)| { - log_data.insert(String::from("span"), Value::from(span.name())); - log_data.insert(String::from("fields"), Value::from(span.fields())); - }); - } + let mut visit = || { + let mut serializer = serializer.serialize_map(None)?; - write!(writer, "{}", serde_json::to_string(&log_data).unwrap())?; - writeln!(writer) + serializer.serialize_key("timestamp")?; + serializer.serialize_value(timestamp.trim())?; + serializer.serialize_key("level")?; + serializer.serialize_value(&format!("{}", meta.level()))?; + serializer.serialize_key("context")?; + serializer.serialize_value(&format!("{}", fmt_ctx))?; + + if self.display_target { + serializer.serialize_key("target")?; + serializer.serialize_value(&format!("{}", meta.target()))?; + } + + let mut visitor = SerdeMapVisitor::new(serializer, Ok(())); + event.record(&mut visitor); + + visitor.finish() + }; + + visit().map_err(|_| fmt::Error) } } @@ -748,9 +775,6 @@ mod test { use std::fmt; use std::sync::Mutex; - #[cfg(feature = "json")] - use serde_json::{json, Value}; - struct MockTime; impl FormatTime for MockTime { fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result { @@ -814,27 +838,10 @@ mod test { let make_writer = || MockWriter::new(&BUF); - let expected = json!({ - "event": { - "message": "some json test", - "metadata": { - "fields": [ - "message" - ], - "file": "tracing-subscriber/src/fmt/format.rs", - "is_event": true, - "is_span": false, - "level": "INFO", - "line": 861, - "module_path": "tracing_subscriber::fmt::format::test", - "name": "event tracing-subscriber/src/fmt/format.rs:861", - "target": "tracing_subscriber::fmt::format::test" - }, - }, - "timestamp": "fake time", - }); + let expected = + "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"context\":\"\",\"target\":\"tracing_subscriber::fmt::format::test\",\"message\":\"some json test\"}"; - test_json(make_writer, &expected, &BUF); + test_json(make_writer, expected, &BUF); } #[cfg(feature = "ansi")] @@ -857,7 +864,7 @@ mod test { } #[cfg(feature = "json")] - fn test_json(make_writer: T, expected: &Value, buf: &Mutex>) + fn test_json(make_writer: T, expected: &str, buf: &Mutex>) where T: crate::fmt::MakeWriter + Send + Sync + 'static, { @@ -872,6 +879,6 @@ mod test { }); let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap(); - assert_eq!(&format!("{}\n", expected), actual.as_str()); + assert_eq!(expected, actual.as_str()); } } From 2857e3f166dc4a70e34e59ac8ebd77798dae847e Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 14:32:12 +0200 Subject: [PATCH 03/30] Better span handling --- tracing-subscriber/src/fmt/format.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index dfc4c8ce16..206c5f9fd4 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -341,17 +341,6 @@ where #[cfg(not(feature = "tracing-log"))] let meta = event.metadata(); - let fmt_ctx = { - #[cfg(feature = "ansi")] - { - FmtCtx::new(&ctx, false) - } - #[cfg(not(feature = "ansi"))] - { - FmtCtx::new(&ctx) - } - }; - let mut serializer = Serializer::new(WriteAdaptor::new(writer)); let mut visit = || { @@ -361,8 +350,12 @@ where serializer.serialize_value(timestamp.trim())?; serializer.serialize_key("level")?; serializer.serialize_value(&format!("{}", meta.level()))?; - serializer.serialize_key("context")?; - serializer.serialize_value(&format!("{}", fmt_ctx))?; + + ctx.with_current(|(_, span)| { + serializer + .serialize_key("span") + .and_then(|_| serializer.serialize_value(span.name())) + }).unwrap_or(Ok(()))?; if self.display_target { serializer.serialize_key("target")?; @@ -839,7 +832,7 @@ mod test { let make_writer = || MockWriter::new(&BUF); let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"context\":\"\",\"target\":\"tracing_subscriber::fmt::format::test\",\"message\":\"some json test\"}"; + "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"target\":\"tracing_subscriber::fmt::format::test\",\"message\":\"some json test\"}"; test_json(make_writer, expected, &BUF); } From c6950278250ad76bf8a9f8c66c9e36dac4625c10 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 14:36:01 +0200 Subject: [PATCH 04/30] fmt --- tracing-subscriber/src/fmt/format.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index 206c5f9fd4..a0d3823e47 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -17,11 +17,11 @@ use tracing_log::NormalizeEvent; use ansi_term::{Colour, Style}; #[cfg(feature = "json")] -use tracing_serde::{WriteAdaptor, SerdeMapVisitor}; +use serde::ser::{SerializeMap, Serializer as _}; #[cfg(feature = "json")] use serde_json::Serializer; #[cfg(feature = "json")] -use serde::ser::{Serializer as _, SerializeMap}; +use tracing_serde::{SerdeMapVisitor, WriteAdaptor}; /// A type that can format a tracing `Event` for a `fmt::Write`. /// @@ -355,7 +355,8 @@ where serializer .serialize_key("span") .and_then(|_| serializer.serialize_value(span.name())) - }).unwrap_or(Ok(()))?; + }) + .unwrap_or(Ok(()))?; if self.display_target { serializer.serialize_key("target")?; From 72615d3413bae8f425c5ab64fd7abf9ee3b25a5a Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 15:06:36 +0200 Subject: [PATCH 05/30] fmt --- tracing-serde/src/lib.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index 6320f6cd87..9bb36ba110 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -22,7 +22,7 @@ pub struct WriteAdaptor<'a> { impl<'a> WriteAdaptor<'a> { pub fn new(fmt_write: &'a mut dyn fmt::Write) -> Self { - Self { fmt_write, } + Self { fmt_write } } } @@ -30,9 +30,9 @@ impl<'a> io::Write for WriteAdaptor<'a> { fn write(&mut self, buf: &[u8]) -> io::Result { let s = String::from_utf8_lossy(buf); - self.fmt_write.write_str(&s).map_err(|e| { - io::Error::new(io::ErrorKind::Other, e) - })?; + self.fmt_write + .write_str(&s) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; Ok(s.as_bytes().len()) } @@ -199,10 +199,7 @@ where S: SerializeMap, { pub fn new(serializer: S, state: Result<(), S::Error>) -> Self { - Self { - serializer, - state, - } + Self { serializer, state } } } From f00b0c63bf7c8739ae76e94dbca46dfbcce1231d Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 15:23:22 +0200 Subject: [PATCH 06/30] Add newline after json data --- tracing-subscriber/src/fmt/format.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index a0d3823e47..96a1bda9f3 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -341,9 +341,8 @@ where #[cfg(not(feature = "tracing-log"))] let meta = event.metadata(); - let mut serializer = Serializer::new(WriteAdaptor::new(writer)); - let mut visit = || { + let mut serializer = Serializer::new(WriteAdaptor::new(writer)); let mut serializer = serializer.serialize_map(None)?; serializer.serialize_key("timestamp")?; @@ -369,7 +368,8 @@ where visitor.finish() }; - visit().map_err(|_| fmt::Error) + visit().map_err(|_| fmt::Error)?; + writeln!(writer) } } @@ -833,7 +833,7 @@ mod test { let make_writer = || MockWriter::new(&BUF); let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"target\":\"tracing_subscriber::fmt::format::test\",\"message\":\"some json test\"}"; + "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"target\":\"tracing_subscriber::fmt::format::test\",\"message\":\"some json test\"}\n"; test_json(make_writer, expected, &BUF); } From 1272054c5eac0615dcc50e1ccbd66b6b8ab57b4d Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 17:40:19 +0200 Subject: [PATCH 07/30] Disable ANSI feature if enabling JSON --- tracing-subscriber/src/fmt/format.rs | 63 +++++++++++++++------------- tracing-subscriber/src/fmt/mod.rs | 2 +- tracing-subscriber/src/fmt/time.rs | 6 +-- tracing-subscriber/src/fmt/writer.rs | 4 +- 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index 96a1bda9f3..cfd57f7248 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -13,7 +13,7 @@ use tracing_core::{ #[cfg(feature = "tracing-log")] use tracing_log::NormalizeEvent; -#[cfg(feature = "ansi")] +#[cfg(all(feature = "ansi", not(feature = "json")))] use ansi_term::{Colour, Style}; #[cfg(feature = "json")] @@ -129,6 +129,7 @@ pub struct Json; pub struct Format { format: PhantomData, timer: T, + #[cfg(not(feature = "json"))] ansi: bool, display_target: bool, } @@ -138,6 +139,7 @@ impl Default for Format { Format { format: PhantomData, timer: SystemTime, + #[cfg(not(feature = "json"))] ansi: true, display_target: true, } @@ -152,6 +154,7 @@ impl Format { Format { format: PhantomData, timer: self.timer, + #[cfg(not(feature = "json"))] ansi: self.ansi, display_target: self.display_target, } @@ -165,7 +168,6 @@ impl Format { Format { format: PhantomData, timer: self.timer, - ansi: self.ansi, display_target: self.display_target, } } @@ -185,6 +187,7 @@ impl Format { Format { format: self.format, timer, + #[cfg(not(feature = "json"))] ansi: self.ansi, display_target: self.display_target, } @@ -195,12 +198,14 @@ impl Format { Format { format: self.format, timer: (), + #[cfg(not(feature = "json"))] ansi: self.ansi, display_target: self.display_target, } } /// Enable ANSI terminal colors for formatted output. + #[cfg(not(feature = "json"))] pub fn with_ansi(self, ansi: bool) -> Format { Format { ansi, ..self } } @@ -231,20 +236,20 @@ where let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); #[cfg(not(feature = "tracing-log"))] let meta = event.metadata(); - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] time::write(&self.timer, writer, self.ansi)?; - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] time::write(&self.timer, writer)?; let (fmt_level, full_ctx) = { - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] { ( FmtLevel::new(meta.level(), self.ansi), FullCtx::new(&ctx, self.ansi), ) } - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] { (FmtLevel::new(meta.level()), FullCtx::new(&ctx)) } @@ -283,20 +288,20 @@ where let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); #[cfg(not(feature = "tracing-log"))] let meta = event.metadata(); - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] time::write(&self.timer, writer, self.ansi)?; - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] time::write(&self.timer, writer)?; let (fmt_level, fmt_ctx) = { - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] { ( FmtLevel::new(meta.level(), self.ansi), FmtCtx::new(&ctx, self.ansi), ) } - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] { (FmtLevel::new(meta.level()), FmtCtx::new(&ctx)) } @@ -525,23 +530,23 @@ impl<'a> fmt::Debug for DefaultVisitor<'a> { struct FmtCtx<'a, N> { ctx: &'a span::Context<'a, N>, - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] ansi: bool, } impl<'a, N: 'a> FmtCtx<'a, N> { - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] pub(crate) fn new(ctx: &'a span::Context<'a, N>, ansi: bool) -> Self { Self { ctx, ansi } } - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] pub(crate) fn new(ctx: &'a span::Context<'a, N>) -> Self { Self { ctx } } } -#[cfg(feature = "ansi")] +#[cfg(all(feature = "ansi", not(feature = "json")))] impl<'a, N> fmt::Display for FmtCtx<'a, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seen = false; @@ -564,7 +569,7 @@ impl<'a, N> fmt::Display for FmtCtx<'a, N> { } } -#[cfg(not(feature = "ansi"))] +#[cfg(any(not(feature = "ansi"), feature = "json"))] impl<'a, N> fmt::Display for FmtCtx<'a, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seen = false; @@ -584,23 +589,23 @@ impl<'a, N> fmt::Display for FmtCtx<'a, N> { struct FullCtx<'a, N> { ctx: &'a span::Context<'a, N>, - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] ansi: bool, } impl<'a, N: 'a> FullCtx<'a, N> { - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] pub(crate) fn new(ctx: &'a span::Context<'a, N>, ansi: bool) -> Self { Self { ctx, ansi } } - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] pub(crate) fn new(ctx: &'a span::Context<'a, N>) -> Self { Self { ctx } } } -#[cfg(feature = "ansi")] +#[cfg(all(feature = "ansi", not(feature = "json")))] impl<'a, N> fmt::Display for FullCtx<'a, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seen = false; @@ -627,7 +632,7 @@ impl<'a, N> fmt::Display for FullCtx<'a, N> { } } -#[cfg(not(feature = "ansi"))] +#[cfg(any(not(feature = "ansi"), feature = "json"))] impl<'a, N> fmt::Display for FullCtx<'a, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seen = false; @@ -650,23 +655,23 @@ impl<'a, N> fmt::Display for FullCtx<'a, N> { struct FmtLevel<'a> { level: &'a Level, - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] ansi: bool, } impl<'a> FmtLevel<'a> { - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] pub(crate) fn new(level: &'a Level, ansi: bool) -> Self { Self { level, ansi } } - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] pub(crate) fn new(level: &'a Level) -> Self { Self { level } } } -#[cfg(not(feature = "ansi"))] +#[cfg(any(not(feature = "ansi"), feature = "json"))] impl<'a> fmt::Display for FmtLevel<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.level { @@ -679,7 +684,7 @@ impl<'a> fmt::Display for FmtLevel<'a> { } } -#[cfg(feature = "ansi")] +#[cfg(all(feature = "ansi", not(feature = "json")))] impl<'a> fmt::Display for FmtLevel<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.ansi { @@ -776,7 +781,7 @@ mod test { } } - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] #[test] fn with_ansi_true() { lazy_static! { @@ -788,7 +793,7 @@ mod test { test_ansi(make_writer, expected, true, &BUF); } - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] #[test] fn with_ansi_false() { lazy_static! { @@ -801,7 +806,7 @@ mod test { test_ansi(make_writer, expected, false, &BUF); } - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] #[test] fn without_ansi() { lazy_static! { @@ -838,7 +843,7 @@ mod test { test_json(make_writer, expected, &BUF); } - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] fn test_ansi(make_writer: T, expected: &str, is_ansi: bool, buf: &Mutex>) where T: crate::fmt::MakeWriter + Send + Sync + 'static, diff --git a/tracing-subscriber/src/fmt/mod.rs b/tracing-subscriber/src/fmt/mod.rs index 5aac66bcf6..46bc09afc7 100644 --- a/tracing-subscriber/src/fmt/mod.rs +++ b/tracing-subscriber/src/fmt/mod.rs @@ -509,7 +509,7 @@ where } /// Enable ANSI encoding for formatted events. - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] pub fn with_ansi(self, ansi: bool) -> Builder, F, W> { Builder { fmt_event: self.fmt_event.with_ansi(ansi), diff --git a/tracing-subscriber/src/fmt/time.rs b/tracing-subscriber/src/fmt/time.rs index 3f97340a1f..64e7f3420b 100644 --- a/tracing-subscriber/src/fmt/time.rs +++ b/tracing-subscriber/src/fmt/time.rs @@ -3,7 +3,7 @@ #[cfg(feature = "chrono")] use chrono; -#[cfg(feature = "ansi")] +#[cfg(all(feature = "ansi", not(feature = "json")))] use ansi_term::Style; use std::fmt; @@ -206,7 +206,7 @@ impl FormatTime for ChronoLocal { } #[inline(always)] -#[cfg(feature = "ansi")] +#[cfg(all(feature = "ansi", not(feature = "json")))] pub(crate) fn write(timer: T, writer: &mut dyn fmt::Write, with_ansi: bool) -> fmt::Result where T: FormatTime, @@ -224,7 +224,7 @@ where } #[inline(always)] -#[cfg(not(feature = "ansi"))] +#[cfg(any(not(feature = "ansi"), feature = "json"))] pub(crate) fn write(timer: T, writer: &mut dyn fmt::Write) -> fmt::Result where T: FormatTime, diff --git a/tracing-subscriber/src/fmt/writer.rs b/tracing-subscriber/src/fmt/writer.rs index 8633e36094..4cee81a327 100644 --- a/tracing-subscriber/src/fmt/writer.rs +++ b/tracing-subscriber/src/fmt/writer.rs @@ -67,7 +67,7 @@ mod test { T: MakeWriter + Send + Sync + 'static, { let subscriber = { - #[cfg(feature = "ansi")] + #[cfg(all(feature = "ansi", not(feature = "json")))] { Subscriber::builder() .with_writer(make_writer) @@ -75,7 +75,7 @@ mod test { .with_ansi(false) .finish() } - #[cfg(not(feature = "ansi"))] + #[cfg(any(not(feature = "ansi"), feature = "json"))] { Subscriber::builder() .with_writer(make_writer) From 4e1ef66a438ba0c45369827e60cb534e96a73597 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 17:43:25 +0200 Subject: [PATCH 08/30] Add a note why we need the `WriteAdaptor` --- tracing-serde/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index 9bb36ba110..29b8a867ea 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -16,6 +16,9 @@ use tracing_core::{ }; /// A bridge between `fmt::Write` and `io::Write`. +/// +/// This is needed because tracing-subscriber's FormatEvent expects a fmt::Write +/// while serde_json's Serializer expects an io::Write. pub struct WriteAdaptor<'a> { fmt_write: &'a mut dyn fmt::Write, } From cd510969cb5d8a64b0918cb4723f8a3c638a61aa Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 18:07:49 +0200 Subject: [PATCH 09/30] Add a note about the `json` feature flag --- tracing-subscriber/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tracing-subscriber/src/lib.rs b/tracing-subscriber/src/lib.rs index ec3b5c9739..43e8dbc76a 100644 --- a/tracing-subscriber/src/lib.rs +++ b/tracing-subscriber/src/lib.rs @@ -28,6 +28,7 @@ //! - `ansi`: Enables `fmt` support for ANSI terminal colors. Enabled by //! default. //! - `registry_unstable`: enables the experimental [`registry`] module. +//! - `json`: Enables `fmt` support for JSON output. Disables the `ansi` feature. //! //! ### Optional Dependencies //! From 8a148adab440e9a7d8e36cf7c0925e88c2e0aef0 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 18:47:23 +0200 Subject: [PATCH 10/30] Revert "Disable ANSI feature if enabling JSON" This reverts commit 3e4c8d9a10862b8770e2dc0f36b5bb1d46d0e394. --- tracing-subscriber/src/fmt/format.rs | 63 +++++++++++++--------------- tracing-subscriber/src/fmt/mod.rs | 2 +- tracing-subscriber/src/fmt/time.rs | 6 +-- tracing-subscriber/src/fmt/writer.rs | 4 +- 4 files changed, 35 insertions(+), 40 deletions(-) diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index cfd57f7248..96a1bda9f3 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -13,7 +13,7 @@ use tracing_core::{ #[cfg(feature = "tracing-log")] use tracing_log::NormalizeEvent; -#[cfg(all(feature = "ansi", not(feature = "json")))] +#[cfg(feature = "ansi")] use ansi_term::{Colour, Style}; #[cfg(feature = "json")] @@ -129,7 +129,6 @@ pub struct Json; pub struct Format { format: PhantomData, timer: T, - #[cfg(not(feature = "json"))] ansi: bool, display_target: bool, } @@ -139,7 +138,6 @@ impl Default for Format { Format { format: PhantomData, timer: SystemTime, - #[cfg(not(feature = "json"))] ansi: true, display_target: true, } @@ -154,7 +152,6 @@ impl Format { Format { format: PhantomData, timer: self.timer, - #[cfg(not(feature = "json"))] ansi: self.ansi, display_target: self.display_target, } @@ -168,6 +165,7 @@ impl Format { Format { format: PhantomData, timer: self.timer, + ansi: self.ansi, display_target: self.display_target, } } @@ -187,7 +185,6 @@ impl Format { Format { format: self.format, timer, - #[cfg(not(feature = "json"))] ansi: self.ansi, display_target: self.display_target, } @@ -198,14 +195,12 @@ impl Format { Format { format: self.format, timer: (), - #[cfg(not(feature = "json"))] ansi: self.ansi, display_target: self.display_target, } } /// Enable ANSI terminal colors for formatted output. - #[cfg(not(feature = "json"))] pub fn with_ansi(self, ansi: bool) -> Format { Format { ansi, ..self } } @@ -236,20 +231,20 @@ where let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); #[cfg(not(feature = "tracing-log"))] let meta = event.metadata(); - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] time::write(&self.timer, writer, self.ansi)?; - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] time::write(&self.timer, writer)?; let (fmt_level, full_ctx) = { - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] { ( FmtLevel::new(meta.level(), self.ansi), FullCtx::new(&ctx, self.ansi), ) } - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] { (FmtLevel::new(meta.level()), FullCtx::new(&ctx)) } @@ -288,20 +283,20 @@ where let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); #[cfg(not(feature = "tracing-log"))] let meta = event.metadata(); - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] time::write(&self.timer, writer, self.ansi)?; - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] time::write(&self.timer, writer)?; let (fmt_level, fmt_ctx) = { - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] { ( FmtLevel::new(meta.level(), self.ansi), FmtCtx::new(&ctx, self.ansi), ) } - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] { (FmtLevel::new(meta.level()), FmtCtx::new(&ctx)) } @@ -530,23 +525,23 @@ impl<'a> fmt::Debug for DefaultVisitor<'a> { struct FmtCtx<'a, N> { ctx: &'a span::Context<'a, N>, - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] ansi: bool, } impl<'a, N: 'a> FmtCtx<'a, N> { - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] pub(crate) fn new(ctx: &'a span::Context<'a, N>, ansi: bool) -> Self { Self { ctx, ansi } } - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] pub(crate) fn new(ctx: &'a span::Context<'a, N>) -> Self { Self { ctx } } } -#[cfg(all(feature = "ansi", not(feature = "json")))] +#[cfg(feature = "ansi")] impl<'a, N> fmt::Display for FmtCtx<'a, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seen = false; @@ -569,7 +564,7 @@ impl<'a, N> fmt::Display for FmtCtx<'a, N> { } } -#[cfg(any(not(feature = "ansi"), feature = "json"))] +#[cfg(not(feature = "ansi"))] impl<'a, N> fmt::Display for FmtCtx<'a, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seen = false; @@ -589,23 +584,23 @@ impl<'a, N> fmt::Display for FmtCtx<'a, N> { struct FullCtx<'a, N> { ctx: &'a span::Context<'a, N>, - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] ansi: bool, } impl<'a, N: 'a> FullCtx<'a, N> { - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] pub(crate) fn new(ctx: &'a span::Context<'a, N>, ansi: bool) -> Self { Self { ctx, ansi } } - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] pub(crate) fn new(ctx: &'a span::Context<'a, N>) -> Self { Self { ctx } } } -#[cfg(all(feature = "ansi", not(feature = "json")))] +#[cfg(feature = "ansi")] impl<'a, N> fmt::Display for FullCtx<'a, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seen = false; @@ -632,7 +627,7 @@ impl<'a, N> fmt::Display for FullCtx<'a, N> { } } -#[cfg(any(not(feature = "ansi"), feature = "json"))] +#[cfg(not(feature = "ansi"))] impl<'a, N> fmt::Display for FullCtx<'a, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seen = false; @@ -655,23 +650,23 @@ impl<'a, N> fmt::Display for FullCtx<'a, N> { struct FmtLevel<'a> { level: &'a Level, - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] ansi: bool, } impl<'a> FmtLevel<'a> { - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] pub(crate) fn new(level: &'a Level, ansi: bool) -> Self { Self { level, ansi } } - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] pub(crate) fn new(level: &'a Level) -> Self { Self { level } } } -#[cfg(any(not(feature = "ansi"), feature = "json"))] +#[cfg(not(feature = "ansi"))] impl<'a> fmt::Display for FmtLevel<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.level { @@ -684,7 +679,7 @@ impl<'a> fmt::Display for FmtLevel<'a> { } } -#[cfg(all(feature = "ansi", not(feature = "json")))] +#[cfg(feature = "ansi")] impl<'a> fmt::Display for FmtLevel<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.ansi { @@ -781,7 +776,7 @@ mod test { } } - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] #[test] fn with_ansi_true() { lazy_static! { @@ -793,7 +788,7 @@ mod test { test_ansi(make_writer, expected, true, &BUF); } - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] #[test] fn with_ansi_false() { lazy_static! { @@ -806,7 +801,7 @@ mod test { test_ansi(make_writer, expected, false, &BUF); } - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] #[test] fn without_ansi() { lazy_static! { @@ -843,7 +838,7 @@ mod test { test_json(make_writer, expected, &BUF); } - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] fn test_ansi(make_writer: T, expected: &str, is_ansi: bool, buf: &Mutex>) where T: crate::fmt::MakeWriter + Send + Sync + 'static, diff --git a/tracing-subscriber/src/fmt/mod.rs b/tracing-subscriber/src/fmt/mod.rs index 46bc09afc7..5aac66bcf6 100644 --- a/tracing-subscriber/src/fmt/mod.rs +++ b/tracing-subscriber/src/fmt/mod.rs @@ -509,7 +509,7 @@ where } /// Enable ANSI encoding for formatted events. - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] pub fn with_ansi(self, ansi: bool) -> Builder, F, W> { Builder { fmt_event: self.fmt_event.with_ansi(ansi), diff --git a/tracing-subscriber/src/fmt/time.rs b/tracing-subscriber/src/fmt/time.rs index 64e7f3420b..3f97340a1f 100644 --- a/tracing-subscriber/src/fmt/time.rs +++ b/tracing-subscriber/src/fmt/time.rs @@ -3,7 +3,7 @@ #[cfg(feature = "chrono")] use chrono; -#[cfg(all(feature = "ansi", not(feature = "json")))] +#[cfg(feature = "ansi")] use ansi_term::Style; use std::fmt; @@ -206,7 +206,7 @@ impl FormatTime for ChronoLocal { } #[inline(always)] -#[cfg(all(feature = "ansi", not(feature = "json")))] +#[cfg(feature = "ansi")] pub(crate) fn write(timer: T, writer: &mut dyn fmt::Write, with_ansi: bool) -> fmt::Result where T: FormatTime, @@ -224,7 +224,7 @@ where } #[inline(always)] -#[cfg(any(not(feature = "ansi"), feature = "json"))] +#[cfg(not(feature = "ansi"))] pub(crate) fn write(timer: T, writer: &mut dyn fmt::Write) -> fmt::Result where T: FormatTime, diff --git a/tracing-subscriber/src/fmt/writer.rs b/tracing-subscriber/src/fmt/writer.rs index 4cee81a327..8633e36094 100644 --- a/tracing-subscriber/src/fmt/writer.rs +++ b/tracing-subscriber/src/fmt/writer.rs @@ -67,7 +67,7 @@ mod test { T: MakeWriter + Send + Sync + 'static, { let subscriber = { - #[cfg(all(feature = "ansi", not(feature = "json")))] + #[cfg(feature = "ansi")] { Subscriber::builder() .with_writer(make_writer) @@ -75,7 +75,7 @@ mod test { .with_ansi(false) .finish() } - #[cfg(any(not(feature = "ansi"), feature = "json"))] + #[cfg(not(feature = "ansi"))] { Subscriber::builder() .with_writer(make_writer) From 522b963c7ad646ed69a0f824e6259f043e492444 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Thu, 10 Oct 2019 18:48:20 +0200 Subject: [PATCH 11/30] Add note how ansi doesn't work with json --- tracing-subscriber/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-subscriber/src/lib.rs b/tracing-subscriber/src/lib.rs index 43e8dbc76a..2d8e8dec81 100644 --- a/tracing-subscriber/src/lib.rs +++ b/tracing-subscriber/src/lib.rs @@ -28,7 +28,7 @@ //! - `ansi`: Enables `fmt` support for ANSI terminal colors. Enabled by //! default. //! - `registry_unstable`: enables the experimental [`registry`] module. -//! - `json`: Enables `fmt` support for JSON output. Disables the `ansi` feature. +//! - `json`: Enables `fmt` support for JSON output. In JSON output the ANSI feature does nothing. //! //! ### Optional Dependencies //! From f652a1bd949e79e58f37668f2e8510dd95e79760 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Fri, 11 Oct 2019 10:40:48 +0200 Subject: [PATCH 12/30] AsSerde for Level, no extra trim, less allocations --- tracing-serde/src/lib.rs | 10 ++++++++++ tracing-subscriber/src/fmt/format.rs | 19 ++++++------------- tracing-subscriber/src/fmt/time.rs | 7 ++++--- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index 29b8a867ea..e1737151e9 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -356,12 +356,22 @@ impl<'a> AsSerde<'a> for tracing_core::span::Record<'a> { } } +impl<'a> AsSerde<'a> for tracing_core::metadata::Level { + type Serializable = SerializeLevel<'a>; + + fn as_serde(&'a self) -> Self::Serializable { + SerializeLevel(self) + } +} + impl<'a> self::sealed::Sealed for Event<'a> {} impl<'a> self::sealed::Sealed for Attributes<'a> {} impl self::sealed::Sealed for Id {} +impl self::sealed::Sealed for Level {} + impl<'a> self::sealed::Sealed for Record<'a> {} impl<'a> self::sealed::Sealed for Metadata<'a> {} diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index 96a1bda9f3..8323d71181 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -21,7 +21,7 @@ use serde::ser::{SerializeMap, Serializer as _}; #[cfg(feature = "json")] use serde_json::Serializer; #[cfg(feature = "json")] -use tracing_serde::{SerdeMapVisitor, WriteAdaptor}; +use tracing_serde::{AsSerde, SerdeMapVisitor, WriteAdaptor}; /// A type that can format a tracing `Event` for a `fmt::Write`. /// @@ -345,21 +345,14 @@ where let mut serializer = Serializer::new(WriteAdaptor::new(writer)); let mut serializer = serializer.serialize_map(None)?; - serializer.serialize_key("timestamp")?; - serializer.serialize_value(timestamp.trim())?; - serializer.serialize_key("level")?; - serializer.serialize_value(&format!("{}", meta.level()))?; + serializer.serialize_entry("timestamp", ×tamp)?; + serializer.serialize_entry("level", &meta.level().as_serde())?; - ctx.with_current(|(_, span)| { - serializer - .serialize_key("span") - .and_then(|_| serializer.serialize_value(span.name())) - }) - .unwrap_or(Ok(()))?; + ctx.with_current(|(_, span)| serializer.serialize_entry("span", span.name())) + .unwrap_or(Ok(()))?; if self.display_target { - serializer.serialize_key("target")?; - serializer.serialize_value(&format!("{}", meta.target()))?; + serializer.serialize_entry("target", meta.target())?; } let mut visitor = SerdeMapVisitor::new(serializer, Ok(())); diff --git a/tracing-subscriber/src/fmt/time.rs b/tracing-subscriber/src/fmt/time.rs index 3f97340a1f..acc7496756 100644 --- a/tracing-subscriber/src/fmt/time.rs +++ b/tracing-subscriber/src/fmt/time.rs @@ -83,20 +83,21 @@ impl From for Uptime { #[cfg(feature = "chrono")] impl FormatTime for SystemTime { fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result { - write!(w, "{} ", chrono::Local::now().format("%b %d %H:%M:%S%.3f")) + write!(w, "{}", chrono::Local::now().format("%b %d %H:%M:%S%.3f")) } } + #[cfg(not(feature = "chrono"))] impl FormatTime for SystemTime { fn format_time(&self, w: &mut fmt::Write) -> fmt::Result { - write!(w, "{:?} ", std::time::SystemTime::now()) + write!(w, "{:?}", std::time::SystemTime::now()) } } impl FormatTime for Uptime { fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result { let e = self.epoch.elapsed(); - write!(w, "{:4}.{:09}s ", e.as_secs(), e.subsec_nanos()) + write!(w, "{:4}.{:09}s", e.as_secs(), e.subsec_nanos()) } } From b25bdaff7eca6ab10c0368d8f32824af73ea6de5 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Fri, 11 Oct 2019 10:49:39 +0200 Subject: [PATCH 13/30] Use a shorter path --- tracing-serde/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index e1737151e9..fd307aa8f2 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -356,7 +356,7 @@ impl<'a> AsSerde<'a> for tracing_core::span::Record<'a> { } } -impl<'a> AsSerde<'a> for tracing_core::metadata::Level { +impl<'a> AsSerde<'a> for Level { type Serializable = SerializeLevel<'a>; fn as_serde(&'a self) -> Self::Serializable { From cb37cc64eb4e09612cc0f325f18ea91a768c7f37 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Fri, 11 Oct 2019 18:17:23 +0200 Subject: [PATCH 14/30] Add json logging to the proxy_server example --- nightly-examples/Cargo.toml | 3 +- nightly-examples/examples/proxy_server.rs | 70 ++++++++++++++++++----- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/nightly-examples/Cargo.toml b/nightly-examples/Cargo.toml index ec14eaab6a..ee4f6e4fb8 100644 --- a/nightly-examples/Cargo.toml +++ b/nightly-examples/Cargo.toml @@ -13,8 +13,9 @@ edition = "2018" [dev-dependencies] tracing = "0.1" -tracing-subscriber = { version = "0.1", path = "../tracing-subscriber" } +tracing-subscriber = { version = "0.1", path = "../tracing-subscriber", features = ["json"] } tracing-futures = { path = "../tracing-futures", default-features = false, features = ["std-future"] } tokio = { git = "https://github.com/tokio-rs/tokio.git" } tracing-attributes = { path = "../tracing-attributes" } futures-preview = "0.3.0-alpha.18" +clap = "2.33" diff --git a/nightly-examples/examples/proxy_server.rs b/nightly-examples/examples/proxy_server.rs index 952a330c9f..523060af05 100644 --- a/nightly-examples/examples/proxy_server.rs +++ b/nightly-examples/examples/proxy_server.rs @@ -9,7 +9,7 @@ //! //! You can showcase this by running this in one terminal: //! -//! cargo +nightly run --example proxy_server +//! cargo +nightly run --example proxy_server -- --log_format=(plain|json) //! //! This in another terminal //! @@ -29,12 +29,11 @@ use tokio::{ net::{TcpListener, TcpStream}, prelude::*, }; - use tracing::{debug, debug_span, info, warn}; use tracing_attributes::instrument; use tracing_futures::Instrument; - -use std::{env, net::SocketAddr}; +use clap::{App, Arg, arg_enum, value_t}; +use std::net::SocketAddr; #[instrument] async fn transfer( @@ -84,23 +83,66 @@ async fn transfer( Ok(()) } +arg_enum! { + #[derive(PartialEq, Debug)] + pub enum LogFormat { + Plain, + Json, + } +} + #[tokio::main] async fn main() -> Result<(), Box> { use tracing_subscriber::{EnvFilter, FmtSubscriber}; - let subscriber = FmtSubscriber::builder() - .with_env_filter(EnvFilter::from_default_env().add_directive("proxy_server=trace".parse()?)) - .finish(); - tracing::subscriber::set_global_default(subscriber)?; + let matches = App::new("Proxy Server Exemple") + .version("1.0") + .arg( + Arg::with_name("log_format") + .possible_values(&LogFormat::variants()) + .case_insensitive(true) + .long("log_format") + .value_name("log_format") + .help("Formating of the logs") + .required(false) + .takes_value(true), + ) + .arg( + Arg::with_name("listen_addr") + .long("listen_addr") + .help("Address to listen on") + .takes_value(true) + .required(false), + ) + .arg( + Arg::with_name("server_addr") + .long("server_addr") + .help("Address to proxy to") + .takes_value(false) + .required(false), + ) + .get_matches(); + + match value_t!(matches, "log_format", LogFormat).unwrap_or(LogFormat::Plain) { + LogFormat::Json => { + let subscriber = FmtSubscriber::builder() + .json() + .with_env_filter(EnvFilter::from_default_env().add_directive("proxy_server=trace".parse()?)) + .finish(); + tracing::subscriber::set_global_default(subscriber)?; + } + LogFormat::Plain => { + let subscriber = FmtSubscriber::builder() + .with_env_filter(EnvFilter::from_default_env().add_directive("proxy_server=trace".parse()?)) + .finish(); + tracing::subscriber::set_global_default(subscriber)?; + } + } - let listen_addr = env::args() - .nth(1) - .unwrap_or_else(|| "127.0.0.1:8081".to_string()); + let listen_addr = matches.value_of("listen_addr").unwrap_or("127.0.0.1:8081"); let listen_addr = listen_addr.parse::()?; - let server_addr = env::args() - .nth(2) - .unwrap_or_else(|| "127.0.0.1:3000".to_string()); + let server_addr = matches.value_of("server_addr").unwrap_or("127.0.0.1:3000"); let server_addr = server_addr.parse::()?; let mut listener = TcpListener::bind(&listen_addr).await?.incoming(); From abebff2f6758718f9151485cdcfba6453b41f95d Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Fri, 11 Oct 2019 18:57:42 +0200 Subject: [PATCH 15/30] Fixes for @hawkw --- tracing-serde/src/lib.rs | 17 +++++++++++++---- tracing-subscriber/Cargo.toml | 4 +++- tracing-subscriber/src/fmt/format.rs | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index fd307aa8f2..2a2128c308 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -31,7 +31,8 @@ impl<'a> WriteAdaptor<'a> { impl<'a> io::Write for WriteAdaptor<'a> { fn write(&mut self, buf: &[u8]) -> io::Result { - let s = String::from_utf8_lossy(buf); + let s = + std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; self.fmt_write .write_str(&s) @@ -45,6 +46,12 @@ impl<'a> io::Write for WriteAdaptor<'a> { } } +impl<'a> fmt::Debug for WriteAdaptor<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("WriteAdaptor { .. }") + } +} + #[derive(Debug)] pub struct SerializeField(Field); @@ -186,12 +193,14 @@ impl<'a> Serialize for SerializeRecord<'a> { S: Serializer, { let serializer = serializer.serialize_map(None)?; - let mut visitor = SerdeMapVisitor::new(serializer, Ok(())); + let mut visitor = SerdeMapVisitor::new(serializer); self.0.record(&mut visitor); visitor.finish() } } +/// A visitor to go through a map of values. +#[derive(Debug)] pub struct SerdeMapVisitor { serializer: S, state: Result<(), S::Error>, @@ -201,8 +210,8 @@ impl SerdeMapVisitor where S: SerializeMap, { - pub fn new(serializer: S, state: Result<(), S::Error>) -> Self { - Self { serializer, state } + pub fn new(serializer: S) -> Self { + Self { serializer, state: Ok(()) } } } diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index 4f9f19765d..457318e06a 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -32,7 +32,6 @@ filter = ["env-filter"] [dependencies] tracing-core = "0.1.2" -tracing-serde = { path = "../tracing-serde", optional = true } # only required by the filter feature matchers = { optional = true, version = "0.0.1" } @@ -45,8 +44,11 @@ tracing-log = { version = "0.1", optional = true, default-features = false } ansi_term = { version = "0.11", optional = true } owning_ref = { version = "0.4.0", optional = true } 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 } +tracing-serde = { path = "../tracing-serde", optional = true } # opt-in deps parking_lot = { version = ">= 0.7, < 0.10", features = ["owning_ref"], optional = true } diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index 8323d71181..f2ebfe6af4 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -355,7 +355,7 @@ where serializer.serialize_entry("target", meta.target())?; } - let mut visitor = SerdeMapVisitor::new(serializer, Ok(())); + let mut visitor = SerdeMapVisitor::new(serializer); event.record(&mut visitor); visitor.finish() From 7897c53aca021318c2acc08401d32803feeec23b Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Sat, 12 Oct 2019 08:08:21 +0000 Subject: [PATCH 16/30] Update tracing-subscriber/src/lib.rs Co-Authored-By: Eliza Weisman --- tracing-subscriber/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-subscriber/src/lib.rs b/tracing-subscriber/src/lib.rs index 2d8e8dec81..5e11ebaf64 100644 --- a/tracing-subscriber/src/lib.rs +++ b/tracing-subscriber/src/lib.rs @@ -28,7 +28,7 @@ //! - `ansi`: Enables `fmt` support for ANSI terminal colors. Enabled by //! default. //! - `registry_unstable`: enables the experimental [`registry`] module. -//! - `json`: Enables `fmt` support for JSON output. In JSON output the ANSI feature does nothing. +//! - `json`: Enables `fmt` support for JSON output. In JSON output, the ANSI feature does nothing. //! //! ### Optional Dependencies //! From d831828ae845ef1a870fc2770a990049829fd1f5 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Mon, 14 Oct 2019 13:48:42 +0200 Subject: [PATCH 17/30] Serialize span and fields into separate objects --- tracing-core/src/event.rs | 5 ++++ tracing-core/src/field.rs | 7 +++++- tracing-log/Cargo.toml | 2 +- tracing-serde/Cargo.toml | 2 +- tracing-serde/src/lib.rs | 36 +++++++++++++++++++++++----- tracing-subscriber/Cargo.toml | 8 +++---- tracing-subscriber/src/fmt/format.rs | 16 ++++++------- tracing-subscriber/src/fmt/span.rs | 18 ++++++++++++++ 8 files changed, 73 insertions(+), 21 deletions(-) diff --git a/tracing-core/src/event.rs b/tracing-core/src/event.rs index 42713da443..235de26d2c 100644 --- a/tracing-core/src/event.rs +++ b/tracing-core/src/event.rs @@ -94,6 +94,11 @@ impl<'a> Event<'a> { self.fields.field_set().iter() } + /// Returns the field values on this `Event`. + pub fn values(&self) -> &field::ValueSet { + &self.fields + } + /// Returns [metadata] describing this `Event`. /// /// [metadata]: ../metadata/struct.Metadata.html diff --git a/tracing-core/src/field.rs b/tracing-core/src/field.rs index 7c3d05ab0d..4043afc7a9 100644 --- a/tracing-core/src/field.rs +++ b/tracing-core/src/field.rs @@ -599,7 +599,7 @@ impl<'a> ValueSet<'a> { /// Visits all the fields in this `ValueSet` with the provided [visitor]. /// /// [visitor]: ../trait.Visit.html - pub(crate) fn record(&self, visitor: &mut dyn Visit) { + pub fn record(&self, visitor: &mut dyn Visit) { let my_callsite = self.callsite(); for (field, value) in self.values { if field.callsite() != my_callsite { @@ -611,6 +611,11 @@ impl<'a> ValueSet<'a> { } } + /// The number of elements in the `ValueSet`. + pub fn len(&self) -> usize { + self.fields.len() + } + /// Returns `true` if this `ValueSet` contains a value for the given `Field`. pub(crate) fn contains(&self, field: &Field) -> bool { field.callsite() == self.callsite() diff --git a/tracing-log/Cargo.toml b/tracing-log/Cargo.toml index e15375efb3..990835c456 100644 --- a/tracing-log/Cargo.toml +++ b/tracing-log/Cargo.toml @@ -23,7 +23,7 @@ log-tracer = [] trace-logger = [] [dependencies] -tracing-core = "0.1.2" +tracing-core = { path = "../tracing-core" } log = { version = "0.4", features = ["std"] } lazy_static = "1.3.0" env_logger = { version = "0.6", optional = true } diff --git a/tracing-serde/Cargo.toml b/tracing-serde/Cargo.toml index 47b9c588df..95d87aa945 100644 --- a/tracing-serde/Cargo.toml +++ b/tracing-serde/Cargo.toml @@ -20,7 +20,7 @@ keywords = ["logging", "tracing", "serialization"] [dependencies] serde = "1" -tracing-core = "0.1.2" +tracing-core = { path = "../tracing-core" } [badges] azure-devops = { project = "tracing/tracing", pipeline = "tokio-rs.tracing", build = "1" } diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index 2a2128c308..e266f70133 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -10,7 +10,7 @@ use serde::{ use tracing_core::{ event::Event, - field::{Field, FieldSet, Visit}, + field::{Field, FieldSet, ValueSet, Visit}, metadata::{Level, Metadata}, span::{Attributes, Id, Record}, }; @@ -160,6 +160,22 @@ impl<'a> Serialize for SerializeEvent<'a> { } } +/// Implements `serde::Serialize` to write `ValueSet` data to a serializer. +#[derive(Debug)] +pub struct SerializeValueSet<'a>(&'a ValueSet<'a>); + +impl<'a> Serialize for SerializeValueSet<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let serializer = serializer.serialize_map(Some(self.0.len()))?; + let mut visitor = SerdeMapVisitor::new(serializer); + self.0.record(&mut visitor); + visitor.finish() + } +} + /// Implements `serde::Serialize` to write `Attributes` data to a serializer. #[derive(Debug)] pub struct SerializeAttributes<'a>(&'a Attributes<'a>); @@ -199,9 +215,7 @@ impl<'a> Serialize for SerializeRecord<'a> { } } -/// A visitor to go through a map of values. -#[derive(Debug)] -pub struct SerdeMapVisitor { +struct SerdeMapVisitor { serializer: S, state: Result<(), S::Error>, } @@ -210,7 +224,7 @@ impl SerdeMapVisitor where S: SerializeMap, { - pub fn new(serializer: S) -> Self { + fn new(serializer: S) -> Self { Self { serializer, state: Ok(()) } } } @@ -258,7 +272,7 @@ impl SerdeMapVisitor { /// Completes serializing the visited object, returning `Ok(())` if all /// fields were serialized correctly, or `Error(S::Error)` if a field could /// not be serialized. - pub fn finish(self) -> Result { + fn finish(self) -> Result { self.state?; self.serializer.end() } @@ -341,6 +355,14 @@ impl<'a> AsSerde<'a> for tracing_core::Event<'a> { } } +impl<'a> AsSerde<'a> for ValueSet<'a> { + type Serializable = SerializeValueSet<'a>; + + fn as_serde(&'a self) -> Self::Serializable { + SerializeValueSet(self) + } +} + impl<'a> AsSerde<'a> for tracing_core::span::Attributes<'a> { type Serializable = SerializeAttributes<'a>; @@ -375,6 +397,8 @@ impl<'a> AsSerde<'a> for Level { impl<'a> self::sealed::Sealed for Event<'a> {} +impl<'a> self::sealed::Sealed for ValueSet<'a> {} + impl<'a> self::sealed::Sealed for Attributes<'a> {} impl self::sealed::Sealed for Id {} diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index 457318e06a..fe0ea52122 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -31,7 +31,7 @@ json = ["tracing-serde", "serde", "serde_json"] filter = ["env-filter"] [dependencies] -tracing-core = "0.1.2" +tracing-core = { path = "../tracing-core" } # only required by the filter feature matchers = { optional = true, version = "0.0.1" } @@ -40,7 +40,7 @@ smallvec = { optional = true, version = "0.6.10"} lazy_static = { optional = true, version = "1" } # fmt -tracing-log = { version = "0.1", optional = true, default-features = false } +tracing-log = { path = "../tracing-log", optional = true, default-features = false } ansi_term = { version = "0.11", optional = true } owning_ref = { version = "0.4.0", optional = true } chrono = { version = "0.4", optional = true } @@ -54,9 +54,9 @@ tracing-serde = { path = "../tracing-serde", optional = true } parking_lot = { version = ">= 0.7, < 0.10", features = ["owning_ref"], optional = true } [dev-dependencies] -tracing = "0.1" +tracing = { path = "../tracing" } log = "0.4" -tracing-log = "0.1" +tracing-log = { path = "../tracing-log" } criterion = { version = "0.3", default_features = false } [badges] diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index f2ebfe6af4..5e3bb2a365 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -21,7 +21,7 @@ use serde::ser::{SerializeMap, Serializer as _}; #[cfg(feature = "json")] use serde_json::Serializer; #[cfg(feature = "json")] -use tracing_serde::{AsSerde, SerdeMapVisitor, WriteAdaptor}; +use tracing_serde::{AsSerde, WriteAdaptor}; /// A type that can format a tracing `Event` for a `fmt::Write`. /// @@ -348,17 +348,15 @@ where serializer.serialize_entry("timestamp", ×tamp)?; serializer.serialize_entry("level", &meta.level().as_serde())?; - ctx.with_current(|(_, span)| serializer.serialize_entry("span", span.name())) - .unwrap_or(Ok(()))?; + ctx.with_current(|(_, span)| { + serializer.serialize_entry("span", &span) + }).unwrap_or(Ok(()))?; if self.display_target { serializer.serialize_entry("target", meta.target())?; } - let mut visitor = SerdeMapVisitor::new(serializer); - event.record(&mut visitor); - - visitor.finish() + serializer.serialize_entry("fields", &event.values().as_serde()) }; visit().map_err(|_| fmt::Error)?; @@ -826,7 +824,7 @@ mod test { let make_writer = || MockWriter::new(&BUF); let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"target\":\"tracing_subscriber::fmt::format::test\",\"message\":\"some json test\"}\n"; + "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"name\":\"json_span\",\"fields\":\"answer=42 number=3\"},\"target\":\"tracing_subscriber::fmt::format::test\",\"fields\":{\"message\":\"some json test\"}\n"; test_json(make_writer, expected, &BUF); } @@ -862,6 +860,8 @@ mod test { .finish(); with_default(subscriber, || { + let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); + let _guard = span.enter(); tracing::info!("some json test"); }); diff --git a/tracing-subscriber/src/fmt/span.rs b/tracing-subscriber/src/fmt/span.rs index 6238a367ec..41f20e70a1 100644 --- a/tracing-subscriber/src/fmt/span.rs +++ b/tracing-subscriber/src/fmt/span.rs @@ -13,6 +13,9 @@ use tracing_core::{dispatcher, Metadata}; use super::format::FormatFields; +#[cfg(feature = "json")] +use serde::{Serialize, Serializer, ser::SerializeMap}; + pub struct Span<'a> { lock: OwningHandle, RwLockReadGuard<'a, Slot>>, } @@ -190,6 +193,21 @@ impl<'a> fmt::Debug for Span<'a> { } } +#[cfg(feature = "json")] +impl<'a> Serialize for Span<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut serializer = serializer.serialize_map(Some(4))?; + + serializer.serialize_entry("name", &self.name())?; + serializer.serialize_entry("fields", &self.fields())?; + + serializer.end() + } +} + // ===== impl Context ===== impl<'a, F> Context<'a, F> { From 3e8bd94b9387e7ebc69b77c7ed88c47090d67399 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Mon, 14 Oct 2019 14:28:10 +0200 Subject: [PATCH 18/30] Fix compilation problems and tests --- examples/Cargo.toml | 4 ++-- nightly-examples/Cargo.toml | 2 +- tracing-attributes/Cargo.toml | 2 +- tracing-attributes/test_async_await/Cargo.toml | 4 ++-- tracing-futures/Cargo.toml | 2 +- tracing-futures/test_std_future/Cargo.toml | 4 ++-- tracing-log/Cargo.toml | 2 +- tracing-macros/Cargo.toml | 4 ++-- tracing-tower/Cargo.toml | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 53a8eed743..8c6d3cd54a 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [dev-dependencies] # tracing crates -tracing = "0.1" -tracing-core = "0.1" +tracing = { version = "0.1", path = "../tracing" } +tracing-core = { version = "0.1", path = "../tracing-core" } tracing-tower = { version = "0.1.0", path = "../tracing-tower" } tracing-subscriber = { version = "0.1", path = "../tracing-subscriber" } tracing-futures = { version = "0.1.0", path = "../tracing-futures" } diff --git a/nightly-examples/Cargo.toml b/nightly-examples/Cargo.toml index ee4f6e4fb8..ef1c18ac25 100644 --- a/nightly-examples/Cargo.toml +++ b/nightly-examples/Cargo.toml @@ -12,7 +12,7 @@ publish = false edition = "2018" [dev-dependencies] -tracing = "0.1" +tracing = { version = "0.1", path = "../tracing" } tracing-subscriber = { version = "0.1", path = "../tracing-subscriber", features = ["json"] } tracing-futures = { path = "../tracing-futures", default-features = false, features = ["std-future"] } tokio = { git = "https://github.com/tokio-rs/tokio.git" } diff --git a/tracing-attributes/Cargo.toml b/tracing-attributes/Cargo.toml index 0b1fea20c5..91ee0b3e28 100644 --- a/tracing-attributes/Cargo.toml +++ b/tracing-attributes/Cargo.toml @@ -44,7 +44,7 @@ quote = "1" [dev-dependencies] -tracing = "0.1" +tracing = { version = "0.1", path = "../tracing" } [badges] azure-devops = { project = "tracing/tracing", pipeline = "tokio-rs.tracing", build = "1" } diff --git a/tracing-attributes/test_async_await/Cargo.toml b/tracing-attributes/test_async_await/Cargo.toml index 04da88edef..721876255b 100644 --- a/tracing-attributes/test_async_await/Cargo.toml +++ b/tracing-attributes/test_async_await/Cargo.toml @@ -14,8 +14,8 @@ edition = "2018" [dev-dependencies] tokio-test = { git = "https://github.com/tokio-rs/tokio.git" } -tracing = "0.1" -tracing-core = "0.1" +tracing = { version = "0.1", path = "../../tracing" } +tracing-core = { version = "0.1", path = "../../tracing-core" } tracing-futures = { path = "../../tracing-futures", features = ["std-future"] } tracing-attributes = { path = ".." } test_std_future = { path = "../../tracing-futures/test_std_future" } diff --git a/tracing-futures/Cargo.toml b/tracing-futures/Cargo.toml index 30a3e56688..7b90b78978 100644 --- a/tracing-futures/Cargo.toml +++ b/tracing-futures/Cargo.toml @@ -29,7 +29,7 @@ tokio-alpha = ["std-future", "tokio_02"] futures = { version = "0.1", optional = true } futures-core-preview = { version = "0.3.0-alpha.19", optional = true } pin-project = { version = "0.4", optional = true } -tracing = "0.1" +tracing = { version = "0.1", path = "../tracing" } tokio-executor = { version = "0.1", optional = true } tokio = { version = "0.1", optional = true } tokio_02 = { package = "tokio", version = "0.2.0-alpha.6", optional = true } diff --git a/tracing-futures/test_std_future/Cargo.toml b/tracing-futures/test_std_future/Cargo.toml index 7788cf5da4..9a861cf01d 100644 --- a/tracing-futures/test_std_future/Cargo.toml +++ b/tracing-futures/test_std_future/Cargo.toml @@ -13,6 +13,6 @@ edition = "2018" [dependencies] tokio-test = { git = "https://github.com/tokio-rs/tokio.git" } -tracing = "0.1" -tracing-core = "0.1.2" +tracing = { version = "0.1", path = "../../tracing" } +tracing-core = { version = "0.1.2", path = "../../tracing-core" } tracing-futures = { path = "..", features = ["std-future"] } diff --git a/tracing-log/Cargo.toml b/tracing-log/Cargo.toml index 990835c456..66458e26ea 100644 --- a/tracing-log/Cargo.toml +++ b/tracing-log/Cargo.toml @@ -29,7 +29,7 @@ lazy_static = "1.3.0" env_logger = { version = "0.6", optional = true } [dev-dependencies] -tracing = "0.1" +tracing = { path = "../tracing" } [badges] azure-devops = { project = "tracing/tracing", pipeline = "tokio-rs.tracing", build = "1" } diff --git a/tracing-macros/Cargo.toml b/tracing-macros/Cargo.toml index c0741f044f..3cd1f09179 100644 --- a/tracing-macros/Cargo.toml +++ b/tracing-macros/Cargo.toml @@ -18,10 +18,10 @@ keywords = ["logging", "tracing"] license = "MIT" [dependencies] -tracing = "0.1" +tracing = { version = "0.1", path = "../tracing" } [dev-dependencies] -tracing-log = "0.1" +tracing-log = { version = "0.1", path = "../tracing-log" } env_logger = "0.5" [badges] diff --git a/tracing-tower/Cargo.toml b/tracing-tower/Cargo.toml index 05fbe31591..ce86fc0c1a 100644 --- a/tracing-tower/Cargo.toml +++ b/tracing-tower/Cargo.toml @@ -21,7 +21,7 @@ license = "MIT" default = ["tower-layer", "tower-util", "http"] [dependencies] -tracing = "0.1" +tracing = { version = "0.1", path = "../tracing" } tracing-futures = { version = "0.1.0", path = "../tracing-futures" } futures = "0.1" tower-service = "0.2" From 4117ad377a0bce6416d72fc06e655060fbac5af2 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Mon, 14 Oct 2019 16:07:38 -0700 Subject: [PATCH 19/30] add the ability to serialize fields as a separate map Signed-off-by: Eliza Weisman --- tracing-serde/src/fields.rs | 55 +++++++++++++++++++++++++++++++++++++ tracing-serde/src/lib.rs | 2 ++ 2 files changed, 57 insertions(+) create mode 100644 tracing-serde/src/fields.rs diff --git a/tracing-serde/src/fields.rs b/tracing-serde/src/fields.rs new file mode 100644 index 0000000000..cb1e3b60f7 --- /dev/null +++ b/tracing-serde/src/fields.rs @@ -0,0 +1,55 @@ +//! Support for serializing fields as `serde` structs or maps. +use super::*; + +#[derive(Debug)] +pub struct SerializeFieldMap<'a, T:>(&'a T); + +pub trait AsMap: Sized + sealed::Sealed { + fn field_map(&self) -> SerializeFieldMap { + SerializeFieldMap(self) + } +} + +impl<'a> AsMap for Event<'a> {} +impl<'a> AsMap for Attributes<'a> {} +impl<'a> AsMap for Record<'a> {} + +// === impl SerializeFieldMap === + +impl<'a> Serialize for SerializeFieldMap<'a, Event<'_>> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let len = self.0.metadata().fields().len(); + let serializer = serializer.serialize_map(Some(len))?; + let mut visitor = SerdeMapVisitor::new(serializer); + self.0.record(&mut visitor); + visitor.finish() + } +} + +impl<'a> Serialize for SerializeFieldMap<'a, Attributes<'_>> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let len = self.0.metadata().fields().len(); + let serializer = serializer.serialize_map(Some(len))?; + let mut visitor = SerdeMapVisitor::new(serializer); + self.0.record(&mut visitor); + visitor.finish() + } +} + +impl<'a> Serialize for SerializeFieldMap<'a, Record<'_>> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let serializer = serializer.serialize_map(None)?; + let mut visitor = SerdeMapVisitor::new(serializer); + self.0.record(&mut visitor); + visitor.finish() + } +} \ No newline at end of file diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index e266f70133..9aff8da382 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -15,6 +15,8 @@ use tracing_core::{ span::{Attributes, Id, Record}, }; +pub mod fields; + /// A bridge between `fmt::Write` and `io::Write`. /// /// This is needed because tracing-subscriber's FormatEvent expects a fmt::Write From 63e8cd681bb21618e689e65c13a69276db3c6148 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Mon, 14 Oct 2019 16:13:27 -0700 Subject: [PATCH 20/30] format fields without requiring `tracing-core` change Signed-off-by: Eliza Weisman --- tracing-subscriber/src/fmt/format.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format.rs index 5e3bb2a365..d078eea0a9 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format.rs @@ -331,6 +331,7 @@ where writer: &mut dyn fmt::Write, event: &Event<'_>, ) -> fmt::Result { + use tracing_serde::fields::AsMap; let mut timestamp = String::new(); self.timer.format_time(&mut timestamp)?; @@ -356,7 +357,7 @@ where serializer.serialize_entry("target", meta.target())?; } - serializer.serialize_entry("fields", &event.values().as_serde()) + serializer.serialize_entry("fields", &event.field_map()) }; visit().map_err(|_| fmt::Error)?; From f1fb7163b66fa642007aec3104f750ebec5e317e Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Mon, 14 Oct 2019 16:17:08 -0700 Subject: [PATCH 21/30] undo tracing-core change Signed-off-by: Eliza Weisman --- examples/Cargo.toml | 4 +-- nightly-examples/Cargo.toml | 2 +- tracing-attributes/Cargo.toml | 2 +- .../test_async_await/Cargo.toml | 4 +-- tracing-core/src/event.rs | 5 ---- tracing-core/src/field.rs | 7 +---- tracing-futures/Cargo.toml | 2 +- tracing-futures/test_std_future/Cargo.toml | 4 +-- tracing-log/Cargo.toml | 4 +-- tracing-macros/Cargo.toml | 4 +-- tracing-serde/Cargo.toml | 2 +- tracing-serde/src/lib.rs | 28 +------------------ tracing-subscriber/Cargo.toml | 8 +++--- tracing-tower/Cargo.toml | 2 +- 14 files changed, 21 insertions(+), 57 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 8c6d3cd54a..53a8eed743 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [dev-dependencies] # tracing crates -tracing = { version = "0.1", path = "../tracing" } -tracing-core = { version = "0.1", path = "../tracing-core" } +tracing = "0.1" +tracing-core = "0.1" tracing-tower = { version = "0.1.0", path = "../tracing-tower" } tracing-subscriber = { version = "0.1", path = "../tracing-subscriber" } tracing-futures = { version = "0.1.0", path = "../tracing-futures" } diff --git a/nightly-examples/Cargo.toml b/nightly-examples/Cargo.toml index ef1c18ac25..ee4f6e4fb8 100644 --- a/nightly-examples/Cargo.toml +++ b/nightly-examples/Cargo.toml @@ -12,7 +12,7 @@ publish = false edition = "2018" [dev-dependencies] -tracing = { version = "0.1", path = "../tracing" } +tracing = "0.1" tracing-subscriber = { version = "0.1", path = "../tracing-subscriber", features = ["json"] } tracing-futures = { path = "../tracing-futures", default-features = false, features = ["std-future"] } tokio = { git = "https://github.com/tokio-rs/tokio.git" } diff --git a/tracing-attributes/Cargo.toml b/tracing-attributes/Cargo.toml index 91ee0b3e28..0b1fea20c5 100644 --- a/tracing-attributes/Cargo.toml +++ b/tracing-attributes/Cargo.toml @@ -44,7 +44,7 @@ quote = "1" [dev-dependencies] -tracing = { version = "0.1", path = "../tracing" } +tracing = "0.1" [badges] azure-devops = { project = "tracing/tracing", pipeline = "tokio-rs.tracing", build = "1" } diff --git a/tracing-attributes/test_async_await/Cargo.toml b/tracing-attributes/test_async_await/Cargo.toml index 721876255b..04da88edef 100644 --- a/tracing-attributes/test_async_await/Cargo.toml +++ b/tracing-attributes/test_async_await/Cargo.toml @@ -14,8 +14,8 @@ edition = "2018" [dev-dependencies] tokio-test = { git = "https://github.com/tokio-rs/tokio.git" } -tracing = { version = "0.1", path = "../../tracing" } -tracing-core = { version = "0.1", path = "../../tracing-core" } +tracing = "0.1" +tracing-core = "0.1" tracing-futures = { path = "../../tracing-futures", features = ["std-future"] } tracing-attributes = { path = ".." } test_std_future = { path = "../../tracing-futures/test_std_future" } diff --git a/tracing-core/src/event.rs b/tracing-core/src/event.rs index 235de26d2c..42713da443 100644 --- a/tracing-core/src/event.rs +++ b/tracing-core/src/event.rs @@ -94,11 +94,6 @@ impl<'a> Event<'a> { self.fields.field_set().iter() } - /// Returns the field values on this `Event`. - pub fn values(&self) -> &field::ValueSet { - &self.fields - } - /// Returns [metadata] describing this `Event`. /// /// [metadata]: ../metadata/struct.Metadata.html diff --git a/tracing-core/src/field.rs b/tracing-core/src/field.rs index 4043afc7a9..7c3d05ab0d 100644 --- a/tracing-core/src/field.rs +++ b/tracing-core/src/field.rs @@ -599,7 +599,7 @@ impl<'a> ValueSet<'a> { /// Visits all the fields in this `ValueSet` with the provided [visitor]. /// /// [visitor]: ../trait.Visit.html - pub fn record(&self, visitor: &mut dyn Visit) { + pub(crate) fn record(&self, visitor: &mut dyn Visit) { let my_callsite = self.callsite(); for (field, value) in self.values { if field.callsite() != my_callsite { @@ -611,11 +611,6 @@ impl<'a> ValueSet<'a> { } } - /// The number of elements in the `ValueSet`. - pub fn len(&self) -> usize { - self.fields.len() - } - /// Returns `true` if this `ValueSet` contains a value for the given `Field`. pub(crate) fn contains(&self, field: &Field) -> bool { field.callsite() == self.callsite() diff --git a/tracing-futures/Cargo.toml b/tracing-futures/Cargo.toml index 7b90b78978..30a3e56688 100644 --- a/tracing-futures/Cargo.toml +++ b/tracing-futures/Cargo.toml @@ -29,7 +29,7 @@ tokio-alpha = ["std-future", "tokio_02"] futures = { version = "0.1", optional = true } futures-core-preview = { version = "0.3.0-alpha.19", optional = true } pin-project = { version = "0.4", optional = true } -tracing = { version = "0.1", path = "../tracing" } +tracing = "0.1" tokio-executor = { version = "0.1", optional = true } tokio = { version = "0.1", optional = true } tokio_02 = { package = "tokio", version = "0.2.0-alpha.6", optional = true } diff --git a/tracing-futures/test_std_future/Cargo.toml b/tracing-futures/test_std_future/Cargo.toml index 9a861cf01d..7788cf5da4 100644 --- a/tracing-futures/test_std_future/Cargo.toml +++ b/tracing-futures/test_std_future/Cargo.toml @@ -13,6 +13,6 @@ edition = "2018" [dependencies] tokio-test = { git = "https://github.com/tokio-rs/tokio.git" } -tracing = { version = "0.1", path = "../../tracing" } -tracing-core = { version = "0.1.2", path = "../../tracing-core" } +tracing = "0.1" +tracing-core = "0.1.2" tracing-futures = { path = "..", features = ["std-future"] } diff --git a/tracing-log/Cargo.toml b/tracing-log/Cargo.toml index 66458e26ea..e15375efb3 100644 --- a/tracing-log/Cargo.toml +++ b/tracing-log/Cargo.toml @@ -23,13 +23,13 @@ log-tracer = [] trace-logger = [] [dependencies] -tracing-core = { path = "../tracing-core" } +tracing-core = "0.1.2" log = { version = "0.4", features = ["std"] } lazy_static = "1.3.0" env_logger = { version = "0.6", optional = true } [dev-dependencies] -tracing = { path = "../tracing" } +tracing = "0.1" [badges] azure-devops = { project = "tracing/tracing", pipeline = "tokio-rs.tracing", build = "1" } diff --git a/tracing-macros/Cargo.toml b/tracing-macros/Cargo.toml index 3cd1f09179..c0741f044f 100644 --- a/tracing-macros/Cargo.toml +++ b/tracing-macros/Cargo.toml @@ -18,10 +18,10 @@ keywords = ["logging", "tracing"] license = "MIT" [dependencies] -tracing = { version = "0.1", path = "../tracing" } +tracing = "0.1" [dev-dependencies] -tracing-log = { version = "0.1", path = "../tracing-log" } +tracing-log = "0.1" env_logger = "0.5" [badges] diff --git a/tracing-serde/Cargo.toml b/tracing-serde/Cargo.toml index 95d87aa945..47b9c588df 100644 --- a/tracing-serde/Cargo.toml +++ b/tracing-serde/Cargo.toml @@ -20,7 +20,7 @@ keywords = ["logging", "tracing", "serialization"] [dependencies] serde = "1" -tracing-core = { path = "../tracing-core" } +tracing-core = "0.1.2" [badges] azure-devops = { project = "tracing/tracing", pipeline = "tokio-rs.tracing", build = "1" } diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index 9aff8da382..2fd4505457 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -10,7 +10,7 @@ use serde::{ use tracing_core::{ event::Event, - field::{Field, FieldSet, ValueSet, Visit}, + field::{Field, FieldSet, Visit}, metadata::{Level, Metadata}, span::{Attributes, Id, Record}, }; @@ -162,22 +162,6 @@ impl<'a> Serialize for SerializeEvent<'a> { } } -/// Implements `serde::Serialize` to write `ValueSet` data to a serializer. -#[derive(Debug)] -pub struct SerializeValueSet<'a>(&'a ValueSet<'a>); - -impl<'a> Serialize for SerializeValueSet<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let serializer = serializer.serialize_map(Some(self.0.len()))?; - let mut visitor = SerdeMapVisitor::new(serializer); - self.0.record(&mut visitor); - visitor.finish() - } -} - /// Implements `serde::Serialize` to write `Attributes` data to a serializer. #[derive(Debug)] pub struct SerializeAttributes<'a>(&'a Attributes<'a>); @@ -357,14 +341,6 @@ impl<'a> AsSerde<'a> for tracing_core::Event<'a> { } } -impl<'a> AsSerde<'a> for ValueSet<'a> { - type Serializable = SerializeValueSet<'a>; - - fn as_serde(&'a self) -> Self::Serializable { - SerializeValueSet(self) - } -} - impl<'a> AsSerde<'a> for tracing_core::span::Attributes<'a> { type Serializable = SerializeAttributes<'a>; @@ -399,8 +375,6 @@ impl<'a> AsSerde<'a> for Level { impl<'a> self::sealed::Sealed for Event<'a> {} -impl<'a> self::sealed::Sealed for ValueSet<'a> {} - impl<'a> self::sealed::Sealed for Attributes<'a> {} impl self::sealed::Sealed for Id {} diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index fe0ea52122..457318e06a 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -31,7 +31,7 @@ json = ["tracing-serde", "serde", "serde_json"] filter = ["env-filter"] [dependencies] -tracing-core = { path = "../tracing-core" } +tracing-core = "0.1.2" # only required by the filter feature matchers = { optional = true, version = "0.0.1" } @@ -40,7 +40,7 @@ smallvec = { optional = true, version = "0.6.10"} lazy_static = { optional = true, version = "1" } # fmt -tracing-log = { path = "../tracing-log", optional = true, default-features = false } +tracing-log = { version = "0.1", optional = true, default-features = false } ansi_term = { version = "0.11", optional = true } owning_ref = { version = "0.4.0", optional = true } chrono = { version = "0.4", optional = true } @@ -54,9 +54,9 @@ tracing-serde = { path = "../tracing-serde", optional = true } parking_lot = { version = ">= 0.7, < 0.10", features = ["owning_ref"], optional = true } [dev-dependencies] -tracing = { path = "../tracing" } +tracing = "0.1" log = "0.4" -tracing-log = { path = "../tracing-log" } +tracing-log = "0.1" criterion = { version = "0.3", default_features = false } [badges] diff --git a/tracing-tower/Cargo.toml b/tracing-tower/Cargo.toml index ce86fc0c1a..05fbe31591 100644 --- a/tracing-tower/Cargo.toml +++ b/tracing-tower/Cargo.toml @@ -21,7 +21,7 @@ license = "MIT" default = ["tower-layer", "tower-util", "http"] [dependencies] -tracing = { version = "0.1", path = "../tracing" } +tracing = "0.1" tracing-futures = { version = "0.1.0", path = "../tracing-futures" } futures = "0.1" tower-service = "0.2" From 013819dd76c684d3fc2791e95f7531eec21a73cf Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Tue, 15 Oct 2019 17:17:38 +0200 Subject: [PATCH 22/30] Almost correct span field recording --- tracing-subscriber/src/fmt/format/json.rs | 254 ++++++++++++++++++ .../src/fmt/{format.rs => format/mod.rs} | 96 +------ tracing-subscriber/src/fmt/mod.rs | 4 +- tracing-subscriber/src/fmt/span.rs | 9 +- 4 files changed, 263 insertions(+), 100 deletions(-) create mode 100644 tracing-subscriber/src/fmt/format/json.rs rename tracing-subscriber/src/fmt/{format.rs => format/mod.rs} (87%) diff --git a/tracing-subscriber/src/fmt/format/json.rs b/tracing-subscriber/src/fmt/format/json.rs new file mode 100644 index 0000000000..33e8426a68 --- /dev/null +++ b/tracing-subscriber/src/fmt/format/json.rs @@ -0,0 +1,254 @@ +use super::{span, Format, FormatEvent, FormatFields, FormatTime}; +use crate::field::MakeVisitor; +use serde::ser::{SerializeMap, Serializer as _}; +use serde_json::Serializer; +use std::{ + collections::BTreeMap, + fmt::{self, Write}, +}; +use tracing_core::{ + field::{self, Field}, + Event, +}; +use tracing_serde::{AsSerde, WriteAdaptor}; + +#[cfg(feature = "tracing-log")] +use tracing_log::NormalizeEvent; + +/// Marker for `Format` that indicates that the verbose json log format should be used. +/// +/// The full format includes fields from all entered spans. +#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] +pub struct Json; + +impl FormatEvent for Format +where + N: for<'writer> FormatFields<'writer>, + T: FormatTime, +{ + fn format_event( + &self, + ctx: &span::Context<'_, N>, + writer: &mut dyn fmt::Write, + event: &Event<'_>, + ) -> fmt::Result { + use tracing_serde::fields::AsMap; + let mut timestamp = String::new(); + self.timer.format_time(&mut timestamp)?; + + #[cfg(feature = "tracing-log")] + let normalized_meta = event.normalized_metadata(); + #[cfg(feature = "tracing-log")] + let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); + #[cfg(not(feature = "tracing-log"))] + let meta = event.metadata(); + + let mut visit = || { + let mut serializer = Serializer::new(WriteAdaptor::new(writer)); + let mut serializer = serializer.serialize_map(None)?; + + serializer.serialize_entry("timestamp", ×tamp)?; + serializer.serialize_entry("level", &meta.level().as_serde())?; + + ctx.with_current(|(_, span)| serializer.serialize_entry("span", &span)) + .unwrap_or(Ok(()))?; + + if self.display_target { + serializer.serialize_entry("target", meta.target())?; + } + + serializer.serialize_entry("fields", &event.field_map()) + }; + + visit().map_err(|_| fmt::Error)?; + writeln!(writer) + } +} + +/// The JSON [`FormatFields`] implementation. +/// +/// [`FormatFields`]: trait.FormatFields.html +#[derive(Debug)] +pub struct JsonFields { + // reserve the ability to add fields to this without causing a breaking + // change in the future. + _private: (), +} + +impl JsonFields { + /// Returns a new JSON [`FormatFields`] implementation. + /// + /// [`FormatFields`]: trait.FormatFields.html + pub fn new() -> Self { + Self { _private: () } + } +} + +impl Default for JsonFields { + fn default() -> Self { + Self::new() + } +} + +impl<'a> MakeVisitor<&'a mut dyn Write> for JsonFields { + type Visitor = JsonVisitor<'a>; + + #[inline] + fn make_visitor(&self, target: &'a mut dyn Write) -> Self::Visitor { + JsonVisitor::new(target) + } +} + +/// The [visitor] produced by [`JsonFields`]'s [`MakeVisitor`] implementation. +/// +/// [visitor]: ../../field/trait.Visit.html +/// [`JsonFields`]: struct.JsonFields.html +/// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html +pub struct JsonVisitor<'a> { + values: BTreeMap<&'a str, serde_json::Value>, + writer: &'a mut dyn Write, +} + +impl<'a> fmt::Debug for JsonVisitor<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_fmt(format_args!("JsonVisitor {{ values: {:?} }}", self.values)) + } +} + +impl<'a> JsonVisitor<'a> { + /// Returns a new default visitor that formats to the provided `writer`. + /// + /// # Arguments + /// - `writer`: the writer to format to. + /// - `is_empty`: whether or not any fields have been previously written to + /// that writer. + pub fn new(writer: &'a mut dyn Write) -> Self { + Self { + values: BTreeMap::new(), + writer, + } + } +} + +impl<'a> crate::field::VisitFmt for JsonVisitor<'a> { + fn writer(&mut self) -> &mut dyn fmt::Write { + self.writer + } +} + +impl<'a> crate::field::VisitOutput for JsonVisitor<'a> { + fn finish(self) -> fmt::Result { + let inner = || { + let mut serializer = Serializer::new(WriteAdaptor::new(self.writer)); + let mut ser_map = serializer.serialize_map(None)?; + + for (k, v) in self.values { + ser_map.serialize_entry(k, &v)?; + } + + ser_map.end() + }; + + if inner().is_err() { + Err(fmt::Error) + } else { + Ok(()) + } + } +} + +impl<'a> field::Visit for JsonVisitor<'a> { + /// Visit a signed 64-bit integer value. + fn record_i64(&mut self, field: &Field, value: i64) { + self.values + .insert(&field.name(), serde_json::Value::from(value)); + } + + /// Visit an unsigned 64-bit integer value. + fn record_u64(&mut self, field: &Field, value: u64) { + self.values + .insert(&field.name(), serde_json::Value::from(value)); + } + + /// Visit a boolean value. + fn record_bool(&mut self, field: &Field, value: bool) { + self.values + .insert(&field.name(), serde_json::Value::from(value)); + } + + /// Visit a string value. + fn record_str(&mut self, field: &Field, value: &str) { + self.values + .insert(&field.name(), serde_json::Value::from(value)); + } + + fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { + match field.name() { + // Skip fields that are actually log metadata that have already been handled + #[cfg(feature = "tracing-log")] + name if name.starts_with("log.") => (), + name if name.starts_with("r#") => { + self.values + .insert(&name[2..], serde_json::Value::from(format!("{:?}", value))); + } + name => { + self.values + .insert(name, serde_json::Value::from(format!("{:?}", value))); + } + }; + } +} + +#[cfg(test)] +mod test { + + use crate::fmt::test::MockWriter; + use crate::fmt::time::FormatTime; + use lazy_static::lazy_static; + use tracing::{self, subscriber::with_default}; + + use std::fmt; + use std::sync::Mutex; + + struct MockTime; + impl FormatTime for MockTime { + fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result { + write!(w, "fake time") + } + } + + #[test] + fn json() { + lazy_static! { + static ref BUF: Mutex> = Mutex::new(vec![]); + } + + let make_writer = || MockWriter::new(&BUF); + + let expected = + "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"name\":\"json_span\",\"fields\":\"{\\\"answer\\\":42,\\\"number\\\":3}\"},\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}\n"; + + test_json(make_writer, expected, &BUF); + } + + #[cfg(feature = "json")] + fn test_json(make_writer: T, expected: &str, buf: &Mutex>) + where + T: crate::fmt::MakeWriter + Send + Sync + 'static, + { + let subscriber = crate::fmt::Subscriber::builder() + .json() + .with_writer(make_writer) + .with_timer(MockTime) + .finish(); + + with_default(subscriber, || { + let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); + let _guard = span.enter(); + tracing::info!("some json test"); + }); + + let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap(); + assert_eq!(expected, actual.as_str()); + } +} diff --git a/tracing-subscriber/src/fmt/format.rs b/tracing-subscriber/src/fmt/format/mod.rs similarity index 87% rename from tracing-subscriber/src/fmt/format.rs rename to tracing-subscriber/src/fmt/format/mod.rs index d078eea0a9..6d4b219318 100644 --- a/tracing-subscriber/src/fmt/format.rs +++ b/tracing-subscriber/src/fmt/format/mod.rs @@ -17,11 +17,10 @@ use tracing_log::NormalizeEvent; use ansi_term::{Colour, Style}; #[cfg(feature = "json")] -use serde::ser::{SerializeMap, Serializer as _}; -#[cfg(feature = "json")] -use serde_json::Serializer; +mod json; + #[cfg(feature = "json")] -use tracing_serde::{AsSerde, WriteAdaptor}; +pub use json::*; /// A type that can format a tracing `Event` for a `fmt::Write`. /// @@ -111,13 +110,6 @@ pub struct Compact; #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] pub struct Full; -/// Marker for `Format` that indicates that the verbose json log format should be used. -/// -/// The full format includes fields from all entered spans. -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] -#[cfg(feature = "json")] -pub struct Json; - /// A pre-configured event formatter. /// /// You will usually want to use this as the `FormatEvent` for a `FmtSubscriber`. @@ -319,52 +311,6 @@ where } } -#[cfg(feature = "json")] -impl FormatEvent for Format -where - N: for<'writer> FormatFields<'writer>, - T: FormatTime, -{ - fn format_event( - &self, - ctx: &span::Context<'_, N>, - writer: &mut dyn fmt::Write, - event: &Event<'_>, - ) -> fmt::Result { - use tracing_serde::fields::AsMap; - let mut timestamp = String::new(); - self.timer.format_time(&mut timestamp)?; - - #[cfg(feature = "tracing-log")] - let normalized_meta = event.normalized_metadata(); - #[cfg(feature = "tracing-log")] - let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); - #[cfg(not(feature = "tracing-log"))] - let meta = event.metadata(); - - let mut visit = || { - let mut serializer = Serializer::new(WriteAdaptor::new(writer)); - let mut serializer = serializer.serialize_map(None)?; - - serializer.serialize_entry("timestamp", ×tamp)?; - serializer.serialize_entry("level", &meta.level().as_serde())?; - - ctx.with_current(|(_, span)| { - serializer.serialize_entry("span", &span) - }).unwrap_or(Ok(()))?; - - if self.display_target { - serializer.serialize_entry("target", meta.target())?; - } - - serializer.serialize_entry("fields", &event.field_map()) - }; - - visit().map_err(|_| fmt::Error)?; - writeln!(writer) - } -} - // === impl FormatFields === impl<'writer, M> FormatFields<'writer> for M where @@ -815,21 +761,6 @@ mod test { assert_eq!(expected, actual.as_str()); } - #[cfg(feature = "json")] - #[test] - fn json() { - lazy_static! { - static ref BUF: Mutex> = Mutex::new(vec![]); - } - - let make_writer = || MockWriter::new(&BUF); - - let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"name\":\"json_span\",\"fields\":\"answer=42 number=3\"},\"target\":\"tracing_subscriber::fmt::format::test\",\"fields\":{\"message\":\"some json test\"}\n"; - - test_json(make_writer, expected, &BUF); - } - #[cfg(feature = "ansi")] fn test_ansi(make_writer: T, expected: &str, is_ansi: bool, buf: &Mutex>) where @@ -848,25 +779,4 @@ mod test { let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap(); assert_eq!(expected, actual.as_str()); } - - #[cfg(feature = "json")] - fn test_json(make_writer: T, expected: &str, buf: &Mutex>) - where - T: crate::fmt::MakeWriter + Send + Sync + 'static, - { - let subscriber = crate::fmt::Subscriber::builder() - .json() - .with_writer(make_writer) - .with_timer(MockTime) - .finish(); - - with_default(subscriber, || { - let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); - let _guard = span.enter(); - tracing::info!("some json test"); - }); - - let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap(); - assert_eq!(expected, actual.as_str()); - } } diff --git a/tracing-subscriber/src/fmt/mod.rs b/tracing-subscriber/src/fmt/mod.rs index 5aac66bcf6..6d92594b1a 100644 --- a/tracing-subscriber/src/fmt/mod.rs +++ b/tracing-subscriber/src/fmt/mod.rs @@ -748,14 +748,14 @@ impl Builder { /// /// See [`format::Json`] #[cfg(feature = "json")] - pub fn json(self) -> Builder, F, W> + pub fn json(self) -> Builder, F, W> where N: for<'writer> FormatFields<'writer> + 'static, { Builder { fmt_event: format::Format::default().json(), filter: self.filter, - fmt_fields: self.fmt_fields, + fmt_fields: format::JsonFields::default(), settings: self.settings, make_writer: self.make_writer, } diff --git a/tracing-subscriber/src/fmt/span.rs b/tracing-subscriber/src/fmt/span.rs index 41f20e70a1..c3ac568c3b 100644 --- a/tracing-subscriber/src/fmt/span.rs +++ b/tracing-subscriber/src/fmt/span.rs @@ -14,7 +14,7 @@ use tracing_core::{dispatcher, Metadata}; use super::format::FormatFields; #[cfg(feature = "json")] -use serde::{Serialize, Serializer, ser::SerializeMap}; +use serde::{Serialize, Serializer, ser::SerializeStruct}; pub struct Span<'a> { lock: OwningHandle, RwLockReadGuard<'a, Slot>>, @@ -199,11 +199,10 @@ impl<'a> Serialize for Span<'a> { where S: Serializer, { - let mut serializer = serializer.serialize_map(Some(4))?; - - serializer.serialize_entry("name", &self.name())?; - serializer.serialize_entry("fields", &self.fields())?; + let mut serializer = serializer.serialize_struct("Span", 2)?; + serializer.serialize_field("name", self.name())?; + serializer.serialize_field("fields", self.fields())?; serializer.end() } } From b1d4b8caafdbfb55bb3cfe67dc47e60af33e1e09 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Wed, 16 Oct 2019 09:25:06 +0200 Subject: [PATCH 23/30] fmt --- tracing-serde/src/fields.rs | 4 ++-- tracing-serde/src/lib.rs | 5 ++++- tracing-subscriber/src/fmt/span.rs | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tracing-serde/src/fields.rs b/tracing-serde/src/fields.rs index cb1e3b60f7..517d1c3cb5 100644 --- a/tracing-serde/src/fields.rs +++ b/tracing-serde/src/fields.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Debug)] -pub struct SerializeFieldMap<'a, T:>(&'a T); +pub struct SerializeFieldMap<'a, T>(&'a T); pub trait AsMap: Sized + sealed::Sealed { fn field_map(&self) -> SerializeFieldMap { @@ -52,4 +52,4 @@ impl<'a> Serialize for SerializeFieldMap<'a, Record<'_>> { self.0.record(&mut visitor); visitor.finish() } -} \ No newline at end of file +} diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index 2fd4505457..1a4106fb9d 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -211,7 +211,10 @@ where S: SerializeMap, { fn new(serializer: S) -> Self { - Self { serializer, state: Ok(()) } + Self { + serializer, + state: Ok(()), + } } } diff --git a/tracing-subscriber/src/fmt/span.rs b/tracing-subscriber/src/fmt/span.rs index c3ac568c3b..9c96e956a5 100644 --- a/tracing-subscriber/src/fmt/span.rs +++ b/tracing-subscriber/src/fmt/span.rs @@ -14,7 +14,7 @@ use tracing_core::{dispatcher, Metadata}; use super::format::FormatFields; #[cfg(feature = "json")] -use serde::{Serialize, Serializer, ser::SerializeStruct}; +use serde::{ser::SerializeStruct, Serialize, Serializer}; pub struct Span<'a> { lock: OwningHandle, RwLockReadGuard<'a, Slot>>, From a1cf246f4dab67ad2c97a7b2ec96b87bcc56e62b Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Fri, 18 Oct 2019 19:11:27 +0200 Subject: [PATCH 24/30] Set logger in a separate function --- nightly-examples/examples/proxy_server.rs | 37 +++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/nightly-examples/examples/proxy_server.rs b/nightly-examples/examples/proxy_server.rs index 523060af05..2f877129b6 100644 --- a/nightly-examples/examples/proxy_server.rs +++ b/nightly-examples/examples/proxy_server.rs @@ -32,7 +32,7 @@ use tokio::{ use tracing::{debug, debug_span, info, warn}; use tracing_attributes::instrument; use tracing_futures::Instrument; -use clap::{App, Arg, arg_enum, value_t}; +use clap::{App, Arg, ArgMatches, arg_enum, value_t}; use std::net::SocketAddr; #[instrument] @@ -123,21 +123,7 @@ async fn main() -> Result<(), Box> { ) .get_matches(); - match value_t!(matches, "log_format", LogFormat).unwrap_or(LogFormat::Plain) { - LogFormat::Json => { - let subscriber = FmtSubscriber::builder() - .json() - .with_env_filter(EnvFilter::from_default_env().add_directive("proxy_server=trace".parse()?)) - .finish(); - tracing::subscriber::set_global_default(subscriber)?; - } - LogFormat::Plain => { - let subscriber = FmtSubscriber::builder() - .with_env_filter(EnvFilter::from_default_env().add_directive("proxy_server=trace".parse()?)) - .finish(); - tracing::subscriber::set_global_default(subscriber)?; - } - } + set_global_default(&matches); let listen_addr = matches.value_of("listen_addr").unwrap_or("127.0.0.1:8081"); let listen_addr = listen_addr.parse::()?; @@ -173,3 +159,22 @@ async fn main() -> Result<(), Box> { Ok(()) } + +fn set_global_default(matches: &ArgMatches) { + match value_t!(matches, "log_format", LogFormat).unwrap_or(LogFormat::Plain) { + LogFormat::Json => { + let subscriber = FmtSubscriber::builder() + .json() + .with_env_filter(EnvFilter::from_default_env().add_directive("proxy_server=trace".parse()?)) + .finish(); + tracing::subscriber::set_global_default(subscriber)?; + } + LogFormat::Plain => { + let subscriber = FmtSubscriber::builder() + .with_env_filter(EnvFilter::from_default_env().add_directive("proxy_server=trace".parse()?)) + .finish(); + tracing::subscriber::set_global_default(subscriber)?; + } + } +} + From c4e9f7f04d2ac5cbd0a5398526301525544ad51a Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 18 Oct 2019 10:51:08 -0700 Subject: [PATCH 25/30] move WriteAdaptor out of serde crate Signed-off-by: Eliza Weisman --- tracing-serde/src/lib.rs | 37 ---------------------- tracing-subscriber/src/fmt/format/json.rs | 38 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index 1a4106fb9d..e60653e92b 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -17,43 +17,6 @@ use tracing_core::{ pub mod fields; -/// A bridge between `fmt::Write` and `io::Write`. -/// -/// This is needed because tracing-subscriber's FormatEvent expects a fmt::Write -/// while serde_json's Serializer expects an io::Write. -pub struct WriteAdaptor<'a> { - fmt_write: &'a mut dyn fmt::Write, -} - -impl<'a> WriteAdaptor<'a> { - pub fn new(fmt_write: &'a mut dyn fmt::Write) -> Self { - Self { fmt_write } - } -} - -impl<'a> io::Write for WriteAdaptor<'a> { - fn write(&mut self, buf: &[u8]) -> io::Result { - let s = - std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; - - self.fmt_write - .write_str(&s) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - - Ok(s.as_bytes().len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl<'a> fmt::Debug for WriteAdaptor<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("WriteAdaptor { .. }") - } -} - #[derive(Debug)] pub struct SerializeField(Field); diff --git a/tracing-subscriber/src/fmt/format/json.rs b/tracing-subscriber/src/fmt/format/json.rs index 33e8426a68..050575a436 100644 --- a/tracing-subscriber/src/fmt/format/json.rs +++ b/tracing-subscriber/src/fmt/format/json.rs @@ -199,6 +199,44 @@ impl<'a> field::Visit for JsonVisitor<'a> { } } + +/// A bridge between `fmt::Write` and `io::Write`. +/// +/// This is needed because tracing-subscriber's FormatEvent expects a fmt::Write +/// while serde_json's Serializer expects an io::Write. +struct WriteAdaptor<'a> { + fmt_write: &'a mut dyn fmt::Write, +} + +impl<'a> WriteAdaptor<'a> { + fn new(fmt_write: &'a mut dyn fmt::Write) -> Self { + Self { fmt_write } + } +} + +impl<'a> io::Write for WriteAdaptor<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + let s = + std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + self.fmt_write + .write_str(&s) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + + Ok(s.as_bytes().len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl<'a> fmt::Debug for WriteAdaptor<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("WriteAdaptor { .. }") + } +} + #[cfg(test)] mod test { From d72d5a79a51a8787ed0a2930e1294934a7e1b027 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 18 Oct 2019 10:57:52 -0700 Subject: [PATCH 26/30] rustfmt Signed-off-by: Eliza Weisman --- tracing-subscriber/src/fmt/format/json.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tracing-subscriber/src/fmt/format/json.rs b/tracing-subscriber/src/fmt/format/json.rs index 050575a436..495148d585 100644 --- a/tracing-subscriber/src/fmt/format/json.rs +++ b/tracing-subscriber/src/fmt/format/json.rs @@ -199,7 +199,6 @@ impl<'a> field::Visit for JsonVisitor<'a> { } } - /// A bridge between `fmt::Write` and `io::Write`. /// /// This is needed because tracing-subscriber's FormatEvent expects a fmt::Write From b6e13eae075b1b85dee4af4abf94f6baa2ec7739 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 18 Oct 2019 11:29:52 -0700 Subject: [PATCH 27/30] fix imports Signed-off-by: Eliza Weisman --- tracing-serde/src/lib.rs | 2 +- tracing-subscriber/src/fmt/format/json.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index e60653e92b..38d5b991e3 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -1,7 +1,7 @@ extern crate serde; extern crate tracing_core; -use std::{fmt, io}; +use std::fmt; use serde::{ ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer}, diff --git a/tracing-subscriber/src/fmt/format/json.rs b/tracing-subscriber/src/fmt/format/json.rs index 495148d585..9f16882cb6 100644 --- a/tracing-subscriber/src/fmt/format/json.rs +++ b/tracing-subscriber/src/fmt/format/json.rs @@ -5,12 +5,13 @@ use serde_json::Serializer; use std::{ collections::BTreeMap, fmt::{self, Write}, + io, }; use tracing_core::{ field::{self, Field}, Event, }; -use tracing_serde::{AsSerde, WriteAdaptor}; +use tracing_serde::AsSerde; #[cfg(feature = "tracing-log")] use tracing_log::NormalizeEvent; From 62c6d5a23fab5370f1fa9640c7b6a05b3ffef32c Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 18 Oct 2019 12:03:31 -0700 Subject: [PATCH 28/30] fix example not compiling Signed-off-by: Eliza Weisman --- nightly-examples/examples/proxy_server.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nightly-examples/examples/proxy_server.rs b/nightly-examples/examples/proxy_server.rs index 2f877129b6..0d12308d85 100644 --- a/nightly-examples/examples/proxy_server.rs +++ b/nightly-examples/examples/proxy_server.rs @@ -93,8 +93,6 @@ arg_enum! { #[tokio::main] async fn main() -> Result<(), Box> { - use tracing_subscriber::{EnvFilter, FmtSubscriber}; - let matches = App::new("Proxy Server Exemple") .version("1.0") .arg( @@ -123,7 +121,7 @@ async fn main() -> Result<(), Box> { ) .get_matches(); - set_global_default(&matches); + set_global_default(&matches)?; let listen_addr = matches.value_of("listen_addr").unwrap_or("127.0.0.1:8081"); let listen_addr = listen_addr.parse::()?; @@ -160,7 +158,8 @@ async fn main() -> Result<(), Box> { Ok(()) } -fn set_global_default(matches: &ArgMatches) { +fn set_global_default(matches: &ArgMatches<'_>) -> Result<(), Box> { + use tracing_subscriber::{FmtSubscriber, filter::EnvFilter}; match value_t!(matches, "log_format", LogFormat).unwrap_or(LogFormat::Plain) { LogFormat::Json => { let subscriber = FmtSubscriber::builder() @@ -176,5 +175,6 @@ fn set_global_default(matches: &ArgMatches) { tracing::subscriber::set_global_default(subscriber)?; } } + Ok(()) } From e53e392fc821f5794392d0f64ea0b42ee19b6ba8 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 18 Oct 2019 12:04:00 -0700 Subject: [PATCH 29/30] fix warnings in example Signed-off-by: Eliza Weisman --- nightly-examples/examples/proxy_server.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nightly-examples/examples/proxy_server.rs b/nightly-examples/examples/proxy_server.rs index 0d12308d85..e6c1c67f26 100644 --- a/nightly-examples/examples/proxy_server.rs +++ b/nightly-examples/examples/proxy_server.rs @@ -37,10 +37,10 @@ use std::net::SocketAddr; #[instrument] async fn transfer( - mut inbound: TcpStream, + inbound: TcpStream, proxy_addr: SocketAddr, ) -> Result<(), Box> { - let mut outbound = TcpStream::connect(&proxy_addr).await?; + let outbound = TcpStream::connect(&proxy_addr).await?; let (mut ri, mut wi) = inbound.split(); let (mut ro, mut wo) = outbound.split(); From fb42bd22ded2a39c9b2b44ee348626ab9276468f Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 18 Oct 2019 14:26:04 -0700 Subject: [PATCH 30/30] fix example again Signed-off-by: Eliza Weisman --- nightly-examples/examples/proxy_server.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nightly-examples/examples/proxy_server.rs b/nightly-examples/examples/proxy_server.rs index e6c1c67f26..0d12308d85 100644 --- a/nightly-examples/examples/proxy_server.rs +++ b/nightly-examples/examples/proxy_server.rs @@ -37,10 +37,10 @@ use std::net::SocketAddr; #[instrument] async fn transfer( - inbound: TcpStream, + mut inbound: TcpStream, proxy_addr: SocketAddr, ) -> Result<(), Box> { - let outbound = TcpStream::connect(&proxy_addr).await?; + let mut outbound = TcpStream::connect(&proxy_addr).await?; let (mut ri, mut wi) = inbound.split(); let (mut ro, mut wo) = outbound.split();