🛈 Note: This is pre-release documentation for the upcoming tracing 0.2.0 ecosystem.

For the release documentation, please see docs.rs, instead.

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]: crate
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//! `Collector` 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.1"
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 `Collector` to format the serialization of `tracing`
65//! types how you'd like.
66//!
67//! ```rust
68//! # use tracing_core::{Collect, Metadata, Event};
69//! # use tracing_core::span::{Attributes, Current, Id, Record};
70//! # use std::sync::atomic::{AtomicUsize, Ordering};
71//! use tracing_serde::AsSerde;
72//! use serde_json::json;
73//!
74//! pub struct JsonCollector {
75//!     next_id: AtomicUsize, // you need to assign span IDs, so you need a counter
76//! }
77//!
78//! impl JsonCollector {
79//!     fn new() -> Self {
80//!         Self { next_id: 1.into() }
81//!     }
82//! }
83//!
84//! impl Collect for JsonCollector {
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//!     # fn current_span(&self) -> Current { Current::unknown() }
112//! }
113//! ```
114//!
115//! After you implement your `Collector`, you can use your `tracing`
116//! collector (`JsonCollector` in the above example) to record serialized
117//! trace data.
118//!
119//! ##  Crate Feature Flags
120//!
121//! The following crate feature flags are available:
122//!
123//! * `std`: Depend on the Rust standard library (enabled by default).
124//!
125//!   `no_std` users may disable this feature with `default-features = false`:
126//!
127//!   ```toml
128//!   [dependencies]
129//!   tracing-serde = { version = "0.2", default-features = false }
130//!   ```
131//
132//!   **Note**:`tracing-serde`'s `no_std` support requires `liballoc`.
133//!
134//! ## Supported Rust Versions
135//!
136//! Tracing is built against the latest stable release. The minimum supported
137//! version is 1.63. The current Tracing version is not guaranteed to build on
138//! Rust versions earlier than the minimum supported version.
139//!
140//! Tracing follows the same compiler support policies as the rest of the Tokio
141//! project. The current stable Rust compiler and the three most recent minor
142//! versions before it will always be supported. For example, if the current
143//! stable compiler version is 1.69, the minimum supported version will not be
144//! increased past 1.66, three minor versions prior. Increasing the minimum
145//! supported compiler version is not considered a semver breaking change as
146//! long as doing so complies with this policy.
147//!
148//! [`tracing`]: https://crates.io/crates/tracing
149//! [`serde`]: https://crates.io/crates/serde
150#![doc(
151    html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
152    html_favicon_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/favicon.ico",
153    issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
154)]
155#![warn(
156    missing_debug_implementations,
157    // missing_docs, // TODO: add documentation
158    rust_2018_idioms,
159    unreachable_pub,
160    bad_style,
161    dead_code,
162    improper_ctypes,
163    non_shorthand_field_patterns,
164    no_mangle_generic_items,
165    overflowing_literals,
166    path_statements,
167    patterns_in_fns_without_body,
168    private_interfaces,
169    private_bounds,
170    unconditional_recursion,
171    unused,
172    unused_allocation,
173    unused_comparisons,
174    unused_parens,
175    while_true
176)]
177// Support using tracing-serde without the standard library!
178#![cfg_attr(not(feature = "std"), no_std)]
179
180use core::fmt;
181
182use serde::{
183    ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer},
184    Serialize,
185};
186
187use tracing_core::{
188    event::Event,
189    field::{Field, FieldSet, Visit},
190    metadata::{Level, Metadata},
191    span::{Attributes, Id, Record},
192};
193
194pub mod fields;
195
196#[derive(Debug)]
197pub struct SerializeField<'a>(&'a Field);
198
199impl Serialize for SerializeField<'_> {
200    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
201    where
202        S: Serializer,
203    {
204        serializer.serialize_str(self.0.name())
205    }
206}
207
208#[derive(Debug)]
209pub struct SerializeFieldSet<'a>(&'a FieldSet);
210
211impl Serialize for SerializeFieldSet<'_> {
212    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
213    where
214        S: Serializer,
215    {
216        let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
217        for element in self.0 {
218            seq.serialize_element(&SerializeField(&element))?;
219        }
220        seq.end()
221    }
222}
223
224#[derive(Debug)]
225pub struct SerializeLevel<'a>(&'a Level);
226
227impl Serialize for SerializeLevel<'_> {
228    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
229    where
230        S: Serializer,
231    {
232        if self.0 == &Level::ERROR {
233            serializer.serialize_str("ERROR")
234        } else if self.0 == &Level::WARN {
235            serializer.serialize_str("WARN")
236        } else if self.0 == &Level::INFO {
237            serializer.serialize_str("INFO")
238        } else if self.0 == &Level::DEBUG {
239            serializer.serialize_str("DEBUG")
240        } else if self.0 == &Level::TRACE {
241            serializer.serialize_str("TRACE")
242        } else {
243            unreachable!()
244        }
245    }
246}
247
248#[derive(Debug)]
249pub struct SerializeId<'a>(&'a Id);
250
251impl Serialize for SerializeId<'_> {
252    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
253    where
254        S: Serializer,
255    {
256        let mut state = serializer.serialize_tuple_struct("Id", 1)?;
257        state.serialize_field(&self.0.into_u64())?;
258        state.end()
259    }
260}
261
262#[derive(Debug)]
263pub struct SerializeMetadata<'a>(&'a Metadata<'a>);
264
265impl Serialize for SerializeMetadata<'_> {
266    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
267    where
268        S: Serializer,
269    {
270        let mut state = serializer.serialize_struct("Metadata", 9)?;
271        state.serialize_field("name", self.0.name())?;
272        state.serialize_field("target", self.0.target())?;
273        state.serialize_field("level", &SerializeLevel(self.0.level()))?;
274        state.serialize_field("module_path", &self.0.module_path())?;
275        state.serialize_field("file", &self.0.file())?;
276        state.serialize_field("line", &self.0.line())?;
277        state.serialize_field("fields", &SerializeFieldSet(self.0.fields()))?;
278        state.serialize_field("is_span", &self.0.is_span())?;
279        state.serialize_field("is_event", &self.0.is_event())?;
280        state.end()
281    }
282}
283
284/// Implements `serde::Serialize` to write `Event` data to a serializer.
285#[derive(Debug)]
286pub struct SerializeEvent<'a>(&'a Event<'a>);
287
288impl Serialize for SerializeEvent<'_> {
289    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
290    where
291        S: Serializer,
292    {
293        let mut serializer = serializer.serialize_struct("Event", 2)?;
294        serializer.serialize_field("metadata", &SerializeMetadata(self.0.metadata()))?;
295        let mut visitor = SerdeStructVisitor {
296            serializer,
297            state: Ok(()),
298        };
299        self.0.record(&mut visitor);
300        visitor.finish()
301    }
302}
303
304/// Implements `serde::Serialize` to write `Attributes` data to a serializer.
305#[derive(Debug)]
306pub struct SerializeAttributes<'a>(&'a Attributes<'a>);
307
308impl Serialize for SerializeAttributes<'_> {
309    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
310    where
311        S: Serializer,
312    {
313        let mut serializer = serializer.serialize_struct("Attributes", 3)?;
314        serializer.serialize_field("metadata", &SerializeMetadata(self.0.metadata()))?;
315        serializer.serialize_field("parent", &self.0.parent().map(SerializeId))?;
316        serializer.serialize_field("is_root", &self.0.is_root())?;
317
318        let mut visitor = SerdeStructVisitor {
319            serializer,
320            state: Ok(()),
321        };
322        self.0.record(&mut visitor);
323        visitor.finish()
324    }
325}
326
327/// Implements `serde::Serialize` to write `Record` data to a serializer.
328#[derive(Debug)]
329pub struct SerializeRecord<'a>(&'a Record<'a>);
330
331impl Serialize for SerializeRecord<'_> {
332    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
333    where
334        S: Serializer,
335    {
336        let serializer = serializer.serialize_map(None)?;
337        let mut visitor = SerdeMapVisitor::new(serializer);
338        self.0.record(&mut visitor);
339        visitor.finish()
340    }
341}
342
343/// Implements `tracing_core::field::Visit` for some `serde::ser::SerializeMap`.
344#[derive(Debug)]
345pub struct SerdeMapVisitor<S: SerializeMap> {
346    serializer: S,
347    state: Result<(), S::Error>,
348}
349
350impl<S> SerdeMapVisitor<S>
351where
352    S: SerializeMap,
353{
354    /// Create a new map visitor.
355    pub fn new(serializer: S) -> Self {
356        Self {
357            serializer,
358            state: Ok(()),
359        }
360    }
361
362    /// Completes serializing the visited object, returning `Ok(())` if all
363    /// fields were serialized correctly, or `Error(S::Error)` if a field could
364    /// not be serialized.
365    pub fn finish(self) -> Result<S::Ok, S::Error> {
366        self.state?;
367        self.serializer.end()
368    }
369
370    /// Completes serializing the visited object, returning ownership of the underlying serializer
371    /// if all fields were serialized correctly, or `Err(S::Error)` if a field could not be
372    /// serialized.
373    pub fn take_serializer(self) -> Result<S, S::Error> {
374        self.state?;
375        Ok(self.serializer)
376    }
377}
378
379impl<S> Visit for SerdeMapVisitor<S>
380where
381    S: SerializeMap,
382{
383    fn record_bool(&mut self, field: &Field, value: bool) {
384        // If previous fields serialized successfully, continue serializing,
385        // otherwise, short-circuit and do nothing.
386        if self.state.is_ok() {
387            self.state = self.serializer.serialize_entry(field.name(), &value)
388        }
389    }
390
391    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
392        if self.state.is_ok() {
393            self.state = self
394                .serializer
395                .serialize_entry(field.name(), &format_args!("{:?}", value))
396        }
397    }
398
399    fn record_u64(&mut self, field: &Field, value: u64) {
400        if self.state.is_ok() {
401            self.state = self.serializer.serialize_entry(field.name(), &value)
402        }
403    }
404
405    fn record_i64(&mut self, field: &Field, value: i64) {
406        if self.state.is_ok() {
407            self.state = self.serializer.serialize_entry(field.name(), &value)
408        }
409    }
410
411    fn record_f64(&mut self, field: &Field, value: f64) {
412        if self.state.is_ok() {
413            self.state = self.serializer.serialize_entry(field.name(), &value)
414        }
415    }
416
417    fn record_str(&mut self, field: &Field, value: &str) {
418        if self.state.is_ok() {
419            self.state = self.serializer.serialize_entry(field.name(), &value)
420        }
421    }
422}
423
424/// Implements `tracing_core::field::Visit` for some `serde::ser::SerializeStruct`.
425#[derive(Debug)]
426pub struct SerdeStructVisitor<S: SerializeStruct> {
427    serializer: S,
428    state: Result<(), S::Error>,
429}
430
431impl<S> Visit for SerdeStructVisitor<S>
432where
433    S: SerializeStruct,
434{
435    fn record_bool(&mut self, field: &Field, value: bool) {
436        // If previous fields serialized successfully, continue serializing,
437        // otherwise, short-circuit and do nothing.
438        if self.state.is_ok() {
439            self.state = self.serializer.serialize_field(field.name(), &value)
440        }
441    }
442
443    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
444        if self.state.is_ok() {
445            self.state = self
446                .serializer
447                .serialize_field(field.name(), &format_args!("{:?}", value))
448        }
449    }
450
451    fn record_u64(&mut self, field: &Field, value: u64) {
452        if self.state.is_ok() {
453            self.state = self.serializer.serialize_field(field.name(), &value)
454        }
455    }
456
457    fn record_i64(&mut self, field: &Field, value: i64) {
458        if self.state.is_ok() {
459            self.state = self.serializer.serialize_field(field.name(), &value)
460        }
461    }
462
463    fn record_f64(&mut self, field: &Field, value: f64) {
464        if self.state.is_ok() {
465            self.state = self.serializer.serialize_field(field.name(), &value)
466        }
467    }
468
469    fn record_str(&mut self, field: &Field, value: &str) {
470        if self.state.is_ok() {
471            self.state = self.serializer.serialize_field(field.name(), &value)
472        }
473    }
474}
475
476impl<S: SerializeStruct> SerdeStructVisitor<S> {
477    /// Completes serializing the visited object, returning `Ok(())` if all
478    /// fields were serialized correctly, or `Error(S::Error)` if a field could
479    /// not be serialized.
480    pub fn finish(self) -> Result<S::Ok, S::Error> {
481        self.state?;
482        self.serializer.end()
483    }
484}
485
486pub trait AsSerde<'a>: self::sealed::Sealed {
487    type Serializable: serde::Serialize + 'a;
488
489    /// `as_serde` borrows a `tracing` value and returns the serialized value.
490    fn as_serde(&'a self) -> Self::Serializable;
491}
492
493impl<'a> AsSerde<'a> for tracing_core::Metadata<'a> {
494    type Serializable = SerializeMetadata<'a>;
495
496    fn as_serde(&'a self) -> Self::Serializable {
497        SerializeMetadata(self)
498    }
499}
500
501impl<'a> AsSerde<'a> for tracing_core::Event<'a> {
502    type Serializable = SerializeEvent<'a>;
503
504    fn as_serde(&'a self) -> Self::Serializable {
505        SerializeEvent(self)
506    }
507}
508
509impl<'a> AsSerde<'a> for tracing_core::span::Attributes<'a> {
510    type Serializable = SerializeAttributes<'a>;
511
512    fn as_serde(&'a self) -> Self::Serializable {
513        SerializeAttributes(self)
514    }
515}
516
517impl<'a> AsSerde<'a> for tracing_core::span::Id {
518    type Serializable = SerializeId<'a>;
519
520    fn as_serde(&'a self) -> Self::Serializable {
521        SerializeId(self)
522    }
523}
524
525impl<'a> AsSerde<'a> for tracing_core::span::Record<'a> {
526    type Serializable = SerializeRecord<'a>;
527
528    fn as_serde(&'a self) -> Self::Serializable {
529        SerializeRecord(self)
530    }
531}
532
533impl<'a> AsSerde<'a> for Level {
534    type Serializable = SerializeLevel<'a>;
535
536    fn as_serde(&'a self) -> Self::Serializable {
537        SerializeLevel(self)
538    }
539}
540
541impl<'a> AsSerde<'a> for Field {
542    type Serializable = SerializeField<'a>;
543
544    fn as_serde(&'a self) -> Self::Serializable {
545        SerializeField(self)
546    }
547}
548
549impl<'a> AsSerde<'a> for FieldSet {
550    type Serializable = SerializeFieldSet<'a>;
551
552    fn as_serde(&'a self) -> Self::Serializable {
553        SerializeFieldSet(self)
554    }
555}
556
557impl self::sealed::Sealed for Event<'_> {}
558
559impl self::sealed::Sealed for Attributes<'_> {}
560
561impl self::sealed::Sealed for Id {}
562
563impl self::sealed::Sealed for Level {}
564
565impl self::sealed::Sealed for Record<'_> {}
566
567impl self::sealed::Sealed for Metadata<'_> {}
568
569impl self::sealed::Sealed for Field {}
570
571impl self::sealed::Sealed for FieldSet {}
572
573mod sealed {
574    pub trait Sealed {}
575}