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.49+][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/master/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. 241 //! 242 //! ### Recording Fields 243 //! 244 //! Structured fields on spans and events are specified using the syntax 245 //! `field_name = field_value`. Fields are separated by commas. 246 //! 247 //! ``` 248 //! # use tracing::{event, Level}; 249 //! # fn main() { 250 //! // records an event with two fields: 251 //! // - "answer", with the value 42 252 //! // - "question", with the value "life, the universe and everything" 253 //! event!(Level::INFO, answer = 42, question = "life, the universe, and everything"); 254 //! # } 255 //! ``` 256 //! 257 //! As shorthand, local variables may be used as field values without an 258 //! assignment, similar to [struct initializers]. For example: 259 //! 260 //! ``` 261 //! # use tracing::{span, Level}; 262 //! # fn main() { 263 //! let user = "ferris"; 264 //! 265 //! span!(Level::TRACE, "login", user); 266 //! // is equivalent to: 267 //! span!(Level::TRACE, "login", user = user); 268 //! # } 269 //!``` 270 //! 271 //! Field names can include dots, but should not be terminated by them: 272 //! ``` 273 //! # use tracing::{span, Level}; 274 //! # fn main() { 275 //! let user = "ferris"; 276 //! let email = "ferris@rust-lang.org"; 277 //! span!(Level::TRACE, "login", user, user.email = email); 278 //! # } 279 //!``` 280 //! 281 //! Since field names can include dots, fields on local structs can be used 282 //! using the local variable shorthand: 283 //! ``` 284 //! # use tracing::{span, Level}; 285 //! # fn main() { 286 //! # struct User { 287 //! # name: &'static str, 288 //! # email: &'static str, 289 //! # } 290 //! let user = User { 291 //! name: "ferris", 292 //! email: "ferris@rust-lang.org", 293 //! }; 294 //! // the span will have the fields `user.name = "ferris"` and 295 //! // `user.email = "ferris@rust-lang.org"`. 296 //! span!(Level::TRACE, "login", user.name, user.email); 297 //! # } 298 //!``` 299 //! 300 //! Fields with names that are not Rust identifiers, or with names that are Rust reserved words, 301 //! may be created using quoted string literals. However, this may not be used with the local 302 //! variable shorthand. 303 //! ``` 304 //! # use tracing::{span, Level}; 305 //! # fn main() { 306 //! // records an event with fields whose names are not Rust identifiers 307 //! // - "guid:x-request-id", containing a `:`, with the value "abcdef" 308 //! // - "type", which is a reserved word, with the value "request" 309 //! span!(Level::TRACE, "api", "guid:x-request-id" = "abcdef", "type" = "request"); 310 //! # } 311 //!``` 312 //! 313 //! The `?` sigil is shorthand that specifies a field should be recorded using 314 //! its [`fmt::Debug`] implementation: 315 //! ``` 316 //! # use tracing::{event, Level}; 317 //! # fn main() { 318 //! #[derive(Debug)] 319 //! struct MyStruct { 320 //! field: &'static str, 321 //! } 322 //! 323 //! let my_struct = MyStruct { 324 //! field: "Hello world!" 325 //! }; 326 //! 327 //! // `my_struct` will be recorded using its `fmt::Debug` implementation. 328 //! event!(Level::TRACE, greeting = ?my_struct); 329 //! // is equivalent to: 330 //! event!(Level::TRACE, greeting = tracing::field::debug(&my_struct)); 331 //! # } 332 //! ``` 333 //! 334 //! The `%` sigil operates similarly, but indicates that the value should be 335 //! recorded using its [`fmt::Display`] implementation: 336 //! ``` 337 //! # use tracing::{event, Level}; 338 //! # fn main() { 339 //! # #[derive(Debug)] 340 //! # struct MyStruct { 341 //! # field: &'static str, 342 //! # } 343 //! # 344 //! # let my_struct = MyStruct { 345 //! # field: "Hello world!" 346 //! # }; 347 //! // `my_struct.field` will be recorded using its `fmt::Display` implementation. 348 //! event!(Level::TRACE, greeting = %my_struct.field); 349 //! // is equivalent to: 350 //! event!(Level::TRACE, greeting = tracing::field::display(&my_struct.field)); 351 //! # } 352 //! ``` 353 //! 354 //! The `%` and `?` sigils may also be used with local variable shorthand: 355 //! 356 //! ``` 357 //! # use tracing::{event, Level}; 358 //! # fn main() { 359 //! # #[derive(Debug)] 360 //! # struct MyStruct { 361 //! # field: &'static str, 362 //! # } 363 //! # 364 //! # let my_struct = MyStruct { 365 //! # field: "Hello world!" 366 //! # }; 367 //! // `my_struct.field` will be recorded using its `fmt::Display` implementation. 368 //! event!(Level::TRACE, %my_struct.field); 369 //! # } 370 //! ``` 371 //! 372 //! Additionally, a span may declare fields with the special value [`Empty`], 373 //! which indicates that that the value for that field does not currently exist 374 //! but may be recorded later. For example: 375 //! 376 //! ``` 377 //! use tracing::{trace_span, field}; 378 //! 379 //! // Create a span with two fields: `greeting`, with the value "hello world", and 380 //! // `parting`, without a value. 381 //! let span = trace_span!("my_span", greeting = "hello world", parting = field::Empty); 382 //! 383 //! // ... 384 //! 385 //! // Now, record a value for parting as well. 386 //! span.record("parting", &"goodbye world!"); 387 //! ``` 388 //! 389 //! Note that a span may have up to 32 fields. The following will not compile: 390 //! 391 //! ```rust,compile_fail 392 //! # use tracing::Level; 393 //! # fn main() { 394 //! let bad_span = span!( 395 //! Level::TRACE, 396 //! "too many fields!", 397 //! a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7, h = 8, i = 9, 398 //! j = 10, k = 11, l = 12, m = 13, n = 14, o = 15, p = 16, q = 17, 399 //! r = 18, s = 19, t = 20, u = 21, v = 22, w = 23, x = 24, y = 25, 400 //! z = 26, aa = 27, bb = 28, cc = 29, dd = 30, ee = 31, ff = 32, gg = 33 401 //! ); 402 //! # } 403 //! ``` 404 //! 405 //! Finally, events may also include human-readable messages, in the form of a 406 //! [format string][fmt] and (optional) arguments, **after** the event's 407 //! key-value fields. If a format string and arguments are provided, 408 //! they will implicitly create a new field named `message` whose value is the 409 //! provided set of format arguments. 410 //! 411 //! For example: 412 //! 413 //! ``` 414 //! # use tracing::{event, Level}; 415 //! # fn main() { 416 //! let question = "the ultimate question of life, the universe, and everything"; 417 //! let answer = 42; 418 //! // records an event with the following fields: 419 //! // - `question.answer` with the value 42, 420 //! // - `question.tricky` with the value `true`, 421 //! // - "message", with the value "the answer to the ultimate question of life, the 422 //! // universe, and everything is 42." 423 //! event!( 424 //! Level::DEBUG, 425 //! question.answer = answer, 426 //! question.tricky = true, 427 //! "the answer to {} is {}.", question, answer 428 //! ); 429 //! # } 430 //! ``` 431 //! 432 //! Specifying a formatted message in this manner does not allocate by default. 433 //! 434 //! [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 435 //! [target]: Metadata::target 436 //! [parent span]: span::Attributes::parent 437 //! [determined contextually]: span::Attributes::is_contextual 438 //! [`fmt::Debug`]: std::fmt::Debug 439 //! [`fmt::Display`]: std::fmt::Display 440 //! [fmt]: std::fmt#usage 441 //! [`Empty`]: field::Empty 442 //! 443 //! ### Shorthand Macros 444 //! 445 //! `tracing` also offers a number of macros with preset verbosity levels. 446 //! The [`trace!`], [`debug!`], [`info!`], [`warn!`], and [`error!`] behave 447 //! similarly to the [`event!`] macro, but with the [`Level`] argument already 448 //! specified, while the corresponding [`trace_span!`], [`debug_span!`], 449 //! [`info_span!`], [`warn_span!`], and [`error_span!`] macros are the same, 450 //! but for the [`span!`] macro. 451 //! 452 //! These are intended both as a shorthand, and for compatibility with the [`log`] 453 //! crate (see the next section). 454 //! 455 //! [`span!`]: span! 456 //! [`event!`]: event! 457 //! [`trace!`]: trace! 458 //! [`debug!`]: debug! 459 //! [`info!`]: info! 460 //! [`warn!`]: warn! 461 //! [`error!`]: error! 462 //! [`trace_span!`]: trace_span! 463 //! [`debug_span!`]: debug_span! 464 //! [`info_span!`]: info_span! 465 //! [`warn_span!`]: warn_span! 466 //! [`error_span!`]: error_span! 467 //! 468 //! ### For `log` Users 469 //! 470 //! Users of the [`log`] crate should note that `tracing` exposes a set of 471 //! macros for creating `Event`s (`trace!`, `debug!`, `info!`, `warn!`, and 472 //! `error!`) which may be invoked with the same syntax as the similarly-named 473 //! macros from the `log` crate. Often, the process of converting a project to 474 //! use `tracing` can begin with a simple drop-in replacement. 475 //! 476 //! Let's consider the `log` crate's yak-shaving example: 477 //! 478 //! ```rust,ignore 479 //! use std::{error::Error, io}; 480 //! use tracing::{debug, error, info, span, warn, Level}; 481 //! 482 //! // the `#[tracing::instrument]` attribute creates and enters a span 483 //! // every time the instrumented function is called. The span is named after the 484 //! // the function or method. Parameters passed to the function are recorded as fields. 485 //! #[tracing::instrument] 486 //! pub fn shave(yak: usize) -> Result<(), Box<dyn Error + 'static>> { 487 //! // this creates an event at the DEBUG level with two fields: 488 //! // - `excitement`, with the key "excitement" and the value "yay!" 489 //! // - `message`, with the key "message" and the value "hello! I'm gonna shave a yak." 490 //! // 491 //! // unlike other fields, `message`'s shorthand initialization is just the string itself. 492 //! debug!(excitement = "yay!", "hello! I'm gonna shave a yak."); 493 //! if yak == 3 { 494 //! warn!("could not locate yak!"); 495 //! // note that this is intended to demonstrate `tracing`'s features, not idiomatic 496 //! // error handling! in a library or application, you should consider returning 497 //! // a dedicated `YakError`. libraries like snafu or thiserror make this easy. 498 //! return Err(io::Error::new(io::ErrorKind::Other, "shaving yak failed!").into()); 499 //! } else { 500 //! debug!("yak shaved successfully"); 501 //! } 502 //! Ok(()) 503 //! } 504 //! 505 //! pub fn shave_all(yaks: usize) -> usize { 506 //! // Constructs a new span named "shaving_yaks" at the TRACE level, 507 //! // and a field whose key is "yaks". This is equivalent to writing: 508 //! // 509 //! // let span = span!(Level::TRACE, "shaving_yaks", yaks = yaks); 510 //! // 511 //! // local variables (`yaks`) can be used as field values 512 //! // without an assignment, similar to struct initializers. 513 //! let _span = span!(Level::TRACE, "shaving_yaks", yaks).entered(); 514 //! 515 //! info!("shaving yaks"); 516 //! 517 //! let mut yaks_shaved = 0; 518 //! for yak in 1..=yaks { 519 //! let res = shave(yak); 520 //! debug!(yak, shaved = res.is_ok()); 521 //! 522 //! if let Err(ref error) = res { 523 //! // Like spans, events can also use the field initialization shorthand. 524 //! // In this instance, `yak` is the field being initalized. 525 //! error!(yak, error = error.as_ref(), "failed to shave yak!"); 526 //! } else { 527 //! yaks_shaved += 1; 528 //! } 529 //! debug!(yaks_shaved); 530 //! } 531 //! 532 //! yaks_shaved 533 //! } 534 //! ``` 535 //! 536 //! ## In libraries 537 //! 538 //! Libraries should link only to the `tracing` crate, and use the provided 539 //! macros to record whatever information will be useful to downstream 540 //! consumers. 541 //! 542 //! ## In executables 543 //! 544 //! In order to record trace events, executables have to use a `Subscriber` 545 //! implementation compatible with `tracing`. A `Subscriber` implements a 546 //! way of collecting trace data, such as by logging it to standard output. 547 //! 548 //! This library does not contain any `Subscriber` implementations; these are 549 //! provided by [other crates](#related-crates). 550 //! 551 //! The simplest way to use a subscriber is to call the [`set_global_default`] 552 //! function: 553 //! 554 //! ``` 555 //! extern crate tracing; 556 //! # pub struct FooSubscriber; 557 //! # use tracing::{span::{Id, Attributes, Record}, Metadata}; 558 //! # impl tracing::Subscriber for FooSubscriber { 559 //! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) } 560 //! # fn record(&self, _: &Id, _: &Record) {} 561 //! # fn event(&self, _: &tracing::Event) {} 562 //! # fn record_follows_from(&self, _: &Id, _: &Id) {} 563 //! # fn enabled(&self, _: &Metadata) -> bool { false } 564 //! # fn enter(&self, _: &Id) {} 565 //! # fn exit(&self, _: &Id) {} 566 //! # } 567 //! # impl FooSubscriber { 568 //! # fn new() -> Self { FooSubscriber } 569 //! # } 570 //! # fn main() { 571 //! 572 //! let my_subscriber = FooSubscriber::new(); 573 //! tracing::subscriber::set_global_default(my_subscriber) 574 //! .expect("setting tracing default failed"); 575 //! # } 576 //! ``` 577 //! 578 //! <pre class="compile_fail" style="white-space:normal;font:inherit;"> 579 //! <strong>Warning</strong>: In general, libraries should <em>not</em> call 580 //! <code>set_global_default()</code>! Doing so will cause conflicts when 581 //! executables that depend on the library try to set the default later. 582 //! </pre> 583 //! 584 //! This subscriber will be used as the default in all threads for the 585 //! remainder of the duration of the program, similar to setting the logger 586 //! in the `log` crate. 587 //! 588 //! In addition, the default subscriber can be set through using the 589 //! [`with_default`] function. This follows the `tokio` pattern of using 590 //! closures to represent executing code in a context that is exited at the end 591 //! of the closure. For example: 592 //! 593 //! ```rust 594 //! # pub struct FooSubscriber; 595 //! # use tracing::{span::{Id, Attributes, Record}, Metadata}; 596 //! # impl tracing::Subscriber for FooSubscriber { 597 //! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) } 598 //! # fn record(&self, _: &Id, _: &Record) {} 599 //! # fn event(&self, _: &tracing::Event) {} 600 //! # fn record_follows_from(&self, _: &Id, _: &Id) {} 601 //! # fn enabled(&self, _: &Metadata) -> bool { false } 602 //! # fn enter(&self, _: &Id) {} 603 //! # fn exit(&self, _: &Id) {} 604 //! # } 605 //! # impl FooSubscriber { 606 //! # fn new() -> Self { FooSubscriber } 607 //! # } 608 //! # fn main() { 609 //! 610 //! let my_subscriber = FooSubscriber::new(); 611 //! # #[cfg(feature = "std")] 612 //! tracing::subscriber::with_default(my_subscriber, || { 613 //! // Any trace events generated in this closure or by functions it calls 614 //! // will be collected by `my_subscriber`. 615 //! }) 616 //! # } 617 //! ``` 618 //! 619 //! This approach allows trace data to be collected by multiple subscribers 620 //! within different contexts in the program. Note that the override only applies to the 621 //! currently executing thread; other threads will not see the change from with_default. 622 //! 623 //! Any trace events generated outside the context of a subscriber will not be collected. 624 //! 625 //! Once a subscriber has been set, instrumentation points may be added to the 626 //! executable using the `tracing` crate's macros. 627 //! 628 //! ## `log` Compatibility 629 //! 630 //! The [`log`] crate provides a simple, lightweight logging facade for Rust. 631 //! While `tracing` builds upon `log`'s foundation with richer structured 632 //! diagnostic data, `log`'s simplicity and ubiquity make it the "lowest common 633 //! denominator" for text-based logging in Rust — a vast majority of Rust 634 //! libraries and applications either emit or consume `log` records. Therefore, 635 //! `tracing` provides multiple forms of interoperability with `log`: `tracing` 636 //! instrumentation can emit `log` records, and a compatibility layer enables 637 //! `tracing` [`Subscriber`]s to consume `log` records as `tracing` [`Event`]s. 638 //! 639 //! ### Emitting `log` Records 640 //! 641 //! This crate provides two feature flags, "log" and "log-always", which will 642 //! cause [spans] and [events] to emit `log` records. When the "log" feature is 643 //! enabled, if no `tracing` `Subscriber` is active, invoking an event macro or 644 //! creating a span with fields will emit a `log` record. This is intended 645 //! primarily for use in libraries which wish to emit diagnostics that can be 646 //! consumed by applications using `tracing` *or* `log`, without paying the 647 //! additional overhead of emitting both forms of diagnostics when `tracing` is 648 //! in use. 649 //! 650 //! Enabling the "log-always" feature will cause `log` records to be emitted 651 //! even if a `tracing` `Subscriber` _is_ set. This is intended to be used in 652 //! applications where a `log` `Logger` is being used to record a textual log, 653 //! and `tracing` is used only to record other forms of diagnostics (such as 654 //! metrics, profiling, or distributed tracing data). Unlike the "log" feature, 655 //! libraries generally should **not** enable the "log-always" feature, as doing 656 //! so will prevent applications from being able to opt out of the `log` records. 657 //! 658 //! See [here][flags] for more details on this crate's feature flags. 659 //! 660 //! The generated `log` records' messages will be a string representation of the 661 //! span or event's fields, and all additional information recorded by `log` 662 //! (target, verbosity level, module path, file, and line number) will also be 663 //! populated. Additionally, `log` records are also generated when spans are 664 //! entered, exited, and closed. Since these additional span lifecycle logs have 665 //! the potential to be very verbose, and don't include additional fields, they 666 //! will always be emitted at the `Trace` level, rather than inheriting the 667 //! level of the span that generated them. Furthermore, they are are categorized 668 //! under a separate `log` target, "tracing::span" (and its sub-target, 669 //! "tracing::span::active", for the logs on entering and exiting a span), which 670 //! may be enabled or disabled separately from other `log` records emitted by 671 //! `tracing`. 672 //! 673 //! ### Consuming `log` Records 674 //! 675 //! The [`tracing-log`] crate provides a compatibility layer which 676 //! allows a `tracing` [`Subscriber`] to consume `log` records as though they 677 //! were `tracing` [events]. This allows applications using `tracing` to record 678 //! the logs emitted by dependencies using `log` as events within the context of 679 //! the application's trace tree. See [that crate's documentation][log-tracer] 680 //! for details. 681 //! 682 //! [log-tracer]: https://docs.rs/tracing-log/latest/tracing_log/#convert-log-records-to-tracing-events 683 //! 684 //! ## Related Crates 685 //! 686 //! In addition to `tracing` and `tracing-core`, the [`tokio-rs/tracing`] repository 687 //! contains several additional crates designed to be used with the `tracing` ecosystem. 688 //! This includes a collection of `Subscriber` implementations, as well as utility 689 //! and adapter crates to assist in writing `Subscriber`s and instrumenting 690 //! applications. 691 //! 692 //! In particular, the following crates are likely to be of interest: 693 //! 694 //! - [`tracing-futures`] provides a compatibility layer with the `futures` 695 //! crate, allowing spans to be attached to `Future`s, `Stream`s, and `Executor`s. 696 //! - [`tracing-subscriber`] provides `Subscriber` implementations and 697 //! utilities for working with `Subscriber`s. This includes a [`FmtSubscriber`] 698 //! `FmtSubscriber` for logging formatted trace data to stdout, with similar 699 //! filtering and formatting to the [`env_logger`] crate. 700 //! - [`tracing-log`] provides a compatibility layer with the [`log`] crate, 701 //! allowing log messages to be recorded as `tracing` `Event`s within the 702 //! trace tree. This is useful when a project using `tracing` have 703 //! dependencies which use `log`. Note that if you're using 704 //! `tracing-subscriber`'s `FmtSubscriber`, you don't need to depend on 705 //! `tracing-log` directly. 706 //! - [`tracing-appender`] provides utilities for outputting tracing data, 707 //! including a file appender and non blocking writer. 708 //! 709 //! Additionally, there are also several third-party crates which are not 710 //! maintained by the `tokio` project. These include: 711 //! 712 //! - [`tracing-timing`] implements inter-event timing metrics on top of `tracing`. 713 //! It provides a subscriber that records the time elapsed between pairs of 714 //! `tracing` events and generates histograms. 715 //! - [`tracing-opentelemetry`] provides a subscriber for emitting traces to 716 //! [OpenTelemetry]-compatible distributed tracing systems. 717 //! - [`tracing-honeycomb`] Provides a layer that reports traces spanning multiple machines to [honeycomb.io]. Backed by [`tracing-distributed`]. 718 //! - [`tracing-distributed`] Provides a generic implementation of a layer that reports traces spanning multiple machines to some backend. 719 //! - [`tracing-actix-web`] provides `tracing` integration for the `actix-web` web framework. 720 //! - [`tracing-actix`] provides `tracing` integration for the `actix` actor 721 //! framework. 722 //! - [`tracing-gelf`] implements a subscriber for exporting traces in Greylog 723 //! GELF format. 724 //! - [`tracing-coz`] provides integration with the [coz] causal profiler 725 //! (Linux-only). 726 //! - [`tracing-bunyan-formatter`] provides a layer implementation that reports events and spans 727 //! in [bunyan] format, enriched with timing information. 728 //! - [`tracing-wasm`] provides a `Subscriber`/`Layer` implementation that reports 729 //! events and spans via browser `console.log` and [User Timing API (`window.performance`)]. 730 //! - [`tracing-web`] provides a layer implementation of level-aware logging of events 731 //! to web browsers' `console.*` and span events to the [User Timing API (`window.performance`)]. 732 //! - [`tide-tracing`] provides a [tide] middleware to trace all incoming requests and responses. 733 //! - [`test-log`] takes care of initializing `tracing` for tests, based on 734 //! environment variables with an `env_logger` compatible syntax. 735 //! - [`tracing-unwrap`] provides convenience methods to report failed unwraps 736 //! on `Result` or `Option` types to a `Subscriber`. 737 //! - [`diesel-tracing`] provides integration with [`diesel`] database connections. 738 //! - [`tracing-tracy`] provides a way to collect [Tracy] profiles in instrumented 739 //! applications. 740 //! - [`tracing-elastic-apm`] provides a layer for reporting traces to [Elastic APM]. 741 //! - [`tracing-etw`] provides a layer for emitting Windows [ETW] events. 742 //! - [`tracing-fluent-assertions`] provides a fluent assertions-style testing 743 //! framework for validating the behavior of `tracing` spans. 744 //! - [`sentry-tracing`] provides a layer for reporting events and traces to [Sentry]. 745 //! - [`tracing-forest`] provides a subscriber that preserves contextual coherence by 746 //! grouping together logs from the same spans during writing. 747 //! - [`tracing-loki`] provides a layer for shipping logs to [Grafana Loki]. 748 //! - [`tracing-logfmt`] provides a layer that formats events and spans into the logfmt format. 749 //! - [`reqwest-tracing`] provides a middleware to trace [`reqwest`] HTTP requests. 750 //! 751 //! If you're the maintainer of a `tracing` ecosystem crate not listed above, 752 //! please let us know! We'd love to add your project to the list! 753 //! 754 //! [`tracing-opentelemetry`]: https://crates.io/crates/tracing-opentelemetry 755 //! [OpenTelemetry]: https://opentelemetry.io/ 756 //! [`tracing-honeycomb`]: https://crates.io/crates/tracing-honeycomb 757 //! [`tracing-distributed`]: https://crates.io/crates/tracing-distributed 758 //! [honeycomb.io]: https://www.honeycomb.io/ 759 //! [`tracing-actix-web`]: https://crates.io/crates/tracing-actix-web 760 //! [`tracing-actix`]: https://crates.io/crates/tracing-actix 761 //! [`tracing-gelf`]: https://crates.io/crates/tracing-gelf 762 //! [`tracing-coz`]: https://crates.io/crates/tracing-coz 763 //! [coz]: https://github.com/plasma-umass/coz 764 //! [`tracing-bunyan-formatter`]: https://crates.io/crates/tracing-bunyan-formatter 765 //! [bunyan]: https://github.com/trentm/node-bunyan 766 //! [`tracing-wasm`]: https://docs.rs/tracing-wasm 767 //! [`tracing-web`]: https://docs.rs/tracing-web 768 //! [User Timing API (`window.performance`)]: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API 769 //! [`tide-tracing`]: https://crates.io/crates/tide-tracing 770 //! [tide]: https://crates.io/crates/tide 771 //! [`test-log`]: https://crates.io/crates/test-log 772 //! [`tracing-unwrap`]: https://docs.rs/tracing-unwrap 773 //! [`diesel`]: https://crates.io/crates/diesel 774 //! [`diesel-tracing`]: https://crates.io/crates/diesel-tracing 775 //! [`tracing-tracy`]: https://crates.io/crates/tracing-tracy 776 //! [Tracy]: https://github.com/wolfpld/tracy 777 //! [`tracing-elastic-apm`]: https://crates.io/crates/tracing-elastic-apm 778 //! [Elastic APM]: https://www.elastic.co/apm 779 //! [`tracing-etw`]: https://github.com/microsoft/tracing-etw 780 //! [ETW]: https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing 781 //! [`tracing-fluent-assertions`]: https://crates.io/crates/tracing-fluent-assertions 782 //! [`sentry-tracing`]: https://crates.io/crates/sentry-tracing 783 //! [Sentry]: https://sentry.io/welcome/ 784 //! [`tracing-forest`]: https://crates.io/crates/tracing-forest 785 //! [`tracing-loki`]: https://crates.io/crates/tracing-loki 786 //! [Grafana Loki]: https://grafana.com/oss/loki/ 787 //! [`tracing-logfmt`]: https://crates.io/crates/tracing-logfmt 788 //! [`reqwest-tracing`]: https://crates.io/crates/reqwest-tracing 789 //! [`reqwest`]: https://crates.io/crates/reqwest 790 //! 791 //! <pre class="ignore" style="white-space:normal;font:inherit;"> 792 //! <strong>Note</strong>: Some of these ecosystem crates are currently 793 //! unreleased and/or in earlier stages of development. They may be less stable 794 //! than <code>tracing</code> and <code>tracing-core</code>. 795 //! </pre> 796 //! 797 //! ## Crate Feature Flags 798 //! 799 //! The following crate [feature flags] are available: 800 //! 801 //! * A set of features controlling the [static verbosity level]. 802 //! * `log`: causes trace instrumentation points to emit [`log`] records as well 803 //! as trace events, if a default `tracing` subscriber has not been set. This 804 //! is intended for use in libraries whose users may be using either `tracing` 805 //! or `log`. 806 //! * `log-always`: Emit `log` records from all `tracing` spans and events, even 807 //! if a `tracing` subscriber has been set. This should be set only by 808 //! applications which intend to collect traces and logs separately; if an 809 //! adapter is used to convert `log` records into `tracing` events, this will 810 //! cause duplicate events to occur. 811 //! * `attributes`: Includes support for the `#[instrument]` attribute. 812 //! This is on by default, but does bring in the `syn` crate as a dependency, 813 //! which may add to the compile time of crates that do not already use it. 814 //! * `std`: Depend on the Rust standard library (enabled by default). 815 //! 816 //! `no_std` users may disable this feature with `default-features = false`: 817 //! 818 //! ```toml 819 //! [dependencies] 820 //! tracing = { version = "0.1.37", default-features = false } 821 //! ``` 822 //! 823 //! <pre class="ignore" style="white-space:normal;font:inherit;"> 824 //! <strong>Note</strong>: <code>tracing</code>'s <code>no_std</code> support 825 //! requires <code>liballoc</code>. 826 //! </pre> 827 //! 828 //! ### Unstable Features 829 //! 830 //! These feature flags enable **unstable** features. The public API may break in 0.1.x 831 //! releases. To enable these features, the `--cfg tracing_unstable` must be passed to 832 //! `rustc` when compiling. 833 //! 834 //! The following unstable feature flags are currently available: 835 //! 836 //! * `valuable`: Enables support for recording [field values] using the 837 //! [`valuable`] crate. 838 //! 839 //! #### Enabling Unstable Features 840 //! 841 //! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS` 842 //! env variable when running `cargo` commands: 843 //! 844 //! ```shell 845 //! RUSTFLAGS="--cfg tracing_unstable" cargo build 846 //! ``` 847 //! Alternatively, the following can be added to the `.cargo/config` file in a 848 //! project to automatically enable the cfg flag for that project: 849 //! 850 //! ```toml 851 //! [build] 852 //! rustflags = ["--cfg", "tracing_unstable"] 853 //! ``` 854 //! 855 //! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section 856 //! [field values]: crate::field 857 //! [`valuable`]: https://crates.io/crates/valuable 858 //! 859 //! ## Supported Rust Versions 860 //! 861 //! Tracing is built against the latest stable release. The minimum supported 862 //! version is 1.49. The current Tracing version is not guaranteed to build on 863 //! Rust versions earlier than the minimum supported version. 864 //! 865 //! Tracing follows the same compiler support policies as the rest of the Tokio 866 //! project. The current stable Rust compiler and the three most recent minor 867 //! versions before it will always be supported. For example, if the current 868 //! stable compiler version is 1.45, the minimum supported version will not be 869 //! increased past 1.42, three minor versions prior. Increasing the minimum 870 //! supported compiler version is not considered a semver breaking change as 871 //! long as doing so complies with this policy. 872 //! 873 //! [`log`]: https://docs.rs/log/0.4.6/log/ 874 //! [span]: mod@span 875 //! [spans]: mod@span 876 //! [`Span`]: span::Span 877 //! [`in_scope`]: span::Span::in_scope 878 //! [event]: Event 879 //! [events]: Event 880 //! [`Subscriber`]: subscriber::Subscriber 881 //! [Subscriber::event]: subscriber::Subscriber::event 882 //! [`enter`]: subscriber::Subscriber::enter 883 //! [`exit`]: subscriber::Subscriber::exit 884 //! [`enabled`]: subscriber::Subscriber::enabled 885 //! [metadata]: Metadata 886 //! [`field::display`]: field::display 887 //! [`field::debug`]: field::debug 888 //! [`set_global_default`]: subscriber::set_global_default 889 //! [`with_default`]: subscriber::with_default 890 //! [`tokio-rs/tracing`]: https://github.com/tokio-rs/tracing 891 //! [`tracing-futures`]: https://crates.io/crates/tracing-futures 892 //! [`tracing-subscriber`]: https://crates.io/crates/tracing-subscriber 893 //! [`tracing-log`]: https://crates.io/crates/tracing-log 894 //! [`tracing-timing`]: https://crates.io/crates/tracing-timing 895 //! [`tracing-appender`]: https://crates.io/crates/tracing-appender 896 //! [`env_logger`]: https://crates.io/crates/env_logger 897 //! [`FmtSubscriber`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/struct.Subscriber.html 898 //! [static verbosity level]: level_filters#compile-time-filters 899 //! [instrument]: https://docs.rs/tracing-attributes/latest/tracing_attributes/attr.instrument.html 900 //! [flags]: #crate-feature-flags 901 #![cfg_attr(not(feature = "std"), no_std)] 902 #![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] 903 #![doc(html_root_url = "https://docs.rs/tracing/0.1.37")] 904 #![doc( 905 html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", 906 issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" 907 )] 908 #![warn( 909 missing_debug_implementations, 910 missing_docs, 911 rust_2018_idioms, 912 unreachable_pub, 913 bad_style, 914 const_err, 915 dead_code, 916 improper_ctypes, 917 non_shorthand_field_patterns, 918 no_mangle_generic_items, 919 overflowing_literals, 920 path_statements, 921 patterns_in_fns_without_body, 922 private_in_public, 923 unconditional_recursion, 924 unused, 925 unused_allocation, 926 unused_comparisons, 927 unused_parens, 928 while_true 929 )] 930 931 #[cfg(not(feature = "std"))] 932 extern crate alloc; 933 934 // Somehow this `use` statement is necessary for us to re-export the `core` 935 // macros on Rust 1.26.0. I'm not sure how this makes it work, but it does. 936 #[allow(unused_imports)] 937 #[doc(hidden)] 938 use tracing_core::*; 939 940 #[doc(inline)] 941 pub use self::instrument::Instrument; 942 pub use self::{dispatcher::Dispatch, event::Event, field::Value, subscriber::Subscriber}; 943 944 #[doc(hidden)] 945 pub use self::span::Id; 946 947 #[doc(hidden)] 948 pub use tracing_core::{ 949 callsite::{self, Callsite}, 950 metadata, 951 }; 952 pub use tracing_core::{event, Level, Metadata}; 953 954 #[doc(inline)] 955 pub use self::span::Span; 956 #[cfg(feature = "attributes")] 957 #[cfg_attr(docsrs, doc(cfg(feature = "attributes")))] 958 #[doc(inline)] 959 pub use tracing_attributes::instrument; 960 961 #[macro_use] 962 mod macros; 963 964 pub mod dispatcher; 965 pub mod field; 966 /// Attach a span to a `std::future::Future`. 967 pub mod instrument; 968 pub mod level_filters; 969 pub mod span; 970 pub(crate) mod stdlib; 971 pub mod subscriber; 972 973 #[doc(hidden)] 974 pub mod __macro_support { 975 pub use crate::callsite::Callsite; 976 use crate::{subscriber::Interest, Metadata}; 977 pub use core::concat; 978 979 /// Callsite implementation used by macro-generated code. 980 /// 981 /// /!\ WARNING: This is *not* a stable API! /!\ 982 /// This type, and all code contained in the `__macro_support` module, is 983 /// a *private* API of `tracing`. It is exposed publicly because it is used 984 /// by the `tracing` macros, but it is not part of the stable versioned API. 985 /// Breaking changes to this module may occur in small-numbered versions 986 /// without warning. 987 pub use tracing_core::callsite::DefaultCallsite as MacroCallsite; 988 989 /// /!\ WARNING: This is *not* a stable API! /!\ 990 /// This function, and all code contained in the `__macro_support` module, is 991 /// a *private* API of `tracing`. It is exposed publicly because it is used 992 /// by the `tracing` macros, but it is not part of the stable versioned API. 993 /// Breaking changes to this module may occur in small-numbered versions 994 /// without warning. __is_enabled(meta: &Metadata<'static>, interest: Interest) -> bool995 pub fn __is_enabled(meta: &Metadata<'static>, interest: Interest) -> bool { 996 interest.is_always() || crate::dispatcher::get_default(|default| default.enabled(meta)) 997 } 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. 1005 #[inline] 1006 #[cfg(feature = "log")] __disabled_span(meta: &'static Metadata<'static>) -> crate::Span1007 pub fn __disabled_span(meta: &'static Metadata<'static>) -> crate::Span { 1008 crate::Span::new_disabled(meta) 1009 } 1010 1011 /// /!\ WARNING: This is *not* a stable API! /!\ 1012 /// This function, and all code contained in the `__macro_support` module, is 1013 /// a *private* API of `tracing`. It is exposed publicly because it is used 1014 /// by the `tracing` macros, but it is not part of the stable versioned API. 1015 /// Breaking changes to this module may occur in small-numbered versions 1016 /// without warning. 1017 #[inline] 1018 #[cfg(not(feature = "log"))] __disabled_span(_: &'static Metadata<'static>) -> crate::Span1019 pub fn __disabled_span(_: &'static Metadata<'static>) -> crate::Span { 1020 crate::Span::none() 1021 } 1022 1023 /// /!\ WARNING: This is *not* a stable API! /!\ 1024 /// This function, and all code contained in the `__macro_support` module, is 1025 /// a *private* API of `tracing`. It is exposed publicly because it is used 1026 /// by the `tracing` macros, but it is not part of the stable versioned API. 1027 /// Breaking changes to this module may occur in small-numbered versions 1028 /// without warning. 1029 #[cfg(feature = "log")] __tracing_log( meta: &Metadata<'static>, logger: &'static dyn log::Log, log_meta: log::Metadata<'_>, values: &tracing_core::field::ValueSet<'_>, )1030 pub fn __tracing_log( 1031 meta: &Metadata<'static>, 1032 logger: &'static dyn log::Log, 1033 log_meta: log::Metadata<'_>, 1034 values: &tracing_core::field::ValueSet<'_>, 1035 ) { 1036 logger.log( 1037 &crate::log::Record::builder() 1038 .file(meta.file()) 1039 .module_path(meta.module_path()) 1040 .line(meta.line()) 1041 .metadata(log_meta) 1042 .args(format_args!( 1043 "{}", 1044 crate::log::LogValueSet { 1045 values, 1046 is_first: true 1047 } 1048 )) 1049 .build(), 1050 ); 1051 } 1052 } 1053 1054 #[cfg(feature = "log")] 1055 #[doc(hidden)] 1056 pub mod log { 1057 use core::fmt; 1058 pub use log::*; 1059 use tracing_core::field::{Field, ValueSet, Visit}; 1060 1061 /// Utility to format [`ValueSet`]s for logging. 1062 pub(crate) struct LogValueSet<'a> { 1063 pub(crate) values: &'a ValueSet<'a>, 1064 pub(crate) is_first: bool, 1065 } 1066 1067 impl<'a> fmt::Display for LogValueSet<'a> { 1068 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1069 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1070 struct LogVisitor<'a, 'b> { 1071 f: &'a mut fmt::Formatter<'b>, 1072 is_first: bool, 1073 result: fmt::Result, 1074 } 1075 1076 impl Visit for LogVisitor<'_, '_> { 1077 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { 1078 let res = if self.is_first { 1079 self.is_first = false; 1080 if field.name() == "message" { 1081 write!(self.f, "{:?}", value) 1082 } else { 1083 write!(self.f, "{}={:?}", field.name(), value) 1084 } 1085 } else { 1086 write!(self.f, " {}={:?}", field.name(), value) 1087 }; 1088 if let Err(err) = res { 1089 self.result = self.result.and(Err(err)); 1090 } 1091 } 1092 1093 fn record_str(&mut self, field: &Field, value: &str) { 1094 if field.name() == "message" { 1095 self.record_debug(field, &format_args!("{}", value)) 1096 } else { 1097 self.record_debug(field, &value) 1098 } 1099 } 1100 } 1101 1102 let mut visit = LogVisitor { 1103 f, 1104 is_first: self.is_first, 1105 result: Ok(()), 1106 }; 1107 self.values.record(&mut visit); 1108 visit.result 1109 } 1110 } 1111 } 1112 1113 mod sealed { 1114 pub trait Sealed {} 1115 } 1116