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.49+][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 `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 Subscriber for JsonSubscriber { 79 //! 80 //! fn new_span(&self, attrs: &Attributes<'_>) -> Id { 81 //! let id = self.next_id.fetch_add(1, Ordering::Relaxed); 82 //! let id = Id::from_u64(id as u64); 83 //! let json = json!({ 84 //! "new_span": { 85 //! "attributes": attrs.as_serde(), 86 //! "id": id.as_serde(), 87 //! }}); 88 //! println!("{}", json); 89 //! id 90 //! } 91 //! 92 //! fn event(&self, event: &Event<'_>) { 93 //! let json = json!({ 94 //! "event": event.as_serde(), 95 //! }); 96 //! println!("{}", json); 97 //! } 98 //! 99 //! // ... 100 //! # fn enabled(&self, _: &Metadata<'_>) -> bool { false } 101 //! # fn enter(&self, _: &Id) {} 102 //! # fn exit(&self, _: &Id) {} 103 //! # fn record(&self, _: &Id, _: &Record<'_>) {} 104 //! # fn record_follows_from(&self, _: &Id, _: &Id) {} 105 //! } 106 //! ``` 107 //! 108 //! After you implement your `Subscriber`, you can use your `tracing` 109 //! subscriber (`JsonSubscriber` in the above example) to record serialized 110 //! trace data. 111 //! 112 //! ### Unstable Features 113 //! 114 //! These feature flags enable **unstable** features. The public API may break in 0.1.x 115 //! releases. To enable these features, the `--cfg tracing_unstable` must be passed to 116 //! `rustc` when compiling. 117 //! 118 //! The following unstable feature flags are currently available: 119 //! 120 //! * `valuable`: Enables [`Visit::record_value`] implementations, for 121 //! serializing values recorded using the [`valuable`] crate. 122 //! 123 //! #### Enabling Unstable Features 124 //! 125 //! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS` 126 //! env variable when running `cargo` commands: 127 //! 128 //! ```shell 129 //! RUSTFLAGS="--cfg tracing_unstable" cargo build 130 //! ``` 131 //! Alternatively, the following can be added to the `.cargo/config` file in a 132 //! project to automatically enable the cfg flag for that project: 133 //! 134 //! ```toml 135 //! [build] 136 //! rustflags = ["--cfg", "tracing_unstable"] 137 //! ``` 138 //! 139 //! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section 140 //! [`valuable`]: https://crates.io/crates/valuable 141 //! 142 //! ## Supported Rust Versions 143 //! 144 //! Tracing is built against the latest stable release. The minimum supported 145 //! version is 1.49. The current Tracing version is not guaranteed to build on 146 //! Rust versions earlier than the minimum supported version. 147 //! 148 //! Tracing follows the same compiler support policies as the rest of the Tokio 149 //! project. The current stable Rust compiler and the three most recent minor 150 //! versions before it will always be supported. For example, if the current 151 //! stable compiler version is 1.45, the minimum supported version will not be 152 //! increased past 1.42, three minor versions prior. Increasing the minimum 153 //! supported compiler version is not considered a semver breaking change as 154 //! long as doing so complies with this policy. 155 //! 156 //! [`tracing`]: https://crates.io/crates/tracing 157 //! [`serde`]: https://crates.io/crates/serde 158 #![doc(html_root_url = "https://docs.rs/tracing-serde/0.1.3")] 159 #![doc( 160 html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", 161 issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" 162 )] 163 #![cfg_attr(docsrs, feature(doc_cfg))] 164 #![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] 165 #![warn( 166 missing_debug_implementations, 167 // missing_docs, // TODO: add documentation 168 rust_2018_idioms, 169 unreachable_pub, 170 bad_style, 171 const_err, 172 dead_code, 173 improper_ctypes, 174 non_shorthand_field_patterns, 175 no_mangle_generic_items, 176 overflowing_literals, 177 path_statements, 178 patterns_in_fns_without_body, 179 private_in_public, 180 unconditional_recursion, 181 unused, 182 unused_allocation, 183 unused_comparisons, 184 unused_parens, 185 while_true 186 )] 187 use std::fmt; 188 189 use serde::{ 190 ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer}, 191 Serialize, 192 }; 193 194 use tracing_core::{ 195 event::Event, 196 field::{Field, FieldSet, Visit}, 197 metadata::{Level, Metadata}, 198 span::{Attributes, Id, Record}, 199 }; 200 201 pub mod fields; 202 203 #[derive(Debug)] 204 pub struct SerializeField(Field); 205 206 impl Serialize for SerializeField { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,207 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 208 where 209 S: Serializer, 210 { 211 serializer.serialize_str(self.0.name()) 212 } 213 } 214 215 #[derive(Debug)] 216 pub struct SerializeFieldSet<'a>(&'a FieldSet); 217 218 impl<'a> Serialize for SerializeFieldSet<'a> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,219 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 220 where 221 S: Serializer, 222 { 223 let mut seq = serializer.serialize_seq(Some(self.0.len()))?; 224 for element in self.0 { 225 seq.serialize_element(element.name())?; 226 } 227 seq.end() 228 } 229 } 230 231 #[derive(Debug)] 232 pub struct SerializeLevel<'a>(&'a Level); 233 234 impl<'a> Serialize for SerializeLevel<'a> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,235 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 236 where 237 S: Serializer, 238 { 239 if self.0 == &Level::ERROR { 240 serializer.serialize_str("ERROR") 241 } else if self.0 == &Level::WARN { 242 serializer.serialize_str("WARN") 243 } else if self.0 == &Level::INFO { 244 serializer.serialize_str("INFO") 245 } else if self.0 == &Level::DEBUG { 246 serializer.serialize_str("DEBUG") 247 } else if self.0 == &Level::TRACE { 248 serializer.serialize_str("TRACE") 249 } else { 250 unreachable!() 251 } 252 } 253 } 254 255 #[derive(Debug)] 256 pub struct SerializeId<'a>(&'a Id); 257 258 impl<'a> Serialize for SerializeId<'a> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,259 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 260 where 261 S: Serializer, 262 { 263 let mut state = serializer.serialize_tuple_struct("Id", 1)?; 264 state.serialize_field(&self.0.into_u64())?; 265 state.end() 266 } 267 } 268 269 #[derive(Debug)] 270 pub struct SerializeMetadata<'a>(&'a Metadata<'a>); 271 272 impl<'a> Serialize for SerializeMetadata<'a> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,273 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 274 where 275 S: Serializer, 276 { 277 let mut state = serializer.serialize_struct("Metadata", 9)?; 278 state.serialize_field("name", self.0.name())?; 279 state.serialize_field("target", self.0.target())?; 280 state.serialize_field("level", &SerializeLevel(self.0.level()))?; 281 state.serialize_field("module_path", &self.0.module_path())?; 282 state.serialize_field("file", &self.0.file())?; 283 state.serialize_field("line", &self.0.line())?; 284 state.serialize_field("fields", &SerializeFieldSet(self.0.fields()))?; 285 state.serialize_field("is_span", &self.0.is_span())?; 286 state.serialize_field("is_event", &self.0.is_event())?; 287 state.end() 288 } 289 } 290 291 /// Implements `serde::Serialize` to write `Event` data to a serializer. 292 #[derive(Debug)] 293 pub struct SerializeEvent<'a>(&'a Event<'a>); 294 295 impl<'a> Serialize for SerializeEvent<'a> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,296 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 297 where 298 S: Serializer, 299 { 300 let mut serializer = serializer.serialize_struct("Event", 2)?; 301 serializer.serialize_field("metadata", &SerializeMetadata(self.0.metadata()))?; 302 let mut visitor = SerdeStructVisitor { 303 serializer, 304 state: Ok(()), 305 }; 306 self.0.record(&mut visitor); 307 visitor.finish() 308 } 309 } 310 311 /// Implements `serde::Serialize` to write `Attributes` data to a serializer. 312 #[derive(Debug)] 313 pub struct SerializeAttributes<'a>(&'a Attributes<'a>); 314 315 impl<'a> Serialize for SerializeAttributes<'a> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,316 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 317 where 318 S: Serializer, 319 { 320 let mut serializer = serializer.serialize_struct("Attributes", 3)?; 321 serializer.serialize_field("metadata", &SerializeMetadata(self.0.metadata()))?; 322 serializer.serialize_field("parent", &self.0.parent().map(SerializeId))?; 323 serializer.serialize_field("is_root", &self.0.is_root())?; 324 325 let mut visitor = SerdeStructVisitor { 326 serializer, 327 state: Ok(()), 328 }; 329 self.0.record(&mut visitor); 330 visitor.finish() 331 } 332 } 333 334 /// Implements `serde::Serialize` to write `Record` data to a serializer. 335 #[derive(Debug)] 336 pub struct SerializeRecord<'a>(&'a Record<'a>); 337 338 impl<'a> Serialize for SerializeRecord<'a> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,339 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 340 where 341 S: Serializer, 342 { 343 let serializer = serializer.serialize_map(None)?; 344 let mut visitor = SerdeMapVisitor::new(serializer); 345 self.0.record(&mut visitor); 346 visitor.finish() 347 } 348 } 349 350 /// Implements `tracing_core::field::Visit` for some `serde::ser::SerializeMap`. 351 #[derive(Debug)] 352 pub struct SerdeMapVisitor<S: SerializeMap> { 353 serializer: S, 354 state: Result<(), S::Error>, 355 } 356 357 impl<S> SerdeMapVisitor<S> 358 where 359 S: SerializeMap, 360 { 361 /// Create a new map visitor. new(serializer: S) -> Self362 pub fn new(serializer: S) -> Self { 363 Self { 364 serializer, 365 state: Ok(()), 366 } 367 } 368 369 /// Completes serializing the visited object, returning `Ok(())` if all 370 /// fields were serialized correctly, or `Error(S::Error)` if a field could 371 /// not be serialized. finish(self) -> Result<S::Ok, S::Error>372 pub fn finish(self) -> Result<S::Ok, S::Error> { 373 self.state?; 374 self.serializer.end() 375 } 376 377 /// Completes serializing the visited object, returning ownership of the underlying serializer 378 /// if all fields were serialized correctly, or `Err(S::Error)` if a field could not be 379 /// serialized. take_serializer(self) -> Result<S, S::Error>380 pub fn take_serializer(self) -> Result<S, S::Error> { 381 self.state?; 382 Ok(self.serializer) 383 } 384 } 385 386 impl<S> Visit for SerdeMapVisitor<S> 387 where 388 S: SerializeMap, 389 { 390 #[cfg(all(tracing_unstable, feature = "valuable"))] 391 #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))] record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>)392 fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) { 393 if self.state.is_ok() { 394 self.state = self 395 .serializer 396 .serialize_entry(field.name(), &valuable_serde::Serializable::new(value)); 397 } 398 } 399 record_bool(&mut self, field: &Field, value: bool)400 fn record_bool(&mut self, field: &Field, value: bool) { 401 // If previous fields serialized successfully, continue serializing, 402 // otherwise, short-circuit and do nothing. 403 if self.state.is_ok() { 404 self.state = self.serializer.serialize_entry(field.name(), &value) 405 } 406 } 407 record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)408 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { 409 if self.state.is_ok() { 410 self.state = self 411 .serializer 412 .serialize_entry(field.name(), &format_args!("{:?}", value)) 413 } 414 } 415 record_u64(&mut self, field: &Field, value: u64)416 fn record_u64(&mut self, field: &Field, value: u64) { 417 if self.state.is_ok() { 418 self.state = self.serializer.serialize_entry(field.name(), &value) 419 } 420 } 421 record_i64(&mut self, field: &Field, value: i64)422 fn record_i64(&mut self, field: &Field, value: i64) { 423 if self.state.is_ok() { 424 self.state = self.serializer.serialize_entry(field.name(), &value) 425 } 426 } 427 record_f64(&mut self, field: &Field, value: f64)428 fn record_f64(&mut self, field: &Field, value: f64) { 429 if self.state.is_ok() { 430 self.state = self.serializer.serialize_entry(field.name(), &value) 431 } 432 } 433 record_str(&mut self, field: &Field, value: &str)434 fn record_str(&mut self, field: &Field, value: &str) { 435 if self.state.is_ok() { 436 self.state = self.serializer.serialize_entry(field.name(), &value) 437 } 438 } 439 } 440 441 /// Implements `tracing_core::field::Visit` for some `serde::ser::SerializeStruct`. 442 #[derive(Debug)] 443 pub struct SerdeStructVisitor<S: SerializeStruct> { 444 serializer: S, 445 state: Result<(), S::Error>, 446 } 447 448 impl<S> Visit for SerdeStructVisitor<S> 449 where 450 S: SerializeStruct, 451 { 452 #[cfg(all(tracing_unstable, feature = "valuable"))] 453 #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))] record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>)454 fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) { 455 if self.state.is_ok() { 456 self.state = self 457 .serializer 458 .serialize_field(field.name(), &valuable_serde::Serializable::new(value)); 459 } 460 } 461 record_bool(&mut self, field: &Field, value: bool)462 fn record_bool(&mut self, field: &Field, value: bool) { 463 // If previous fields serialized successfully, continue serializing, 464 // otherwise, short-circuit and do nothing. 465 if self.state.is_ok() { 466 self.state = self.serializer.serialize_field(field.name(), &value) 467 } 468 } 469 record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)470 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { 471 if self.state.is_ok() { 472 self.state = self 473 .serializer 474 .serialize_field(field.name(), &format_args!("{:?}", value)) 475 } 476 } 477 record_u64(&mut self, field: &Field, value: u64)478 fn record_u64(&mut self, field: &Field, value: u64) { 479 if self.state.is_ok() { 480 self.state = self.serializer.serialize_field(field.name(), &value) 481 } 482 } 483 record_i64(&mut self, field: &Field, value: i64)484 fn record_i64(&mut self, field: &Field, value: i64) { 485 if self.state.is_ok() { 486 self.state = self.serializer.serialize_field(field.name(), &value) 487 } 488 } 489 record_f64(&mut self, field: &Field, value: f64)490 fn record_f64(&mut self, field: &Field, value: f64) { 491 if self.state.is_ok() { 492 self.state = self.serializer.serialize_field(field.name(), &value) 493 } 494 } 495 record_str(&mut self, field: &Field, value: &str)496 fn record_str(&mut self, field: &Field, value: &str) { 497 if self.state.is_ok() { 498 self.state = self.serializer.serialize_field(field.name(), &value) 499 } 500 } 501 } 502 503 impl<S: SerializeStruct> SerdeStructVisitor<S> { 504 /// Completes serializing the visited object, returning `Ok(())` if all 505 /// fields were serialized correctly, or `Error(S::Error)` if a field could 506 /// not be serialized. finish(self) -> Result<S::Ok, S::Error>507 pub fn finish(self) -> Result<S::Ok, S::Error> { 508 self.state?; 509 self.serializer.end() 510 } 511 } 512 513 pub trait AsSerde<'a>: self::sealed::Sealed { 514 type Serializable: serde::Serialize + 'a; 515 516 /// `as_serde` borrows a `tracing` value and returns the serialized value. as_serde(&'a self) -> Self::Serializable517 fn as_serde(&'a self) -> Self::Serializable; 518 } 519 520 impl<'a> AsSerde<'a> for tracing_core::Metadata<'a> { 521 type Serializable = SerializeMetadata<'a>; 522 as_serde(&'a self) -> Self::Serializable523 fn as_serde(&'a self) -> Self::Serializable { 524 SerializeMetadata(self) 525 } 526 } 527 528 impl<'a> AsSerde<'a> for tracing_core::Event<'a> { 529 type Serializable = SerializeEvent<'a>; 530 as_serde(&'a self) -> Self::Serializable531 fn as_serde(&'a self) -> Self::Serializable { 532 SerializeEvent(self) 533 } 534 } 535 536 impl<'a> AsSerde<'a> for tracing_core::span::Attributes<'a> { 537 type Serializable = SerializeAttributes<'a>; 538 as_serde(&'a self) -> Self::Serializable539 fn as_serde(&'a self) -> Self::Serializable { 540 SerializeAttributes(self) 541 } 542 } 543 544 impl<'a> AsSerde<'a> for tracing_core::span::Id { 545 type Serializable = SerializeId<'a>; 546 as_serde(&'a self) -> Self::Serializable547 fn as_serde(&'a self) -> Self::Serializable { 548 SerializeId(self) 549 } 550 } 551 552 impl<'a> AsSerde<'a> for tracing_core::span::Record<'a> { 553 type Serializable = SerializeRecord<'a>; 554 as_serde(&'a self) -> Self::Serializable555 fn as_serde(&'a self) -> Self::Serializable { 556 SerializeRecord(self) 557 } 558 } 559 560 impl<'a> AsSerde<'a> for Level { 561 type Serializable = SerializeLevel<'a>; 562 as_serde(&'a self) -> Self::Serializable563 fn as_serde(&'a self) -> Self::Serializable { 564 SerializeLevel(self) 565 } 566 } 567 568 impl<'a> AsSerde<'a> for FieldSet { 569 type Serializable = SerializeFieldSet<'a>; 570 as_serde(&'a self) -> Self::Serializable571 fn as_serde(&'a self) -> Self::Serializable { 572 SerializeFieldSet(self) 573 } 574 } 575 576 impl<'a> self::sealed::Sealed for Event<'a> {} 577 578 impl<'a> self::sealed::Sealed for Attributes<'a> {} 579 580 impl self::sealed::Sealed for Id {} 581 582 impl self::sealed::Sealed for Level {} 583 584 impl<'a> self::sealed::Sealed for Record<'a> {} 585 586 impl<'a> self::sealed::Sealed for Metadata<'a> {} 587 588 impl self::sealed::Sealed for FieldSet {} 589 590 mod sealed { 591 pub trait Sealed {} 592 } 593