Skip to main content

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 (v0.2.x)][docs-v0.2.x-badge]][docs-v0.2.x-url]
7//!
8//! [docs-badge]: https://docs.rs/tracing-serde/badge.svg
9//! [docs-url]: https://docs.rs/tracing-serde
10//! [docs-v0.2.x-badge]: https://img.shields.io/badge/docs-v0.2.x-blue
11//! [docs-v0.2.x-url]: https://tracing.rs/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.65+][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.65. 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/main/assets/logo-type.png",
166    html_favicon_url = "https://raw.githubusercontent.com/tokio-rs/tracing/main/assets/favicon.ico",
167    issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
168)]
169#![cfg_attr(docsrs, feature(doc_cfg))]
170#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
171#![warn(
172    missing_debug_implementations,
173    // missing_docs, // TODO: add documentation
174    rust_2018_idioms,
175    unreachable_pub,
176    bad_style,
177    dead_code,
178    improper_ctypes,
179    non_shorthand_field_patterns,
180    no_mangle_generic_items,
181    overflowing_literals,
182    path_statements,
183    patterns_in_fns_without_body,
184    private_interfaces,
185    private_bounds,
186    unconditional_recursion,
187    unused,
188    unused_allocation,
189    unused_comparisons,
190    unused_parens,
191    while_true
192)]
193use std::fmt;
194
195use serde::{
196    ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer},
197    Serialize,
198};
199
200use tracing_core::{
201    event::Event,
202    field::{Field, FieldSet, Visit},
203    metadata::{Level, Metadata},
204    span::{Attributes, Id, Record},
205};
206
207pub mod fields;
208
209#[derive(Debug)]
210pub struct SerializeField<'a>(&'a Field);
211
212impl Serialize for SerializeField<'_> {
213    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
214    where
215        S: Serializer,
216    {
217        serializer.serialize_str(self.0.name())
218    }
219}
220
221#[derive(Debug)]
222pub struct SerializeFieldSet<'a>(&'a FieldSet);
223
224impl Serialize for SerializeFieldSet<'_> {
225    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
226    where
227        S: Serializer,
228    {
229        let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
230        for element in self.0 {
231            seq.serialize_element(&SerializeField(&element))?;
232        }
233        seq.end()
234    }
235}
236
237#[derive(Debug)]
238pub struct SerializeLevel<'a>(&'a Level);
239
240impl Serialize for SerializeLevel<'_> {
241    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
242    where
243        S: Serializer,
244    {
245        if self.0 == &Level::ERROR {
246            serializer.serialize_str("ERROR")
247        } else if self.0 == &Level::WARN {
248            serializer.serialize_str("WARN")
249        } else if self.0 == &Level::INFO {
250            serializer.serialize_str("INFO")
251        } else if self.0 == &Level::DEBUG {
252            serializer.serialize_str("DEBUG")
253        } else if self.0 == &Level::TRACE {
254            serializer.serialize_str("TRACE")
255        } else {
256            unreachable!()
257        }
258    }
259}
260
261#[derive(Debug)]
262pub struct SerializeId<'a>(&'a Id);
263
264impl Serialize for SerializeId<'_> {
265    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
266    where
267        S: Serializer,
268    {
269        let mut state = serializer.serialize_tuple_struct("Id", 1)?;
270        state.serialize_field(&self.0.into_u64())?;
271        state.end()
272    }
273}
274
275#[derive(Debug)]
276pub struct SerializeMetadata<'a>(&'a Metadata<'a>);
277
278impl Serialize for SerializeMetadata<'_> {
279    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
280    where
281        S: Serializer,
282    {
283        let mut state = serializer.serialize_struct("Metadata", 9)?;
284        state.serialize_field("name", self.0.name())?;
285        state.serialize_field("target", self.0.target())?;
286        state.serialize_field("level", &SerializeLevel(self.0.level()))?;
287        state.serialize_field("module_path", &self.0.module_path())?;
288        state.serialize_field("file", &self.0.file())?;
289        state.serialize_field("line", &self.0.line())?;
290        state.serialize_field("fields", &SerializeFieldSet(self.0.fields()))?;
291        state.serialize_field("is_span", &self.0.is_span())?;
292        state.serialize_field("is_event", &self.0.is_event())?;
293        state.end()
294    }
295}
296
297/// Implements `serde::Serialize` to write `Event` data to a serializer.
298#[derive(Debug)]
299pub struct SerializeEvent<'a>(&'a Event<'a>);
300
301impl Serialize for SerializeEvent<'_> {
302    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
303    where
304        S: Serializer,
305    {
306        let mut serializer = serializer.serialize_struct("Event", 2)?;
307        serializer.serialize_field("metadata", &SerializeMetadata(self.0.metadata()))?;
308        let mut visitor = SerdeStructVisitor {
309            serializer,
310            state: Ok(()),
311        };
312        self.0.record(&mut visitor);
313        visitor.finish()
314    }
315}
316
317/// Implements `serde::Serialize` to write `Attributes` data to a serializer.
318#[derive(Debug)]
319pub struct SerializeAttributes<'a>(&'a Attributes<'a>);
320
321impl Serialize for SerializeAttributes<'_> {
322    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
323    where
324        S: Serializer,
325    {
326        let mut serializer = serializer.serialize_struct("Attributes", 3)?;
327        serializer.serialize_field("metadata", &SerializeMetadata(self.0.metadata()))?;
328        serializer.serialize_field("parent", &self.0.parent().map(SerializeId))?;
329        serializer.serialize_field("is_root", &self.0.is_root())?;
330
331        let mut visitor = SerdeStructVisitor {
332            serializer,
333            state: Ok(()),
334        };
335        self.0.record(&mut visitor);
336        visitor.finish()
337    }
338}
339
340/// Implements `serde::Serialize` to write `Record` data to a serializer.
341#[derive(Debug)]
342pub struct SerializeRecord<'a>(&'a Record<'a>);
343
344impl Serialize for SerializeRecord<'_> {
345    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
346    where
347        S: Serializer,
348    {
349        let serializer = serializer.serialize_map(None)?;
350        let mut visitor = SerdeMapVisitor::new(serializer);
351        self.0.record(&mut visitor);
352        visitor.finish()
353    }
354}
355
356/// Implements `tracing_core::field::Visit` for some `serde::ser::SerializeMap`.
357#[derive(Debug)]
358pub struct SerdeMapVisitor<S: SerializeMap> {
359    serializer: S,
360    state: Result<(), S::Error>,
361}
362
363impl<S> SerdeMapVisitor<S>
364where
365    S: SerializeMap,
366{
367    /// Create a new map visitor.
368    pub fn new(serializer: S) -> Self {
369        Self {
370            serializer,
371            state: Ok(()),
372        }
373    }
374
375    /// Completes serializing the visited object, returning `Ok(())` if all
376    /// fields were serialized correctly, or `Error(S::Error)` if a field could
377    /// not be serialized.
378    pub fn finish(self) -> Result<S::Ok, S::Error> {
379        self.state?;
380        self.serializer.end()
381    }
382
383    /// Completes serializing the visited object, returning ownership of the underlying serializer
384    /// if all fields were serialized correctly, or `Err(S::Error)` if a field could not be
385    /// serialized.
386    pub fn take_serializer(self) -> Result<S, S::Error> {
387        self.state?;
388        Ok(self.serializer)
389    }
390}
391
392impl<S> Visit for SerdeMapVisitor<S>
393where
394    S: SerializeMap,
395{
396    #[cfg(all(tracing_unstable, feature = "valuable"))]
397    #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
398    fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) {
399        if self.state.is_ok() {
400            self.state = self
401                .serializer
402                .serialize_entry(field.name(), &valuable_serde::Serializable::new(value));
403        }
404    }
405
406    fn record_bool(&mut self, field: &Field, value: bool) {
407        // If previous fields serialized successfully, continue serializing,
408        // otherwise, short-circuit and do nothing.
409        if self.state.is_ok() {
410            self.state = self.serializer.serialize_entry(field.name(), &value)
411        }
412    }
413
414    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
415        if self.state.is_ok() {
416            self.state = self
417                .serializer
418                .serialize_entry(field.name(), &format_args!("{:?}", value))
419        }
420    }
421
422    fn record_u64(&mut self, field: &Field, value: u64) {
423        if self.state.is_ok() {
424            self.state = self.serializer.serialize_entry(field.name(), &value)
425        }
426    }
427
428    fn record_i64(&mut self, field: &Field, value: i64) {
429        if self.state.is_ok() {
430            self.state = self.serializer.serialize_entry(field.name(), &value)
431        }
432    }
433
434    fn record_f64(&mut self, field: &Field, value: f64) {
435        if self.state.is_ok() {
436            self.state = self.serializer.serialize_entry(field.name(), &value)
437        }
438    }
439
440    fn record_str(&mut self, field: &Field, value: &str) {
441        if self.state.is_ok() {
442            self.state = self.serializer.serialize_entry(field.name(), &value)
443        }
444    }
445}
446
447/// Implements `tracing_core::field::Visit` for some `serde::ser::SerializeStruct`.
448#[derive(Debug)]
449pub struct SerdeStructVisitor<S: SerializeStruct> {
450    serializer: S,
451    state: Result<(), S::Error>,
452}
453
454impl<S> Visit for SerdeStructVisitor<S>
455where
456    S: SerializeStruct,
457{
458    #[cfg(all(tracing_unstable, feature = "valuable"))]
459    #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
460    fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) {
461        if self.state.is_ok() {
462            self.state = self
463                .serializer
464                .serialize_field(field.name(), &valuable_serde::Serializable::new(value));
465        }
466    }
467
468    fn record_bool(&mut self, field: &Field, value: bool) {
469        // If previous fields serialized successfully, continue serializing,
470        // otherwise, short-circuit and do nothing.
471        if self.state.is_ok() {
472            self.state = self.serializer.serialize_field(field.name(), &value)
473        }
474    }
475
476    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
477        if self.state.is_ok() {
478            self.state = self
479                .serializer
480                .serialize_field(field.name(), &format_args!("{:?}", value))
481        }
482    }
483
484    fn record_u64(&mut self, field: &Field, value: u64) {
485        if self.state.is_ok() {
486            self.state = self.serializer.serialize_field(field.name(), &value)
487        }
488    }
489
490    fn record_i64(&mut self, field: &Field, value: i64) {
491        if self.state.is_ok() {
492            self.state = self.serializer.serialize_field(field.name(), &value)
493        }
494    }
495
496    fn record_f64(&mut self, field: &Field, value: f64) {
497        if self.state.is_ok() {
498            self.state = self.serializer.serialize_field(field.name(), &value)
499        }
500    }
501
502    fn record_str(&mut self, field: &Field, value: &str) {
503        if self.state.is_ok() {
504            self.state = self.serializer.serialize_field(field.name(), &value)
505        }
506    }
507}
508
509impl<S: SerializeStruct> SerdeStructVisitor<S> {
510    /// Completes serializing the visited object, returning `Ok(())` if all
511    /// fields were serialized correctly, or `Error(S::Error)` if a field could
512    /// not be serialized.
513    pub fn finish(self) -> Result<S::Ok, S::Error> {
514        self.state?;
515        self.serializer.end()
516    }
517}
518
519pub trait AsSerde<'a>: self::sealed::Sealed {
520    type Serializable: serde::Serialize + 'a;
521
522    /// `as_serde` borrows a `tracing` value and returns the serialized value.
523    fn as_serde(&'a self) -> Self::Serializable;
524}
525
526impl<'a> AsSerde<'a> for tracing_core::Metadata<'a> {
527    type Serializable = SerializeMetadata<'a>;
528
529    fn as_serde(&'a self) -> Self::Serializable {
530        SerializeMetadata(self)
531    }
532}
533
534impl<'a> AsSerde<'a> for tracing_core::Event<'a> {
535    type Serializable = SerializeEvent<'a>;
536
537    fn as_serde(&'a self) -> Self::Serializable {
538        SerializeEvent(self)
539    }
540}
541
542impl<'a> AsSerde<'a> for tracing_core::span::Attributes<'a> {
543    type Serializable = SerializeAttributes<'a>;
544
545    fn as_serde(&'a self) -> Self::Serializable {
546        SerializeAttributes(self)
547    }
548}
549
550impl<'a> AsSerde<'a> for tracing_core::span::Id {
551    type Serializable = SerializeId<'a>;
552
553    fn as_serde(&'a self) -> Self::Serializable {
554        SerializeId(self)
555    }
556}
557
558impl<'a> AsSerde<'a> for tracing_core::span::Record<'a> {
559    type Serializable = SerializeRecord<'a>;
560
561    fn as_serde(&'a self) -> Self::Serializable {
562        SerializeRecord(self)
563    }
564}
565
566impl<'a> AsSerde<'a> for Level {
567    type Serializable = SerializeLevel<'a>;
568
569    fn as_serde(&'a self) -> Self::Serializable {
570        SerializeLevel(self)
571    }
572}
573
574impl<'a> AsSerde<'a> for Field {
575    type Serializable = SerializeField<'a>;
576
577    fn as_serde(&'a self) -> Self::Serializable {
578        SerializeField(self)
579    }
580}
581
582impl<'a> AsSerde<'a> for FieldSet {
583    type Serializable = SerializeFieldSet<'a>;
584
585    fn as_serde(&'a self) -> Self::Serializable {
586        SerializeFieldSet(self)
587    }
588}
589
590impl self::sealed::Sealed for Event<'_> {}
591
592impl self::sealed::Sealed for Attributes<'_> {}
593
594impl self::sealed::Sealed for Id {}
595
596impl self::sealed::Sealed for Level {}
597
598impl self::sealed::Sealed for Record<'_> {}
599
600impl self::sealed::Sealed for Metadata<'_> {}
601
602impl self::sealed::Sealed for Field {}
603
604impl self::sealed::Sealed for FieldSet {}
605
606mod sealed {
607    pub trait Sealed {}
608}