1 //! A scoped, structured logging and diagnostics system. 2 //! 3 //! # Overview 4 //! 5 //! `tracing` is a framework for instrumenting Rust programs to collect 6 //! structured, event-based diagnostic information. 7 //! 8 //! In asynchronous systems like Tokio, interpreting traditional log messages can 9 //! often be quite challenging. Since individual tasks are multiplexed on the same 10 //! thread, associated events and log lines are intermixed making it difficult to 11 //! trace the logic flow. `tracing` expands upon logging-style diagnostics by 12 //! allowing libraries and applications to record structured events with additional 13 //! information about *temporality* and *causality* — unlike a log message, a span 14 //! in `tracing` has a beginning and end time, may be entered and exited by the 15 //! flow of execution, and may exist within a nested tree of similar spans. In 16 //! addition, `tracing` spans are *structured*, with the ability to record typed 17 //! data as well as textual messages. 18 //! 19 //! The `tracing` crate provides the APIs necessary for instrumenting libraries 20 //! and applications to emit trace data. 21 //! 22 //! *Compiler support: [requires `rustc` 1.56+][msrv]* 23 //! 24 //! [msrv]: #supported-rust-versions 25 //! # Core Concepts 26 //! 27 //! The core of `tracing`'s API is composed of _spans_, _events_ and 28 //! _subscribers_. We'll cover these in turn. 29 //! 30 //! ## Spans 31 //! 32 //! To record the flow of execution through a program, `tracing` introduces the 33 //! concept of [spans]. Unlike a log line that represents a _moment in 34 //! time_, a span represents a _period of time_ with a beginning and an end. When a 35 //! program begins executing in a context or performing a unit of work, it 36 //! _enters_ that context's span, and when it stops executing in that context, 37 //! it _exits_ the span. The span in which a thread is currently executing is 38 //! referred to as that thread's _current_ span. 39 //! 40 //! For example: 41 //! ``` 42 //! use tracing::{span, Level}; 43 //! # fn main() { 44 //! let span = span!(Level::TRACE, "my_span"); 45 //! // `enter` returns a RAII guard which, when dropped, exits the span. this 46 //! // indicates that we are in the span for the current lexical scope. 47 //! let _enter = span.enter(); 48 //! // perform some work in the context of `my_span`... 49 //! # } 50 //!``` 51 //! 52 //! The [`span` module][span]'s documentation provides further details on how to 53 //! use spans. 54 //! 55 //! <div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;"> 56 //! 57 //! **Warning**: In asynchronous code that uses async/await syntax, 58 //! `Span::enter` may produce incorrect traces if the returned drop 59 //! guard is held across an await point. See 60 //! [the method documentation][Span#in-asynchronous-code] for details. 61 //! 62 //! </pre></div> 63 //! 64 //! ## Events 65 //! 66 //! An [`Event`] represents a _moment_ in time. It signifies something that 67 //! happened while a trace was being recorded. `Event`s are comparable to the log 68 //! records emitted by unstructured logging code, but unlike a typical log line, 69 //! an `Event` may occur within the context of a span. 70 //! 71 //! For example: 72 //! ``` 73 //! use tracing::{event, span, Level}; 74 //! 75 //! # fn main() { 76 //! // records an event outside of any span context: 77 //! event!(Level::INFO, "something happened"); 78 //! 79 //! let span = span!(Level::INFO, "my_span"); 80 //! let _guard = span.enter(); 81 //! 82 //! // records an event within "my_span". 83 //! event!(Level::DEBUG, "something happened inside my_span"); 84 //! # } 85 //!``` 86 //! 87 //! In general, events should be used to represent points in time _within_ a 88 //! span — a request returned with a given status code, _n_ new items were 89 //! taken from a queue, and so on. 90 //! 91 //! The [`Event` struct][`Event`] documentation provides further details on using 92 //! events. 93 //! 94 //! ## Subscribers 95 //! 96 //! As `Span`s and `Event`s occur, they are recorded or aggregated by 97 //! implementations of the [`Subscriber`] trait. `Subscriber`s are notified 98 //! when an `Event` takes place and when a `Span` is entered or exited. These 99 //! notifications are represented by the following `Subscriber` trait methods: 100 //! 101 //! + [`event`][Subscriber::event], called when an `Event` takes place, 102 //! + [`enter`], called when execution enters a `Span`, 103 //! + [`exit`], called when execution exits a `Span` 104 //! 105 //! In addition, subscribers may implement the [`enabled`] function to _filter_ 106 //! the notifications they receive based on [metadata] describing each `Span` 107 //! or `Event`. If a call to `Subscriber::enabled` returns `false` for a given 108 //! set of metadata, that `Subscriber` will *not* be notified about the 109 //! corresponding `Span` or `Event`. For performance reasons, if no currently 110 //! active subscribers express interest in a given set of metadata by returning 111 //! `true`, then the corresponding `Span` or `Event` will never be constructed. 112 //! 113 //! # Usage 114 //! 115 //! First, add this to your `Cargo.toml`: 116 //! 117 //! ```toml 118 //! [dependencies] 119 //! tracing = "0.1" 120 //! ``` 121 //! 122 //! ## Recording Spans and Events 123 //! 124 //! Spans and events are recorded using macros. 125 //! 126 //! ### Spans 127 //! 128 //! The [`span!`] macro expands to a [`Span` struct][`Span`] which is used to 129 //! record a span. The [`Span::enter`] method on that struct records that the 130 //! span has been entered, and returns a [RAII] guard object, which will exit 131 //! the span when dropped. 132 //! 133 //! For example: 134 //! 135 //! ```rust 136 //! use tracing::{span, Level}; 137 //! # fn main() { 138 //! // Construct a new span named "my span" with trace log level. 139 //! let span = span!(Level::TRACE, "my span"); 140 //! 141 //! // Enter the span, returning a guard object. 142 //! let _enter = span.enter(); 143 //! 144 //! // Any trace events that occur before the guard is dropped will occur 145 //! // within the span. 146 //! 147 //! // Dropping the guard will exit the span. 148 //! # } 149 //! ``` 150 //! 151 //! The [`#[instrument]`][instrument] attribute provides an easy way to 152 //! add `tracing` spans to functions. A function annotated with `#[instrument]` 153 //! will create and enter a span with that function's name every time the 154 //! function is called, with arguments to that function will be recorded as 155 //! fields using `fmt::Debug`. 156 //! 157 //! For example: 158 //! ```ignore 159 //! # // this doctest is ignored because we don't have a way to say 160 //! # // that it should only be run with cfg(feature = "attributes") 161 //! use tracing::{Level, event, instrument}; 162 //! 163 //! #[instrument] 164 //! pub fn my_function(my_arg: usize) { 165 //! // This event will be recorded inside a span named `my_function` with the 166 //! // field `my_arg`. 167 //! event!(Level::INFO, "inside my_function!"); 168 //! // ... 169 //! } 170 //! # fn main() {} 171 //! ``` 172 //! 173 //! For functions which don't have built-in tracing support and can't have 174 //! the `#[instrument]` attribute applied (such as from an external crate), 175 //! the [`Span` struct][`Span`] has a [`in_scope()` method][`in_scope`] 176 //! which can be used to easily wrap synchonous code in a span. 177 //! 178 //! For example: 179 //! ```rust 180 //! use tracing::info_span; 181 //! 182 //! # fn doc() -> Result<(), ()> { 183 //! # mod serde_json { 184 //! # pub(crate) fn from_slice(buf: &[u8]) -> Result<(), ()> { Ok(()) } 185 //! # } 186 //! # let buf: [u8; 0] = []; 187 //! let json = info_span!("json.parse").in_scope(|| serde_json::from_slice(&buf))?; 188 //! # let _ = json; // suppress unused variable warning 189 //! # Ok(()) 190 //! # } 191 //! ``` 192 //! 193 //! You can find more examples showing how to use this crate [here][examples]. 194 //! 195 //! [RAII]: https://github.com/rust-unofficial/patterns/blob/main/src/patterns/behavioural/RAII.md 196 //! [examples]: https://github.com/tokio-rs/tracing/tree/master/examples 197 //! 198 //! ### Events 199 //! 200 //! [`Event`]s are recorded using the [`event!`] macro: 201 //! 202 //! ```rust 203 //! # fn main() { 204 //! use tracing::{event, Level}; 205 //! event!(Level::INFO, "something has happened!"); 206 //! # } 207 //! ``` 208 //! 209 //! ## Using the Macros 210 //! 211 //! The [`span!`] and [`event!`] macros as well as the `#[instrument]` attribute 212 //! use fairly similar syntax, with some exceptions. 213 //! 214 //! ### Configuring Attributes 215 //! 216 //! Both macros require a [`Level`] specifying the verbosity of the span or 217 //! event. Optionally, the, [target] and [parent span] may be overridden. If the 218 //! target and parent span are not overridden, they will default to the 219 //! module path where the macro was invoked and the current span (as determined 220 //! by the subscriber), respectively. 221 //! 222 //! For example: 223 //! 224 //! ``` 225 //! # use tracing::{span, event, Level}; 226 //! # fn main() { 227 //! span!(target: "app_spans", Level::TRACE, "my span"); 228 //! event!(target: "app_events", Level::INFO, "something has happened!"); 229 //! # } 230 //! ``` 231 //! ``` 232 //! # use tracing::{span, event, Level}; 233 //! # fn main() { 234 //! let span = span!(Level::TRACE, "my span"); 235 //! event!(parent: &span, Level::INFO, "something has happened!"); 236 //! # } 237 //! ``` 238 //! 239 //! The span macros also take a string literal after the level, to set the name 240 //! of the span (as above). In the case of the event macros, the name of the event can 241 //! be overridden (the default is `event file:line`) using the `name:` specifier. 242 //! 243 //! ``` 244 //! # use tracing::{span, event, Level}; 245 //! # fn main() { 246 //! span!(Level::TRACE, "my span"); 247 //! event!(name: "some_info", Level::INFO, "something has happened!"); 248 //! # } 249 //! ``` 250 //! 251 //! ### Recording Fields 252 //! 253 //! Structured fields on spans and events are specified using the syntax 254 //! `field_name = field_value`. Fields are separated by commas. 255 //! 256 //! ``` 257 //! # use tracing::{event, Level}; 258 //! # fn main() { 259 //! // records an event with two fields: 260 //! // - "answer", with the value 42 261 //! // - "question", with the value "life, the universe and everything" 262 //! event!(Level::INFO, answer = 42, question = "life, the universe, and everything"); 263 //! # } 264 //! ``` 265 //! 266 //! As shorthand, local variables may be used as field values without an 267 //! assignment, similar to [struct initializers]. For example: 268 //! 269 //! ``` 270 //! # use tracing::{span, Level}; 271 //! # fn main() { 272 //! let user = "ferris"; 273 //! 274 //! span!(Level::TRACE, "login", user); 275 //! // is equivalent to: 276 //! span!(Level::TRACE, "login", user = user); 277 //! # } 278 //!``` 279 //! 280 //! Field names can include dots, but should not be terminated by them: 281 //! ``` 282 //! # use tracing::{span, Level}; 283 //! # fn main() { 284 //! let user = "ferris"; 285 //! let email = "[email protected]"; 286 //! span!(Level::TRACE, "login", user, user.email = email); 287 //! # } 288 //!``` 289 //! 290 //! Since field names can include dots, fields on local structs can be used 291 //! using the local variable shorthand: 292 //! ``` 293 //! # use tracing::{span, Level}; 294 //! # fn main() { 295 //! # struct User { 296 //! # name: &'static str, 297 //! # email: &'static str, 298 //! # } 299 //! let user = User { 300 //! name: "ferris", 301 //! email: "[email protected]", 302 //! }; 303 //! // the span will have the fields `user.name = "ferris"` and 304 //! // `user.email = "[email protected]"`. 305 //! span!(Level::TRACE, "login", user.name, user.email); 306 //! # } 307 //!``` 308 //! 309 //! Fields with names that are not Rust identifiers, or with names that are Rust reserved words, 310 //! may be created using quoted string literals. However, this may not be used with the local 311 //! variable shorthand. 312 //! ``` 313 //! # use tracing::{span, Level}; 314 //! # fn main() { 315 //! // records an event with fields whose names are not Rust identifiers 316 //! // - "guid:x-request-id", containing a `:`, with the value "abcdef" 317 //! // - "type", which is a reserved word, with the value "request" 318 //! span!(Level::TRACE, "api", "guid:x-request-id" = "abcdef", "type" = "request"); 319 //! # } 320 //!``` 321 //! 322 //! Constant expressions can also be used as field names. Constants 323 //! must be enclosed in curly braces (`{}`) to indicate that the *value* 324 //! of the constant is to be used as the field name, rather than the 325 //! constant's name. For example: 326 //! ``` 327 //! # use tracing::{span, Level}; 328 //! # fn main() { 329 //! const RESOURCE_NAME: &str = "foo"; 330 //! // this span will have the field `foo = "some_id"` 331 //! span!(Level::TRACE, "get", { RESOURCE_NAME } = "some_id"); 332 //! # } 333 //!``` 334 //! 335 //! The `?` sigil is shorthand that specifies a field should be recorded using 336 //! its [`fmt::Debug`] implementation: 337 //! ``` 338 //! # use tracing::{event, Level}; 339 //! # fn main() { 340 //! #[derive(Debug)] 341 //! struct MyStruct { 342 //! field: &'static str, 343 //! } 344 //! 345 //! let my_struct = MyStruct { 346 //! field: "Hello world!" 347 //! }; 348 //! 349 //! // `my_struct` will be recorded using its `fmt::Debug` implementation. 350 //! event!(Level::TRACE, greeting = ?my_struct); 351 //! // is equivalent to: 352 //! event!(Level::TRACE, greeting = tracing::field::debug(&my_struct)); 353 //! # } 354 //! ``` 355 //! 356 //! The `%` sigil operates similarly, but indicates that the value should be 357 //! recorded using its [`fmt::Display`] implementation: 358 //! ``` 359 //! # use tracing::{event, Level}; 360 //! # fn main() { 361 //! # #[derive(Debug)] 362 //! # struct MyStruct { 363 //! # field: &'static str, 364 //! # } 365 //! # 366 //! # let my_struct = MyStruct { 367 //! # field: "Hello world!" 368 //! # }; 369 //! // `my_struct.field` will be recorded using its `fmt::Display` implementation. 370 //! event!(Level::TRACE, greeting = %my_struct.field); 371 //! // is equivalent to: 372 //! event!(Level::TRACE, greeting = tracing::field::display(&my_struct.field)); 373 //! # } 374 //! ``` 375 //! 376 //! The `%` and `?` sigils may also be used with local variable shorthand: 377 //! 378 //! ``` 379 //! # use tracing::{event, Level}; 380 //! # fn main() { 381 //! # #[derive(Debug)] 382 //! # struct MyStruct { 383 //! # field: &'static str, 384 //! # } 385 //! # 386 //! # let my_struct = MyStruct { 387 //! # field: "Hello world!" 388 //! # }; 389 //! // `my_struct.field` will be recorded using its `fmt::Display` implementation. 390 //! event!(Level::TRACE, %my_struct.field); 391 //! # } 392 //! ``` 393 //! 394 //! Additionally, a span may declare fields with the special value [`Empty`], 395 //! which indicates that that the value for that field does not currently exist 396 //! but may be recorded later. For example: 397 //! 398 //! ``` 399 //! use tracing::{trace_span, field}; 400 //! 401 //! // Create a span with two fields: `greeting`, with the value "hello world", and 402 //! // `parting`, without a value. 403 //! let span = trace_span!("my_span", greeting = "hello world", parting = field::Empty); 404 //! 405 //! // ... 406 //! 407 //! // Now, record a value for parting as well. 408 //! span.record("parting", &"goodbye world!"); 409 //! ``` 410 //! 411 //! Finally, events may also include human-readable messages, in the form of a 412 //! [format string][fmt] and (optional) arguments, **after** the event's 413 //! key-value fields. If a format string and arguments are provided, 414 //! they will implicitly create a new field named `message` whose value is the 415 //! provided set of format arguments. 416 //! 417 //! For example: 418 //! 419 //! ``` 420 //! # use tracing::{event, Level}; 421 //! # fn main() { 422 //! let question = "the ultimate question of life, the universe, and everything"; 423 //! let answer = 42; 424 //! // records an event with the following fields: 425 //! // - `question.answer` with the value 42, 426 //! // - `question.tricky` with the value `true`, 427 //! // - "message", with the value "the answer to the ultimate question of life, the 428 //! // universe, and everything is 42." 429 //! event!( 430 //! Level::DEBUG, 431 //! question.answer = answer, 432 //! question.tricky = true, 433 //! "the answer to {} is {}.", question, answer 434 //! ); 435 //! # } 436 //! ``` 437 //! 438 //! Specifying a formatted message in this manner does not allocate by default. 439 //! 440 //! [struct initializers]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-the-field-init-shorthand-when-variables-and-fields-have-the-same-name 441 //! [target]: Metadata::target 442 //! [parent span]: span::Attributes::parent 443 //! [determined contextually]: span::Attributes::is_contextual 444 //! [`fmt::Debug`]: std::fmt::Debug 445 //! [`fmt::Display`]: std::fmt::Display 446 //! [fmt]: std::fmt#usage 447 //! [`Empty`]: field::Empty 448 //! 449 //! ### Shorthand Macros 450 //! 451 //! `tracing` also offers a number of macros with preset verbosity levels. 452 //! The [`trace!`], [`debug!`], [`info!`], [`warn!`], and [`error!`] behave 453 //! similarly to the [`event!`] macro, but with the [`Level`] argument already 454 //! specified, while the corresponding [`trace_span!`], [`debug_span!`], 455 //! [`info_span!`], [`warn_span!`], and [`error_span!`] macros are the same, 456 //! but for the [`span!`] macro. 457 //! 458 //! These are intended both as a shorthand, and for compatibility with the [`log`] 459 //! crate (see the next section). 460 //! 461 //! [`span!`]: span! 462 //! [`event!`]: event! 463 //! [`trace!`]: trace! 464 //! [`debug!`]: debug! 465 //! [`info!`]: info! 466 //! [`warn!`]: warn! 467 //! [`error!`]: error! 468 //! [`trace_span!`]: trace_span! 469 //! [`debug_span!`]: debug_span! 470 //! [`info_span!`]: info_span! 471 //! [`warn_span!`]: warn_span! 472 //! [`error_span!`]: error_span! 473 //! 474 //! ### For `log` Users 475 //! 476 //! Users of the [`log`] crate should note that `tracing` exposes a set of 477 //! macros for creating `Event`s (`trace!`, `debug!`, `info!`, `warn!`, and 478 //! `error!`) which may be invoked with the same syntax as the similarly-named 479 //! macros from the `log` crate. Often, the process of converting a project to 480 //! use `tracing` can begin with a simple drop-in replacement. 481 //! 482 //! Let's consider the `log` crate's yak-shaving example: 483 //! 484 //! ```rust,ignore 485 //! use std::{error::Error, io}; 486 //! use tracing::{debug, error, info, span, warn, Level}; 487 //! 488 //! // the `#[tracing::instrument]` attribute creates and enters a span 489 //! // every time the instrumented function is called. The span is named after the 490 //! // the function or method. Parameters passed to the function are recorded as fields. 491 //! #[tracing::instrument] 492 //! pub fn shave(yak: usize) -> Result<(), Box<dyn Error + 'static>> { 493 //! // this creates an event at the DEBUG level with two fields: 494 //! // - `excitement`, with the key "excitement" and the value "yay!" 495 //! // - `message`, with the key "message" and the value "hello! I'm gonna shave a yak." 496 //! // 497 //! // unlike other fields, `message`'s shorthand initialization is just the string itself. 498 //! debug!(excitement = "yay!", "hello! I'm gonna shave a yak."); 499 //! if yak == 3 { 500 //! warn!("could not locate yak!"); 501 //! // note that this is intended to demonstrate `tracing`'s features, not idiomatic 502 //! // error handling! in a library or application, you should consider returning 503 //! // a dedicated `YakError`. libraries like snafu or thiserror make this easy. 504 //! return Err(io::Error::new(io::ErrorKind::Other, "shaving yak failed!").into()); 505 //! } else { 506 //! debug!("yak shaved successfully"); 507 //! } 508 //! Ok(()) 509 //! } 510 //! 511 //! pub fn shave_all(yaks: usize) -> usize { 512 //! // Constructs a new span named "shaving_yaks" at the TRACE level, 513 //! // and a field whose key is "yaks". This is equivalent to writing: 514 //! // 515 //! // let span = span!(Level::TRACE, "shaving_yaks", yaks = yaks); 516 //! // 517 //! // local variables (`yaks`) can be used as field values 518 //! // without an assignment, similar to struct initializers. 519 //! let _span = span!(Level::TRACE, "shaving_yaks", yaks).entered(); 520 //! 521 //! info!("shaving yaks"); 522 //! 523 //! let mut yaks_shaved = 0; 524 //! for yak in 1..=yaks { 525 //! let res = shave(yak); 526 //! debug!(yak, shaved = res.is_ok()); 527 //! 528 //! if let Err(ref error) = res { 529 //! // Like spans, events can also use the field initialization shorthand. 530 //! // In this instance, `yak` is the field being initalized. 531 //! error!(yak, error = error.as_ref(), "failed to shave yak!"); 532 //! } else { 533 //! yaks_shaved += 1; 534 //! } 535 //! debug!(yaks_shaved); 536 //! } 537 //! 538 //! yaks_shaved 539 //! } 540 //! ``` 541 //! 542 //! ## In libraries 543 //! 544 //! Libraries should link only to the `tracing` crate, and use the provided 545 //! macros to record whatever information will be useful to downstream 546 //! consumers. 547 //! 548 //! ## In executables 549 //! 550 //! In order to record trace events, executables have to use a `Subscriber` 551 //! implementation compatible with `tracing`. A `Subscriber` implements a 552 //! way of collecting trace data, such as by logging it to standard output. 553 //! 554 //! This library does not contain any `Subscriber` implementations; these are 555 //! provided by [other crates](#related-crates). 556 //! 557 //! The simplest way to use a subscriber is to call the [`set_global_default`] 558 //! function: 559 //! 560 //! ``` 561 //! extern crate tracing; 562 //! # pub struct FooSubscriber; 563 //! # use tracing::{span::{Id, Attributes, Record}, Metadata}; 564 //! # impl tracing::Subscriber for FooSubscriber { 565 //! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) } 566 //! # fn record(&self, _: &Id, _: &Record) {} 567 //! # fn event(&self, _: &tracing::Event) {} 568 //! # fn record_follows_from(&self, _: &Id, _: &Id) {} 569 //! # fn enabled(&self, _: &Metadata) -> bool { false } 570 //! # fn enter(&self, _: &Id) {} 571 //! # fn exit(&self, _: &Id) {} 572 //! # } 573 //! # impl FooSubscriber { 574 //! # fn new() -> Self { FooSubscriber } 575 //! # } 576 //! # fn main() { 577 //! 578 //! let my_subscriber = FooSubscriber::new(); 579 //! tracing::subscriber::set_global_default(my_subscriber) 580 //! .expect("setting tracing default failed"); 581 //! # } 582 //! ``` 583 //! 584 //! <pre class="compile_fail" style="white-space:normal;font:inherit;"> 585 //! <strong>Warning</strong>: In general, libraries should <em>not</em> call 586 //! <code>set_global_default()</code>! Doing so will cause conflicts when 587 //! executables that depend on the library try to set the default later. 588 //! </pre> 589 //! 590 //! This subscriber will be used as the default in all threads for the 591 //! remainder of the duration of the program, similar to setting the logger 592 //! in the `log` crate. 593 //! 594 //! In addition, the default subscriber can be set through using the 595 //! [`with_default`] function. This follows the `tokio` pattern of using 596 //! closures to represent executing code in a context that is exited at the end 597 //! of the closure. For example: 598 //! 599 //! ```rust 600 //! # pub struct FooSubscriber; 601 //! # use tracing::{span::{Id, Attributes, Record}, Metadata}; 602 //! # impl tracing::Subscriber for FooSubscriber { 603 //! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) } 604 //! # fn record(&self, _: &Id, _: &Record) {} 605 //! # fn event(&self, _: &tracing::Event) {} 606 //! # fn record_follows_from(&self, _: &Id, _: &Id) {} 607 //! # fn enabled(&self, _: &Metadata) -> bool { false } 608 //! # fn enter(&self, _: &Id) {} 609 //! # fn exit(&self, _: &Id) {} 610 //! # } 611 //! # impl FooSubscriber { 612 //! # fn new() -> Self { FooSubscriber } 613 //! # } 614 //! # fn main() { 615 //! 616 //! let my_subscriber = FooSubscriber::new(); 617 //! # #[cfg(feature = "std")] 618 //! tracing::subscriber::with_default(my_subscriber, || { 619 //! // Any trace events generated in this closure or by functions it calls 620 //! // will be collected by `my_subscriber`. 621 //! }) 622 //! # } 623 //! ``` 624 //! 625 //! This approach allows trace data to be collected by multiple subscribers 626 //! within different contexts in the program. Note that the override only applies to the 627 //! currently executing thread; other threads will not see the change from with_default. 628 //! 629 //! Any trace events generated outside the context of a subscriber will not be collected. 630 //! 631 //! Once a subscriber has been set, instrumentation points may be added to the 632 //! executable using the `tracing` crate's macros. 633 //! 634 //! ## `log` Compatibility 635 //! 636 //! The [`log`] crate provides a simple, lightweight logging facade for Rust. 637 //! While `tracing` builds upon `log`'s foundation with richer structured 638 //! diagnostic data, `log`'s simplicity and ubiquity make it the "lowest common 639 //! denominator" for text-based logging in Rust — a vast majority of Rust 640 //! libraries and applications either emit or consume `log` records. Therefore, 641 //! `tracing` provides multiple forms of interoperability with `log`: `tracing` 642 //! instrumentation can emit `log` records, and a compatibility layer enables 643 //! `tracing` [`Subscriber`]s to consume `log` records as `tracing` [`Event`]s. 644 //! 645 //! ### Emitting `log` Records 646 //! 647 //! This crate provides two feature flags, "log" and "log-always", which will 648 //! cause [spans] and [events] to emit `log` records. When the "log" feature is 649 //! enabled, if no `tracing` `Subscriber` is active, invoking an event macro or 650 //! creating a span with fields will emit a `log` record. This is intended 651 //! primarily for use in libraries which wish to emit diagnostics that can be 652 //! consumed by applications using `tracing` *or* `log`, without paying the 653 //! additional overhead of emitting both forms of diagnostics when `tracing` is 654 //! in use. 655 //! 656 //! Enabling the "log-always" feature will cause `log` records to be emitted 657 //! even if a `tracing` `Subscriber` _is_ set. This is intended to be used in 658 //! applications where a `log` `Logger` is being used to record a textual log, 659 //! and `tracing` is used only to record other forms of diagnostics (such as 660 //! metrics, profiling, or distributed tracing data). Unlike the "log" feature, 661 //! libraries generally should **not** enable the "log-always" feature, as doing 662 //! so will prevent applications from being able to opt out of the `log` records. 663 //! 664 //! See [here][flags] for more details on this crate's feature flags. 665 //! 666 //! The generated `log` records' messages will be a string representation of the 667 //! span or event's fields, and all additional information recorded by `log` 668 //! (target, verbosity level, module path, file, and line number) will also be 669 //! populated. Additionally, `log` records are also generated when spans are 670 //! entered, exited, and closed. Since these additional span lifecycle logs have 671 //! the potential to be very verbose, and don't include additional fields, they 672 //! will always be emitted at the `Trace` level, rather than inheriting the 673 //! level of the span that generated them. Furthermore, they are are categorized 674 //! under a separate `log` target, "tracing::span" (and its sub-target, 675 //! "tracing::span::active", for the logs on entering and exiting a span), which 676 //! may be enabled or disabled separately from other `log` records emitted by 677 //! `tracing`. 678 //! 679 //! ### Consuming `log` Records 680 //! 681 //! The [`tracing-log`] crate provides a compatibility layer which 682 //! allows a `tracing` [`Subscriber`] to consume `log` records as though they 683 //! were `tracing` [events]. This allows applications using `tracing` to record 684 //! the logs emitted by dependencies using `log` as events within the context of 685 //! the application's trace tree. See [that crate's documentation][log-tracer] 686 //! for details. 687 //! 688 //! [log-tracer]: https://docs.rs/tracing-log/latest/tracing_log/#convert-log-records-to-tracing-events 689 //! 690 //! ## Related Crates 691 //! 692 //! In addition to `tracing` and `tracing-core`, the [`tokio-rs/tracing`] repository 693 //! contains several additional crates designed to be used with the `tracing` ecosystem. 694 //! This includes a collection of `Subscriber` implementations, as well as utility 695 //! and adapter crates to assist in writing `Subscriber`s and instrumenting 696 //! applications. 697 //! 698 //! In particular, the following crates are likely to be of interest: 699 //! 700 //! - [`tracing-futures`] provides a compatibility layer with the `futures` 701 //! crate, allowing spans to be attached to `Future`s, `Stream`s, and `Executor`s. 702 //! - [`tracing-subscriber`] provides `Subscriber` implementations and 703 //! utilities for working with `Subscriber`s. This includes a [`FmtSubscriber`] 704 //! `FmtSubscriber` for logging formatted trace data to stdout, with similar 705 //! filtering and formatting to the [`env_logger`] crate. 706 //! - [`tracing-log`] provides a compatibility layer with the [`log`] crate, 707 //! allowing log messages to be recorded as `tracing` `Event`s within the 708 //! trace tree. This is useful when a project using `tracing` have 709 //! dependencies which use `log`. Note that if you're using 710 //! `tracing-subscriber`'s `FmtSubscriber`, you don't need to depend on 711 //! `tracing-log` directly. 712 //! - [`tracing-appender`] provides utilities for outputting tracing data, 713 //! including a file appender and non blocking writer. 714 //! 715 //! Additionally, there are also several third-party crates which are not 716 //! maintained by the `tokio` project. These include: 717 //! 718 //! - [`tracing-timing`] implements inter-event timing metrics on top of `tracing`. 719 //! It provides a subscriber that records the time elapsed between pairs of 720 //! `tracing` events and generates histograms. 721 //! - [`tracing-opentelemetry`] provides a subscriber for emitting traces to 722 //! [OpenTelemetry]-compatible distributed tracing systems. 723 //! - [`tracing-honeycomb`] Provides a layer that reports traces spanning multiple machines to [honeycomb.io]. Backed by [`tracing-distributed`]. 724 //! - [`tracing-distributed`] Provides a generic implementation of a layer that reports traces spanning multiple machines to some backend. 725 //! - [`tracing-actix-web`] provides `tracing` integration for the `actix-web` web framework. 726 //! - [`tracing-actix`] provides `tracing` integration for the `actix` actor 727 //! framework. 728 //! - [`axum-insights`] provides `tracing` integration and Application insights export for the `axum` web framework. 729 //! - [`tracing-gelf`] implements a subscriber for exporting traces in Greylog 730 //! GELF format. 731 //! - [`tracing-coz`] provides integration with the [coz] causal profiler 732 //! (Linux-only). 733 //! - [`tracing-bunyan-formatter`] provides a layer implementation that reports events and spans 734 //! in [bunyan] format, enriched with timing information. 735 //! - [`tracing-wasm`] provides a `Subscriber`/`Layer` implementation that reports 736 //! events and spans via browser `console.log` and [User Timing API (`window.performance`)]. 737 //! - [`tracing-web`] provides a layer implementation of level-aware logging of events 738 //! to web browsers' `console.*` and span events to the [User Timing API (`window.performance`)]. 739 //! - [`tide-tracing`] provides a [tide] middleware to trace all incoming requests and responses. 740 //! - [`test-log`] takes care of initializing `tracing` for tests, based on 741 //! environment variables with an `env_logger` compatible syntax. 742 //! - [`tracing-unwrap`] provides convenience methods to report failed unwraps 743 //! on `Result` or `Option` types to a `Subscriber`. 744 //! - [`diesel-tracing`] provides integration with [`diesel`] database connections. 745 //! - [`tracing-tracy`] provides a way to collect [Tracy] profiles in instrumented 746 //! applications. 747 //! - [`tracing-elastic-apm`] provides a layer for reporting traces to [Elastic APM]. 748 //! - [`tracing-etw`] provides a layer for emitting Windows [ETW] events. 749 //! - [`tracing-fluent-assertions`] provides a fluent assertions-style testing 750 //! framework for validating the behavior of `tracing` spans. 751 //! - [`sentry-tracing`] provides a layer for reporting events and traces to [Sentry]. 752 //! - [`tracing-forest`] provides a subscriber that preserves contextual coherence by 753 //! grouping together logs from the same spans during writing. 754 //! - [`tracing-loki`] provides a layer for shipping logs to [Grafana Loki]. 755 //! - [`tracing-logfmt`] provides a layer that formats events and spans into the logfmt format. 756 //! - [`reqwest-tracing`] provides a middleware to trace [`reqwest`] HTTP requests. 757 //! - [`tracing-cloudwatch`] provides a layer that sends events to AWS CloudWatch Logs. 758 //! - [`clippy-tracing`] provides a tool to add, remove and check for `tracing::instrument`. 759 //! 760 //! If you're the maintainer of a `tracing` ecosystem crate not listed above, 761 //! please let us know! We'd love to add your project to the list! 762 //! 763 //! [`tracing-opentelemetry`]: https://crates.io/crates/tracing-opentelemetry 764 //! [OpenTelemetry]: https://opentelemetry.io/ 765 //! [`tracing-honeycomb`]: https://crates.io/crates/tracing-honeycomb 766 //! [`tracing-distributed`]: https://crates.io/crates/tracing-distributed 767 //! [honeycomb.io]: https://www.honeycomb.io/ 768 //! [`tracing-actix-web`]: https://crates.io/crates/tracing-actix-web 769 //! [`tracing-actix`]: https://crates.io/crates/tracing-actix 770 //! [`axum-insights`]: https://crates.io/crates/axum-insights 771 //! [`tracing-gelf`]: https://crates.io/crates/tracing-gelf 772 //! [`tracing-coz`]: https://crates.io/crates/tracing-coz 773 //! [coz]: https://github.com/plasma-umass/coz 774 //! [`tracing-bunyan-formatter`]: https://crates.io/crates/tracing-bunyan-formatter 775 //! [bunyan]: https://github.com/trentm/node-bunyan 776 //! [`tracing-wasm`]: https://docs.rs/tracing-wasm 777 //! [`tracing-web`]: https://docs.rs/tracing-web 778 //! [User Timing API (`window.performance`)]: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API 779 //! [`tide-tracing`]: https://crates.io/crates/tide-tracing 780 //! [tide]: https://crates.io/crates/tide 781 //! [`test-log`]: https://crates.io/crates/test-log 782 //! [`tracing-unwrap`]: https://docs.rs/tracing-unwrap 783 //! [`diesel`]: https://crates.io/crates/diesel 784 //! [`diesel-tracing`]: https://crates.io/crates/diesel-tracing 785 //! [`tracing-tracy`]: https://crates.io/crates/tracing-tracy 786 //! [Tracy]: https://github.com/wolfpld/tracy 787 //! [`tracing-elastic-apm`]: https://crates.io/crates/tracing-elastic-apm 788 //! [Elastic APM]: https://www.elastic.co/apm 789 //! [`tracing-etw`]: https://github.com/microsoft/rust_win_etw/tree/main/win_etw_tracing 790 //! [ETW]: https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing 791 //! [`tracing-fluent-assertions`]: https://crates.io/crates/tracing-fluent-assertions 792 //! [`sentry-tracing`]: https://crates.io/crates/sentry-tracing 793 //! [Sentry]: https://sentry.io/welcome/ 794 //! [`tracing-forest`]: https://crates.io/crates/tracing-forest 795 //! [`tracing-loki`]: https://crates.io/crates/tracing-loki 796 //! [Grafana Loki]: https://grafana.com/oss/loki/ 797 //! [`tracing-logfmt`]: https://crates.io/crates/tracing-logfmt 798 //! [`reqwest-tracing`]: https://crates.io/crates/reqwest-tracing 799 //! [`reqwest`]: https://crates.io/crates/reqwest 800 //! [`tracing-cloudwatch`]: https://crates.io/crates/tracing-cloudwatch 801 //! [`clippy-tracing`]: https://crates.io/crates/clippy-tracing 802 //! 803 //! <pre class="ignore" style="white-space:normal;font:inherit;"> 804 //! <strong>Note</strong>: Some of these ecosystem crates are currently 805 //! unreleased and/or in earlier stages of development. They may be less stable 806 //! than <code>tracing</code> and <code>tracing-core</code>. 807 //! </pre> 808 //! 809 //! ## Crate Feature Flags 810 //! 811 //! The following crate [feature flags] are available: 812 //! 813 //! * A set of features controlling the [static verbosity level]. 814 //! * `log`: causes trace instrumentation points to emit [`log`] records as well 815 //! as trace events, if a default `tracing` subscriber has not been set. This 816 //! is intended for use in libraries whose users may be using either `tracing` 817 //! or `log`. 818 //! * `log-always`: Emit `log` records from all `tracing` spans and events, even 819 //! if a `tracing` subscriber has been set. This should be set only by 820 //! applications which intend to collect traces and logs separately; if an 821 //! adapter is used to convert `log` records into `tracing` events, this will 822 //! cause duplicate events to occur. 823 //! * `attributes`: Includes support for the `#[instrument]` attribute. 824 //! This is on by default, but does bring in the `syn` crate as a dependency, 825 //! which may add to the compile time of crates that do not already use it. 826 //! * `std`: Depend on the Rust standard library (enabled by default). 827 //! 828 //! `no_std` users may disable this feature with `default-features = false`: 829 //! 830 //! ```toml 831 //! [dependencies] 832 //! tracing = { version = "0.1.38", default-features = false } 833 //! ``` 834 //! 835 //! <pre class="ignore" style="white-space:normal;font:inherit;"> 836 //! <strong>Note</strong>: <code>tracing</code>'s <code>no_std</code> support 837 //! requires <code>liballoc</code>. 838 //! </pre> 839 //! 840 //! ### Unstable Features 841 //! 842 //! These feature flags enable **unstable** features. The public API may break in 0.1.x 843 //! releases. To enable these features, the `--cfg tracing_unstable` must be passed to 844 //! `rustc` when compiling. 845 //! 846 //! The following unstable feature flags are currently available: 847 //! 848 //! * `valuable`: Enables support for recording [field values] using the 849 //! [`valuable`] crate. 850 //! 851 //! #### Enabling Unstable Features 852 //! 853 //! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS` 854 //! env variable when running `cargo` commands: 855 //! 856 //! ```shell 857 //! RUSTFLAGS="--cfg tracing_unstable" cargo build 858 //! ``` 859 //! Alternatively, the following can be added to the `.cargo/config` file in a 860 //! project to automatically enable the cfg flag for that project: 861 //! 862 //! ```toml 863 //! [build] 864 //! rustflags = ["--cfg", "tracing_unstable"] 865 //! ``` 866 //! 867 //! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section 868 //! [field values]: crate::field 869 //! [`valuable`]: https://crates.io/crates/valuable 870 //! 871 //! ## Supported Rust Versions 872 //! 873 //! Tracing is built against the latest stable release. The minimum supported 874 //! version is 1.56. The current Tracing version is not guaranteed to build on 875 //! Rust versions earlier than the minimum supported version. 876 //! 877 //! Tracing follows the same compiler support policies as the rest of the Tokio 878 //! project. The current stable Rust compiler and the three most recent minor 879 //! versions before it will always be supported. For example, if the current 880 //! stable compiler version is 1.69, the minimum supported version will not be 881 //! increased past 1.66, three minor versions prior. Increasing the minimum 882 //! supported compiler version is not considered a semver breaking change as 883 //! long as doing so complies with this policy. 884 //! 885 //! [`log`]: https://docs.rs/log/0.4.6/log/ 886 //! [span]: mod@span 887 //! [spans]: mod@span 888 //! [`Span`]: span::Span 889 //! [`in_scope`]: span::Span::in_scope 890 //! [event]: Event 891 //! [events]: Event 892 //! [`Subscriber`]: subscriber::Subscriber 893 //! [Subscriber::event]: subscriber::Subscriber::event 894 //! [`enter`]: subscriber::Subscriber::enter 895 //! [`exit`]: subscriber::Subscriber::exit 896 //! [`enabled`]: subscriber::Subscriber::enabled 897 //! [metadata]: Metadata 898 //! [`field::display`]: field::display 899 //! [`field::debug`]: field::debug 900 //! [`set_global_default`]: subscriber::set_global_default 901 //! [`with_default`]: subscriber::with_default 902 //! [`tokio-rs/tracing`]: https://github.com/tokio-rs/tracing 903 //! [`tracing-futures`]: https://crates.io/crates/tracing-futures 904 //! [`tracing-subscriber`]: https://crates.io/crates/tracing-subscriber 905 //! [`tracing-log`]: https://crates.io/crates/tracing-log 906 //! [`tracing-timing`]: https://crates.io/crates/tracing-timing 907 //! [`tracing-appender`]: https://crates.io/crates/tracing-appender 908 //! [`env_logger`]: https://crates.io/crates/env_logger 909 //! [`FmtSubscriber`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/struct.Subscriber.html 910 //! [static verbosity level]: level_filters#compile-time-filters 911 //! [instrument]: https://docs.rs/tracing-attributes/latest/tracing_attributes/attr.instrument.html 912 //! [flags]: #crate-feature-flags 913 #![cfg_attr(not(feature = "std"), no_std)] 914 #![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] 915 #![doc( 916 html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", 917 issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" 918 )] 919 #![warn( 920 missing_debug_implementations, 921 missing_docs, 922 rust_2018_idioms, 923 unreachable_pub, 924 bad_style, 925 dead_code, 926 improper_ctypes, 927 non_shorthand_field_patterns, 928 no_mangle_generic_items, 929 overflowing_literals, 930 path_statements, 931 patterns_in_fns_without_body, 932 private_in_public, 933 unconditional_recursion, 934 unused, 935 unused_allocation, 936 unused_comparisons, 937 unused_parens, 938 while_true 939 )] 940 941 #[cfg(not(feature = "std"))] 942 extern crate alloc; 943 944 // Somehow this `use` statement is necessary for us to re-export the `core` 945 // macros on Rust 1.26.0. I'm not sure how this makes it work, but it does. 946 #[allow(unused_imports)] 947 #[doc(hidden)] 948 use tracing_core::*; 949 950 #[doc(inline)] 951 pub use self::instrument::Instrument; 952 pub use self::{dispatcher::Dispatch, event::Event, field::Value, subscriber::Subscriber}; 953 954 #[doc(hidden)] 955 pub use self::span::Id; 956 957 #[doc(hidden)] 958 pub use tracing_core::{ 959 callsite::{self, Callsite}, 960 metadata, 961 }; 962 pub use tracing_core::{event, Level, Metadata}; 963 964 #[doc(inline)] 965 pub use self::span::Span; 966 #[cfg(feature = "attributes")] 967 #[cfg_attr(docsrs, doc(cfg(feature = "attributes")))] 968 #[doc(inline)] 969 pub use tracing_attributes::instrument; 970 971 #[macro_use] 972 mod macros; 973 974 pub mod dispatcher; 975 pub mod field; 976 /// Attach a span to a `std::future::Future`. 977 pub mod instrument; 978 pub mod level_filters; 979 pub mod span; 980 pub(crate) mod stdlib; 981 pub mod subscriber; 982 983 #[doc(hidden)] 984 pub mod __macro_support { 985 pub use crate::callsite::Callsite; 986 use crate::{subscriber::Interest, Metadata}; 987 pub use core::concat; 988 989 /// Callsite implementation used by macro-generated code. 990 /// 991 /// /!\ WARNING: This is *not* a stable API! /!\ 992 /// This type, and all code contained in the `__macro_support` module, is 993 /// a *private* API of `tracing`. It is exposed publicly because it is used 994 /// by the `tracing` macros, but it is not part of the stable versioned API. 995 /// Breaking changes to this module may occur in small-numbered versions 996 /// without warning. 997 pub use tracing_core::callsite::DefaultCallsite as MacroCallsite; 998 999 /// /!\ WARNING: This is *not* a stable API! /!\ 1000 /// This function, and all code contained in the `__macro_support` module, is 1001 /// a *private* API of `tracing`. It is exposed publicly because it is used 1002 /// by the `tracing` macros, but it is not part of the stable versioned API. 1003 /// Breaking changes to this module may occur in small-numbered versions 1004 /// without warning. __is_enabled(meta: &Metadata<'static>, interest: Interest) -> bool1005 pub fn __is_enabled(meta: &Metadata<'static>, interest: Interest) -> bool { 1006 interest.is_always() || crate::dispatcher::get_default(|default| default.enabled(meta)) 1007 } 1008 1009 /// /!\ WARNING: This is *not* a stable API! /!\ 1010 /// This function, and all code contained in the `__macro_support` module, is 1011 /// a *private* API of `tracing`. It is exposed publicly because it is used 1012 /// by the `tracing` macros, but it is not part of the stable versioned API. 1013 /// Breaking changes to this module may occur in small-numbered versions 1014 /// without warning. 1015 #[inline] 1016 #[cfg(feature = "log")] __disabled_span(meta: &'static Metadata<'static>) -> crate::Span1017 pub fn __disabled_span(meta: &'static Metadata<'static>) -> crate::Span { 1018 crate::Span::new_disabled(meta) 1019 } 1020 1021 /// /!\ WARNING: This is *not* a stable API! /!\ 1022 /// This function, and all code contained in the `__macro_support` module, is 1023 /// a *private* API of `tracing`. It is exposed publicly because it is used 1024 /// by the `tracing` macros, but it is not part of the stable versioned API. 1025 /// Breaking changes to this module may occur in small-numbered versions 1026 /// without warning. 1027 #[inline] 1028 #[cfg(not(feature = "log"))] __disabled_span(_: &'static Metadata<'static>) -> crate::Span1029 pub fn __disabled_span(_: &'static Metadata<'static>) -> crate::Span { 1030 crate::Span::none() 1031 } 1032 1033 /// /!\ WARNING: This is *not* a stable API! /!\ 1034 /// This function, and all code contained in the `__macro_support` module, is 1035 /// a *private* API of `tracing`. It is exposed publicly because it is used 1036 /// by the `tracing` macros, but it is not part of the stable versioned API. 1037 /// Breaking changes to this module may occur in small-numbered versions 1038 /// without warning. 1039 #[cfg(feature = "log")] __tracing_log( meta: &Metadata<'static>, logger: &'static dyn log::Log, log_meta: log::Metadata<'_>, values: &tracing_core::field::ValueSet<'_>, )1040 pub fn __tracing_log( 1041 meta: &Metadata<'static>, 1042 logger: &'static dyn log::Log, 1043 log_meta: log::Metadata<'_>, 1044 values: &tracing_core::field::ValueSet<'_>, 1045 ) { 1046 logger.log( 1047 &crate::log::Record::builder() 1048 .file(meta.file()) 1049 .module_path(meta.module_path()) 1050 .line(meta.line()) 1051 .metadata(log_meta) 1052 .args(format_args!( 1053 "{}", 1054 crate::log::LogValueSet { 1055 values, 1056 is_first: true 1057 } 1058 )) 1059 .build(), 1060 ); 1061 } 1062 } 1063 1064 #[cfg(feature = "log")] 1065 #[doc(hidden)] 1066 pub mod log { 1067 use core::fmt; 1068 pub use log::*; 1069 use tracing_core::field::{Field, ValueSet, Visit}; 1070 1071 /// Utility to format [`ValueSet`]s for logging. 1072 pub(crate) struct LogValueSet<'a> { 1073 pub(crate) values: &'a ValueSet<'a>, 1074 pub(crate) is_first: bool, 1075 } 1076 1077 impl<'a> fmt::Display for LogValueSet<'a> { 1078 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1079 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1080 struct LogVisitor<'a, 'b> { 1081 f: &'a mut fmt::Formatter<'b>, 1082 is_first: bool, 1083 result: fmt::Result, 1084 } 1085 1086 impl Visit for LogVisitor<'_, '_> { 1087 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { 1088 let res = if self.is_first { 1089 self.is_first = false; 1090 if field.name() == "message" { 1091 write!(self.f, "{:?}", value) 1092 } else { 1093 write!(self.f, "{}={:?}", field.name(), value) 1094 } 1095 } else { 1096 write!(self.f, " {}={:?}", field.name(), value) 1097 }; 1098 if let Err(err) = res { 1099 self.result = self.result.and(Err(err)); 1100 } 1101 } 1102 1103 fn record_str(&mut self, field: &Field, value: &str) { 1104 if field.name() == "message" { 1105 self.record_debug(field, &format_args!("{}", value)) 1106 } else { 1107 self.record_debug(field, &value) 1108 } 1109 } 1110 } 1111 1112 let mut visit = LogVisitor { 1113 f, 1114 is_first: self.is_first, 1115 result: Ok(()), 1116 }; 1117 self.values.record(&mut visit); 1118 visit.result 1119 } 1120 } 1121 } 1122 1123 mod sealed { 1124 pub trait Sealed {} 1125 } 1126