tracing_serde/
lib.rs

1//! # tracing-serde
2//!
3//! An adapter for serializing [`tracing`] types using [`serde`].
4//!
5//! [![Documentation][docs-badge]][docs-url]
6//! [![Documentation (master)][docs-master-badge]][docs-master-url]
7//!
8//! [docs-badge]: https://docs.rs/tracing-serde/badge.svg
9//! [docs-url]: https://docs.rs/tracing-serde
10//! [docs-master-badge]: https://img.shields.io/badge/docs-master-blue
11//! [docs-master-url]: https://tracing-rs.netlify.com/tracing_serde
12//!
13//! ## Overview
14//!
15//! [`tracing`] is a framework for instrumenting Rust programs to collect
16//! scoped, structured, and async-aware diagnostics.`tracing-serde` enables
17//! serializing `tracing` types using [`serde`].
18//!
19//! Traditional logging is based on human-readable text messages.
20//! `tracing` gives us machine-readable structured diagnostic
21//! information. This lets us interact with diagnostic data
22//! programmatically. With `tracing-serde`, you can implement a
23//! `Subscriber` to serialize your `tracing` types and make use of the
24//! existing ecosystem of `serde` serializers to talk with distributed
25//! tracing systems.
26//!
27//! Serializing diagnostic information allows us to do more with our logged
28//! values. For instance, when working with logging data in JSON gives us
29//! pretty-print when we're debugging in development and you can emit JSON
30//! and tracing data to monitor your services in production.
31//!
32//! The `tracing` crate provides the APIs necessary for instrumenting
33//! libraries and applications to emit trace data.
34//!
35//! *Compiler support: [requires `rustc` 1.63+][msrv]*
36//!
37//! [msrv]: #supported-rust-versions
38//!
39//! ## Usage
40//!
41//! First, add this to your `Cargo.toml`:
42//!
43//! ```toml
44//! [dependencies]
45//! tracing = "0.1"
46//! tracing-serde = "0.2"
47//! ```
48//!
49//! Next, add this to your crate:
50//!
51//! ```rust
52//! use tracing_serde::AsSerde;
53//! ```
54//!
55//! Please read the [`tracing` documentation](https://docs.rs/tracing/latest/tracing/index.html)
56//! for more information on how to create trace data.
57//!
58//! This crate provides the `as_serde` function, via the `AsSerde` trait,
59//! which enables serializing the `Attributes`, `Event`, `Id`, `Metadata`,
60//! and `Record` `tracing` values.
61//!
62//! For the full example, please see the [examples](../examples) folder.
63//!
64//! Implement a `Subscriber` to format the serialization of `tracing`
65//! types how you'd like.
66//!
67//! ```rust
68//! # use tracing_core::{Subscriber, Metadata, Event};
69//! # use tracing_core::span::{Attributes, Id, Record};
70//! # use std::sync::atomic::{AtomicUsize, Ordering};
71//! use tracing_serde::AsSerde;
72//! use serde_json::json;
73//!
74//! pub struct JsonSubscriber {
75//!     next_id: AtomicUsize, // you need to assign span IDs, so you need a counter
76//! }
77//!
78//! impl JsonSubscriber {
79//!     fn new() -> Self {
80//!         Self { next_id: 1.into() }
81//!     }
82//! }
83//!
84//! impl Subscriber for JsonSubscriber {
85//!
86//!     fn new_span(&self, attrs: &Attributes<'_>) -> Id {
87//!         let id = self.next_id.fetch_add(1, Ordering::Relaxed);
88//!         let id = Id::from_u64(id as u64);
89//!         let json = json!({
90//!         "new_span": {
91//!             "attributes": attrs.as_serde(),
92//!             "id": id.as_serde(),
93//!         }});
94//!         println!("{}", json);
95//!         id
96//!     }
97//!
98//!     fn event(&self, event: &Event<'_>) {
99//!         let json = json!({
100//!            "event": event.as_serde(),
101//!         });
102//!         println!("{}", json);
103//!     }
104//!
105//!     // ...
106//!     # fn enabled(&self, _: &Metadata<'_>) -> bool { true }
107//!     # fn enter(&self, _: &Id) {}
108//!     # fn exit(&self, _: &Id) {}
109//!     # fn record(&self, _: &Id, _: &Record<'_>) {}
110//!     # fn record_follows_from(&self, _: &Id, _: &Id) {}
111//! }
112//! ```
113//!
114//! After you implement your `Subscriber`, you can use your `tracing`
115//! subscriber (`JsonSubscriber` in the above example) to record serialized
116//! trace data.
117//!
118//! ### Unstable Features
119//!
120//! These feature flags enable **unstable** features. The public API may break in 0.1.x
121//! releases. To enable these features, the `--cfg tracing_unstable` must be passed to
122//! `rustc` when compiling.
123//!
124//! The following unstable feature flags are currently available:
125//!
126//! * `valuable`: Enables [`Visit::record_value`] implementations, for
127//!   serializing values recorded using the [`valuable`] crate.
128//!
129//! #### Enabling Unstable Features
130//!
131//! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS`
132//! env variable when running `cargo` commands:
133//!
134//! ```shell
135//! RUSTFLAGS="--cfg tracing_unstable" cargo build
136//! ```
137//! Alternatively, the following can be added to the `.cargo/config` file in a
138//! project to automatically enable the cfg flag for that project:
139//!
140//! ```toml
141//! [build]
142//! rustflags = ["--cfg", "tracing_unstable"]
143//! ```
144//!
145//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
146//! [`valuable`]: https://crates.io/crates/valuable
147//!
148//! ## Supported Rust Versions
149//!
150//! Tracing is built against the latest stable release. The minimum supported
151//! version is 1.63. The current Tracing version is not guaranteed to build on
152//! Rust versions earlier than the minimum supported version.
153//!
154//! Tracing follows the same compiler support policies as the rest of the Tokio
155//! project. The current stable Rust compiler and the three most recent minor
156//! versions before it will always be supported. For example, if the current
157//! stable compiler version is 1.69, the minimum supported version will not be
158//! increased past 1.66, three minor versions prior. Increasing the minimum
159//! supported compiler version is not considered a semver breaking change as
160//! long as doing so complies with this policy.
161//!
162//! [`tracing`]: https://crates.io/crates/tracing
163//! [`serde`]: https://crates.io/crates/serde
164#![doc(
165    html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
166    issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
167)]
168#![cfg_attr(docsrs, feature(doc_cfg))]
169#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
170#![warn(
171    missing_debug_implementations,
172    // missing_docs, // TODO: add documentation
173    rust_2018_idioms,
174    unreachable_pub,
175    bad_style,
176    dead_code,
177    improper_ctypes,
178    non_shorthand_field_patterns,
179    no_mangle_generic_items,
180    overflowing_literals,
181    path_statements,
182    patterns_in_fns_without_body,
183    private_interfaces,
184    private_bounds,
185    unconditional_recursion,
186    unused,
187    unused_allocation,
188    unused_comparisons,
189    unused_parens,
190    while_true
191)]
192use std::fmt;
193
194use serde::{
195    ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer},
196    Serialize,
197};
198
199use tracing_core::{
200    event::Event,
201    field::{Field, FieldSet, Visit},
202    metadata::{Level, Metadata},
203    span::{Attributes, Id, Record},
204};
205
206pub mod fields;
207
208#[derive(Debug)]
209pub struct SerializeField<'a>(&'a Field);
210
211impl<'a> Serialize for SerializeField<'a> {
212    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
213    where
214        S: Serializer,
215    {
216        serializer.serialize_str(self.0.name())
217    }
218}
219
220#[derive(Debug)]
221pub struct SerializeFieldSet<'a>(&'a FieldSet);
222
223impl<'a> Serialize for SerializeFieldSet<'a> {
224    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
225    where
226        S: Serializer,
227    {
228        let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
229        for element in self.0 {
230            seq.serialize_element(&SerializeField(&element))?;
231        }
232        seq.end()
233    }
234}
235
236#[derive(Debug)]
237pub struct SerializeLevel<'a>(&'a Level);
238
239impl<'a> Serialize for SerializeLevel<'a> {
240    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
241    where
242        S: Serializer,
243    {
244        if self.0 == &Level::ERROR {
245            serializer.serialize_str("ERROR")
246        } else if self.0 == &Level::WARN {
247            serializer.serialize_str("WARN")
248        } else if self.0 == &Level::INFO {
249            serializer.serialize_str("INFO")
250        } else if self.0 == &Level::DEBUG {
251            serializer.serialize_str("DEBUG")
252        } else if self.0 == &Level::TRACE {
253            serializer.serialize_str("TRACE")
254        } else {
255            unreachable!()
256        }
257    }
258}
259
260#[derive(Debug)]
261pub struct SerializeId<'a>(&'a Id);
262
263impl<'a> Serialize for SerializeId<'a> {
264    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
265    where
266        S: Serializer,
267    {
268        let mut state = serializer.serialize_tuple_struct("Id", 1)?;
269        state.serialize_field(&self.0.into_u64())?;
270        state.end()
271    }
272}
273
274#[derive(Debug)]
275pub struct SerializeMetadata<'a>(&'a Metadata<'a>);
276
277impl<'a> Serialize for SerializeMetadata<'a> {
278    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
279    where
280        S: Serializer,
281    {
282        let mut state = serializer.serialize_struct("Metadata", 9)?;
283        state.serialize_field("name", self.0.name())?;
284        state.serialize_field("target", self.0.target())?;
285        state.serialize_field("level", &SerializeLevel(self.0.level()))?;
286        state.serialize_field("module_path", &self.0.module_path())?;
287        state.serialize_field("file", &self.0.file())?;
288        state.serialize_field("line", &self.0.line())?;
289        state.serialize_field("fields", &SerializeFieldSet(self.0.fields()))?;
290        state.serialize_field("is_span", &self.0.is_span())?;
291        state.serialize_field("is_event", &self.0.is_event())?;
292        state.end()
293    }
294}
295
296/// Implements `serde::Serialize` to write `Event` data to a serializer.
297#[derive(Debug)]
298pub struct SerializeEvent<'a>(&'a Event<'a>);
299
300impl<'a> Serialize for SerializeEvent<'a> {
301    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
302    where
303        S: Serializer,
304    {
305        let mut serializer = serializer.serialize_struct("Event", 2)?;
306        serializer.serialize_field("metadata", &SerializeMetadata(self.0.metadata()))?;
307        let mut visitor = SerdeStructVisitor {
308            serializer,
309            state: Ok(()),
310        };
311        self.0.record(&mut visitor);
312        visitor.finish()
313    }
314}
315
316/// Implements `serde::Serialize` to write `Attributes` data to a serializer.
317#[derive(Debug)]
318pub struct SerializeAttributes<'a>(&'a Attributes<'a>);
319
320impl<'a> Serialize for SerializeAttributes<'a> {
321    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
322    where
323        S: Serializer,
324    {
325        let mut serializer = serializer.serialize_struct("Attributes", 3)?;
326        serializer.serialize_field("metadata", &SerializeMetadata(self.0.metadata()))?;
327        serializer.serialize_field("parent", &self.0.parent().map(SerializeId))?;
328        serializer.serialize_field("is_root", &self.0.is_root())?;
329
330        let mut visitor = SerdeStructVisitor {
331            serializer,
332            state: Ok(()),
333        };
334        self.0.record(&mut visitor);
335        visitor.finish()
336    }
337}
338
339/// Implements `serde::Serialize` to write `Record` data to a serializer.
340#[derive(Debug)]
341pub struct SerializeRecord<'a>(&'a Record<'a>);
342
343impl<'a> Serialize for SerializeRecord<'a> {
344    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
345    where
346        S: Serializer,
347    {
348        let serializer = serializer.serialize_map(None)?;
349        let mut visitor = SerdeMapVisitor::new(serializer);
350        self.0.record(&mut visitor);
351        visitor.finish()
352    }
353}
354
355/// Implements `tracing_core::field::Visit` for some `serde::ser::SerializeMap`.
356#[derive(Debug)]
357pub struct SerdeMapVisitor<S: SerializeMap> {
358    serializer: S,
359    state: Result<(), S::Error>,
360}
361
362impl<S> SerdeMapVisitor<S>
363where
364    S: SerializeMap,
365{
366    /// Create a new map visitor.
367    pub fn new(serializer: S) -> Self {
368        Self {
369            serializer,
370            state: Ok(()),
371        }
372    }
373
374    /// Completes serializing the visited object, returning `Ok(())` if all
375    /// fields were serialized correctly, or `Error(S::Error)` if a field could
376    /// not be serialized.
377    pub fn finish(self) -> Result<S::Ok, S::Error> {
378        self.state?;
379        self.serializer.end()
380    }
381
382    /// Completes serializing the visited object, returning ownership of the underlying serializer
383    /// if all fields were serialized correctly, or `Err(S::Error)` if a field could not be
384    /// serialized.
385    pub fn take_serializer(self) -> Result<S, S::Error> {
386        self.state?;
387        Ok(self.serializer)
388    }
389}
390
391impl<S> Visit for SerdeMapVisitor<S>
392where
393    S: SerializeMap,
394{
395    #[cfg(all(tracing_unstable, feature = "valuable"))]
396    #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
397    fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) {
398        if self.state.is_ok() {
399            self.state = self
400                .serializer
401                .serialize_entry(field.name(), &valuable_serde::Serializable::new(value));
402        }
403    }
404
405    fn record_bool(&mut self, field: &Field, value: bool) {
406        // If previous fields serialized successfully, continue serializing,
407        // otherwise, short-circuit and do nothing.
408        if self.state.is_ok() {
409            self.state = self.serializer.serialize_entry(field.name(), &value)
410        }
411    }
412
413    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
414        if self.state.is_ok() {
415            self.state = self
416                .serializer
417                .serialize_entry(field.name(), &format_args!("{:?}", value))
418        }
419    }
420
421    fn record_u64(&mut self, field: &Field, value: u64) {
422        if self.state.is_ok() {
423            self.state = self.serializer.serialize_entry(field.name(), &value)
424        }
425    }
426
427    fn record_i64(&mut self, field: &Field, value: i64) {
428        if self.state.is_ok() {
429            self.state = self.serializer.serialize_entry(field.name(), &value)
430        }
431    }
432
433    fn record_f64(&mut self, field: &Field, value: f64) {
434        if self.state.is_ok() {
435            self.state = self.serializer.serialize_entry(field.name(), &value)
436        }
437    }
438
439    fn record_str(&mut self, field: &Field, value: &str) {
440        if self.state.is_ok() {
441            self.state = self.serializer.serialize_entry(field.name(), &value)
442        }
443    }
444}
445
446/// Implements `tracing_core::field::Visit` for some `serde::ser::SerializeStruct`.
447#[derive(Debug)]
448pub struct SerdeStructVisitor<S: SerializeStruct> {
449    serializer: S,
450    state: Result<(), S::Error>,
451}
452
453impl<S> Visit for SerdeStructVisitor<S>
454where
455    S: SerializeStruct,
456{
457    #[cfg(all(tracing_unstable, feature = "valuable"))]
458    #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
459    fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) {
460        if self.state.is_ok() {
461            self.state = self
462                .serializer
463                .serialize_field(field.name(), &valuable_serde::Serializable::new(value));
464        }
465    }
466
467    fn record_bool(&mut self, field: &Field, value: bool) {
468        // If previous fields serialized successfully, continue serializing,
469        // otherwise, short-circuit and do nothing.
470        if self.state.is_ok() {
471            self.state = self.serializer.serialize_field(field.name(), &value)
472        }
473    }
474
475    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
476        if self.state.is_ok() {
477            self.state = self
478                .serializer
479                .serialize_field(field.name(), &format_args!("{:?}", value))
480        }
481    }
482
483    fn record_u64(&mut self, field: &Field, value: u64) {
484        if self.state.is_ok() {
485            self.state = self.serializer.serialize_field(field.name(), &value)
486        }
487    }
488
489    fn record_i64(&mut self, field: &Field, value: i64) {
490        if self.state.is_ok() {
491            self.state = self.serializer.serialize_field(field.name(), &value)
492        }
493    }
494
495    fn record_f64(&mut self, field: &Field, value: f64) {
496        if self.state.is_ok() {
497            self.state = self.serializer.serialize_field(field.name(), &value)
498        }
499    }
500
501    fn record_str(&mut self, field: &Field, value: &str) {
502        if self.state.is_ok() {
503            self.state = self.serializer.serialize_field(field.name(), &value)
504        }
505    }
506}
507
508impl<S: SerializeStruct> SerdeStructVisitor<S> {
509    /// Completes serializing the visited object, returning `Ok(())` if all
510    /// fields were serialized correctly, or `Error(S::Error)` if a field could
511    /// not be serialized.
512    pub fn finish(self) -> Result<S::Ok, S::Error> {
513        self.state?;
514        self.serializer.end()
515    }
516}
517
518pub trait AsSerde<'a>: self::sealed::Sealed {
519    type Serializable: serde::Serialize + 'a;
520
521    /// `as_serde` borrows a `tracing` value and returns the serialized value.
522    fn as_serde(&'a self) -> Self::Serializable;
523}
524
525impl<'a> AsSerde<'a> for tracing_core::Metadata<'a> {
526    type Serializable = SerializeMetadata<'a>;
527
528    fn as_serde(&'a self) -> Self::Serializable {
529        SerializeMetadata(self)
530    }
531}
532
533impl<'a> AsSerde<'a> for tracing_core::Event<'a> {
534    type Serializable = SerializeEvent<'a>;
535
536    fn as_serde(&'a self) -> Self::Serializable {
537        SerializeEvent(self)
538    }
539}
540
541impl<'a> AsSerde<'a> for tracing_core::span::Attributes<'a> {
542    type Serializable = SerializeAttributes<'a>;
543
544    fn as_serde(&'a self) -> Self::Serializable {
545        SerializeAttributes(self)
546    }
547}
548
549impl<'a> AsSerde<'a> for tracing_core::span::Id {
550    type Serializable = SerializeId<'a>;
551
552    fn as_serde(&'a self) -> Self::Serializable {
553        SerializeId(self)
554    }
555}
556
557impl<'a> AsSerde<'a> for tracing_core::span::Record<'a> {
558    type Serializable = SerializeRecord<'a>;
559
560    fn as_serde(&'a self) -> Self::Serializable {
561        SerializeRecord(self)
562    }
563}
564
565impl<'a> AsSerde<'a> for Level {
566    type Serializable = SerializeLevel<'a>;
567
568    fn as_serde(&'a self) -> Self::Serializable {
569        SerializeLevel(self)
570    }
571}
572
573impl<'a> AsSerde<'a> for Field {
574    type Serializable = SerializeField<'a>;
575
576    fn as_serde(&'a self) -> Self::Serializable {
577        SerializeField(self)
578    }
579}
580
581impl<'a> AsSerde<'a> for FieldSet {
582    type Serializable = SerializeFieldSet<'a>;
583
584    fn as_serde(&'a self) -> Self::Serializable {
585        SerializeFieldSet(self)
586    }
587}
588
589impl<'a> self::sealed::Sealed for Event<'a> {}
590
591impl<'a> self::sealed::Sealed for Attributes<'a> {}
592
593impl self::sealed::Sealed for Id {}
594
595impl self::sealed::Sealed for Level {}
596
597impl<'a> self::sealed::Sealed for Record<'a> {}
598
599impl<'a> self::sealed::Sealed for Metadata<'a> {}
600
601impl self::sealed::Sealed for Field {}
602
603impl self::sealed::Sealed for FieldSet {}
604
605mod sealed {
606    pub trait Sealed {}
607}