1 use super::{Format, FormatEvent, FormatFields, FormatTime, Writer};
2 use crate::{
3     field::{RecordFields, VisitOutput},
4     fmt::{
5         fmt_layer::{FmtContext, FormattedFields},
6         writer::WriteAdaptor,
7     },
8     registry::LookupSpan,
9 };
10 use serde::ser::{SerializeMap, Serializer as _};
11 use serde_json::Serializer;
12 use std::{
13     collections::BTreeMap,
14     fmt::{self, Write},
15 };
16 use tracing_core::{
17     field::{self, Field},
18     span::Record,
19     Event, Subscriber,
20 };
21 use tracing_serde::AsSerde;
22 
23 #[cfg(feature = "tracing-log")]
24 use tracing_log::NormalizeEvent;
25 
26 /// Marker for `Format` that indicates that the verbose JSON log format should be used.
27 ///
28 /// The full format includes fields from all entered spans.
29 ///
30 /// # Example Output
31 ///
32 /// ```json
33 /// {
34 ///     "timestamp":"Feb 20 11:28:15.096",
35 ///     "level":"INFO",
36 ///     "fields":{"message":"some message","key":"value"}
37 ///     "target":"mycrate",
38 ///     "span":{name":"leaf"},
39 ///     "spans":[{"name":"root"},{"name":"leaf"}],
40 /// }
41 /// ```
42 ///
43 /// # Options
44 ///
45 /// - [`Json::flatten_event`] can be used to enable flattening event fields into
46 /// the root
47 /// - [`Json::with_current_span`] can be used to control logging of the current
48 /// span
49 /// - [`Json::with_span_list`] can be used to control logging of the span list
50 /// object.
51 ///
52 /// By default, event fields are not flattened, and both current span and span
53 /// list are logged.
54 ///
55 /// [`Json::flatten_event`]: #method.flatten_event
56 /// [`Json::with_current_span`]: #method.with_current_span
57 /// [`Json::with_span_list`]: #method.with_span_list
58 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
59 pub struct Json {
60     pub(crate) flatten_event: bool,
61     pub(crate) display_current_span: bool,
62     pub(crate) display_span_list: bool,
63 }
64 
65 impl Json {
66     /// If set to `true` event metadata will be flattened into the root object.
flatten_event(&mut self, flatten_event: bool)67     pub fn flatten_event(&mut self, flatten_event: bool) {
68         self.flatten_event = flatten_event;
69     }
70 
71     /// If set to `false`, formatted events won't contain a field for the current span.
with_current_span(&mut self, display_current_span: bool)72     pub fn with_current_span(&mut self, display_current_span: bool) {
73         self.display_current_span = display_current_span;
74     }
75 
76     /// If set to `false`, formatted events won't contain a list of all currently
77     /// entered spans. Spans are logged in a list from root to leaf.
with_span_list(&mut self, display_span_list: bool)78     pub fn with_span_list(&mut self, display_span_list: bool) {
79         self.display_span_list = display_span_list;
80     }
81 }
82 
83 struct SerializableContext<'a, 'b, Span, N>(
84     &'b crate::layer::Context<'a, Span>,
85     std::marker::PhantomData<N>,
86 )
87 where
88     Span: Subscriber + for<'lookup> crate::registry::LookupSpan<'lookup>,
89     N: for<'writer> FormatFields<'writer> + 'static;
90 
91 impl<'a, 'b, Span, N> serde::ser::Serialize for SerializableContext<'a, 'b, Span, N>
92 where
93     Span: Subscriber + for<'lookup> crate::registry::LookupSpan<'lookup>,
94     N: for<'writer> FormatFields<'writer> + 'static,
95 {
serialize<Ser>(&self, serializer_o: Ser) -> Result<Ser::Ok, Ser::Error> where Ser: serde::ser::Serializer,96     fn serialize<Ser>(&self, serializer_o: Ser) -> Result<Ser::Ok, Ser::Error>
97     where
98         Ser: serde::ser::Serializer,
99     {
100         use serde::ser::SerializeSeq;
101         let mut serializer = serializer_o.serialize_seq(None)?;
102 
103         if let Some(leaf_span) = self.0.lookup_current() {
104             for span in leaf_span.scope().from_root() {
105                 serializer.serialize_element(&SerializableSpan(&span, self.1))?;
106             }
107         }
108 
109         serializer.end()
110     }
111 }
112 
113 struct SerializableSpan<'a, 'b, Span, N>(
114     &'b crate::registry::SpanRef<'a, Span>,
115     std::marker::PhantomData<N>,
116 )
117 where
118     Span: for<'lookup> crate::registry::LookupSpan<'lookup>,
119     N: for<'writer> FormatFields<'writer> + 'static;
120 
121 impl<'a, 'b, Span, N> serde::ser::Serialize for SerializableSpan<'a, 'b, Span, N>
122 where
123     Span: for<'lookup> crate::registry::LookupSpan<'lookup>,
124     N: for<'writer> FormatFields<'writer> + 'static,
125 {
serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> where Ser: serde::ser::Serializer,126     fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
127     where
128         Ser: serde::ser::Serializer,
129     {
130         let mut serializer = serializer.serialize_map(None)?;
131 
132         let ext = self.0.extensions();
133         let data = ext
134             .get::<FormattedFields<N>>()
135             .expect("Unable to find FormattedFields in extensions; this is a bug");
136 
137         // TODO: let's _not_ do this, but this resolves
138         // https://github.com/tokio-rs/tracing/issues/391.
139         // We should probably rework this to use a `serde_json::Value` or something
140         // similar in a JSON-specific layer, but I'd (david)
141         // rather have a uglier fix now rather than shipping broken JSON.
142         match serde_json::from_str::<serde_json::Value>(data) {
143             Ok(serde_json::Value::Object(fields)) => {
144                 for field in fields {
145                     serializer.serialize_entry(&field.0, &field.1)?;
146                 }
147             }
148             // We have fields for this span which are valid JSON but not an object.
149             // This is probably a bug, so panic if we're in debug mode
150             Ok(_) if cfg!(debug_assertions) => panic!(
151                 "span '{}' had malformed fields! this is a bug.\n  error: invalid JSON object\n  fields: {:?}",
152                 self.0.metadata().name(),
153                 data
154             ),
155             // If we *aren't* in debug mode, it's probably best not to
156             // crash the program, let's log the field found but also an
157             // message saying it's type  is invalid
158             Ok(value) => {
159                 serializer.serialize_entry("field", &value)?;
160                 serializer.serialize_entry("field_error", "field was no a valid object")?
161             }
162             // We have previously recorded fields for this span
163             // should be valid JSON. However, they appear to *not*
164             // be valid JSON. This is almost certainly a bug, so
165             // panic if we're in debug mode
166             Err(e) if cfg!(debug_assertions) => panic!(
167                 "span '{}' had malformed fields! this is a bug.\n  error: {}\n  fields: {:?}",
168                 self.0.metadata().name(),
169                 e,
170                 data
171             ),
172             // If we *aren't* in debug mode, it's probably best not
173             // crash the program, but let's at least make sure it's clear
174             // that the fields are not supposed to be missing.
175             Err(e) => serializer.serialize_entry("field_error", &format!("{}", e))?,
176         };
177         serializer.serialize_entry("name", self.0.metadata().name())?;
178         serializer.end()
179     }
180 }
181 
182 impl<S, N, T> FormatEvent<S, N> for Format<Json, T>
183 where
184     S: Subscriber + for<'lookup> LookupSpan<'lookup>,
185     N: for<'writer> FormatFields<'writer> + 'static,
186     T: FormatTime,
187 {
format_event( &self, ctx: &FmtContext<'_, S, N>, mut writer: Writer<'_>, event: &Event<'_>, ) -> fmt::Result where S: Subscriber + for<'a> LookupSpan<'a>,188     fn format_event(
189         &self,
190         ctx: &FmtContext<'_, S, N>,
191         mut writer: Writer<'_>,
192         event: &Event<'_>,
193     ) -> fmt::Result
194     where
195         S: Subscriber + for<'a> LookupSpan<'a>,
196     {
197         let mut timestamp = String::new();
198         self.timer.format_time(&mut Writer::new(&mut timestamp))?;
199 
200         #[cfg(feature = "tracing-log")]
201         let normalized_meta = event.normalized_metadata();
202         #[cfg(feature = "tracing-log")]
203         let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
204         #[cfg(not(feature = "tracing-log"))]
205         let meta = event.metadata();
206 
207         let mut visit = || {
208             let mut serializer = Serializer::new(WriteAdaptor::new(&mut writer));
209 
210             let mut serializer = serializer.serialize_map(None)?;
211 
212             if self.display_timestamp {
213                 serializer.serialize_entry("timestamp", &timestamp)?;
214             }
215 
216             if self.display_level {
217                 serializer.serialize_entry("level", &meta.level().as_serde())?;
218             }
219 
220             let format_field_marker: std::marker::PhantomData<N> = std::marker::PhantomData;
221 
222             let current_span = if self.format.display_current_span || self.format.display_span_list
223             {
224                 event
225                     .parent()
226                     .and_then(|id| ctx.span(id))
227                     .or_else(|| ctx.lookup_current())
228             } else {
229                 None
230             };
231 
232             if self.format.flatten_event {
233                 let mut visitor = tracing_serde::SerdeMapVisitor::new(serializer);
234                 event.record(&mut visitor);
235 
236                 serializer = visitor.take_serializer()?;
237             } else {
238                 use tracing_serde::fields::AsMap;
239                 serializer.serialize_entry("fields", &event.field_map())?;
240             };
241 
242             if self.display_target {
243                 serializer.serialize_entry("target", meta.target())?;
244             }
245 
246             if self.format.display_current_span {
247                 if let Some(ref span) = current_span {
248                     serializer
249                         .serialize_entry("span", &SerializableSpan(span, format_field_marker))
250                         .unwrap_or(());
251                 }
252             }
253 
254             if self.format.display_span_list && current_span.is_some() {
255                 serializer.serialize_entry(
256                     "spans",
257                     &SerializableContext(&ctx.ctx, format_field_marker),
258                 )?;
259             }
260 
261             if self.display_thread_name {
262                 let current_thread = std::thread::current();
263                 match current_thread.name() {
264                     Some(name) => {
265                         serializer.serialize_entry("threadName", name)?;
266                     }
267                     // fall-back to thread id when name is absent and ids are not enabled
268                     None if !self.display_thread_id => {
269                         serializer
270                             .serialize_entry("threadName", &format!("{:?}", current_thread.id()))?;
271                     }
272                     _ => {}
273                 }
274             }
275 
276             if self.display_thread_id {
277                 serializer
278                     .serialize_entry("threadId", &format!("{:?}", std::thread::current().id()))?;
279             }
280 
281             serializer.end()
282         };
283 
284         visit().map_err(|_| fmt::Error)?;
285         writeln!(writer)
286     }
287 }
288 
289 impl Default for Json {
default() -> Json290     fn default() -> Json {
291         Json {
292             flatten_event: false,
293             display_current_span: true,
294             display_span_list: true,
295         }
296     }
297 }
298 
299 /// The JSON [`FormatFields`] implementation.
300 ///
301 /// [`FormatFields`]: trait.FormatFields.html
302 #[derive(Debug)]
303 pub struct JsonFields {
304     // reserve the ability to add fields to this without causing a breaking
305     // change in the future.
306     _private: (),
307 }
308 
309 impl JsonFields {
310     /// Returns a new JSON [`FormatFields`] implementation.
311     ///
312     /// [`FormatFields`]: trait.FormatFields.html
new() -> Self313     pub fn new() -> Self {
314         Self { _private: () }
315     }
316 }
317 
318 impl Default for JsonFields {
default() -> Self319     fn default() -> Self {
320         Self::new()
321     }
322 }
323 
324 impl<'a> FormatFields<'a> for JsonFields {
325     /// Format the provided `fields` to the provided `writer`, returning a result.
format_fields<R: RecordFields>(&self, mut writer: Writer<'_>, fields: R) -> fmt::Result326     fn format_fields<R: RecordFields>(&self, mut writer: Writer<'_>, fields: R) -> fmt::Result {
327         let mut v = JsonVisitor::new(&mut writer);
328         fields.record(&mut v);
329         v.finish()
330     }
331 
332     /// Record additional field(s) on an existing span.
333     ///
334     /// By default, this appends a space to the current set of fields if it is
335     /// non-empty, and then calls `self.format_fields`. If different behavior is
336     /// required, the default implementation of this method can be overridden.
add_fields( &self, current: &'a mut FormattedFields<Self>, fields: &Record<'_>, ) -> fmt::Result337     fn add_fields(
338         &self,
339         current: &'a mut FormattedFields<Self>,
340         fields: &Record<'_>,
341     ) -> fmt::Result {
342         if current.is_empty() {
343             // If there are no previously recorded fields, we can just reuse the
344             // existing string.
345             let mut writer = current.as_writer();
346             let mut v = JsonVisitor::new(&mut writer);
347             fields.record(&mut v);
348             v.finish()?;
349             return Ok(());
350         }
351 
352         // If fields were previously recorded on this span, we need to parse
353         // the current set of fields as JSON, add the new fields, and
354         // re-serialize them. Otherwise, if we just appended the new fields
355         // to a previously serialized JSON object, we would end up with
356         // malformed JSON.
357         //
358         // XXX(eliza): this is far from efficient, but unfortunately, it is
359         // necessary as long as the JSON formatter is implemented on top of
360         // an interface that stores all formatted fields as strings.
361         //
362         // We should consider reimplementing the JSON formatter as a
363         // separate layer, rather than a formatter for the `fmt` layer —
364         // then, we could store fields as JSON values, and add to them
365         // without having to parse and re-serialize.
366         let mut new = String::new();
367         let map: BTreeMap<&'_ str, serde_json::Value> =
368             serde_json::from_str(current).map_err(|_| fmt::Error)?;
369         let mut v = JsonVisitor::new(&mut new);
370         v.values = map;
371         fields.record(&mut v);
372         v.finish()?;
373         current.fields = new;
374 
375         Ok(())
376     }
377 }
378 
379 /// The [visitor] produced by [`JsonFields`]'s [`MakeVisitor`] implementation.
380 ///
381 /// [visitor]: ../../field/trait.Visit.html
382 /// [`JsonFields`]: struct.JsonFields.html
383 /// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html
384 pub struct JsonVisitor<'a> {
385     values: BTreeMap<&'a str, serde_json::Value>,
386     writer: &'a mut dyn Write,
387 }
388 
389 impl<'a> fmt::Debug for JsonVisitor<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result390     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
391         f.write_fmt(format_args!("JsonVisitor {{ values: {:?} }}", self.values))
392     }
393 }
394 
395 impl<'a> JsonVisitor<'a> {
396     /// Returns a new default visitor that formats to the provided `writer`.
397     ///
398     /// # Arguments
399     /// - `writer`: the writer to format to.
400     /// - `is_empty`: whether or not any fields have been previously written to
401     ///   that writer.
new(writer: &'a mut dyn Write) -> Self402     pub fn new(writer: &'a mut dyn Write) -> Self {
403         Self {
404             values: BTreeMap::new(),
405             writer,
406         }
407     }
408 }
409 
410 impl<'a> crate::field::VisitFmt for JsonVisitor<'a> {
writer(&mut self) -> &mut dyn fmt::Write411     fn writer(&mut self) -> &mut dyn fmt::Write {
412         self.writer
413     }
414 }
415 
416 impl<'a> crate::field::VisitOutput<fmt::Result> for JsonVisitor<'a> {
finish(self) -> fmt::Result417     fn finish(self) -> fmt::Result {
418         let inner = || {
419             let mut serializer = Serializer::new(WriteAdaptor::new(self.writer));
420             let mut ser_map = serializer.serialize_map(None)?;
421 
422             for (k, v) in self.values {
423                 ser_map.serialize_entry(k, &v)?;
424             }
425 
426             ser_map.end()
427         };
428 
429         if inner().is_err() {
430             Err(fmt::Error)
431         } else {
432             Ok(())
433         }
434     }
435 }
436 
437 impl<'a> field::Visit for JsonVisitor<'a> {
438     /// Visit a double precision floating point value.
record_f64(&mut self, field: &Field, value: f64)439     fn record_f64(&mut self, field: &Field, value: f64) {
440         self.values
441             .insert(field.name(), serde_json::Value::from(value));
442     }
443 
444     /// Visit a signed 64-bit integer value.
record_i64(&mut self, field: &Field, value: i64)445     fn record_i64(&mut self, field: &Field, value: i64) {
446         self.values
447             .insert(field.name(), serde_json::Value::from(value));
448     }
449 
450     /// Visit an unsigned 64-bit integer value.
record_u64(&mut self, field: &Field, value: u64)451     fn record_u64(&mut self, field: &Field, value: u64) {
452         self.values
453             .insert(field.name(), serde_json::Value::from(value));
454     }
455 
456     /// Visit a boolean value.
record_bool(&mut self, field: &Field, value: bool)457     fn record_bool(&mut self, field: &Field, value: bool) {
458         self.values
459             .insert(field.name(), serde_json::Value::from(value));
460     }
461 
462     /// Visit a string value.
record_str(&mut self, field: &Field, value: &str)463     fn record_str(&mut self, field: &Field, value: &str) {
464         self.values
465             .insert(field.name(), serde_json::Value::from(value));
466     }
467 
record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)468     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
469         match field.name() {
470             // Skip fields that are actually log metadata that have already been handled
471             #[cfg(feature = "tracing-log")]
472             name if name.starts_with("log.") => (),
473             name if name.starts_with("r#") => {
474                 self.values
475                     .insert(&name[2..], serde_json::Value::from(format!("{:?}", value)));
476             }
477             name => {
478                 self.values
479                     .insert(name, serde_json::Value::from(format!("{:?}", value)));
480             }
481         };
482     }
483 }
484 #[cfg(test)]
485 mod test {
486     use super::*;
487     use crate::fmt::{format::FmtSpan, test::MockMakeWriter, time::FormatTime, SubscriberBuilder};
488     use tracing::{self, subscriber::with_default};
489 
490     use std::fmt;
491 
492     struct MockTime;
493     impl FormatTime for MockTime {
format_time(&self, w: &mut Writer<'_>) -> fmt::Result494         fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
495             write!(w, "fake time")
496         }
497     }
498 
subscriber() -> SubscriberBuilder<JsonFields, Format<Json>>499     fn subscriber() -> SubscriberBuilder<JsonFields, Format<Json>> {
500         SubscriberBuilder::default().json()
501     }
502 
503     #[test]
json()504     fn json() {
505         let expected =
506         "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n";
507         let subscriber = subscriber()
508             .flatten_event(false)
509             .with_current_span(true)
510             .with_span_list(true);
511         test_json(expected, subscriber, || {
512             let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
513             let _guard = span.enter();
514             tracing::info!("some json test");
515         });
516     }
517 
518     #[test]
json_flattened_event()519     fn json_flattened_event() {
520         let expected =
521         "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"message\":\"some json test\"}\n";
522 
523         let subscriber = subscriber()
524             .flatten_event(true)
525             .with_current_span(true)
526             .with_span_list(true);
527         test_json(expected, subscriber, || {
528             let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
529             let _guard = span.enter();
530             tracing::info!("some json test");
531         });
532     }
533 
534     #[test]
json_disabled_current_span_event()535     fn json_disabled_current_span_event() {
536         let expected =
537         "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n";
538         let subscriber = subscriber()
539             .flatten_event(false)
540             .with_current_span(false)
541             .with_span_list(true);
542         test_json(expected, subscriber, || {
543             let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
544             let _guard = span.enter();
545             tracing::info!("some json test");
546         });
547     }
548 
549     #[test]
json_disabled_span_list_event()550     fn json_disabled_span_list_event() {
551         let expected =
552         "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n";
553         let subscriber = subscriber()
554             .flatten_event(false)
555             .with_current_span(true)
556             .with_span_list(false);
557         test_json(expected, subscriber, || {
558             let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
559             let _guard = span.enter();
560             tracing::info!("some json test");
561         });
562     }
563 
564     #[test]
json_nested_span()565     fn json_nested_span() {
566         let expected =
567         "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":43,\"name\":\"nested_json_span\",\"number\":4},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3},{\"answer\":43,\"name\":\"nested_json_span\",\"number\":4}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n";
568         let subscriber = subscriber()
569             .flatten_event(false)
570             .with_current_span(true)
571             .with_span_list(true);
572         test_json(expected, subscriber, || {
573             let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
574             let _guard = span.enter();
575             let span = tracing::span!(
576                 tracing::Level::INFO,
577                 "nested_json_span",
578                 answer = 43,
579                 number = 4
580             );
581             let _guard = span.enter();
582             tracing::info!("some json test");
583         });
584     }
585 
586     #[test]
json_no_span()587     fn json_no_span() {
588         let expected =
589         "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n";
590         let subscriber = subscriber()
591             .flatten_event(false)
592             .with_current_span(true)
593             .with_span_list(true);
594         test_json(expected, subscriber, || {
595             tracing::info!("some json test");
596         });
597     }
598 
599     #[test]
record_works()600     fn record_works() {
601         // This test reproduces issue #707, where using `Span::record` causes
602         // any events inside the span to be ignored.
603 
604         let make_writer = MockMakeWriter::default();
605         let subscriber = crate::fmt()
606             .json()
607             .with_writer(make_writer.clone())
608             .finish();
609 
610         with_default(subscriber, || {
611             tracing::info!("an event outside the root span");
612             assert_eq!(
613                 parse_as_json(&make_writer)["fields"]["message"],
614                 "an event outside the root span"
615             );
616 
617             let span = tracing::info_span!("the span", na = tracing::field::Empty);
618             span.record("na", &"value");
619             let _enter = span.enter();
620 
621             tracing::info!("an event inside the root span");
622             assert_eq!(
623                 parse_as_json(&make_writer)["fields"]["message"],
624                 "an event inside the root span"
625             );
626         });
627     }
628 
629     #[test]
json_span_event_show_correct_context()630     fn json_span_event_show_correct_context() {
631         let buffer = MockMakeWriter::default();
632         let subscriber = subscriber()
633             .with_writer(buffer.clone())
634             .flatten_event(false)
635             .with_current_span(true)
636             .with_span_list(false)
637             .with_span_events(FmtSpan::FULL)
638             .finish();
639 
640         with_default(subscriber, || {
641             let context = "parent";
642             let parent_span = tracing::info_span!("parent_span", context);
643 
644             let event = parse_as_json(&buffer);
645             assert_eq!(event["fields"]["message"], "new");
646             assert_eq!(event["span"]["context"], "parent");
647 
648             let _parent_enter = parent_span.enter();
649             let event = parse_as_json(&buffer);
650             assert_eq!(event["fields"]["message"], "enter");
651             assert_eq!(event["span"]["context"], "parent");
652 
653             let context = "child";
654             let child_span = tracing::info_span!("child_span", context);
655             let event = parse_as_json(&buffer);
656             assert_eq!(event["fields"]["message"], "new");
657             assert_eq!(event["span"]["context"], "child");
658 
659             let _child_enter = child_span.enter();
660             let event = parse_as_json(&buffer);
661             assert_eq!(event["fields"]["message"], "enter");
662             assert_eq!(event["span"]["context"], "child");
663 
664             drop(_child_enter);
665             let event = parse_as_json(&buffer);
666             assert_eq!(event["fields"]["message"], "exit");
667             assert_eq!(event["span"]["context"], "child");
668 
669             drop(child_span);
670             let event = parse_as_json(&buffer);
671             assert_eq!(event["fields"]["message"], "close");
672             assert_eq!(event["span"]["context"], "child");
673 
674             drop(_parent_enter);
675             let event = parse_as_json(&buffer);
676             assert_eq!(event["fields"]["message"], "exit");
677             assert_eq!(event["span"]["context"], "parent");
678 
679             drop(parent_span);
680             let event = parse_as_json(&buffer);
681             assert_eq!(event["fields"]["message"], "close");
682             assert_eq!(event["span"]["context"], "parent");
683         });
684     }
685 
686     #[test]
json_span_event_with_no_fields()687     fn json_span_event_with_no_fields() {
688         // Check span events serialize correctly.
689         // Discussion: https://github.com/tokio-rs/tracing/issues/829#issuecomment-661984255
690         let buffer = MockMakeWriter::default();
691         let subscriber = subscriber()
692             .with_writer(buffer.clone())
693             .flatten_event(false)
694             .with_current_span(false)
695             .with_span_list(false)
696             .with_span_events(FmtSpan::FULL)
697             .finish();
698 
699         with_default(subscriber, || {
700             let span = tracing::info_span!("valid_json");
701             assert_eq!(parse_as_json(&buffer)["fields"]["message"], "new");
702 
703             let _enter = span.enter();
704             assert_eq!(parse_as_json(&buffer)["fields"]["message"], "enter");
705 
706             drop(_enter);
707             assert_eq!(parse_as_json(&buffer)["fields"]["message"], "exit");
708 
709             drop(span);
710             assert_eq!(parse_as_json(&buffer)["fields"]["message"], "close");
711         });
712     }
713 
parse_as_json(buffer: &MockMakeWriter) -> serde_json::Value714     fn parse_as_json(buffer: &MockMakeWriter) -> serde_json::Value {
715         let buf = String::from_utf8(buffer.buf().to_vec()).unwrap();
716         let json = buf
717             .lines()
718             .last()
719             .expect("expected at least one line to be written!");
720         match serde_json::from_str(json) {
721             Ok(v) => v,
722             Err(e) => panic!(
723                 "assertion failed: JSON shouldn't be malformed\n  error: {}\n  json: {}",
724                 e, json
725             ),
726         }
727     }
728 
test_json<T>( expected: &str, builder: crate::fmt::SubscriberBuilder<JsonFields, Format<Json>>, producer: impl FnOnce() -> T, )729     fn test_json<T>(
730         expected: &str,
731         builder: crate::fmt::SubscriberBuilder<JsonFields, Format<Json>>,
732         producer: impl FnOnce() -> T,
733     ) {
734         let make_writer = MockMakeWriter::default();
735         let subscriber = builder
736             .with_writer(make_writer.clone())
737             .with_timer(MockTime)
738             .finish();
739 
740         with_default(subscriber, producer);
741 
742         let buf = make_writer.buf();
743         let actual = std::str::from_utf8(&buf[..]).unwrap();
744         assert_eq!(
745             serde_json::from_str::<std::collections::HashMap<&str, serde_json::Value>>(expected)
746                 .unwrap(),
747             serde_json::from_str(actual).unwrap()
748         );
749     }
750 }
751