diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
commit | 94a0819fe3a0d679c3042a77bfe6a2afc505daea (patch) | |
tree | 2b827afe6a05f3538db3f7803a88c4587fe85648 /vendor/tracing-subscriber | |
parent | Adding upstream version 1.64.0+dfsg1. (diff) | |
download | rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.tar.xz rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.zip |
Adding upstream version 1.66.0+dfsg1.upstream/1.66.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/tracing-subscriber')
77 files changed, 0 insertions, 27714 deletions
diff --git a/vendor/tracing-subscriber/.cargo-checksum.json b/vendor/tracing-subscriber/.cargo-checksum.json deleted file mode 100644 index 509cf43fc..000000000 --- a/vendor/tracing-subscriber/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"29fe135a995cb47126440183c4d42f842ad08ec0b3796a701f28cc83991b73b8","Cargo.toml":"62d5ba5d1eef80f27e41b45b3d9bde666143ab488b39e2f675774855142e0022","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"5ea57d24ff4451b10feb2689f1046d8d43bf6af4ee60285e676dfd1a586c65db","benches/enter.rs":"4a94a04e2abd07950ef2f0b646f4dcdf4ff00abf6396edb5a53c8b41b7691b1a","benches/filter.rs":"6374005ffa47fa19880bb95e3e37406f40ea72a02c5136f4d5eb4c663d452b18","benches/filter_log.rs":"612716bdf9a188093e84d014a4847f18157f148f7d64e54150cd5c91ac709a8a","benches/fmt.rs":"5a0ff37967ffef3a221eebb78855d031e2e883a8a67528c8e794cc6f16cbee8a","benches/support/mod.rs":"72bef51154da9c9b3d81300195c1929a818858fa4b4fc2aa07b49ca586f4cd39","src/field/debug.rs":"4ab50198a0b042d92fefa77b5cac0aef7ba6936149fa555f4b6e2036dcd7f2d7","src/field/delimited.rs":"5e7967637dc3181c097637dcb2a95f35db16583b5fc293b30211db5779ab21ab","src/field/display.rs":"da8cfcb22a39f451f075e2c3a9ce5193c6afe19853cdbd643239657cac5b7e47","src/field/mod.rs":"cb8ab273159f42fc8ebe71c82acc63c962e546328fc4aa9fd5948ce996ef9e05","src/filter/directive.rs":"6341c3a1c8b6d33171647964c35816317c81b03bb098b493f1f1a22222f6ce84","src/filter/env/builder.rs":"8f527b1b0e3d9c572046235e0304146a574fe114b757af90a1c07851a07ba2cf","src/filter/env/directive.rs":"ecd2a7ffb882869f8ea9b0398f5af58ce1797a216b9dc9086c21363d1d500e77","src/filter/env/field.rs":"e1e32a2fc39884c9a5df1d5047128e43f1d0720c0b9daa6bf1e08ca9bcc5f537","src/filter/env/mod.rs":"8403df3f061a1c266b6ab6b30b03c6eb32c1c9354037a2d1eeb36817932e6ea5","src/filter/filter_fn.rs":"0debbc4a4b4d2a57b2a06905017ac908bf34b0a64aaf961535fbf6f4d5a700a9","src/filter/layer_filters/combinator.rs":"abf90b8d7a21486b28f20d4b648395b2b95a35b526bbdaba63bd2c0181ae9e87","src/filter/layer_filters/mod.rs":"2046a860b21751791dae61d20219b3d59049b84fb289ea1fca7796d214c5643c","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"8ebfd0dc92415ff27ec552f20919e598842a87186f13f120449053a96e1e3307","src/filter/targets.rs":"eaa11d620017269770da5b2b97302b3beb81187242912260ca98e6d60ea77780","src/fmt/fmt_layer.rs":"5042d3e2eba5f68e9041c94b52f26ab17b84f68c54d16e4c0edd9d3a3699f727","src/fmt/format/json.rs":"554985ed40f7c59787aae87626144241ca973929e33979c54f821b673b71fec9","src/fmt/format/mod.rs":"a5f6b879802d353192235cf85aa8653afa3e8ead09955e631a39415324ce42d2","src/fmt/format/pretty.rs":"30fac9a916f3b9f572efa3b650c6dab7d86a57ce903cdbba6c6c0a52064cf238","src/fmt/mod.rs":"d5274d1f8106dc7497d2be7c6d874aeca15b9ca0fd4e0c6775d3774e75b30099","src/fmt/time/datetime.rs":"778d4604d800e46b940087394e7b72750738b554e02aea523fa9820ab0768c08","src/fmt/time/mod.rs":"30c97a9d3abd099f52c4c91c7b5f0d29ed9d54d80d1718c6fb74bfd664589de1","src/fmt/time/time_crate.rs":"1bfd59516a583e396afc1770250aa8c06b52f6162a6e7b2cadb860b7eebd9d76","src/fmt/writer.rs":"1931125cf14019b66b42a9ff95e5794f344697f799c021b4a7d48fd7eb7b58f4","src/layer/context.rs":"77137d8b2810c9059ce7838c3b665748bcb9765487d6103b92596e08b0e9e84b","src/layer/layered.rs":"945e42296ce3e86aa405eb31efdef4346cdfd84111f36700cc73e473e3ce5b28","src/layer/mod.rs":"b4febff42ea5ae12b92b8c73b7c691d9486e671446da99669fc5348314721cc9","src/layer/tests.rs":"3e974d627c4bc4269cfa10c82c890e596c9d46af8e6bc03c6c117bde1237e948","src/lib.rs":"bbe402c3ff042550b265976a688a0e3a95ac9ece77f290992e93fd2f51643f5c","src/macros.rs":"e184bffc6b5999c48e365ad08343dca764a5fb711b789beb26bd1d5f1d767726","src/prelude.rs":"088635def33be9a4c4b6ed934dc22540c555e27d62f7625a43aa9c0e525ca467","src/registry/extensions.rs":"0418b39287bbc06cc95b8cecd6a25aa808b8e04714d842340ff75db458cafe5b","src/registry/mod.rs":"76627b056ce39d006708a6273b6418d001b688f016f58aa546e7821d1ef7f3bb","src/registry/sharded.rs":"aaac353632b1bbb804048b40cdfce9877688efa0679ae42ab36a095fd3e3877f","src/registry/stack.rs":"9ef333d6a8a28a064e80ff1e376dbb07bc597009010ec332b2dc3ab435d737c2","src/reload.rs":"478f7612e19fa606cfa16f2791e426267256fe5799c3918b57209d3ebfa70406","src/sync.rs":"7f78f3de5b618a999be0e61f936a233975e7769f1ebb55a0e48c3d199e9c45e3","src/util.rs":"55b4e9d63112f9d5a12a287273a9b1212741058384332d3edc024168cacfd627","tests/cached_layer_filters_dont_break_other_layers.rs":"b2084542a014abeff821b30b2b8c21e32bfdcffae53ce5335fb588f557fa4244","tests/duplicate_spans.rs":"3bf35184fb7d1dc5f33e5098820febbec37ef3ccd06b693d11b5585affb60ff4","tests/env_filter/main.rs":"b2d89ee7aaf94f0563e4e5b025cf43186ec61657b763b7c0ae010ff548635251","tests/env_filter/per_layer.rs":"19e9998922f24ec368fcbcda406f43a95335551c4c1669b509bbfc1ef216432a","tests/event_enabling.rs":"15e301a8ff6c74c454547dad15a47b5f11fc54e539162191f21462b6d5080830","tests/field_filter.rs":"fb8735801ba7ecabb421ca361bd1c846841aee63eecbdd665f9544a1cec70f67","tests/filter_log.rs":"086f1e708a2e7389024d7e36d963947909d94c1975db92f4fc425b5cba2af533","tests/fmt_max_level_hint.rs":"d4c6d6f976ae41ab8052fa610a7337ad7150802cbd5634cb30fc45c1f215cfcd","tests/hinted_layer_filters_dont_break_other_layers.rs":"d5ba9cfb6784cf59f007e673ad549dc722d109f6b3d4a69f6aa11b25ca10b469","tests/layer_filter_interests_are_cached.rs":"d036d1c4bc3754e94ebfdda9c841f4858ccec40aba0720f3fbf26c817bfe5a83","tests/layer_filters/boxed.rs":"04db459721a26d6502a2b3fbe42154c5a451021a9374a18c017d10971f44e0c0","tests/layer_filters/combinators.rs":"cdbfaa37fa5b0439ec2ae8028601d22120ff2a42867a2af8a3b27fc58e70cb6c","tests/layer_filters/downcast_raw.rs":"9b90ead571543cbe14e89b4fe637360d9baf3069f6f656ed3bdf65e7318648f1","tests/layer_filters/filter_scopes.rs":"02611bc58d0d8a67a127eca8cab1b2d9a9901bd2c8a8daad41adf6089b28aee0","tests/layer_filters/main.rs":"fe0ed219b79bcbb2ece4c224ee5bf05662fe3b23a224f746b273afdb1abc0fbd","tests/layer_filters/targets.rs":"138e3f9ddd68571d94c5aff9d54ee2fbc5f44724c6ee42477a411740ccb79ee6","tests/layer_filters/trees.rs":"4df7b5cf12da44a9255c56e5b80e2b0cf84820230ba916f324c67bc3ee4e4605","tests/layer_filters/vec.rs":"eaf2e7fe0a76633cc02bc729513202a5fb169e2bdb5a8042d8c7bd1f7092691d","tests/multiple_layer_filter_interests_cached.rs":"1ea195f03e58d715228ec1b604f85bda2fc82812d05b2f6370d5edd34a035f32","tests/option.rs":"071af56d21e1438b112c7698790328f4797d2d4dd4c7e4857ea8d4825f1fac89","tests/registry_max_level_hint.rs":"ba386d32b8d13832d7009163241c3d0723488c0393d85647eb9368776251e4fc","tests/registry_with_subscriber.rs":"61a545e1bf3f75efd0dd18c20bb93e8a1f2e0158b342179a94228c4cbd5bb9cc","tests/reload.rs":"9a1b0bcb838a0f11beb528db7e578f12cc26e1592236dd7c2fa849271025e72c","tests/same_len_filters.rs":"eceb745f7f5b6c8737c1860a58e2cf98a048fc486dee4379e94485f41c92c925","tests/support.rs":"d5d8ae7a143bda971e24dcba01137be0efea957d732b43502fd845c3bc952f8b","tests/unhinted_layer_filters_dont_break_other_layers.rs":"519cfef4977e511af938546d4208c645a28248c8ed8666daf180f0ad32f0a261","tests/utils.rs":"2c37d9f39010767190f72cb2b3faa3131985764aa547027197108299a9a6bb9e","tests/vec.rs":"d1176f3e1b0954129792a28282b95084d417143b0cc4e35887b95cee3c675392","tests/vec_subscriber_filter_interests_cached.rs":"115a0f097cd649c570eabe74f82791bbe15b2de32a2eef403575661798aadd82"},"package":"3a713421342a5a666b7577783721d3117f1b69a393df803ee17bb73b1e122a59"}
\ No newline at end of file diff --git a/vendor/tracing-subscriber/CHANGELOG.md b/vendor/tracing-subscriber/CHANGELOG.md deleted file mode 100644 index 35747566e..000000000 --- a/vendor/tracing-subscriber/CHANGELOG.md +++ /dev/null @@ -1,1212 +0,0 @@ -# 0.3.14 (Jul 1, 2022) - -This release fixes multiple filtering bugs in the `Layer` implementations for -`Option<impl Layer>` and `Vec<impl Layer>`. - -### Fixed - -- **layer**: `Layer::event_enabled` implementation for `Option<impl Layer<S>>` - returning `false` when the `Option` is `None`, disabling all events globally - ([#2193]) -- **layer**: `Layer::max_level_hint` implementation for `Option<impl Layer<S>>` - incorrectly disabling max level filtering when the option is `None` ([#2195]) -- **layer**: `Layer::max_level_hint` implementation for `Vec<impl Layer<S>>` - returning `LevelFilter::ERROR` rather than `LevelFilter::OFF` when the `Vec` - is empty ([#2195]) - -Thanks to @CAD97 and @guswynn for contributing to this release! - -[#2193]: https://github.com/tokio-rs/tracing/pull/2193 -[#2195]: https://github.com/tokio-rs/tracing/pull/2195 - -# 0.3.13 (Jun 30, 2022) (YANKED) - -This release of `tracing-subscriber` fixes a compilation failure due to an -incorrect `tracing-core` dependency that was introduced in v0.3.12. - -### Changed - -- **tracing_core**: Updated minimum dependency version to 0.1.28 ([#2190]) - -[#2190]: https://github.com/tokio-rs/tracing/pull/2190 - -# 0.3.12 (Jun 29, 2022) (YANKED) - -This release of `tracing-subscriber` adds a new `Layer::event_enabled` method, -which allows `Layer`s to filter events *after* their field values are recorded; -a `Filter` implementation for `reload::Layer`, to make using `reload` with -per-layer filtering more ergonomic, and additional inherent method downcasting -APIs for the `Layered` type. In addition, it includes dependency updates, and -minor fixes for documentation and feature flagging. - -### Added - -- **layer**: `Layer::event_enabled` method, which can be implemented to filter - events based on their field values ([#2008]) -- **reload**: `Filter` implementation for `reload::Layer` ([#2159]) -- **layer**: `Layered::downcast_ref` and `Layered::is` inherent methods - ([#2160]) - -### Changed - -- **parking_lot**: Updated dependency on `parking_lot` to 0.13.0 ([#2143]) -- Replaced `lazy_static` dependency with `once_cell` ([#2147]) - -### Fixed - -- Don't enable `tracing-core` features by default ([#2107]) -- Several documentation link and typo fixes ([#2064], [#2068], #[2077], [#2161], - [#1088]) - -Thanks to @ben0x539, @jamesmunns, @georgemp, @james7132, @jswrenn, @CAD97, and -@guswynn for contributing to this release! - -[#2008]: https://github.com/tokio-rs/tracing/pull/2008 -[#2159]: https://github.com/tokio-rs/tracing/pull/2159 -[#2160]: https://github.com/tokio-rs/tracing/pull/2160 -[#2143]: https://github.com/tokio-rs/tracing/pull/2143 -[#2107]: https://github.com/tokio-rs/tracing/pull/2107 -[#2064]: https://github.com/tokio-rs/tracing/pull/2064 -[#2068]: https://github.com/tokio-rs/tracing/pull/2068 -[#2077]: https://github.com/tokio-rs/tracing/pull/2077 -[#2161]: https://github.com/tokio-rs/tracing/pull/2161 -[#1088]: https://github.com/tokio-rs/tracing/pull/1088 - -# 0.3.11 (Apr 9, 2022) - -This is a bugfix release for the `Filter` implementation for `EnvFilter` added -in [v0.3.10]. - -### Fixed - -- **env-filter**: Added missing `Filter::on_record` callback to `EnvFilter`'s - `Filter` impl ([#2058]) -- **env-filter**: Fixed method resolution issues when calling `EnvFilter` - methods with both the `Filter` and `Layer` traits in scope ([#2057]) -- **env-filter**: Fixed `EnvFilter::builder().parse()` and other parsing methods - returning an error when parsing an empty string ([#2052]) - -Thanks to new contributor @Ma124 for contributing to this release! - -[v0.3.10]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.10 -[#2058]: https://github.com/tokio-rs/tracing/pull/2058 -[#2057]: https://github.com/tokio-rs/tracing/pull/2057 -[#2052]: https://github.com/tokio-rs/tracing/pull/2052 - -# 0.3.10 (Apr 1, 2022) - -This release adds several new features, including a `Filter` implementation and -new builder API for `EnvFilter`, support for using a `Vec<L> where L: Layer` as -a `Layer`, and a number of smaller API improvements to make working with dynamic -and reloadable layers easier. - -### Added - -- **registry**: Implement `Filter` for `EnvFilter`, allowing it to be used with - per-layer filtering ([#1983]) -- **registry**: `Filter::on_new_span`, `Filter::on_enter`, - `Filter::on_exit`, `Filter::on_close` and `Filter::on_record` callbacks to - allow `Filter`s to track span states internally ([#1973], [#2017], [#2031]) -- **registry**: `Filtered::filter` and `Filtered::filter_mut` accessors - ([#1959]) -- **registry**: `Filtered::inner` and `Filtered::inner_mut` accessors to borrow - the wrapped `Layer` ([#2034]) -- **layer**: Implement `Layer` for `Vec<L: Layer>`, to allow composing together - a dynamically sized list of `Layer`s ([#2027]) -- **layer**: `Layer::boxed` method to make type-erasing `Layer`s easier - ([#2026]) -- **fmt**: `fmt::Layer::writer` and `fmt::Layer::writer_mut` accessors ([#2034]) -- **fmt**: `fmt::Layer::set_ansi` method to allow changing the ANSI formatting - configuration at runtime ([#2034]) -- **env-filter**: `EnvFilter::builder` to configure a new `EnvFilter` prior to - parsing it ([#2035]) -- Several documentation fixes and improvements ([#1972], [#1971], [#2023], - [#2023]) - -### Fixed - -- **fmt**: `fmt::Layer`'s auto traits no longer depend on the `Subscriber` type - parameter's auto traits ([#2025]) -- **env-filter**: Fixed missing help text when the `ansi` feature is disabled - ([#2029]) - -Thanks to new contributors @TimoFreiberg and @wagenet, as well as @CAD97 for -contributing to this release! - -[#1983]: https://github.com/tokio-rs/tracing/pull/1983 -[#1973]: https://github.com/tokio-rs/tracing/pull/1973 -[#2017]: https://github.com/tokio-rs/tracing/pull/2017 -[#2031]: https://github.com/tokio-rs/tracing/pull/2031 -[#1959]: https://github.com/tokio-rs/tracing/pull/1959 -[#2034]: https://github.com/tokio-rs/tracing/pull/2034 -[#2027]: https://github.com/tokio-rs/tracing/pull/2027 -[#2026]: https://github.com/tokio-rs/tracing/pull/2026 -[#2035]: https://github.com/tokio-rs/tracing/pull/2035 -[#1972]: https://github.com/tokio-rs/tracing/pull/1972 -[#1971]: https://github.com/tokio-rs/tracing/pull/1971 -[#2023]: https://github.com/tokio-rs/tracing/pull/2023 -[#2025]: https://github.com/tokio-rs/tracing/pull/2025 -[#2029]: https://github.com/tokio-rs/tracing/pull/2029 - -# 0.3.9 (Feb 17, 2022) - -This release updates the minimum supported Rust version (MSRV) to 1.49.0, and -updates the (optional) dependency on `parking_lot` to v0.12. - -### Changed - -- Updated minimum supported Rust version (MSRV) to 1.49.0 ([#1913]) -- `parking_lot`: updated to v0.12 ([008339d]) - -### Added - -- **fmt**: Documentation improvements ([#1926], [#1927]) - -[#1913]: https://github.com/tokio-rs/tracing/pull/1913 -[#1926]: https://github.com/tokio-rs/tracing/pull/1926 -[#1927]: https://github.com/tokio-rs/tracing/pull/1927 -[008339d]: https://github.com/tokio-rs/tracing/commit/008339d1e8750ffe7b4634fc7789bda0c522424f - -# 0.3.8 (Feb 4, 2022) - -This release adds *experimental* support for recording structured field -values using the [`valuable`] crate to the `format::Json` formatter. In -particular, user-defined types which are recorded using their -[`valuable::Valuable`] implementations will be serialized as JSON objects, -rather than using their `fmt::Debug` representation. See [this blog post][post] -for details on `valuable`. - -Note that `valuable` support currently requires `--cfg tracing_unstable`. See -the documentation for details. - -Additionally, this release includes a number of other smaller API improvements. - -### Added - -- **json**: Experimental support for recording [`valuable`] values as structured - JSON ([#1862], [#1901]) -- **filter**: `Targets::would_enable` method for testing if a `Targets` filter - would enable a given target ([#1903]) -- **fmt**: `map_event_format`, `map_fmt_fields`, and `map_writer` methods to - `fmt::Layer` and `fmt::SubscriberBuilder` ([#1871]) - -### Changed - -- `tracing-core`: updated to [0.1.22][core-0.1.22] - -### Fixed - -- Set `smallvec` minimal version to 1.2.0, to fix compilation errors with `-Z - minimal-versions` ([#1890]) -- Minor documentation fixes ([#1902], [#1893]) - -Thanks to @guswynn, @glts, and @lilyball for contributing to this release! - -[`valuable`]: https://crates.io/crates/valuable -[`valuable::Valuable`]: https://docs.rs/valuable/latest/valuable/trait.Valuable.html -[post]: https://tokio.rs/blog/2021-05-valuable -[core-0.1.22]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.22 -[#1862]: https://github.com/tokio-rs/tracing/pull/1862 -[#1901]: https://github.com/tokio-rs/tracing/pull/1901 -[#1903]: https://github.com/tokio-rs/tracing/pull/1903 -[#1871]: https://github.com/tokio-rs/tracing/pull/1871 -[#1890]: https://github.com/tokio-rs/tracing/pull/1890 -[#1902]: https://github.com/tokio-rs/tracing/pull/1902 -[#1893]: https://github.com/tokio-rs/tracing/pull/1893 - -# 0.3.7 (Jan 25, 2022) - -This release adds combinators for combining filters. - -Additionally, this release also updates the `thread-local` crate to v1.1.4, -fixing warnings for the security advisory [RUSTSEC-2022-0006]. Note that -previous versions of `tracing-subscriber` did not use any of the `thread-local` -crate's APIs effected by the vulnerability. However, updating the version fixes -warnings emitted by `cargo audit` and similar tools. - -### Added - -- **filter**: Added combinators for combining filters ([#1578]) - -### Fixed - -- **registry**: Updated `thread-local` to v1.1.4 ([#1858]) - -Thanks to new contributor @matze for contributing to this release! - -[RUSTSEC-2022-0006]: https://rustsec.org/advisories/RUSTSEC-2022-0006 -[#1578]: https://github.com/tokio-rs/tracing/pull/1578 -[#1858]: https://github.com/tokio-rs/tracing/pull/1858 - -# 0.3.6 (Jan 14, 2022) - -This release adds configuration options to `tracing_subscriber::fmt` to log -source code locations for events. -### Added - -- **fmt**: Added `with_file` and `with_line_number` - configuration methods to `fmt::Format`, `fmt::SubscriberBuilder`, and - `fmt::Layer` ([#1773]) - -### Fixed - -- **fmt**: Removed incorrect leading comma from span fields with the `Pretty` - formatter ([#1833]) - -### Deprecated - -- **fmt**: Deprecated `Pretty::with_source_location`, as it can now be replaced - by the more general `Format`, `SubscriberBuilder`, and `Layer` methods - ([#1773]) - -Thanks to new contributor @renecouto for contributing to this release! - -[#1773]: https://github.com/tokio-rs/tracing/pull/1773 -[#1833]: https://github.com/tokio-rs/tracing/pull/1833 - -# 0.3.5 (Dec 29, 2021) - -This release re-enables `RUST_LOG` filtering in `tracing_subscriber::fmt`'s -default initialization methods, and adds an `OffsetLocalTime` formatter for -using local timestamps with the `time` crate. - -### Added - -- **fmt**: Added `OffsetLocalTime` formatter to `fmt::time` for formatting local - timestamps with a fixed offset ([#1772]) - -### Fixed - -- **fmt**: Added a `Targets` filter to `fmt::init()` and `fmt::try_init()` when - the "env-filter" feature is disabled, so that `RUST_LOG` is still honored - ([#1781]) - -Thanks to @marienz and @ishitatsuyuki for contributing to this release! - -[#1772]: https://github.com/tokio-rs/tracing/pull/1772 -[#1781]: https://github.com/tokio-rs/tracing/pull/1781 - -# 0.3.4 (Dec 23, 2021) - -This release contains bugfixes for the `fmt` module, as well as documentation -improvements. - -### Fixed - -- **fmt**: Fixed `fmt` not emitting log lines when timestamp formatting fails - ([#1689]) -- **fmt**: Fixed double space before thread IDs with `Pretty` formatter - ([#1778]) -- Several documentation improvements ([#1608], [#1699], [#1701]) - -[#1689]: https://github.com/tokio-rs/tracing/pull/1689 -[#1778]: https://github.com/tokio-rs/tracing/pull/1778 -[#1608]: https://github.com/tokio-rs/tracing/pull/1608 -[#1699]: https://github.com/tokio-rs/tracing/pull/1699 -[#1701]: https://github.com/tokio-rs/tracing/pull/1701 - -Thanks to new contributors @Swatinem and @rukai for contributing to this -release! - -# 0.3.3 (Nov 29, 2021) - -This release fixes a pair of regressions in `tracing-subscriber`'s `fmt` module. - -### Fixed - -- **fmt**: Fixed missing event fields with `Compact` formatter ([#1755]) -- **fmt**: Fixed `PrettyFields` formatter (and thus `format::Pretty` event - formatter) ignoring the `fmt::Layer`'s ANSI color code configuration ([#1747]) - -[#1755]: https://github.com/tokio-rs/tracing/pull/1755 -[#1747]: https://github.com/tokio-rs/tracing/pull/1747 - -# 0.3.2 (Nov 19, 2021) - -### Fixed - -- **fmt**: Fixed `MakeWriter` filtering not working with `BoxMakeWriter` - ([#1694]) - -### Added - -- **fmt**: `Writer::has_ansi_escapes` method to check if an output supports ANSI - terminal formatting escape codes ([#1696]) -- **fmt**: Added additional ANSI terminal formatting to field formatters when - supported ([#1702]) -- **fmt**: Added `FmtContext::span_scope`, `FmtContext::event_scope`, and - `FmtContext::parent_span` methods for accessing the current span and its scope - when formatting an event ([#1728]) -- **fmt**: Improved documentation on implementing event formatters ([#1727]) - -[#1694]: https://github.com/tokio-rs/tracing/pull/1694 -[#1696]: https://github.com/tokio-rs/tracing/pull/1696 -[#1702]: https://github.com/tokio-rs/tracing/pull/1702 -[#1728]: https://github.com/tokio-rs/tracing/pull/1728 -[#1727]: https://github.com/tokio-rs/tracing/pull/1727 -# 0.3.1 (Oct 25, 2021) - -This release fixes a few issues related to feature flagging. - -### Fixed - -- **time**: Compilation error when enabling the "time" feature flag without also - enabling the "local-time" feature flag ([#1685]) -- **registry**: Unused method warnings when the "std" feature is enabled but the - "registry" feature is disabled ([#1686]) - -[#1685]: https://github.com/tokio-rs/tracing/pull/1685 -[#1686]: https://github.com/tokio-rs/tracing/pull/1686 - -# 0.3.0 (Oct 22, 2021) - -This is a breaking release of `tracing-subscriber`. The primary breaking change -in this release is the removal of the dependency on the [`chrono` crate], due to -[RUSTSEC-2020-0159]. To replace `chrono`, support is added for formatting -timestamps using the [`time` crate] instead. - -In addition, this release includes a number of other breaking API changes, such -as adding (limited) support for `#![no_std]` targets, removing previously -deprecated APIs, and more. - -### Breaking Changes - -- Removed APIs deprecated in the v0.2.x release series. -- Renamed `Layer::new_span` to `Layer::on_new_span` ([#1674]) -- Removed `Layer` impl for `Arc<L: Layer<S>>` and `Arc<dyn Layer<S> + ...>` - ([#1649]) -- Replaced the [`chrono` crate] with the [`time` crate] for timestamp formatting, to - resolve [RUSTSEC-2020-0159] ([#1646]) -- Removed `json` and `env-filter` from default features. They must now be - enabled explictly ([#1647]). This means that `RUST_LOG`-based filters _will not_ - work unless the `env-filter` feature is enabled. -- Changed `FormatEvent::format_event` and `FormatFields::format_fields` - trait methods to take a `Writer` type, rather than a `&mut dyn fmt::Write` - trait object ([#1661]) -- Changed the signature of the `MakeWriter` trait by adding a lifetime parameter - ([#781]) - -### Changed - -- **layer**: Renamed `Layer::new_span` to `Layer::on_new_span` ([#1674]) -- **fmt**: Changed `FormatEvent::format_event` and `FormatFields::format_fields` - trait methods to take a `Writer` type, rather than a `&mut dyn fmt::Write` - trait object ([#1661]) -- **json**, **env-filter**: `json` and `env-filter` feature flags are no longer - enabled by default ([#1647]) -### Removed - -- Removed deprecated `CurrentSpan` type ([#1320]) -- **registry**: Removed deprecated `SpanRef::parents` iterator, replaced by - `SpanRef::scope` in [#1431] ([#1648)]) -- **layer**: Removed deprecated `Context::scope` iterator, replaced by - `Context::span_scope` and `Context::event_scope` in [#1431] and [#1434] - ([#1648)]) -- **layer**: Removed `Layer` impl for `Arc<L: Layer<S>>` and - `Arc<dyn Layer<S> + ...>`. These interfere with per-layer filtering. ([#1649]) -- **fmt**: Removed deprecated `LayerBuilder` type ([#1673]) -- **fmt**: Removed `fmt::Layer::on_event` (renamed to `fmt::Layer::fmt_event`) - ([#1673]) -- **fmt**, **chrono**: Removed the `chrono` feature flag and APIs for using the - [`chrono` crate] for timestamp formatting ([#1646]) -### Added - -- **fmt**, **time**: `LocalTime` and `UtcTime` types for formatting timestamps - using the [`time` crate] ([#1646]) -- **fmt**: Added a lifetime parameter to the `MakeWriter` trait, allowing it to - return a borrowed writer. This enables implementations of `MakeWriter` for - types such as `Mutex<T: io::Write>` and `std::fs::File`. ([#781]) -- **env-filter**: Documentation improvements ([#1637]) -- Support for some APIs on `#![no_std]` targets, by disabling the `std` feature - flag ([#1660]) - -Thanks to @Folyd and @nmathewson for contributing to this release! - -[#1320]: https://github.com/tokio-rs/tracing/pull/1320 -[#1673]: https://github.com/tokio-rs/tracing/pull/1673 -[#1674]: https://github.com/tokio-rs/tracing/pull/1674 -[#1646]: https://github.com/tokio-rs/tracing/pull/1646 -[#1647]: https://github.com/tokio-rs/tracing/pull/1647 -[#1648]: https://github.com/tokio-rs/tracing/pull/1648 -[#1649]: https://github.com/tokio-rs/tracing/pull/1649 -[#1660]: https://github.com/tokio-rs/tracing/pull/1660 -[#1661]: https://github.com/tokio-rs/tracing/pull/1661 -[#1431]: https://github.com/tokio-rs/tracing/pull/1431 -[#1434]: https://github.com/tokio-rs/tracing/pull/1434 -[#781]: https://github.com/tokio-rs/tracing/pull/781 - -[`chrono` crate]: https://crates.io/crates/chrono -[`time` crate]: https://crates.io/crates/time -[RUSTSEC-2020-0159]: https://rustsec.org/advisories/RUSTSEC-2020-0159.html - -# 0.2.25 (October 5, 2021) - -This release fixes an issue where a `Layer` implementation's custom -`downcast_raw` implementation was lost when wrapping that layer with a per-layer -filter. - -### Fixed - -- **registry**: Forward `Filtered::downcast_raw` to wrapped `Layer` ([#1619]) - -### Added - -- Documentation improvements ([#1596], [#1601]) - -Thanks to @bryanburgers for contributing to this release! - -[#1619]: https://github.com/tokio-rs/tracing/pull/1619 -[#1601]: https://github.com/tokio-rs/tracing/pull/1601 -[#1596]: https://github.com/tokio-rs/tracing/pull/1596 - -# 0.2.24 (September 19, 2021) - -This release contains a number of bug fixes, including a fix for -`tracing-subscriber` failing to compile on the minimum supported Rust version of -1.42.0. It also adds `IntoIterator` implementations for the `Targets` type. - -### Fixed - -- Fixed compilation on Rust 1.42.0 ([#1580], [#1581]) -- **registry**: Ensure per-layer filter `enabled` state is cleared when a global - filter short-circuits filter evaluation ([#1575]) -- **layer**: Fixed `Layer::on_layer` not being called for `Box`ed `Layer`s, - which broke per-layer filtering ([#1576]) - -### Added - -- **filter**: Added `Targets::iter`, returning an iterator over the set of - target-level pairs enabled by a `Targets` filter ([#1574]) -- **filter**: Added `IntoIterator` implementations for `Targets` and `&Targets` - ([#1574]) - -Thanks to new contributor @connec for contributing to this release! - -[#1580]: https://github.com/tokio-rs/tracing/pull/1580 -[#1581]: https://github.com/tokio-rs/tracing/pull/1581 -[#1575]: https://github.com/tokio-rs/tracing/pull/1575 -[#1576]: https://github.com/tokio-rs/tracing/pull/1576 -[#1574]: https://github.com/tokio-rs/tracing/pull/1574 - -# 0.2.23 (September 16, 2021) - -This release fixes a few bugs in the per-layer filtering API added in v0.2.21. - -### Fixed - -- **env-filter**: Fixed excessive `EnvFilter` memory use ([#1568]) -- **filter**: Fixed a panic that may occur in debug mode when using per-layer - filters together with global filters ([#1569]) -- Fixed incorrect documentation formatting ([#1572]) - -[#1568]: https://github.com/tokio-rs/tracing/pull/1568 -[#1569]: https://github.com/tokio-rs/tracing/pull/1569 -[#1572]: https://github.com/tokio-rs/tracing/pull/1572 - -# 0.2.22 (September 13, 2021) - -This fixes a regression where the `filter::ParseError` type was accidentally -renamed. - -### Fixed - -- **filter**: Fix `filter::ParseError` accidentally being renamed to - `filter::DirectiveParseError` ([#1558]) - -[#1558]: https://github.com/tokio-rs/tracing/pull/1558 - -# 0.2.21 (September 12, 2021) - -This release introduces the [`Filter`] trait, a new API for [per-layer -filtering][plf]. This allows controlling which spans and events are recorded by -various layers individually, rather than globally. - -In addition, it adds a new [`Targets`] filter, which provides a lighter-weight -version of the filtering provided by [`EnvFilter`], as well as other smaller API -improvements and fixes. - -### Deprecated - -- **registry**: `SpanRef::parent_id`, which cannot properly support per-layer - filtering. Use `.parent().map(SpanRef::id)` instead. ([#1523]) - -### Fixed - -- **layer** `Context` methods that are provided when the `Subscriber` implements - `LookupSpan` no longer require the "registry" feature flag ([#1525]) -- **layer** `fmt::Debug` implementation for `Layered` no longer requires the `S` - type parameter to implement `Debug` ([#1528]) - -### Added - -- **registry**: `Filter` trait, `Filtered` type, `Layer::with_filter` method, - and other APIs for per-layer filtering ([#1523]) -- **filter**: `FilterFn` and `DynFilterFn` types that implement global (`Layer`) - and per-layer (`Filter`) filtering for closures and function pointers - ([#1523]) -- **filter**: `Targets` filter, which implements a lighter-weight form of - `EnvFilter`-like filtering ([#1550]) -- **env-filter**: Added support for filtering on floating-point values ([#1507]) -- **layer**: `Layer::on_layer` callback, called when layering the `Layer` onto a -`Subscriber` ([#1523]) -- **layer**: `Layer` implementations for `Box<L>` and `Arc<L>` where `L: Layer` - ([#1536]) -- **layer**: `Layer` implementations for `Box<dyn Layer<S> + Send + Sync + 'static>` - and `Arc<dyn Layer<S> + Send + Sync + 'static>` ([#1536]) -- A number of small documentation fixes and improvements ([#1553], [#1544], - [#1539], [#1524]) - -Special thanks to new contributors @jsgf and @maxburke for contributing to this -release! - -[`Filter`]: https://docs.rs/tracing-subscriber/0.2.21/tracing_subscriber/layer/trait.Filter.html -[plf]: https://docs.rs/tracing-subscriber/0.2.21/tracing_subscriber/layer/index.html#per-layer-filtering -[`Targets`]: https://docs.rs/tracing-subscriber/0.2.21/tracing_subscriber/filter/struct.Targets.html -[`EnvFilter`]: https://docs.rs/tracing-subscriber/0.2.21/tracing_subscriber/filter/struct.EnvFilter.html -[#1507]: https://github.com/tokio-rs/tracing/pull/1507 -[#1523]: https://github.com/tokio-rs/tracing/pull/1523 -[#1524]: https://github.com/tokio-rs/tracing/pull/1524 -[#1525]: https://github.com/tokio-rs/tracing/pull/1525 -[#1528]: https://github.com/tokio-rs/tracing/pull/1528 -[#1539]: https://github.com/tokio-rs/tracing/pull/1539 -[#1544]: https://github.com/tokio-rs/tracing/pull/1544 -[#1550]: https://github.com/tokio-rs/tracing/pull/1550 -[#1553]: https://github.com/tokio-rs/tracing/pull/1553 - -# 0.2.20 (August 17, 2021) - -### Fixed - -- **fmt**: Fixed `fmt` printing only the first `source` for errors with a chain - of sources ([#1460]) -- **fmt**: Fixed missing space between level and event in the `Pretty` formatter - ([#1498]) -- **json**: Fixed `Json` formatter not honoring `without_time` and `with_level` - configurations ([#1463]) - -### Added - -- **registry**: Improved panic message when cloning a span whose ID doesn't - exist, to aid in debugging issues with multiple subscribers ([#1483]) -- **registry**: Improved documentation on span ID generation ([#1453]) - -[#1460]: https://github.com/tokio-rs/tracing/pull/1460 -[#1483]: https://github.com/tokio-rs/tracing/pull/1483 -[#1463]: https://github.com/tokio-rs/tracing/pull/1463 -[#1453]: https://github.com/tokio-rs/tracing/pull/1453 -[#1498]: https://github.com/tokio-rs/tracing/pull/1498 - -Thanks to new contributors @joshtriplett and @lerouxrgd, and returning -contributor @teozkr, for contributing to this release! - -# 0.2.19 (June 25, 2021) - -### Deprecated - -- **registry**: `SpanRef::parents`, `SpanRef::from_root`, and `Context::scope` - iterators, which are replaced by new `SpanRef::scope` and `Scope::from_root` - iterators ([#1413]) - -### Added - -- **registry**: `SpanRef::scope` method, which returns a leaf-to-root `Iterator` - including the leaf span ([#1413]) -- **registry**: `Scope::from_root` method, which reverses the `scope` iterator - to iterate root-to-leaf ([#1413]) -- **registry**: `Context::event_span` method, which looks up the parent span of - an event ([#1434]) -- **registry**: `Context::event_scope` method, returning a `Scope` iterator over - the span scope of an event ([#1434]) -- **fmt**: `MakeWriter::make_writer_for` method, which allows returning a - different writer based on a span or event's metadata ([#1141]) -- **fmt**: `MakeWriterExt` trait, with `with_max_level`, `with_min_level`, - `with_filter`, `and`, and `or_else` combinators ([#1274]) -- **fmt**: `MakeWriter` implementation for `Arc<W> where &W: io::Write` - ([#1274]) - -Thanks to @teozkr and @Folyd for contributing to this release! - -[#1413]: https://github.com/tokio-rs/tracing/pull/1413 -[#1434]: https://github.com/tokio-rs/tracing/pull/1434 -[#1141]: https://github.com/tokio-rs/tracing/pull/1141 -[#1274]: https://github.com/tokio-rs/tracing/pull/1274 - -# 0.2.18 (April 30, 2021) - -### Deprecated - -- Deprecated the `CurrentSpan` type, which is inefficient and largely superseded - by the `registry` API ([#1321]) - -### Fixed - -- **json**: Invalid JSON emitted for events in spans with no fields ([#1333]) -- **json**: Missing span data for synthesized new span, exit, and close events - ([#1334]) -- **fmt**: Extra space before log lines when timestamps are disabled ([#1355]) - -### Added - -- **env-filter**: Support for filters on spans whose names contain any - characters other than `{` and `]` ([#1368]) - -Thanks to @Folyd, and new contributors @akinnane and @aym-v for contributing to -this release! - -[#1321]: https://github.com/tokio-rs/tracing/pull/1321 -[#1333]: https://github.com/tokio-rs/tracing/pull/1333 -[#1334]: https://github.com/tokio-rs/tracing/pull/1334 -[#1355]: https://github.com/tokio-rs/tracing/pull/1355 -[#1368]: https://github.com/tokio-rs/tracing/pull/1368 - -# 0.2.17 (March 12, 2021) - -### Fixed - -- **fmt**: `Pretty` formatter now honors `with_ansi(false)` to disable ANSI - terminal formatting ([#1240]) -- **fmt**: Fixed extra padding when using `Pretty` formatter ([#1275]) -- **chrono**: Removed extra trailing space with `ChronoLocal` time formatter - ([#1103]) - -### Added - -- **fmt**: Added `FmtContext::current_span()` method, returning the current span - ([#1290]) -- **fmt**: `FmtSpan` variants may now be combined using the `|` operator for - more granular control over what span events are generated ([#1277]) - -Thanks to new contributors @cratelyn, @dignati, and @zicklag, as well as @Folyd, -@matklad, and @najamelan, for contributing to this release! - -[#1240]: https://github.com/tokio-rs/tracing/pull/1240 -[#1275]: https://github.com/tokio-rs/tracing/pull/1275 -[#1103]: https://github.com/tokio-rs/tracing/pull/1103 -[#1290]: https://github.com/tokio-rs/tracing/pull/1290 -[#1277]: https://github.com/tokio-rs/tracing/pull/1277 - -# 0.2.16 (February 19, 2021) - -### Fixed - -- **env-filter**: Fixed directives where the level is in mixed case (such as - `Info`) failing to parse ([#1126]) -- **fmt**: Fixed `fmt::Subscriber` not providing a max-level hint ([#1251]) -- `tracing-subscriber` no longer enables `tracing` and `tracing-core`'s default - features ([#1144]) - -### Changed - -- **chrono**: Updated `chrono` dependency to 0.4.16 ([#1189]) -- **log**: Updated `tracing-log` dependency to 0.1.2 - -Thanks to @salewski, @taiki-e, @davidpdrsn and @markdingram for contributing to -this release! - -[#1126]: https://github.com/tokio-rs/tracing/pull/1126 -[#1251]: https://github.com/tokio-rs/tracing/pull/1251 -[#1144]: https://github.com/tokio-rs/tracing/pull/1144 -[#1189]: https://github.com/tokio-rs/tracing/pull/1189 - -# 0.2.15 (November 2, 2020) - -### Fixed - -- **fmt**: Fixed wrong lifetime parameters on `FormatFields` impl for - `FmtContext` ([#1082]) - -### Added - -- **fmt**: `format::Pretty`, an aesthetically pleasing, human-readable event - formatter for local development and user-facing CLIs ([#1080]) -- **fmt**: `FmtContext::field_format`, which returns the subscriber's field - formatter ([#1082]) - -[#1082]: https://github.com/tokio-rs/tracing/pull/1082 -[#1080]: https://github.com/tokio-rs/tracing/pull/1080 - -# 0.2.14 (October 22, 2020) - -### Fixed - -- **registry**: Fixed `Registry::new` allocating an excessively large amount of - memory, most of which would never be used ([#1064]) - -### Changed - -- **registry**: Improved `new_span` performance by reusing `HashMap` allocations - for `Extensions` ([#1064]) -- **registry**: Significantly improved the performance of `Registry::enter` and - `Registry::exit` ([#1058]) - -[#1064]: https://github.com/tokio-rs/tracing/pull/1064 -[#1058]: https://github.com/tokio-rs/tracing/pull/1058 - -# 0.2.13 (October 7, 2020) - -### Changed - -- Updated `tracing-core` to 0.1.17 ([#992]) - -### Added - -- **env-filter**: Added support for filtering on targets which contain dashes - ([#1014]) -- **env-filter**: Added a warning when creating an `EnvFilter` that contains - directives that would enable a level disabled by the `tracing` crate's - `static_max_level` features ([#1021]) - -Thanks to @jyn514 and @bkchr for contributing to this release! - -[#992]: https://github.com/tokio-rs/tracing/pull/992 -[#1014]: https://github.com/tokio-rs/tracing/pull/1014 -[#1021]: https://github.com/tokio-rs/tracing/pull/1021 - -# 0.2.12 (September 11, 2020) - -### Fixed - -- **env-filter**: Fixed a regression where `Option<Level>` lost its - `Into<LevelFilter>` impl ([#966]) -- **env-filter**: Fixed `EnvFilter` enabling spans that should not be enabled - when multiple subscribers are in use ([#927]) - -### Changed - -- **json**: `format::Json` now outputs fields in a more readable order ([#892]) -- Updated `tracing-core` dependency to 0.1.16 - -### Added - -- **fmt**: Add `BoxMakeWriter` for erasing the type of a `MakeWriter` - implementation ([#958]) -- **fmt**: Add `TestWriter` `MakeWriter` implementation to support libtest - output capturing ([#938]) -- **layer**: Add `Layer` impl for `Option<T> where T: Layer` ([#910]) -- **env-filter**: Add `From<Level>` impl for `Directive` ([#918]) -- Multiple documentation fixes and improvements - -Thanks to @Pothulapati, @samrg472, @bryanburgers, @keetonian, and @SriRamanujam -for contributing to this release! - -[#927]: https://github.com/tokio-rs/tracing/pull/927 -[#966]: https://github.com/tokio-rs/tracing/pull/966 -[#958]: https://github.com/tokio-rs/tracing/pull/958 -[#892]: https://github.com/tokio-rs/tracing/pull/892 -[#938]: https://github.com/tokio-rs/tracing/pull/938 -[#910]: https://github.com/tokio-rs/tracing/pull/910 -[#918]: https://github.com/tokio-rs/tracing/pull/918 - -# 0.2.11 (August 10, 2020) - -### Fixed - -- **env-filter**: Incorrect max level hint when filters involving span field - values are in use (#907) -- **registry**: Fixed inconsistent span stacks when multiple registries are in - use on the same thread (#901) - -### Changed - -- **env-filter**: `regex` dependency enables fewer unused feature flags (#899) - -Thanks to @bdonlan and @jeromegn for contributing to this release! - -# 0.2.10 (July 31, 2020) - -### Fixed - -- **docs**: Incorrect formatting (#862) - -### Changed - -- **filter**: `LevelFilter` is now a re-export of the - `tracing_core::LevelFilter` type, it can now be used interchangably with the - versions in `tracing` and `tracing-core` (#853) -- **filter**: Significant performance improvements when comparing `LevelFilter`s - and `Level`s (#853) -- Updated the minimum `tracing-core` dependency to 0.1.12 (#853) - -### Added - -- **filter**: `LevelFilter` and `EnvFilter` now participate in `tracing-core`'s - max level hinting, improving performance significantly in some use cases where - levels are disabled globally (#853) - -# 0.2.9 (July 23, 2020) - -### Fixed - -- **fmt**: Fixed compilation failure on MSRV when the `chrono` feature is - disabled (#844) - -### Added - -- **fmt**: Span lookup methods defined by `layer::Context` are now also provided - by `FmtContext` (#834) - -# 0.2.8 (July 17, 2020) - -### Changed - -- **fmt**: When the `chrono` dependency is enabled, the `SystemTime` timestamp - formatter now emits human-readable timestamps rather than using `SystemTime`'s - `fmt::Debug`implementation (`chrono` is still required for customized - timestamp formatting) (#807) -- **ansi**: Updated `ansi_term` dependency to 0.12 (#816) - -### Added - -- **json**: `with_span_list` method to configure the JSON formatter to include a - list of all spans in the current trace in formatting events (similarly to the - text formatter) (#741) -- **json**: `with_current_span` method to configure the JSON formatter to include - a field for the _current_ span (the leaf of the trace) in formatted events - (#741) -- **fmt**: `with_thread_names` and `with_thread_ids` methods to configure - `fmt::Subscriber`s and `fmt::Layer`s to include the thread name and/or thread ID - of the current thread when formatting events (#818) - -Thanks to new contributors @mockersf, @keetonian, and @Pothulapati for -contributing to this release! - -# 0.2.7 (July 1, 2020) - -### Changed - -- **parking_lot**: Updated the optional `parking_lot` dependency to accept the - latest `parking_lot` version (#774) - -### Fixed - -- **fmt**: Fixed events with explicitly overridden parent spans being formatted - as though they were children of the current span (#767) - -### Added - -- **fmt**: Added the option to print synthesized events when spans are created, - entered, exited, and closed, including span durations (#761) -- Documentation clarification and improvement (#762, #769) - -Thanks to @rkuhn, @greenwoodcm, and @Ralith for contributing to this release! - -# 0.2.6 (June 19, 2020) - -### Fixed - -- **fmt**: Fixed an issue in the JSON formatter where using `Span::record` would - result in malformed spans (#709) - -# 0.2.5 (April 21, 2020) - -### Changed - -- **fmt**: Bump sharded-slab dependency (#679) - -### Fixed - -- **fmt**: remove trailing space in `ChronoUtc` `format_time` (#677) - -# 0.2.4 (April 6, 2020) - -This release includes several API ergonomics improvements, including shorthand -constructors for many types, and an extension trait for initializing subscribers -using method-chaining style. Additionally, several bugs in less commonly used -`fmt` APIs were fixed. - -### Added - -- **fmt**: Shorthand free functions for constructing most types in `fmt` - (including `tracing_subscriber::fmt()` to return a `SubscriberBuilder`, - `tracing_subscriber::fmt::layer()` to return a format `Layer`, etc) (#660) -- **registry**: Shorthand free function `tracing_subscriber::registry()` to - construct a new registry (#660) -- Added `SubscriberInitExt` extension trait for more ergonomic subscriber - initialization (#660) - -### Changed - -- **fmt**: Moved `LayerBuilder` methods to `Layer` (#655) - -### Deprecated - -- **fmt**: `LayerBuilder`, as `Layer` now implements all builder methods (#655) - -### Fixed - -- **fmt**: Fixed `Compact` formatter not omitting levels with - `with_level(false)` (#657) -- **fmt**: Fixed `fmt::Layer` duplicating the fields for a new span if another - layer has already formatted its fields (#634) -- **fmt**: Added missing space when using `record` to add new fields to a span - that already has fields (#659) -- Updated outdated documentation (#647) - - -# 0.2.3 (March 5, 2020) - -### Fixed - -- **env-filter**: Regression where filter directives were selected in the order - they were listed, rather than most specific first (#624) - -# 0.2.2 (February 27, 2020) - -### Added - -- **fmt**: Added `flatten_event` to `SubscriberBuilder` (#599) -- **fmt**: Added `with_level` to `SubscriberBuilder` (#594) - -# 0.2.1 (February 13, 2020) - -### Changed - -- **filter**: `EnvFilter` directive selection now behaves correctly (i.e. like - `env_logger`) (#583) - -### Fixed - -- **filter**: Fixed `EnvFilter` incorrectly allowing less-specific filter - directives to enable events that are disabled by more-specific filters (#583) -- **filter**: Multiple significant `EnvFilter` performance improvements, - especially when filtering events generated by `log` records (#578, #583) -- **filter**: Replaced `BTreeMap` with `Vec` in `DirectiveSet`, improving - iteration performance significantly with typical numbers of filter directives - (#580) - -A big thank-you to @samschlegel for lots of help with `EnvFilter` performance -tuning in this release! - -# 0.2.0 (February 4, 2020) - -### Breaking Changes - -- **fmt**: Renamed `Context` to `FmtContext` (#420, #425) -- **fmt**: Renamed `Builder` to `SubscriberBuilder` (#420) -- **filter**: Removed `Filter`. Use `EnvFilter` instead (#434) - -### Added - -- **registry**: `Registry`, a `Subscriber` implementation that `Layer`s can use - as a high-performance, in-memory span store. (#420, #425, #432, #433, #435) -- **registry**: Added `LookupSpan` trait, implemented by `Subscriber`s to expose - stored span data to `Layer`s (#420) -- **fmt**: Added `fmt::Layer`, to allow composing log formatting with other `Layer`s -- **fmt**: Added support for JSON field and event formatting (#377, #415) -- **filter**: Documentation for filtering directives (#554) - -### Changed - -- **fmt**: Renamed `Context` to `FmtContext` (#420, #425) (BREAKING) -- **fmt**: Renamed `Builder` to `SubscriberBuilder` (#420) (BREAKING) -- **fmt**: Reimplemented `fmt::Subscriber` in terms of the `Registry` - and `Layer`s (#420) - -### Removed - -- **filter**: Removed `Filter`. Use `EnvFilter` instead (#434) (BREAKING) - -### Fixed - -- **fmt**: Fixed memory leaks in the slab used to store per-span data - (3c35048) -- **fmt**: `fmt::SubscriberBuilder::init` not setting up `log` compatibility - (#489) -- **fmt**: Spans closed by a child span closing not also closing _their_ - parents (#514) -- **Layer**: Fixed `Layered` subscribers failing to downcast to their own type - (#549) -- **Layer**: Fixed `Layer::downcast_ref` returning invalid references (#454) - -# 0.2.0-alpha.6 (February 3, 2020) - -### Fixed - -- **fmt**: Fixed empty `{}` printed after spans with no fields (f079f2d) -- **fmt**: Fixed inconsistent formatting when ANSI colors are disabled (506a482) -- **fmt**: Fixed mis-aligned levels when ANSI colors are disabled (eba1adb) -- Fixed warnings on nightly Rust compilers (#558) - -# 0.2.0-alpha.5 (January 31, 2020) - -### Added - -- **env_filter**: Documentation for filtering directives (#554) -- **registry**, **env_filter**: Updated `smallvec` dependency to 0.1 (#543) - -### Fixed - -- **registry**: Fixed a memory leak in the slab used to store per-span data - (3c35048) -- **Layer**: Fixed `Layered` subscribers failing to downcast to their own type - (#549) -- **fmt**: Fixed a panic when multiple layers insert `FormattedFields` - extensions from the same formatter type (1c3bb70) -- **fmt**: Fixed `fmt::Layer::on_record` inserting a new `FormattedFields` when - formatted fields for a span already exist (1c3bb70) - -# 0.2.0-alpha.4 (January 11, 2020) - -### Fixed - -- **registry**: Removed inadvertently committed `dbg!` macros (#533) - -# 0.2.0-alpha.3 (January 10, 2020) - -### Added - -- **fmt**: Public `FormattedFields::new` constructor (#478) -- **fmt**: Added examples to `fmt::Layer` documentation (#510) -- Documentation now shows what feature flags are required by each API item (#525) - -### Fixed - -- **fmt**: Missing space between timestamp and level (#480) -- **fmt**: Incorrect formatting with `with_target(false)` (#481) -- **fmt**: `fmt::SubscriberBuilder::init` not setting up `log` compatibility - (#489) -- **registry**: Spans exited out of order not being closed properly on exit - (#509) -- **registry**: Memory leak when spans are closed by a child span closing (#514) -- **registry**: Spans closed by a child span closing not also closing _their_ - parents (#514) -- Compilation errors with `no-default-features` (#499, #500) - -# 0.2.0-alpha.2 (December 8, 2019) - -### Added - -- `LookupSpans` implementation for `Layered` (#448) -- `SpanRef::from_root` to iterate over a span's parents from the root (#460) -- `Context::scope`, to iterate over the current context from the root (#460) -- `Context::lookup_current`, which returns a `SpanRef` to the current - span's data (#460) - -### Changed - -- Lifetimes on some new `Context` methods to be less restrictive (#460) - -### Fixed - -- `Layer::downcast_ref` returning invalid references (#454) -- Compilation failure on 32-bit platforms (#462) -- Compilation failure with ANSI formatters (#438) - -# 0.2.0-alpha.1 (November 18, 2019) - -### Added - -- `Registry`, a reusable span store that `Layer`s can use a - high-performance, in-memory store. (#420, #425, #432, #433, #435) -- Reimplemented `fmt::Subscriber` in terms of the `Registry` - and `Layer`s (#420) -- Add benchmarks for fmt subscriber (#421) -- Add support for JSON field and event formatting (#377, #415) - -### Changed - -- **BREAKING**: Change `fmt::format::FormatFields` and - `fmt::format::FormatEvent` to accept a mandatory `FmtContext`. These - `FormatFields` and `FormatEvent` will likely see additional breaking - changes in subsequent alpha. (#420, #425) -- **BREAKING**: Removed `Filter`. Use `EnvFilter` instead (#434) - -### Contributers - -Thanks to all the contributers to this release! - -- @pimeys for #377 and #415 - -# 0.1.6 (October 29, 2019) - -### Added - -- Add `init` and `try_init` functions to `FmtSubscriber` (#385) -- Add `ChronoUtc` and `ChronoLocal` timers, RFC 3339 support (#387) -- Add `tracing::subscriber::set_default` which sets the default - subscriber and returns a drop guard. This drop guard will reset the - dispatch on drop (#388). - -### Fixed - -- Fix default level for `EnvFilter`. Setting `RUST_LOG=target` - previously only the `ERROR` level, while it should enable everything. - `tracing-subscriber` now defaults to `TRACE` if no level is specified - (#401) -- Fix `tracing-log` feature flag for init + try_init. The feature flag - `tracing_log` was used instead of the correct `tracing-log`. As a - result, both `tracing-log` and `tracing_log` needed to be specified in - order to initialize the global logger. Only `tracing-log` needs to be - specified now (#400). - -### Contributers - -Thanks to all the contributers to this release! - -- @emschwartz for #385, #387, #400 and #401 -- @bIgBV for #388 - -# 0.1.5 (October 7, 2019) - -### Fixed - -- Spans not being closed properly when `FmtSubscriber::current_span` is used - (#371) - -# 0.1.4 (September 26, 2019) - -### Fixed - -- Spans entered twice on the same thread sometimes being completely exited when - the more deeply-nested entry is exited (#361) -- Setting `with_ansi(false)` on `FmtSubscriber` not disabling ANSI color - formatting for timestamps (#354) -- Incorrect reference counting in `FmtSubscriber` that could cause spans to not - be closed when all references are dropped (#366) - -# 0.1.3 (September 16, 2019) - -### Fixed - -- `Layered` subscribers not properly forwarding calls to `current_span` - (#350) - -# 0.1.2 (September 12, 2019) - -### Fixed - -- `EnvFilter` ignoring directives with targets that are the same number of - characters (#333) -- `EnvFilter` failing to properly apply filter directives to events generated - from `log` records by`tracing-log` (#344) - -### Changed - -- Renamed `Filter` to `EnvFilter`, deprecated `Filter` (#339) -- Renamed "filter" feature flag to "env-filter", deprecated "filter" (#339) -- `FmtSubscriber` now defaults to enabling only the `INFO` level and above when - a max level filter or `EnvFilter` is not set (#336) -- Made `parking_lot` dependency an opt-in feature flag (#348) - -### Added - -- `EnvFilter::add_directive` to add new directives to filters after they are - constructed (#334) -- `fmt::Builder::with_max_level` to set a global level filter for a - `FmtSubscriber` without requiring the use of `EnvFilter` (#336) -- `Layer` implementation for `LevelFilter` (#336) -- `EnvFilter` now implements `fmt::Display` (#329) - -### Removed - -- Removed dependency on `crossbeam-util` (#348) - -# 0.1.1 (September 4, 2019) - -### Fixed - -- Potential double panic in `CurrentSpan` (#325) - -# 0.1.0 (September 3, 2019) - -- Initial release diff --git a/vendor/tracing-subscriber/Cargo.toml b/vendor/tracing-subscriber/Cargo.toml deleted file mode 100644 index 1d15642a2..000000000 --- a/vendor/tracing-subscriber/Cargo.toml +++ /dev/null @@ -1,232 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2018" -rust-version = "1.49.0" -name = "tracing-subscriber" -version = "0.3.14" -authors = [ - "Eliza Weisman <eliza@buoyant.io>", - "David Barsky <me@davidbarsky.com>", - "Tokio Contributors <team@tokio.rs>", -] -description = """ -Utilities for implementing and composing `tracing` subscribers. -""" -homepage = "https://tokio.rs" -readme = "README.md" -keywords = [ - "logging", - "tracing", - "metrics", - "subscriber", -] -categories = [ - "development-tools::debugging", - "development-tools::profiling", - "asynchronous", -] -license = "MIT" -repository = "https://github.com/tokio-rs/tracing" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = [ - "--cfg", - "docsrs", -] - -[[bench]] -name = "filter" -harness = false - -[[bench]] -name = "filter_log" -harness = false - -[[bench]] -name = "fmt" -harness = false - -[[bench]] -name = "enter" -harness = false - -[dependencies.ansi_term] -version = "0.12" -optional = true - -[dependencies.matchers] -version = "0.1.0" -optional = true - -[dependencies.once_cell] -version = "1.12" -optional = true - -[dependencies.parking_lot] -version = "0.12" -optional = true - -[dependencies.regex] -version = "1" -features = ["std"] -optional = true -default-features = false - -[dependencies.serde] -version = "1.0" -optional = true - -[dependencies.serde_json] -version = "1.0" -optional = true - -[dependencies.sharded-slab] -version = "0.1.0" -optional = true - -[dependencies.smallvec] -version = "1.2.0" -optional = true - -[dependencies.thread_local] -version = "1.1.4" -optional = true - -[dependencies.time] -version = "0.3" -features = ["formatting"] -optional = true - -[dependencies.tracing] -version = "0.1" -optional = true -default-features = false - -[dependencies.tracing-core] -version = "0.1.28" -default-features = false - -[dependencies.tracing-log] -version = "0.1.2" -features = [ - "log-tracer", - "std", -] -optional = true -default-features = false - -[dependencies.tracing-serde] -version = "0.1.3" -optional = true - -[dev-dependencies.criterion] -version = "0.3" -default_features = false - -[dev-dependencies.log] -version = "0.4" - -[dev-dependencies.regex] -version = "1" -features = ["std"] -default-features = false - -[dev-dependencies.time] -version = "0.3" -features = [ - "formatting", - "macros", -] - -[dev-dependencies.tokio] -version = "1" -features = [ - "rt", - "macros", -] - -[dev-dependencies.tracing] -version = "0.1" - -[dev-dependencies.tracing-futures] -version = "0.2" -features = [ - "std-future", - "std", -] -default-features = false - -[dev-dependencies.tracing-log] -version = "0.1.2" - -[features] -alloc = [] -ansi = [ - "fmt", - "ansi_term", -] -default = [ - "smallvec", - "fmt", - "ansi", - "tracing-log", - "std", -] -env-filter = [ - "matchers", - "regex", - "once_cell", - "tracing", - "std", - "thread_local", -] -fmt = [ - "registry", - "std", -] -json = [ - "tracing-serde", - "serde", - "serde_json", -] -local-time = ["time/local-offset"] -registry = [ - "sharded-slab", - "thread_local", - "std", -] -std = [ - "alloc", - "tracing-core/std", -] -valuable = [ - "tracing-core/valuable", - "valuable_crate", - "valuable-serde", - "tracing-serde/valuable", -] - -[target."cfg(tracing_unstable)".dependencies.valuable-serde] -version = "0.1.0" -optional = true -default_features = false - -[target."cfg(tracing_unstable)".dependencies.valuable_crate] -version = "0.1.0" -optional = true -default_features = false -package = "valuable" - -[badges.maintenance] -status = "experimental" diff --git a/vendor/tracing-subscriber/LICENSE b/vendor/tracing-subscriber/LICENSE deleted file mode 100644 index cdb28b4b5..000000000 --- a/vendor/tracing-subscriber/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2019 Tokio Contributors - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/vendor/tracing-subscriber/README.md b/vendor/tracing-subscriber/README.md deleted file mode 100644 index 95242b37e..000000000 --- a/vendor/tracing-subscriber/README.md +++ /dev/null @@ -1,61 +0,0 @@ -![Tracing — Structured, application-level diagnostics][splash] - -[splash]: https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/splash.svg - -# tracing-subscriber - -Utilities for implementing and composing [`tracing`][tracing] subscribers. - -[![Crates.io][crates-badge]][crates-url] -[![Documentation][docs-badge]][docs-url] -[![Documentation (master)][docs-master-badge]][docs-master-url] -[![MIT licensed][mit-badge]][mit-url] -[![Build Status][actions-badge]][actions-url] -[![Discord chat][discord-badge]][discord-url] -![maintenance status][maint-badge] - -[Documentation][docs-url] | [Chat][discord-url] - -[tracing]: https://github.com/tokio-rs/tracing/tree/master/tracing -[tracing-fmt]: https://github.com/tokio-rs/tracing/tree/master/tracing-subscriber -[crates-badge]: https://img.shields.io/crates/v/tracing-subscriber.svg -[crates-url]: https://crates.io/crates/tracing-subscriber -[docs-badge]: https://docs.rs/tracing-subscriber/badge.svg -[docs-url]: https://docs.rs/tracing-subscriber/0.3.14 -[docs-master-badge]: https://img.shields.io/badge/docs-master-blue -[docs-master-url]: https://tracing-rs.netlify.com/tracing_subscriber -[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg -[mit-url]: LICENSE -[actions-badge]: https://github.com/tokio-rs/tracing/workflows/CI/badge.svg -[actions-url]:https://github.com/tokio-rs/tracing/actions?query=workflow%3ACI -[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white -[discord-url]: https://discord.gg/EeF3cQw -[maint-badge]: https://img.shields.io/badge/maintenance-experimental-blue.svg - -*Compiler support: [requires `rustc` 1.49+][msrv]* - -[msrv]: #supported-rust-versions - -## Supported Rust Versions - -Tracing is built against the latest stable release. The minimum supported -version is 1.49. The current Tracing version is not guaranteed to build on Rust -versions earlier than the minimum supported version. - -Tracing follows the same compiler support policies as the rest of the Tokio -project. The current stable Rust compiler and the three most recent minor -versions before it will always be supported. For example, if the current stable -compiler version is 1.45, the minimum supported version will not be increased -past 1.42, three minor versions prior. Increasing the minimum supported compiler -version is not considered a semver breaking change as long as doing so complies -with this policy. - -## License - -This project is licensed under the [MIT license](LICENSE). - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in Tracing by you, shall be licensed as MIT, without any additional -terms or conditions. diff --git a/vendor/tracing-subscriber/benches/enter.rs b/vendor/tracing-subscriber/benches/enter.rs deleted file mode 100644 index 49c6e730a..000000000 --- a/vendor/tracing-subscriber/benches/enter.rs +++ /dev/null @@ -1,64 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use tracing_subscriber::prelude::*; - -fn enter(c: &mut Criterion) { - let mut group = c.benchmark_group("enter"); - let _subscriber = tracing_subscriber::fmt() - .with_max_level(tracing::Level::INFO) - .finish() - .set_default(); - group.bench_function("enabled", |b| { - let span = tracing::info_span!("foo"); - b.iter_with_large_drop(|| span.enter()) - }); - group.bench_function("disabled", |b| { - let span = tracing::debug_span!("foo"); - b.iter_with_large_drop(|| span.enter()) - }); -} - -fn enter_exit(c: &mut Criterion) { - let mut group = c.benchmark_group("enter_exit"); - let _subscriber = tracing_subscriber::fmt() - .with_max_level(tracing::Level::INFO) - .finish() - .set_default(); - group.bench_function("enabled", |b| { - let span = tracing::info_span!("foo"); - b.iter(|| span.enter()) - }); - group.bench_function("disabled", |b| { - let span = tracing::debug_span!("foo"); - b.iter(|| span.enter()) - }); -} - -fn enter_many(c: &mut Criterion) { - let mut group = c.benchmark_group("enter_many"); - let _subscriber = tracing_subscriber::fmt() - .with_max_level(tracing::Level::INFO) - .finish() - .set_default(); - group.bench_function("enabled", |b| { - let span1 = tracing::info_span!("span1"); - let _e1 = span1.enter(); - let span2 = tracing::info_span!("span2"); - let _e2 = span2.enter(); - let span3 = tracing::info_span!("span3"); - let _e3 = span3.enter(); - let span = tracing::info_span!("foo"); - b.iter_with_large_drop(|| span.enter()) - }); - group.bench_function("disabled", |b| { - let span1 = tracing::info_span!("span1"); - let _e1 = span1.enter(); - let span2 = tracing::info_span!("span2"); - let _e2 = span2.enter(); - let span3 = tracing::info_span!("span3"); - let _e3 = span3.enter(); - let span = tracing::debug_span!("foo"); - b.iter_with_large_drop(|| span.enter()) - }); -} -criterion_group!(benches, enter, enter_exit, enter_many); -criterion_main!(benches); diff --git a/vendor/tracing-subscriber/benches/filter.rs b/vendor/tracing-subscriber/benches/filter.rs deleted file mode 100644 index 91ab9c91d..000000000 --- a/vendor/tracing-subscriber/benches/filter.rs +++ /dev/null @@ -1,308 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use std::time::Duration; -use tracing::{dispatcher::Dispatch, span, Event, Id, Metadata}; -use tracing_subscriber::{prelude::*, EnvFilter}; - -mod support; -use support::MultithreadedBench; - -/// A subscriber that is enabled but otherwise does nothing. -struct EnabledSubscriber; - -impl tracing::Subscriber for EnabledSubscriber { - fn new_span(&self, span: &span::Attributes<'_>) -> Id { - let _ = span; - Id::from_u64(0xDEAD_FACE) - } - - fn event(&self, event: &Event<'_>) { - let _ = event; - } - - fn record(&self, span: &Id, values: &span::Record<'_>) { - let _ = (span, values); - } - - fn record_follows_from(&self, span: &Id, follows: &Id) { - let _ = (span, follows); - } - - fn enabled(&self, metadata: &Metadata<'_>) -> bool { - let _ = metadata; - true - } - - fn enter(&self, span: &Id) { - let _ = span; - } - - fn exit(&self, span: &Id) { - let _ = span; - } -} - -fn bench_static(c: &mut Criterion) { - let mut group = c.benchmark_group("static"); - - group.bench_function("baseline_single_threaded", |b| { - tracing::subscriber::with_default(EnabledSubscriber, || { - b.iter(|| { - tracing::info!(target: "static_filter", "hi"); - tracing::debug!(target: "static_filter", "hi"); - tracing::warn!(target: "static_filter", "hi"); - tracing::trace!(target: "foo", "hi"); - }) - }); - }); - group.bench_function("single_threaded", |b| { - let filter = "static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::info!(target: "static_filter", "hi"); - tracing::debug!(target: "static_filter", "hi"); - tracing::warn!(target: "static_filter", "hi"); - tracing::trace!(target: "foo", "hi"); - }) - }); - }); - group.bench_function("enabled_one", |b| { - let filter = "static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("enabled_many", |b| { - let filter = "foo=debug,bar=trace,baz=error,quux=warn,static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_level_one", |b| { - let filter = "static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::debug!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_level_many", |b| { - let filter = "foo=debug,bar=info,baz=error,quux=warn,static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::trace!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_one", |b| { - let filter = "foo=info".parse::<EnvFilter>().expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_many", |b| { - let filter = "foo=debug,bar=trace,baz=error,quux=warn,whibble=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("baseline_multithreaded", |b| { - let dispatch = Dispatch::new(EnabledSubscriber); - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(|| { - tracing::info!(target: "static_filter", "hi"); - }) - .thread(|| { - tracing::debug!(target: "static_filter", "hi"); - }) - .thread(|| { - tracing::warn!(target: "static_filter", "hi"); - }) - .thread(|| { - tracing::warn!(target: "foo", "hi"); - }) - .run(); - total += elapsed; - } - total - }) - }); - group.bench_function("multithreaded", |b| { - let filter = "static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - let dispatch = Dispatch::new(EnabledSubscriber.with(filter)); - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(|| { - tracing::info!(target: "static_filter", "hi"); - }) - .thread(|| { - tracing::debug!(target: "static_filter", "hi"); - }) - .thread(|| { - tracing::warn!(target: "static_filter", "hi"); - }) - .thread(|| { - tracing::warn!(target: "foo", "hi"); - }) - .run(); - total += elapsed; - } - total - }); - }); - group.finish(); -} - -fn bench_dynamic(c: &mut Criterion) { - let mut group = c.benchmark_group("dynamic"); - - group.bench_function("baseline_single_threaded", |b| { - tracing::subscriber::with_default(EnabledSubscriber, || { - b.iter(|| { - tracing::info_span!("foo").in_scope(|| { - tracing::info!("hi"); - tracing::debug!("hi"); - }); - tracing::info_span!("bar").in_scope(|| { - tracing::warn!("hi"); - }); - tracing::trace!("hi"); - }) - }); - }); - group.bench_function("single_threaded", |b| { - let filter = "[foo]=trace".parse::<EnvFilter>().expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::info_span!("foo").in_scope(|| { - tracing::info!("hi"); - tracing::debug!("hi"); - }); - tracing::info_span!("bar").in_scope(|| { - tracing::warn!("hi"); - }); - tracing::trace!("hi"); - }) - }); - }); - group.bench_function("baseline_multithreaded", |b| { - let dispatch = Dispatch::new(EnabledSubscriber); - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(|| { - let span = tracing::info_span!("foo"); - let _ = span.enter(); - tracing::info!("hi"); - }) - .thread(|| { - let span = tracing::info_span!("foo"); - let _ = span.enter(); - tracing::debug!("hi"); - }) - .thread(|| { - let span = tracing::info_span!("bar"); - let _ = span.enter(); - tracing::debug!("hi"); - }) - .thread(|| { - tracing::trace!("hi"); - }) - .run(); - total += elapsed; - } - total - }) - }); - group.bench_function("multithreaded", |b| { - let filter = "[foo]=trace".parse::<EnvFilter>().expect("should parse"); - let dispatch = Dispatch::new(EnabledSubscriber.with(filter)); - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(|| { - let span = tracing::info_span!("foo"); - let _ = span.enter(); - tracing::info!("hi"); - }) - .thread(|| { - let span = tracing::info_span!("foo"); - let _ = span.enter(); - tracing::debug!("hi"); - }) - .thread(|| { - let span = tracing::info_span!("bar"); - let _ = span.enter(); - tracing::debug!("hi"); - }) - .thread(|| { - tracing::trace!("hi"); - }) - .run(); - total += elapsed; - } - total - }) - }); - - group.finish(); -} - -fn bench_mixed(c: &mut Criterion) { - let mut group = c.benchmark_group("mixed"); - group.bench_function("disabled", |b| { - let filter = "[foo]=trace,bar[quux]=debug,[{baz}]=debug,asdf=warn,wibble=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_by_level", |b| { - let filter = "[foo]=info,bar[quux]=debug,asdf=warn,static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::trace!(target: "static_filter", "hi"); - }) - }); - }); -} - -criterion_group!(benches, bench_static, bench_dynamic, bench_mixed); -criterion_main!(benches); diff --git a/vendor/tracing-subscriber/benches/filter_log.rs b/vendor/tracing-subscriber/benches/filter_log.rs deleted file mode 100644 index 4dcf3b4ec..000000000 --- a/vendor/tracing-subscriber/benches/filter_log.rs +++ /dev/null @@ -1,315 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use std::time::Duration; -use tracing::{dispatcher::Dispatch, span, Event, Id, Metadata}; -use tracing_subscriber::{prelude::*, EnvFilter}; - -mod support; -use support::MultithreadedBench; - -/// A subscriber that is enabled but otherwise does nothing. -struct EnabledSubscriber; - -impl tracing::Subscriber for EnabledSubscriber { - fn new_span(&self, span: &span::Attributes<'_>) -> Id { - let _ = span; - Id::from_u64(0xDEAD_FACE) - } - - fn event(&self, event: &Event<'_>) { - let _ = event; - } - - fn record(&self, span: &Id, values: &span::Record<'_>) { - let _ = (span, values); - } - - fn record_follows_from(&self, span: &Id, follows: &Id) { - let _ = (span, follows); - } - - fn enabled(&self, metadata: &Metadata<'_>) -> bool { - let _ = metadata; - true - } - - fn enter(&self, span: &Id) { - let _ = span; - } - - fn exit(&self, span: &Id) { - let _ = span; - } -} - -fn bench_static(c: &mut Criterion) { - let _ = tracing_log::LogTracer::init(); - - let mut group = c.benchmark_group("log/static"); - - group.bench_function("baseline_single_threaded", |b| { - tracing::subscriber::with_default(EnabledSubscriber, || { - b.iter(|| { - log::info!(target: "static_filter", "hi"); - log::debug!(target: "static_filter", "hi"); - log::warn!(target: "static_filter", "hi"); - log::trace!(target: "foo", "hi"); - }) - }); - }); - group.bench_function("single_threaded", |b| { - let filter = "static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::info!(target: "static_filter", "hi"); - log::debug!(target: "static_filter", "hi"); - log::warn!(target: "static_filter", "hi"); - log::trace!(target: "foo", "hi"); - }) - }); - }); - group.bench_function("enabled_one", |b| { - let filter = "static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("enabled_many", |b| { - let filter = "foo=debug,bar=trace,baz=error,quux=warn,static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_level_one", |b| { - let filter = "static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::debug!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_level_many", |b| { - let filter = "foo=debug,bar=info,baz=error,quux=warn,static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::trace!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_one", |b| { - let filter = "foo=info".parse::<EnvFilter>().expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_many", |b| { - let filter = "foo=debug,bar=trace,baz=error,quux=warn,whibble=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("baseline_multithreaded", |b| { - let dispatch = Dispatch::new(EnabledSubscriber); - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(|| { - log::info!(target: "static_filter", "hi"); - }) - .thread(|| { - log::debug!(target: "static_filter", "hi"); - }) - .thread(|| { - log::warn!(target: "static_filter", "hi"); - }) - .thread(|| { - log::warn!(target: "foo", "hi"); - }) - .run(); - total += elapsed; - } - total - }) - }); - group.bench_function("multithreaded", |b| { - let filter = "static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - let dispatch = Dispatch::new(EnabledSubscriber.with(filter)); - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(|| { - log::info!(target: "static_filter", "hi"); - }) - .thread(|| { - log::debug!(target: "static_filter", "hi"); - }) - .thread(|| { - log::warn!(target: "static_filter", "hi"); - }) - .thread(|| { - log::warn!(target: "foo", "hi"); - }) - .run(); - total += elapsed; - } - total - }); - }); - group.finish(); -} - -fn bench_dynamic(c: &mut Criterion) { - let _ = tracing_log::LogTracer::init(); - - let mut group = c.benchmark_group("log/dynamic"); - - group.bench_function("baseline_single_threaded", |b| { - tracing::subscriber::with_default(EnabledSubscriber, || { - b.iter(|| { - tracing::info_span!("foo").in_scope(|| { - log::info!("hi"); - log::debug!("hi"); - }); - tracing::info_span!("bar").in_scope(|| { - log::warn!("hi"); - }); - log::trace!("hi"); - }) - }); - }); - group.bench_function("single_threaded", |b| { - let filter = "[foo]=trace".parse::<EnvFilter>().expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - tracing::info_span!("foo").in_scope(|| { - log::info!("hi"); - log::debug!("hi"); - }); - tracing::info_span!("bar").in_scope(|| { - log::warn!("hi"); - }); - log::trace!("hi"); - }) - }); - }); - group.bench_function("baseline_multithreaded", |b| { - let dispatch = Dispatch::new(EnabledSubscriber); - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(|| { - let span = tracing::info_span!("foo"); - let _ = span.enter(); - log::info!("hi"); - }) - .thread(|| { - let span = tracing::info_span!("foo"); - let _ = span.enter(); - log::debug!("hi"); - }) - .thread(|| { - let span = tracing::info_span!("bar"); - let _ = span.enter(); - log::debug!("hi"); - }) - .thread(|| { - log::trace!("hi"); - }) - .run(); - total += elapsed; - } - total - }) - }); - group.bench_function("multithreaded", |b| { - let filter = "[foo]=trace".parse::<EnvFilter>().expect("should parse"); - let dispatch = Dispatch::new(EnabledSubscriber.with(filter)); - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(|| { - let span = tracing::info_span!("foo"); - let _ = span.enter(); - log::info!("hi"); - }) - .thread(|| { - let span = tracing::info_span!("foo"); - let _ = span.enter(); - log::debug!("hi"); - }) - .thread(|| { - let span = tracing::info_span!("bar"); - let _ = span.enter(); - log::debug!("hi"); - }) - .thread(|| { - log::trace!("hi"); - }) - .run(); - total += elapsed; - } - total - }) - }); - - group.finish(); -} - -fn bench_mixed(c: &mut Criterion) { - let _ = tracing_log::LogTracer::init(); - - let mut group = c.benchmark_group("log/mixed"); - - group.bench_function("disabled", |b| { - let filter = "[foo]=trace,bar[quux]=debug,[{baz}]=debug,asdf=warn,wibble=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::info!(target: "static_filter", "hi"); - }) - }); - }); - group.bench_function("disabled_by_level", |b| { - let filter = "[foo]=info,bar[quux]=debug,asdf=warn,static_filter=info" - .parse::<EnvFilter>() - .expect("should parse"); - tracing::subscriber::with_default(EnabledSubscriber.with(filter), || { - b.iter(|| { - log::trace!(target: "static_filter", "hi"); - }) - }); - }); -} - -criterion_group!(benches, bench_static, bench_dynamic, bench_mixed); -criterion_main!(benches); diff --git a/vendor/tracing-subscriber/benches/fmt.rs b/vendor/tracing-subscriber/benches/fmt.rs deleted file mode 100644 index a039e66d4..000000000 --- a/vendor/tracing-subscriber/benches/fmt.rs +++ /dev/null @@ -1,331 +0,0 @@ -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; -use std::{io, time::Duration}; - -mod support; -use support::MultithreadedBench; - -/// A fake writer that doesn't actually do anything. -/// -/// We want to measure the subscriber's overhead, *not* the performance of -/// stdout/file writers. Using a no-op Write implementation lets us only measure -/// the subscriber's overhead. -struct NoWriter; - -impl io::Write for NoWriter { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl NoWriter { - fn new() -> Self { - Self - } -} - -fn bench_new_span(c: &mut Criterion) { - bench_thrpt(c, "new_span", |group, i| { - group.bench_with_input(BenchmarkId::new("single_thread", i), i, |b, &i| { - tracing::dispatcher::with_default(&mk_dispatch(), || { - b.iter(|| { - for n in 0..i { - let _span = tracing::info_span!("span", n); - } - }) - }); - }); - group.bench_with_input(BenchmarkId::new("multithreaded", i), i, |b, &i| { - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - let dispatch = mk_dispatch(); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(move || { - for n in 0..i { - let _span = tracing::info_span!("span", n); - } - }) - .thread(move || { - for n in 0..i { - let _span = tracing::info_span!("span", n); - } - }) - .thread(move || { - for n in 0..i { - let _span = tracing::info_span!("span", n); - } - }) - .thread(move || { - for n in 0..i { - let _span = tracing::info_span!("span", n); - } - }) - .run(); - total += elapsed; - } - total - }) - }); - }); -} - -type Group<'a> = criterion::BenchmarkGroup<'a, criterion::measurement::WallTime>; -fn bench_thrpt(c: &mut Criterion, name: &'static str, mut f: impl FnMut(&mut Group<'_>, &usize)) { - const N_SPANS: &[usize] = &[1, 10, 50]; - - let mut group = c.benchmark_group(name); - for spans in N_SPANS { - group.throughput(Throughput::Elements(*spans as u64)); - f(&mut group, spans); - } - group.finish(); -} - -fn mk_dispatch() -> tracing::Dispatch { - let subscriber = tracing_subscriber::FmtSubscriber::builder() - .with_writer(NoWriter::new) - .finish(); - tracing::Dispatch::new(subscriber) -} - -fn bench_event(c: &mut Criterion) { - bench_thrpt(c, "event", |group, i| { - group.bench_with_input(BenchmarkId::new("root/single_threaded", i), i, |b, &i| { - let dispatch = mk_dispatch(); - tracing::dispatcher::with_default(&dispatch, || { - b.iter(|| { - for n in 0..i { - tracing::info!(n); - } - }) - }); - }); - group.bench_with_input(BenchmarkId::new("root/multithreaded", i), i, |b, &i| { - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - let dispatch = mk_dispatch(); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread(move || { - for n in 0..i { - tracing::info!(n); - } - }) - .thread(move || { - for n in 0..i { - tracing::info!(n); - } - }) - .thread(move || { - for n in 0..i { - tracing::info!(n); - } - }) - .thread(move || { - for n in 0..i { - tracing::info!(n); - } - }) - .run(); - total += elapsed; - } - total - }) - }); - group.bench_with_input( - BenchmarkId::new("unique_parent/single_threaded", i), - i, - |b, &i| { - tracing::dispatcher::with_default(&mk_dispatch(), || { - let span = tracing::info_span!("unique_parent", foo = false); - let _guard = span.enter(); - b.iter(|| { - for n in 0..i { - tracing::info!(n); - } - }) - }); - }, - ); - group.bench_with_input( - BenchmarkId::new("unique_parent/multithreaded", i), - i, - |b, &i| { - b.iter_custom(|iters| { - let mut total = Duration::from_secs(0); - let dispatch = mk_dispatch(); - for _ in 0..iters { - let bench = MultithreadedBench::new(dispatch.clone()); - let elapsed = bench - .thread_with_setup(move |start| { - let span = tracing::info_span!("unique_parent", foo = false); - let _guard = span.enter(); - start.wait(); - for n in 0..i { - tracing::info!(n); - } - }) - .thread_with_setup(move |start| { - let span = tracing::info_span!("unique_parent", foo = false); - let _guard = span.enter(); - start.wait(); - for n in 0..i { - tracing::info!(n); - } - }) - .thread_with_setup(move |start| { - let span = tracing::info_span!("unique_parent", foo = false); - let _guard = span.enter(); - start.wait(); - for n in 0..i { - tracing::info!(n); - } - }) - .thread_with_setup(move |start| { - let span = tracing::info_span!("unique_parent", foo = false); - let _guard = span.enter(); - start.wait(); - for n in 0..i { - tracing::info!(n); - } - }) - .run(); - total += elapsed; - } - total - }) - }, - ); - group.bench_with_input( - BenchmarkId::new("shared_parent/multithreaded", i), - i, - |b, &i| { - b.iter_custom(|iters| { - let dispatch = mk_dispatch(); - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let parent = tracing::dispatcher::with_default(&dispatch, || { - tracing::info_span!("shared_parent", foo = "hello world") - }); - let bench = MultithreadedBench::new(dispatch.clone()); - let parent2 = parent.clone(); - bench.thread_with_setup(move |start| { - let _guard = parent2.enter(); - start.wait(); - for n in 0..i { - tracing::info!(n); - } - }); - let parent2 = parent.clone(); - bench.thread_with_setup(move |start| { - let _guard = parent2.enter(); - start.wait(); - for n in 0..i { - tracing::info!(n); - } - }); - let parent2 = parent.clone(); - bench.thread_with_setup(move |start| { - let _guard = parent2.enter(); - start.wait(); - for n in 0..i { - tracing::info!(n); - } - }); - let parent2 = parent.clone(); - bench.thread_with_setup(move |start| { - let _guard = parent2.enter(); - start.wait(); - for n in 0..i { - tracing::info!(n); - } - }); - let elapsed = bench.run(); - total += elapsed; - } - total - }) - }, - ); - group.bench_with_input( - BenchmarkId::new("multi-parent/multithreaded", i), - i, - |b, &i| { - b.iter_custom(|iters| { - let dispatch = mk_dispatch(); - let mut total = Duration::from_secs(0); - for _ in 0..iters { - let parent = tracing::dispatcher::with_default(&dispatch, || { - tracing::info_span!("multiparent", foo = "hello world") - }); - let bench = MultithreadedBench::new(dispatch.clone()); - let parent2 = parent.clone(); - bench.thread_with_setup(move |start| { - let _guard = parent2.enter(); - start.wait(); - let mut span = tracing::info_span!("parent"); - for n in 0..i { - let s = tracing::info_span!(parent: &span, "parent2", n, i); - s.in_scope(|| { - tracing::info!(n); - }); - span = s; - } - }); - let parent2 = parent.clone(); - bench.thread_with_setup(move |start| { - let _guard = parent2.enter(); - start.wait(); - let mut span = tracing::info_span!("parent"); - for n in 0..i { - let s = tracing::info_span!(parent: &span, "parent2", n, i); - s.in_scope(|| { - tracing::info!(n); - }); - span = s; - } - }); - let parent2 = parent.clone(); - bench.thread_with_setup(move |start| { - let _guard = parent2.enter(); - start.wait(); - let mut span = tracing::info_span!("parent"); - for n in 0..i { - let s = tracing::info_span!(parent: &span, "parent2", n, i); - s.in_scope(|| { - tracing::info!(n); - }); - span = s; - } - }); - let parent2 = parent.clone(); - bench.thread_with_setup(move |start| { - let _guard = parent2.enter(); - start.wait(); - let mut span = tracing::info_span!("parent"); - for n in 0..i { - let s = tracing::info_span!(parent: &span, "parent2", n, i); - s.in_scope(|| { - tracing::info!(n); - }); - span = s; - } - }); - let elapsed = bench.run(); - total += elapsed; - } - total - }) - }, - ); - }); -} - -criterion_group!(benches, bench_new_span, bench_event); -criterion_main!(benches); diff --git a/vendor/tracing-subscriber/benches/support/mod.rs b/vendor/tracing-subscriber/benches/support/mod.rs deleted file mode 100644 index 25e9e7e22..000000000 --- a/vendor/tracing-subscriber/benches/support/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -use std::{ - sync::{Arc, Barrier}, - thread, - time::{Duration, Instant}, -}; -use tracing::dispatcher::Dispatch; - -#[derive(Clone)] -pub(super) struct MultithreadedBench { - start: Arc<Barrier>, - end: Arc<Barrier>, - dispatch: Dispatch, -} - -impl MultithreadedBench { - pub(super) fn new(dispatch: Dispatch) -> Self { - Self { - start: Arc::new(Barrier::new(5)), - end: Arc::new(Barrier::new(5)), - dispatch, - } - } - - pub(super) fn thread(&self, f: impl FnOnce() + Send + 'static) -> &Self { - self.thread_with_setup(|start| { - start.wait(); - f() - }) - } - - pub(super) fn thread_with_setup(&self, f: impl FnOnce(&Barrier) + Send + 'static) -> &Self { - let this = self.clone(); - thread::spawn(move || { - let dispatch = this.dispatch.clone(); - tracing::dispatcher::with_default(&dispatch, move || { - f(&*this.start); - this.end.wait(); - }) - }); - self - } - - pub(super) fn run(&self) -> Duration { - self.start.wait(); - let t0 = Instant::now(); - self.end.wait(); - t0.elapsed() - } -} diff --git a/vendor/tracing-subscriber/src/field/debug.rs b/vendor/tracing-subscriber/src/field/debug.rs deleted file mode 100644 index cc67d29fe..000000000 --- a/vendor/tracing-subscriber/src/field/debug.rs +++ /dev/null @@ -1,111 +0,0 @@ -//! `MakeVisitor` wrappers for working with `fmt::Debug` fields. -use super::{MakeVisitor, VisitFmt, VisitOutput}; -use tracing_core::field::{Field, Visit}; - -use core::fmt; - -/// A visitor wrapper that ensures any `fmt::Debug` fields are formatted using -/// the alternate (`:#`) formatter. -#[derive(Debug, Clone)] -pub struct Alt<V>(V); - -// TODO(eliza): When `error` as a primitive type is stable, add a -// `DisplayErrors` wrapper... - -// === impl Alt === -// -impl<V> Alt<V> { - /// Wraps the provided visitor so that any `fmt::Debug` fields are formatted - /// using the alternative (`:#`) formatter. - pub fn new(inner: V) -> Self { - Alt(inner) - } -} - -impl<T, V> MakeVisitor<T> for Alt<V> -where - V: MakeVisitor<T>, -{ - type Visitor = Alt<V::Visitor>; - - #[inline] - fn make_visitor(&self, target: T) -> Self::Visitor { - Alt(self.0.make_visitor(target)) - } -} - -impl<V> Visit for Alt<V> -where - V: Visit, -{ - #[inline] - fn record_f64(&mut self, field: &Field, value: f64) { - self.0.record_f64(field, value) - } - - #[inline] - fn record_i64(&mut self, field: &Field, value: i64) { - self.0.record_i64(field, value) - } - - #[inline] - fn record_u64(&mut self, field: &Field, value: u64) { - self.0.record_u64(field, value) - } - - #[inline] - fn record_bool(&mut self, field: &Field, value: bool) { - self.0.record_bool(field, value) - } - - /// Visit a string value. - fn record_str(&mut self, field: &Field, value: &str) { - self.0.record_str(field, value) - } - - // TODO(eliza): add RecordError when stable - // fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) { - // self.record_debug(field, &format_args!("{}", value)) - // } - - #[inline] - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - self.0.record_debug(field, &format_args!("{:#?}", value)) - } -} - -impl<V, O> VisitOutput<O> for Alt<V> -where - V: VisitOutput<O>, -{ - #[inline] - fn finish(self) -> O { - self.0.finish() - } -} - -feature! { - #![feature = "std"] - use super::VisitWrite; - use std::io; - - impl<V> VisitWrite for Alt<V> - where - V: VisitWrite, - { - #[inline] - fn writer(&mut self) -> &mut dyn io::Write { - self.0.writer() - } - } -} - -impl<V> VisitFmt for Alt<V> -where - V: VisitFmt, -{ - #[inline] - fn writer(&mut self) -> &mut dyn fmt::Write { - self.0.writer() - } -} diff --git a/vendor/tracing-subscriber/src/field/delimited.rs b/vendor/tracing-subscriber/src/field/delimited.rs deleted file mode 100644 index 98634cea9..000000000 --- a/vendor/tracing-subscriber/src/field/delimited.rs +++ /dev/null @@ -1,184 +0,0 @@ -//! A `MakeVisitor` wrapper that separates formatted fields with a delimiter. -use super::{MakeVisitor, VisitFmt, VisitOutput}; - -use core::fmt; -use tracing_core::field::{Field, Visit}; - -/// A `MakeVisitor` wrapper that wraps a visitor that writes formatted output so -/// that a delimiter is inserted between writing formatted field values. -#[derive(Debug, Clone)] -pub struct Delimited<D, V> { - delimiter: D, - inner: V, -} - -/// A visitor wrapper that inserts a delimiter after the wrapped visitor formats -/// a field value. -#[derive(Debug)] -pub struct VisitDelimited<D, V> { - delimiter: D, - seen: bool, - inner: V, - err: fmt::Result, -} - -// === impl Delimited === - -impl<D, V, T> MakeVisitor<T> for Delimited<D, V> -where - D: AsRef<str> + Clone, - V: MakeVisitor<T>, - V::Visitor: VisitFmt, -{ - type Visitor = VisitDelimited<D, V::Visitor>; - fn make_visitor(&self, target: T) -> Self::Visitor { - let inner = self.inner.make_visitor(target); - VisitDelimited::new(self.delimiter.clone(), inner) - } -} - -impl<D, V> Delimited<D, V> { - /// Returns a new [`MakeVisitor`] implementation that wraps `inner` so that - /// it will format each visited field separated by the provided `delimiter`. - /// - /// [`MakeVisitor`]: super::MakeVisitor - pub fn new(delimiter: D, inner: V) -> Self { - Self { delimiter, inner } - } -} - -// === impl VisitDelimited === - -impl<D, V> VisitDelimited<D, V> { - /// Returns a new [`Visit`] implementation that wraps `inner` so that - /// each formatted field is separated by the provided `delimiter`. - /// - /// [`Visit`]: tracing_core::field::Visit - pub fn new(delimiter: D, inner: V) -> Self { - Self { - delimiter, - inner, - seen: false, - err: Ok(()), - } - } - - fn delimit(&mut self) - where - V: VisitFmt, - D: AsRef<str>, - { - if self.err.is_err() { - return; - } - - if self.seen { - self.err = self.inner.writer().write_str(self.delimiter.as_ref()); - } - - self.seen = true; - } -} - -impl<D, V> Visit for VisitDelimited<D, V> -where - V: VisitFmt, - D: AsRef<str>, -{ - fn record_i64(&mut self, field: &Field, value: i64) { - self.delimit(); - self.inner.record_i64(field, value); - } - - fn record_u64(&mut self, field: &Field, value: u64) { - self.delimit(); - self.inner.record_u64(field, value); - } - - fn record_bool(&mut self, field: &Field, value: bool) { - self.delimit(); - self.inner.record_bool(field, value); - } - - fn record_str(&mut self, field: &Field, value: &str) { - self.delimit(); - self.inner.record_str(field, value); - } - - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - self.delimit(); - self.inner.record_debug(field, value); - } -} - -impl<D, V> VisitOutput<fmt::Result> for VisitDelimited<D, V> -where - V: VisitFmt, - D: AsRef<str>, -{ - fn finish(self) -> fmt::Result { - self.err?; - self.inner.finish() - } -} - -impl<D, V> VisitFmt for VisitDelimited<D, V> -where - V: VisitFmt, - D: AsRef<str>, -{ - fn writer(&mut self) -> &mut dyn fmt::Write { - self.inner.writer() - } -} - -#[cfg(test)] -#[cfg(all(test, feature = "alloc"))] -mod test { - use super::*; - use crate::field::test_util::*; - - #[test] - fn delimited_visitor() { - let mut s = String::new(); - let visitor = DebugVisitor::new(&mut s); - let mut visitor = VisitDelimited::new(", ", visitor); - - TestAttrs1::with(|attrs| attrs.record(&mut visitor)); - visitor.finish().unwrap(); - - assert_eq!( - s.as_str(), - "question=\"life, the universe, and everything\", tricky=true, can_you_do_it=true" - ); - } - - #[test] - fn delimited_new_visitor() { - let make = Delimited::new("; ", MakeDebug); - - TestAttrs1::with(|attrs| { - let mut s = String::new(); - { - let mut v = make.make_visitor(&mut s); - attrs.record(&mut v); - } - assert_eq!( - s.as_str(), - "question=\"life, the universe, and everything\"; tricky=true; can_you_do_it=true" - ); - }); - - TestAttrs2::with(|attrs| { - let mut s = String::new(); - { - let mut v = make.make_visitor(&mut s); - attrs.record(&mut v); - } - assert_eq!( - s.as_str(), - "question=None; question.answer=42; tricky=true; can_you_do_it=false" - ); - }); - } -} diff --git a/vendor/tracing-subscriber/src/field/display.rs b/vendor/tracing-subscriber/src/field/display.rs deleted file mode 100644 index 78a039ce1..000000000 --- a/vendor/tracing-subscriber/src/field/display.rs +++ /dev/null @@ -1,117 +0,0 @@ -//! `MakeVisitor` wrappers for working with `fmt::Display` fields. -use super::{MakeVisitor, VisitFmt, VisitOutput}; -use tracing_core::field::{Field, Visit}; - -use core::fmt; - -/// A visitor wrapper that ensures any strings named "message" are formatted -/// using `fmt::Display` -#[derive(Debug, Clone)] -pub struct Messages<V>(V); - -// TODO(eliza): When `error` as a primitive type is stable, add a -// `DisplayErrors` wrapper... - -// === impl Messages === -// -impl<V> Messages<V> { - /// Returns a new [`MakeVisitor`] implementation that will wrap `inner` so - /// that any strings named `message` are formatted using `fmt::Display`. - /// - /// [`MakeVisitor`]: super::MakeVisitor - pub fn new(inner: V) -> Self { - Messages(inner) - } -} - -impl<T, V> MakeVisitor<T> for Messages<V> -where - V: MakeVisitor<T>, -{ - type Visitor = Messages<V::Visitor>; - - #[inline] - fn make_visitor(&self, target: T) -> Self::Visitor { - Messages(self.0.make_visitor(target)) - } -} - -impl<V> Visit for Messages<V> -where - V: Visit, -{ - #[inline] - fn record_f64(&mut self, field: &Field, value: f64) { - self.0.record_f64(field, value) - } - - #[inline] - fn record_i64(&mut self, field: &Field, value: i64) { - self.0.record_i64(field, value) - } - - #[inline] - fn record_u64(&mut self, field: &Field, value: u64) { - self.0.record_u64(field, value) - } - - #[inline] - fn record_bool(&mut self, field: &Field, value: bool) { - self.0.record_bool(field, value) - } - - /// Visit a string value. - fn record_str(&mut self, field: &Field, value: &str) { - if field.name() == "message" { - self.0.record_debug(field, &format_args!("{}", value)) - } else { - self.0.record_str(field, value) - } - } - - // TODO(eliza): add RecordError when stable - // fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) { - // self.record_debug(field, &format_args!("{}", value)) - // } - - #[inline] - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - self.0.record_debug(field, value) - } -} - -impl<V, O> VisitOutput<O> for Messages<V> -where - V: VisitOutput<O>, -{ - #[inline] - fn finish(self) -> O { - self.0.finish() - } -} - -feature! { - #![feature = "std"] - use super::VisitWrite; - use std::io; - - impl<V> VisitWrite for Messages<V> - where - V: VisitWrite, - { - #[inline] - fn writer(&mut self) -> &mut dyn io::Write { - self.0.writer() - } - } -} - -impl<V> VisitFmt for Messages<V> -where - V: VisitFmt, -{ - #[inline] - fn writer(&mut self) -> &mut dyn fmt::Write { - self.0.writer() - } -} diff --git a/vendor/tracing-subscriber/src/field/mod.rs b/vendor/tracing-subscriber/src/field/mod.rs deleted file mode 100644 index 5dfddb362..000000000 --- a/vendor/tracing-subscriber/src/field/mod.rs +++ /dev/null @@ -1,366 +0,0 @@ -//! Utilities for working with [fields] and [field visitors]. -//! -//! [fields]: tracing_core::field -//! [field visitors]: tracing_core::field::Visit -use core::{fmt, marker::PhantomData}; -pub use tracing_core::field::Visit; -use tracing_core::{ - span::{Attributes, Record}, - Event, -}; -pub mod debug; -pub mod delimited; -pub mod display; - -/// Creates new [visitors]. -/// -/// A type implementing `MakeVisitor` represents a composable factory for types -/// implementing the [`Visit` trait][visitors]. The `MakeVisitor` trait defines -/// a single function, `make_visitor`, which takes in a `T`-typed `target` and -/// returns a type implementing `Visit` configured for that target. A target may -/// be a string, output stream, or data structure that the visitor will record -/// data to, configuration variables that determine the visitor's behavior, or -/// `()` when no input is required to produce a visitor. -/// -/// [visitors]: tracing_core::field::Visit -pub trait MakeVisitor<T> { - /// The visitor type produced by this `MakeVisitor`. - type Visitor: Visit; - - /// Make a new visitor for the provided `target`. - fn make_visitor(&self, target: T) -> Self::Visitor; -} - -/// A [visitor] that produces output once it has visited a set of fields. -/// -/// [visitor]: tracing_core::field::Visit -pub trait VisitOutput<Out>: Visit { - /// Completes the visitor, returning any output. - /// - /// This is called once a full set of fields has been visited. - fn finish(self) -> Out; - - /// Visit a set of fields, and return the output of finishing the visitor - /// once the fields have been visited. - fn visit<R>(mut self, fields: &R) -> Out - where - R: RecordFields, - Self: Sized, - { - fields.record(&mut self); - self.finish() - } -} - -/// Extension trait implemented by types which can be recorded by a [visitor]. -/// -/// This allows writing code that is generic over `tracing_core`'s -/// [`span::Attributes`][attr], [`span::Record`][rec], and [`Event`][event] -/// types. These types all provide inherent `record` methods that allow a -/// visitor to record their fields, but there is no common trait representing this. -/// -/// With `RecordFields`, we can write code like this: -/// ``` -/// use tracing_core::field::Visit; -/// # use tracing_core::field::Field; -/// use tracing_subscriber::field::RecordFields; -/// -/// struct MyVisitor { -/// // ... -/// } -/// # impl MyVisitor { fn new() -> Self { Self{} } } -/// impl Visit for MyVisitor { -/// // ... -/// # fn record_debug(&mut self, _: &Field, _: &dyn std::fmt::Debug) {} -/// } -/// -/// fn record_with_my_visitor<R>(r: R) -/// where -/// R: RecordFields, -/// { -/// let mut visitor = MyVisitor::new(); -/// r.record(&mut visitor); -/// } -/// ``` -/// [visitor]: tracing_core::field::Visit -/// [attr]: tracing_core::span::Attributes -/// [rec]: tracing_core::span::Record -/// [event]: tracing_core::event::Event -pub trait RecordFields: crate::sealed::Sealed<RecordFieldsMarker> { - /// Record all the fields in `self` with the provided `visitor`. - fn record(&self, visitor: &mut dyn Visit); -} - -/// Extension trait implemented for all `MakeVisitor` implementations that -/// produce a visitor implementing `VisitOutput`. -pub trait MakeOutput<T, Out> -where - Self: MakeVisitor<T> + crate::sealed::Sealed<(T, Out)>, - Self::Visitor: VisitOutput<Out>, -{ - /// Visits all fields in `fields` with a new visitor constructed from - /// `target`. - fn visit_with<F>(&self, target: T, fields: &F) -> Out - where - F: RecordFields, - { - self.make_visitor(target).visit(fields) - } -} - -feature! { - #![feature = "std"] - use std::io; - - /// Extension trait implemented by visitors to indicate that they write to an - /// `io::Write` instance, and allow access to that writer. - pub trait VisitWrite: VisitOutput<Result<(), io::Error>> { - /// Returns the writer that this visitor writes to. - fn writer(&mut self) -> &mut dyn io::Write; - } -} - -/// Extension trait implemented by visitors to indicate that they write to a -/// `fmt::Write` instance, and allow access to that writer. -pub trait VisitFmt: VisitOutput<fmt::Result> { - /// Returns the formatter that this visitor writes to. - fn writer(&mut self) -> &mut dyn fmt::Write; -} - -/// Extension trait providing `MakeVisitor` combinators. -pub trait MakeExt<T> -where - Self: MakeVisitor<T> + Sized, - Self: crate::sealed::Sealed<MakeExtMarker<T>>, -{ - /// Wraps `self` so that any `fmt::Debug` fields are recorded using the - /// alternate formatter (`{:#?}`). - fn debug_alt(self) -> debug::Alt<Self> { - debug::Alt::new(self) - } - - /// Wraps `self` so that any string fields named "message" are recorded - /// using `fmt::Display`. - fn display_messages(self) -> display::Messages<Self> { - display::Messages::new(self) - } - - /// Wraps `self` so that when fields are formatted to a writer, they are - /// separated by the provided `delimiter`. - fn delimited<D>(self, delimiter: D) -> delimited::Delimited<D, Self> - where - D: AsRef<str> + Clone, - Self::Visitor: VisitFmt, - { - delimited::Delimited::new(delimiter, self) - } -} - -// === impl RecordFields === - -impl<'a> crate::sealed::Sealed<RecordFieldsMarker> for Event<'a> {} -impl<'a> RecordFields for Event<'a> { - fn record(&self, visitor: &mut dyn Visit) { - Event::record(self, visitor) - } -} - -impl<'a> crate::sealed::Sealed<RecordFieldsMarker> for Attributes<'a> {} -impl<'a> RecordFields for Attributes<'a> { - fn record(&self, visitor: &mut dyn Visit) { - Attributes::record(self, visitor) - } -} - -impl<'a> crate::sealed::Sealed<RecordFieldsMarker> for Record<'a> {} -impl<'a> RecordFields for Record<'a> { - fn record(&self, visitor: &mut dyn Visit) { - Record::record(self, visitor) - } -} - -impl<'a, F> crate::sealed::Sealed<RecordFieldsMarker> for &'a F where F: RecordFields {} -impl<'a, F> RecordFields for &'a F -where - F: RecordFields, -{ - fn record(&self, visitor: &mut dyn Visit) { - F::record(*self, visitor) - } -} - -// === blanket impls === - -impl<T, V, F> MakeVisitor<T> for F -where - F: Fn(T) -> V, - V: Visit, -{ - type Visitor = V; - fn make_visitor(&self, target: T) -> Self::Visitor { - (self)(target) - } -} - -impl<T, Out, M> crate::sealed::Sealed<(T, Out)> for M -where - M: MakeVisitor<T>, - M::Visitor: VisitOutput<Out>, -{ -} - -impl<T, Out, M> MakeOutput<T, Out> for M -where - M: MakeVisitor<T>, - M::Visitor: VisitOutput<Out>, -{ -} - -impl<T, M> crate::sealed::Sealed<MakeExtMarker<T>> for M where M: MakeVisitor<T> + Sized {} - -impl<T, M> MakeExt<T> for M -where - M: MakeVisitor<T> + Sized, - M: crate::sealed::Sealed<MakeExtMarker<T>>, -{ -} - -#[derive(Debug)] -#[doc(hidden)] -pub struct MakeExtMarker<T> { - _p: PhantomData<T>, -} - -#[derive(Debug)] -#[doc(hidden)] -pub struct RecordFieldsMarker { - _p: (), -} - -#[cfg(all(test, feature = "alloc"))] -#[macro_use] -pub(in crate::field) mod test_util { - use super::*; - pub(in crate::field) use alloc::string::String; - use tracing_core::{ - callsite::Callsite, - field::{Field, Value}, - metadata::{Kind, Level, Metadata}, - }; - - pub(crate) struct TestAttrs1; - pub(crate) struct TestAttrs2; - - impl TestAttrs1 { - pub(crate) fn with<T>(f: impl FnOnce(Attributes<'_>) -> T) -> T { - let fieldset = TEST_META_1.fields(); - let values = &[ - ( - &fieldset.field("question").unwrap(), - Some(&"life, the universe, and everything" as &dyn Value), - ), - (&fieldset.field("question.answer").unwrap(), None), - ( - &fieldset.field("tricky").unwrap(), - Some(&true as &dyn Value), - ), - ( - &fieldset.field("can_you_do_it").unwrap(), - Some(&true as &dyn Value), - ), - ]; - let valueset = fieldset.value_set(values); - let attrs = tracing_core::span::Attributes::new(&TEST_META_1, &valueset); - f(attrs) - } - } - - impl TestAttrs2 { - pub(crate) fn with<T>(f: impl FnOnce(Attributes<'_>) -> T) -> T { - let fieldset = TEST_META_1.fields(); - let none = tracing_core::field::debug(&Option::<&str>::None); - let values = &[ - ( - &fieldset.field("question").unwrap(), - Some(&none as &dyn Value), - ), - ( - &fieldset.field("question.answer").unwrap(), - Some(&42 as &dyn Value), - ), - ( - &fieldset.field("tricky").unwrap(), - Some(&true as &dyn Value), - ), - ( - &fieldset.field("can_you_do_it").unwrap(), - Some(&false as &dyn Value), - ), - ]; - let valueset = fieldset.value_set(values); - let attrs = tracing_core::span::Attributes::new(&TEST_META_1, &valueset); - f(attrs) - } - } - - struct TestCallsite1; - static TEST_CALLSITE_1: &'static dyn Callsite = &TestCallsite1; - static TEST_META_1: Metadata<'static> = tracing_core::metadata! { - name: "field_test1", - target: module_path!(), - level: Level::INFO, - fields: &["question", "question.answer", "tricky", "can_you_do_it"], - callsite: TEST_CALLSITE_1, - kind: Kind::SPAN, - }; - - impl Callsite for TestCallsite1 { - fn set_interest(&self, _: tracing_core::subscriber::Interest) { - unimplemented!() - } - - fn metadata(&self) -> &Metadata<'_> { - &TEST_META_1 - } - } - - pub(crate) struct MakeDebug; - pub(crate) struct DebugVisitor<'a> { - writer: &'a mut dyn fmt::Write, - err: fmt::Result, - } - - impl<'a> DebugVisitor<'a> { - pub(crate) fn new(writer: &'a mut dyn fmt::Write) -> Self { - Self { - writer, - err: Ok(()), - } - } - } - - impl<'a> Visit for DebugVisitor<'a> { - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - write!(self.writer, "{}={:?}", field, value).unwrap(); - } - } - - impl<'a> VisitOutput<fmt::Result> for DebugVisitor<'a> { - fn finish(self) -> fmt::Result { - self.err - } - } - - impl<'a> VisitFmt for DebugVisitor<'a> { - fn writer(&mut self) -> &mut dyn fmt::Write { - self.writer - } - } - - impl<'a> MakeVisitor<&'a mut dyn fmt::Write> for MakeDebug { - type Visitor = DebugVisitor<'a>; - fn make_visitor(&self, w: &'a mut dyn fmt::Write) -> DebugVisitor<'a> { - DebugVisitor::new(w) - } - } -} diff --git a/vendor/tracing-subscriber/src/filter/directive.rs b/vendor/tracing-subscriber/src/filter/directive.rs deleted file mode 100644 index 2ae3f0f24..000000000 --- a/vendor/tracing-subscriber/src/filter/directive.rs +++ /dev/null @@ -1,456 +0,0 @@ -use crate::filter::level::{self, LevelFilter}; -#[cfg(not(feature = "smallvec"))] -use alloc::vec; -#[cfg(not(feature = "std"))] -use alloc::{string::String, vec::Vec}; - -use core::{cmp::Ordering, fmt, iter::FromIterator, slice, str::FromStr}; -use tracing_core::{Level, Metadata}; -/// Indicates that a string could not be parsed as a filtering directive. -#[derive(Debug)] -pub struct ParseError { - kind: ParseErrorKind, -} - -/// A directive which will statically enable or disable a given callsite. -/// -/// Unlike a dynamic directive, this can be cached by the callsite. -#[derive(Debug, PartialEq, Eq, Clone)] -pub(crate) struct StaticDirective { - pub(in crate::filter) target: Option<String>, - pub(in crate::filter) field_names: Vec<String>, - pub(in crate::filter) level: LevelFilter, -} - -#[cfg(feature = "smallvec")] -pub(crate) type FilterVec<T> = smallvec::SmallVec<[T; 8]>; -#[cfg(not(feature = "smallvec"))] -pub(crate) type FilterVec<T> = Vec<T>; - -#[derive(Debug, PartialEq, Clone)] -pub(in crate::filter) struct DirectiveSet<T> { - directives: FilterVec<T>, - pub(in crate::filter) max_level: LevelFilter, -} - -pub(in crate::filter) trait Match { - fn cares_about(&self, meta: &Metadata<'_>) -> bool; - fn level(&self) -> &LevelFilter; -} - -#[derive(Debug)] -enum ParseErrorKind { - #[cfg(feature = "std")] - Field(Box<dyn std::error::Error + Send + Sync>), - Level(level::ParseError), - Other(Option<&'static str>), -} - -// === impl DirectiveSet === - -impl<T> DirectiveSet<T> { - #[cfg(feature = "env-filter")] - pub(crate) fn is_empty(&self) -> bool { - self.directives.is_empty() - } - - pub(crate) fn iter(&self) -> slice::Iter<'_, T> { - self.directives.iter() - } -} - -impl<T: Ord> Default for DirectiveSet<T> { - fn default() -> Self { - Self { - directives: FilterVec::new(), - max_level: LevelFilter::OFF, - } - } -} - -impl<T: Match + Ord> DirectiveSet<T> { - pub(crate) fn directives(&self) -> impl Iterator<Item = &T> { - self.directives.iter() - } - - pub(crate) fn directives_for<'a>( - &'a self, - metadata: &'a Metadata<'a>, - ) -> impl Iterator<Item = &'a T> + 'a { - self.directives().filter(move |d| d.cares_about(metadata)) - } - - pub(crate) fn add(&mut self, directive: T) { - // does this directive enable a more verbose level than the current - // max? if so, update the max level. - let level = *directive.level(); - if level > self.max_level { - self.max_level = level; - } - // insert the directive into the vec of directives, ordered by - // specificity (length of target + number of field filters). this - // ensures that, when finding a directive to match a span or event, we - // search the directive set in most specific first order. - match self.directives.binary_search(&directive) { - Ok(i) => self.directives[i] = directive, - Err(i) => self.directives.insert(i, directive), - } - } - - #[cfg(test)] - pub(in crate::filter) fn into_vec(self) -> FilterVec<T> { - self.directives - } -} - -impl<T: Match + Ord> FromIterator<T> for DirectiveSet<T> { - fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { - let mut this = Self::default(); - this.extend(iter); - this - } -} - -impl<T: Match + Ord> Extend<T> for DirectiveSet<T> { - fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { - for directive in iter.into_iter() { - self.add(directive); - } - } -} - -impl<T> IntoIterator for DirectiveSet<T> { - type Item = T; - - #[cfg(feature = "smallvec")] - type IntoIter = smallvec::IntoIter<[T; 8]>; - #[cfg(not(feature = "smallvec"))] - type IntoIter = vec::IntoIter<T>; - - fn into_iter(self) -> Self::IntoIter { - self.directives.into_iter() - } -} - -// === impl Statics === - -impl DirectiveSet<StaticDirective> { - pub(crate) fn enabled(&self, meta: &Metadata<'_>) -> bool { - let level = meta.level(); - match self.directives_for(meta).next() { - Some(d) => d.level >= *level, - None => false, - } - } - - /// Same as `enabled` above, but skips `Directive`'s with fields. - pub(crate) fn target_enabled(&self, target: &str, level: &Level) -> bool { - match self.directives_for_target(target).next() { - Some(d) => d.level >= *level, - None => false, - } - } - - pub(crate) fn directives_for_target<'a>( - &'a self, - target: &'a str, - ) -> impl Iterator<Item = &'a StaticDirective> + 'a { - self.directives() - .filter(move |d| d.cares_about_target(target)) - } -} - -// === impl StaticDirective === - -impl StaticDirective { - pub(in crate::filter) fn new( - target: Option<String>, - field_names: Vec<String>, - level: LevelFilter, - ) -> Self { - Self { - target, - field_names, - level, - } - } - - pub(in crate::filter) fn cares_about_target(&self, to_check: &str) -> bool { - // Does this directive have a target filter, and does it match the - // metadata's target? - if let Some(ref target) = self.target { - if !to_check.starts_with(&target[..]) { - return false; - } - } - - if !self.field_names.is_empty() { - return false; - } - - true - } -} - -impl Ord for StaticDirective { - fn cmp(&self, other: &StaticDirective) -> Ordering { - // We attempt to order directives by how "specific" they are. This - // ensures that we try the most specific directives first when - // attempting to match a piece of metadata. - - // First, we compare based on whether a target is specified, and the - // lengths of those targets if both have targets. - let ordering = self - .target - .as_ref() - .map(String::len) - .cmp(&other.target.as_ref().map(String::len)) - // Then we compare how many field names are matched by each directive. - .then_with(|| self.field_names.len().cmp(&other.field_names.len())) - // Finally, we fall back to lexicographical ordering if the directives are - // equally specific. Although this is no longer semantically important, - // we need to define a total ordering to determine the directive's place - // in the BTreeMap. - .then_with(|| { - self.target - .cmp(&other.target) - .then_with(|| self.field_names[..].cmp(&other.field_names[..])) - }) - .reverse(); - - #[cfg(debug_assertions)] - { - if ordering == Ordering::Equal { - debug_assert_eq!( - self.target, other.target, - "invariant violated: Ordering::Equal must imply a.target == b.target" - ); - debug_assert_eq!( - self.field_names, other.field_names, - "invariant violated: Ordering::Equal must imply a.field_names == b.field_names" - ); - } - } - - ordering - } -} - -impl PartialOrd for StaticDirective { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl Match for StaticDirective { - fn cares_about(&self, meta: &Metadata<'_>) -> bool { - // Does this directive have a target filter, and does it match the - // metadata's target? - if let Some(ref target) = self.target { - if !meta.target().starts_with(&target[..]) { - return false; - } - } - - if meta.is_event() && !self.field_names.is_empty() { - let fields = meta.fields(); - for name in &self.field_names { - if fields.field(name).is_none() { - return false; - } - } - } - - true - } - - fn level(&self) -> &LevelFilter { - &self.level - } -} - -impl Default for StaticDirective { - fn default() -> Self { - StaticDirective { - target: None, - field_names: Vec::new(), - level: LevelFilter::ERROR, - } - } -} - -impl fmt::Display for StaticDirective { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut wrote_any = false; - if let Some(ref target) = self.target { - fmt::Display::fmt(target, f)?; - wrote_any = true; - } - - if !self.field_names.is_empty() { - f.write_str("[")?; - - let mut fields = self.field_names.iter(); - if let Some(field) = fields.next() { - write!(f, "{{{}", field)?; - for field in fields { - write!(f, ",{}", field)?; - } - f.write_str("}")?; - } - - f.write_str("]")?; - wrote_any = true; - } - - if wrote_any { - f.write_str("=")?; - } - - fmt::Display::fmt(&self.level, f) - } -} - -impl FromStr for StaticDirective { - type Err = ParseError; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - // This method parses a filtering directive in one of the following - // forms: - // - // * `foo=trace` (TARGET=LEVEL) - // * `foo[{bar,baz}]=info` (TARGET[{FIELD,+}]=LEVEL) - // * `trace` (bare LEVEL) - // * `foo` (bare TARGET) - let mut split = s.split('='); - let part0 = split - .next() - .ok_or_else(|| ParseError::msg("string must not be empty"))?; - - // Directive includes an `=`: - // * `foo=trace` - // * `foo[{bar}]=trace` - // * `foo[{bar,baz}]=trace` - if let Some(part1) = split.next() { - if split.next().is_some() { - return Err(ParseError::msg( - "too many '=' in filter directive, expected 0 or 1", - )); - } - - let mut split = part0.split("[{"); - let target = split.next().map(String::from); - let mut field_names = Vec::new(); - // Directive includes fields: - // * `foo[{bar}]=trace` - // * `foo[{bar,baz}]=trace` - if let Some(maybe_fields) = split.next() { - if split.next().is_some() { - return Err(ParseError::msg( - "too many '[{' in filter directive, expected 0 or 1", - )); - } - - if !maybe_fields.ends_with("}]") { - return Err(ParseError::msg("expected fields list to end with '}]'")); - } - - let fields = maybe_fields - .trim_end_matches("}]") - .split(',') - .filter_map(|s| { - if s.is_empty() { - None - } else { - Some(String::from(s)) - } - }); - field_names.extend(fields); - }; - let level = part1.parse()?; - return Ok(Self { - level, - field_names, - target, - }); - } - - // Okay, the part after the `=` was empty, the directive is either a - // bare level or a bare target. - // * `foo` - // * `info` - Ok(match part0.parse::<LevelFilter>() { - Ok(level) => Self { - level, - target: None, - field_names: Vec::new(), - }, - Err(_) => Self { - target: Some(String::from(part0)), - level: LevelFilter::TRACE, - field_names: Vec::new(), - }, - }) - } -} - -// === impl ParseError === - -impl ParseError { - #[cfg(feature = "env-filter")] - pub(crate) fn new() -> Self { - ParseError { - kind: ParseErrorKind::Other(None), - } - } - - pub(crate) fn msg(s: &'static str) -> Self { - ParseError { - kind: ParseErrorKind::Other(Some(s)), - } - } -} - -impl fmt::Display for ParseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - ParseErrorKind::Other(None) => f.pad("invalid filter directive"), - ParseErrorKind::Other(Some(msg)) => write!(f, "invalid filter directive: {}", msg), - ParseErrorKind::Level(ref l) => l.fmt(f), - #[cfg(feature = "std")] - ParseErrorKind::Field(ref e) => write!(f, "invalid field filter: {}", e), - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for ParseError { - fn description(&self) -> &str { - "invalid filter directive" - } - - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self.kind { - ParseErrorKind::Other(_) => None, - ParseErrorKind::Level(ref l) => Some(l), - ParseErrorKind::Field(ref n) => Some(n.as_ref()), - } - } -} - -#[cfg(feature = "std")] -impl From<Box<dyn std::error::Error + Send + Sync>> for ParseError { - fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self { - Self { - kind: ParseErrorKind::Field(e), - } - } -} - -impl From<level::ParseError> for ParseError { - fn from(l: level::ParseError) -> Self { - Self { - kind: ParseErrorKind::Level(l), - } - } -} diff --git a/vendor/tracing-subscriber/src/filter/env/builder.rs b/vendor/tracing-subscriber/src/filter/env/builder.rs deleted file mode 100644 index 36b520543..000000000 --- a/vendor/tracing-subscriber/src/filter/env/builder.rs +++ /dev/null @@ -1,324 +0,0 @@ -use super::{ - directive::{self, Directive}, - EnvFilter, FromEnvError, -}; -use crate::sync::RwLock; -use std::env; -use thread_local::ThreadLocal; -use tracing::level_filters::STATIC_MAX_LEVEL; - -/// A [builder] for constructing new [`EnvFilter`]s. -/// -/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html -#[derive(Debug, Clone)] -pub struct Builder { - regex: bool, - env: Option<String>, - default_directive: Option<Directive>, -} - -impl Builder { - /// Sets whether span field values can be matched with regular expressions. - /// - /// If this is `true`, field filter directives will be interpreted as - /// regular expressions if they are not able to be interpreted as a `bool`, - /// `i64`, `u64`, or `f64` literal. If this is `false,` those field values - /// will be interpreted as literal [`std::fmt::Debug`] output instead. - /// - /// By default, regular expressions are enabled. - /// - /// **Note**: when [`EnvFilter`]s are constructed from untrusted inputs, - /// disabling regular expressions is strongly encouraged. - pub fn with_regex(self, regex: bool) -> Self { - Self { regex, ..self } - } - - /// Sets a default [filtering directive] that will be added to the filter if - /// the parsed string or environment variable contains no filter directives. - /// - /// By default, there is no default directive. - /// - /// # Examples - /// - /// If [`parse`], [`parse_lossy`], [`from_env`], or [`from_env_lossy`] are - /// called with an empty string or environment variable, the default - /// directive is used instead: - /// - /// ```rust - /// # fn main() -> Result<(), Box<dyn std::error::Error>> { - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// let filter = EnvFilter::builder() - /// .with_default_directive(LevelFilter::INFO.into()) - /// .parse("")?; - /// - /// assert_eq!(format!("{}", filter), "info"); - /// # Ok(()) } - /// ``` - /// - /// Note that the `lossy` variants ([`parse_lossy`] and [`from_env_lossy`]) - /// will ignore any invalid directives. If all directives in a filter - /// string or environment variable are invalid, those methods will also use - /// the default directive: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// let filter = EnvFilter::builder() - /// .with_default_directive(LevelFilter::INFO.into()) - /// .parse_lossy("some_target=fake level,foo::bar=lolwut"); - /// - /// assert_eq!(format!("{}", filter), "info"); - /// ``` - /// - /// - /// If the string or environment variable contains valid filtering - /// directives, the default directive is not used: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// let filter = EnvFilter::builder() - /// .with_default_directive(LevelFilter::INFO.into()) - /// .parse_lossy("foo=trace"); - /// - /// // The default directive is *not* used: - /// assert_eq!(format!("{}", filter), "foo=trace"); - /// ``` - /// - /// Parsing a more complex default directive from a string: - /// - /// ```rust - /// # fn main() -> Result<(), Box<dyn std::error::Error>> { - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// let default = "myapp=debug".parse() - /// .expect("hard-coded default directive should be valid"); - /// - /// let filter = EnvFilter::builder() - /// .with_default_directive(default) - /// .parse("")?; - /// - /// assert_eq!(format!("{}", filter), "myapp=debug"); - /// # Ok(()) } - /// ``` - /// - /// [`parse_lossy`]: Self::parse_lossy - /// [`from_env_lossy`]: Self::from_env_lossy - /// [`parse`]: Self::parse - /// [`from_env`]: Self::from_env - pub fn with_default_directive(self, default_directive: Directive) -> Self { - Self { - default_directive: Some(default_directive), - ..self - } - } - - /// Sets the name of the environment variable used by the [`from_env`], - /// [`from_env_lossy`], and [`try_from_env`] methods. - /// - /// By default, this is the value of [`EnvFilter::DEFAULT_ENV`] - /// (`RUST_LOG`). - /// - /// [`from_env`]: Self::from_env - /// [`from_env_lossy`]: Self::from_env_lossy - /// [`try_from_env`]: Self::try_from_env - pub fn with_env_var(self, var: impl ToString) -> Self { - Self { - env: Some(var.to_string()), - ..self - } - } - - /// Returns a new [`EnvFilter`] from the directives in the given string, - /// *ignoring* any that are invalid. - pub fn parse_lossy<S: AsRef<str>>(&self, dirs: S) -> EnvFilter { - let directives = dirs - .as_ref() - .split(',') - .filter(|s| !s.is_empty()) - .filter_map(|s| match Directive::parse(s, self.regex) { - Ok(d) => Some(d), - Err(err) => { - eprintln!("ignoring `{}`: {}", s, err); - None - } - }); - self.from_directives(directives) - } - - /// Returns a new [`EnvFilter`] from the directives in the given string, - /// or an error if any are invalid. - pub fn parse<S: AsRef<str>>(&self, dirs: S) -> Result<EnvFilter, directive::ParseError> { - let dirs = dirs.as_ref(); - if dirs.is_empty() { - return Ok(self.from_directives(std::iter::empty())); - } - let directives = dirs - .split(',') - .filter(|s| !s.is_empty()) - .map(|s| Directive::parse(s, self.regex)) - .collect::<Result<Vec<_>, _>>()?; - Ok(self.from_directives(directives)) - } - - /// Returns a new [`EnvFilter`] from the directives in the configured - /// environment variable, ignoring any directives that are invalid. - pub fn from_env_lossy(&self) -> EnvFilter { - let var = env::var(self.env_var_name()).unwrap_or_default(); - self.parse_lossy(var) - } - - /// Returns a new [`EnvFilter`] from the directives in the in the configured - /// environment variable, or an error if the environment variable is not set - /// or contains invalid directives. - pub fn from_env(&self) -> Result<EnvFilter, FromEnvError> { - let var = env::var(self.env_var_name()).unwrap_or_default(); - self.parse(var).map_err(Into::into) - } - - /// Returns a new [`EnvFilter`] from the directives in the in the configured - /// environment variable, or an error if the environment variable is not set - /// or contains invalid directives. - pub fn try_from_env(&self) -> Result<EnvFilter, FromEnvError> { - let var = env::var(self.env_var_name())?; - self.parse(var).map_err(Into::into) - } - - // TODO(eliza): consider making this a public API? - // Clippy doesn't love this naming, because it suggests that `from_` methods - // should not take a `Self`...but in this case, it's the `EnvFilter` that is - // being constructed "from" the directives, rather than the builder itself. - #[allow(clippy::wrong_self_convention)] - pub(super) fn from_directives( - &self, - directives: impl IntoIterator<Item = Directive>, - ) -> EnvFilter { - use tracing::Level; - - let mut directives: Vec<_> = directives.into_iter().collect(); - let mut disabled = Vec::new(); - for directive in &mut directives { - if directive.level > STATIC_MAX_LEVEL { - disabled.push(directive.clone()); - } - if !self.regex { - directive.deregexify(); - } - } - - if !disabled.is_empty() { - #[cfg(feature = "ansi_term")] - use ansi_term::{Color, Style}; - // NOTE: We can't use a configured `MakeWriter` because the EnvFilter - // has no knowledge of any underlying subscriber or collector, which - // may or may not use a `MakeWriter`. - let warn = |msg: &str| { - #[cfg(not(feature = "ansi_term"))] - let msg = format!("warning: {}", msg); - #[cfg(feature = "ansi_term")] - let msg = { - let bold = Style::new().bold(); - let mut warning = Color::Yellow.paint("warning"); - warning.style_ref_mut().is_bold = true; - format!("{}{} {}", warning, bold.paint(":"), bold.paint(msg)) - }; - eprintln!("{}", msg); - }; - let ctx_prefixed = |prefix: &str, msg: &str| { - #[cfg(not(feature = "ansi_term"))] - let msg = format!("{} {}", prefix, msg); - #[cfg(feature = "ansi_term")] - let msg = { - let mut equal = Color::Fixed(21).paint("="); // dark blue - equal.style_ref_mut().is_bold = true; - format!(" {} {} {}", equal, Style::new().bold().paint(prefix), msg) - }; - eprintln!("{}", msg); - }; - let ctx_help = |msg| ctx_prefixed("help:", msg); - let ctx_note = |msg| ctx_prefixed("note:", msg); - let ctx = |msg: &str| { - #[cfg(not(feature = "ansi_term"))] - let msg = format!("note: {}", msg); - #[cfg(feature = "ansi_term")] - let msg = { - let mut pipe = Color::Fixed(21).paint("|"); - pipe.style_ref_mut().is_bold = true; - format!(" {} {}", pipe, msg) - }; - eprintln!("{}", msg); - }; - warn("some trace filter directives would enable traces that are disabled statically"); - for directive in disabled { - let target = if let Some(target) = &directive.target { - format!("the `{}` target", target) - } else { - "all targets".into() - }; - let level = directive - .level - .into_level() - .expect("=off would not have enabled any filters"); - ctx(&format!( - "`{}` would enable the {} level for {}", - directive, level, target - )); - } - ctx_note(&format!("the static max level is `{}`", STATIC_MAX_LEVEL)); - let help_msg = || { - let (feature, filter) = match STATIC_MAX_LEVEL.into_level() { - Some(Level::TRACE) => unreachable!( - "if the max level is trace, no static filtering features are enabled" - ), - Some(Level::DEBUG) => ("max_level_debug", Level::TRACE), - Some(Level::INFO) => ("max_level_info", Level::DEBUG), - Some(Level::WARN) => ("max_level_warn", Level::INFO), - Some(Level::ERROR) => ("max_level_error", Level::WARN), - None => return ("max_level_off", String::new()), - }; - (feature, format!("{} ", filter)) - }; - let (feature, earlier_level) = help_msg(); - ctx_help(&format!( - "to enable {}logging, remove the `{}` feature", - earlier_level, feature - )); - } - - let (dynamics, statics) = Directive::make_tables(directives); - let has_dynamics = !dynamics.is_empty(); - - let mut filter = EnvFilter { - statics, - dynamics, - has_dynamics, - by_id: RwLock::new(Default::default()), - by_cs: RwLock::new(Default::default()), - scope: ThreadLocal::new(), - regex: self.regex, - }; - - if !has_dynamics && filter.statics.is_empty() { - if let Some(ref default) = self.default_directive { - filter = filter.add_directive(default.clone()); - } - } - - filter - } - - fn env_var_name(&self) -> &str { - self.env.as_deref().unwrap_or(EnvFilter::DEFAULT_ENV) - } -} - -impl Default for Builder { - fn default() -> Self { - Self { - regex: true, - env: None, - default_directive: None, - } - } -} diff --git a/vendor/tracing-subscriber/src/filter/env/directive.rs b/vendor/tracing-subscriber/src/filter/env/directive.rs deleted file mode 100644 index f062e6ef9..000000000 --- a/vendor/tracing-subscriber/src/filter/env/directive.rs +++ /dev/null @@ -1,860 +0,0 @@ -pub(crate) use crate::filter::directive::{FilterVec, ParseError, StaticDirective}; -use crate::filter::{ - directive::{DirectiveSet, Match}, - env::{field, FieldMap}, - level::LevelFilter, -}; -use once_cell::sync::Lazy; -use regex::Regex; -use std::{cmp::Ordering, fmt, iter::FromIterator, str::FromStr}; -use tracing_core::{span, Level, Metadata}; - -/// A single filtering directive. -// TODO(eliza): add a builder for programmatically constructing directives? -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))] -pub struct Directive { - in_span: Option<String>, - fields: Vec<field::Match>, - pub(crate) target: Option<String>, - pub(crate) level: LevelFilter, -} - -/// A set of dynamic filtering directives. -pub(super) type Dynamics = DirectiveSet<Directive>; - -/// A set of static filtering directives. -pub(super) type Statics = DirectiveSet<StaticDirective>; - -pub(crate) type CallsiteMatcher = MatchSet<field::CallsiteMatch>; -pub(crate) type SpanMatcher = MatchSet<field::SpanMatch>; - -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct MatchSet<T> { - field_matches: FilterVec<T>, - base_level: LevelFilter, -} - -impl Directive { - pub(super) fn has_name(&self) -> bool { - self.in_span.is_some() - } - - pub(super) fn has_fields(&self) -> bool { - !self.fields.is_empty() - } - - pub(super) fn to_static(&self) -> Option<StaticDirective> { - if !self.is_static() { - return None; - } - - // TODO(eliza): these strings are all immutable; we should consider - // `Arc`ing them to make this more efficient... - let field_names = self.fields.iter().map(field::Match::name).collect(); - - Some(StaticDirective::new( - self.target.clone(), - field_names, - self.level, - )) - } - - fn is_static(&self) -> bool { - !self.has_name() && !self.fields.iter().any(field::Match::has_value) - } - - pub(super) fn is_dynamic(&self) -> bool { - self.has_name() || self.has_fields() - } - - pub(crate) fn field_matcher(&self, meta: &Metadata<'_>) -> Option<field::CallsiteMatch> { - let fieldset = meta.fields(); - let fields = self - .fields - .iter() - .filter_map( - |field::Match { - ref name, - ref value, - }| { - if let Some(field) = fieldset.field(name) { - let value = value.as_ref().cloned()?; - Some(Ok((field, value))) - } else { - Some(Err(())) - } - }, - ) - .collect::<Result<FieldMap<_>, ()>>() - .ok()?; - Some(field::CallsiteMatch { - fields, - level: self.level, - }) - } - - pub(super) fn make_tables( - directives: impl IntoIterator<Item = Directive>, - ) -> (Dynamics, Statics) { - // TODO(eliza): this could be made more efficient... - let (dyns, stats): (Vec<Directive>, Vec<Directive>) = - directives.into_iter().partition(Directive::is_dynamic); - let statics = stats - .into_iter() - .filter_map(|d| d.to_static()) - .chain(dyns.iter().filter_map(Directive::to_static)) - .collect(); - (Dynamics::from_iter(dyns), statics) - } - - pub(super) fn deregexify(&mut self) { - for field in &mut self.fields { - field.value = match field.value.take() { - Some(field::ValueMatch::Pat(pat)) => { - Some(field::ValueMatch::Debug(pat.into_debug_match())) - } - x => x, - } - } - } - - pub(super) fn parse(from: &str, regex: bool) -> Result<Self, ParseError> { - static DIRECTIVE_RE: Lazy<Regex> = Lazy::new(|| Regex::new( - r"(?x) - ^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ | - # ^^^. - # `note: we match log level names case-insensitively - ^ - (?: # target name or span name - (?P<target>[\w:-]+)|(?P<span>\[[^\]]*\]) - ){1,2} - (?: # level or nothing - =(?P<level>(?i:trace|debug|info|warn|error|off|[0-5]))? - # ^^^. - # `note: we match log level names case-insensitively - )? - $ - " - ) - .unwrap()); - static SPAN_PART_RE: Lazy<Regex> = - Lazy::new(|| Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap()); - static FIELD_FILTER_RE: Lazy<Regex> = - // TODO(eliza): this doesn't _currently_ handle value matchers that include comma - // characters. We should fix that. - Lazy::new(|| Regex::new(r#"(?x) - ( - # field name - [[:word:]][[[:word:]]\.]* - # value part (optional) - (?:=[^,]+)? - ) - # trailing comma or EOS - (?:,\s?|$) - "#).unwrap()); - - let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?; - - if let Some(level) = caps - .name("global_level") - .and_then(|s| s.as_str().parse().ok()) - { - return Ok(Directive { - level, - ..Default::default() - }); - } - - let target = caps.name("target").and_then(|c| { - let s = c.as_str(); - if s.parse::<LevelFilter>().is_ok() { - None - } else { - Some(s.to_owned()) - } - }); - - let (in_span, fields) = caps - .name("span") - .and_then(|cap| { - let cap = cap.as_str().trim_matches(|c| c == '[' || c == ']'); - let caps = SPAN_PART_RE.captures(cap)?; - let span = caps.name("name").map(|c| c.as_str().to_owned()); - let fields = caps - .name("fields") - .map(|c| { - FIELD_FILTER_RE - .find_iter(c.as_str()) - .map(|c| field::Match::parse(c.as_str(), regex)) - .collect::<Result<Vec<_>, _>>() - }) - .unwrap_or_else(|| Ok(Vec::new())); - Some((span, fields)) - }) - .unwrap_or_else(|| (None, Ok(Vec::new()))); - - let level = caps - .name("level") - .and_then(|l| l.as_str().parse().ok()) - // Setting the target without the level enables every level for that target - .unwrap_or(LevelFilter::TRACE); - - Ok(Self { - level, - target, - in_span, - fields: fields?, - }) - } -} - -impl Match for Directive { - fn cares_about(&self, meta: &Metadata<'_>) -> bool { - // Does this directive have a target filter, and does it match the - // metadata's target? - if let Some(ref target) = self.target { - if !meta.target().starts_with(&target[..]) { - return false; - } - } - - // Do we have a name filter, and does it match the metadata's name? - // TODO(eliza): put name globbing here? - if let Some(ref name) = self.in_span { - if name != meta.name() { - return false; - } - } - - // Does the metadata define all the fields that this directive cares about? - let actual_fields = meta.fields(); - for expected_field in &self.fields { - // Does the actual field set (from the metadata) contain this field? - if actual_fields.field(&expected_field.name).is_none() { - return false; - } - } - - true - } - - fn level(&self) -> &LevelFilter { - &self.level - } -} - -impl FromStr for Directive { - type Err = ParseError; - fn from_str(from: &str) -> Result<Self, Self::Err> { - Directive::parse(from, true) - } -} - -impl Default for Directive { - fn default() -> Self { - Directive { - level: LevelFilter::OFF, - target: None, - in_span: None, - fields: Vec::new(), - } - } -} - -impl PartialOrd for Directive { - fn partial_cmp(&self, other: &Directive) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for Directive { - fn cmp(&self, other: &Directive) -> Ordering { - // We attempt to order directives by how "specific" they are. This - // ensures that we try the most specific directives first when - // attempting to match a piece of metadata. - - // First, we compare based on whether a target is specified, and the - // lengths of those targets if both have targets. - let ordering = self - .target - .as_ref() - .map(String::len) - .cmp(&other.target.as_ref().map(String::len)) - // Next compare based on the presence of span names. - .then_with(|| self.in_span.is_some().cmp(&other.in_span.is_some())) - // Then we compare how many fields are defined by each - // directive. - .then_with(|| self.fields.len().cmp(&other.fields.len())) - // Finally, we fall back to lexicographical ordering if the directives are - // equally specific. Although this is no longer semantically important, - // we need to define a total ordering to determine the directive's place - // in the BTreeMap. - .then_with(|| { - self.target - .cmp(&other.target) - .then_with(|| self.in_span.cmp(&other.in_span)) - .then_with(|| self.fields[..].cmp(&other.fields[..])) - }) - .reverse(); - - #[cfg(debug_assertions)] - { - if ordering == Ordering::Equal { - debug_assert_eq!( - self.target, other.target, - "invariant violated: Ordering::Equal must imply a.target == b.target" - ); - debug_assert_eq!( - self.in_span, other.in_span, - "invariant violated: Ordering::Equal must imply a.in_span == b.in_span" - ); - debug_assert_eq!( - self.fields, other.fields, - "invariant violated: Ordering::Equal must imply a.fields == b.fields" - ); - } - } - - ordering - } -} - -impl fmt::Display for Directive { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut wrote_any = false; - if let Some(ref target) = self.target { - fmt::Display::fmt(target, f)?; - wrote_any = true; - } - - if self.in_span.is_some() || !self.fields.is_empty() { - f.write_str("[")?; - - if let Some(ref span) = self.in_span { - fmt::Display::fmt(span, f)?; - } - - let mut fields = self.fields.iter(); - if let Some(field) = fields.next() { - write!(f, "{{{}", field)?; - for field in fields { - write!(f, ",{}", field)?; - } - f.write_str("}")?; - } - - f.write_str("]")?; - wrote_any = true; - } - - if wrote_any { - f.write_str("=")?; - } - - fmt::Display::fmt(&self.level, f) - } -} - -impl From<LevelFilter> for Directive { - fn from(level: LevelFilter) -> Self { - Self { - level, - ..Self::default() - } - } -} - -impl From<Level> for Directive { - fn from(level: Level) -> Self { - LevelFilter::from_level(level).into() - } -} - -// === impl Dynamics === - -impl Dynamics { - pub(crate) fn matcher(&self, metadata: &Metadata<'_>) -> Option<CallsiteMatcher> { - let mut base_level = None; - let field_matches = self - .directives_for(metadata) - .filter_map(|d| { - if let Some(f) = d.field_matcher(metadata) { - return Some(f); - } - match base_level { - Some(ref b) if d.level > *b => base_level = Some(d.level), - None => base_level = Some(d.level), - _ => {} - } - None - }) - .collect(); - - if let Some(base_level) = base_level { - Some(CallsiteMatcher { - field_matches, - base_level, - }) - } else if !field_matches.is_empty() { - Some(CallsiteMatcher { - field_matches, - base_level: base_level.unwrap_or(LevelFilter::OFF), - }) - } else { - None - } - } - - pub(crate) fn has_value_filters(&self) -> bool { - self.directives() - .any(|d| d.fields.iter().any(|f| f.value.is_some())) - } -} - -// ===== impl DynamicMatch ===== - -impl CallsiteMatcher { - /// Create a new `SpanMatch` for a given instance of the matched callsite. - pub(crate) fn to_span_match(&self, attrs: &span::Attributes<'_>) -> SpanMatcher { - let field_matches = self - .field_matches - .iter() - .map(|m| { - let m = m.to_span_match(); - attrs.record(&mut m.visitor()); - m - }) - .collect(); - SpanMatcher { - field_matches, - base_level: self.base_level, - } - } -} - -impl SpanMatcher { - /// Returns the level currently enabled for this callsite. - pub(crate) fn level(&self) -> LevelFilter { - self.field_matches - .iter() - .filter_map(field::SpanMatch::filter) - .max() - .unwrap_or(self.base_level) - } - - pub(crate) fn record_update(&self, record: &span::Record<'_>) { - for m in &self.field_matches { - record.record(&mut m.visitor()) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - fn parse_directives(dirs: impl AsRef<str>) -> Vec<Directive> { - dirs.as_ref() - .split(',') - .filter_map(|s| s.parse().ok()) - .collect() - } - - fn expect_parse(dirs: impl AsRef<str>) -> Vec<Directive> { - dirs.as_ref() - .split(',') - .map(|s| { - s.parse() - .unwrap_or_else(|err| panic!("directive '{:?}' should parse: {}", s, err)) - }) - .collect() - } - - #[test] - fn directive_ordering_by_target_len() { - // TODO(eliza): it would be nice to have a property-based test for this - // instead. - let mut dirs = expect_parse( - "foo::bar=debug,foo::bar::baz=trace,foo=info,a_really_long_name_with_no_colons=warn", - ); - dirs.sort_unstable(); - - let expected = vec![ - "a_really_long_name_with_no_colons", - "foo::bar::baz", - "foo::bar", - "foo", - ]; - let sorted = dirs - .iter() - .map(|d| d.target.as_ref().unwrap()) - .collect::<Vec<_>>(); - - assert_eq!(expected, sorted); - } - #[test] - fn directive_ordering_by_span() { - // TODO(eliza): it would be nice to have a property-based test for this - // instead. - let mut dirs = expect_parse("bar[span]=trace,foo=debug,baz::quux=info,a[span]=warn"); - dirs.sort_unstable(); - - let expected = vec!["baz::quux", "bar", "foo", "a"]; - let sorted = dirs - .iter() - .map(|d| d.target.as_ref().unwrap()) - .collect::<Vec<_>>(); - - assert_eq!(expected, sorted); - } - - #[test] - fn directive_ordering_uses_lexicographic_when_equal() { - // TODO(eliza): it would be nice to have a property-based test for this - // instead. - let mut dirs = expect_parse("span[b]=debug,b=debug,a=trace,c=info,span[a]=info"); - dirs.sort_unstable(); - - let expected = vec![ - ("span", Some("b")), - ("span", Some("a")), - ("c", None), - ("b", None), - ("a", None), - ]; - let sorted = dirs - .iter() - .map(|d| { - ( - d.target.as_ref().unwrap().as_ref(), - d.in_span.as_ref().map(String::as_ref), - ) - }) - .collect::<Vec<_>>(); - - assert_eq!(expected, sorted); - } - - // TODO: this test requires the parser to support directives with multiple - // fields, which it currently can't handle. We should enable this test when - // that's implemented. - #[test] - #[ignore] - fn directive_ordering_by_field_num() { - // TODO(eliza): it would be nice to have a property-based test for this - // instead. - let mut dirs = expect_parse( - "b[{foo,bar}]=info,c[{baz,quuux,quuux}]=debug,a[{foo}]=warn,bar[{field}]=trace,foo=debug,baz::quux=info" - ); - dirs.sort_unstable(); - - let expected = vec!["baz::quux", "bar", "foo", "c", "b", "a"]; - let sorted = dirs - .iter() - .map(|d| d.target.as_ref().unwrap()) - .collect::<Vec<_>>(); - - assert_eq!(expected, sorted); - } - - #[test] - fn parse_directives_ralith() { - let dirs = parse_directives("common=trace,server=trace"); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("common".to_string())); - assert_eq!(dirs[0].level, LevelFilter::TRACE); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("server".to_string())); - assert_eq!(dirs[1].level, LevelFilter::TRACE); - assert_eq!(dirs[1].in_span, None); - } - - #[test] - fn parse_directives_ralith_uc() { - let dirs = parse_directives("common=INFO,server=DEBUG"); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("common".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("server".to_string())); - assert_eq!(dirs[1].level, LevelFilter::DEBUG); - assert_eq!(dirs[1].in_span, None); - } - - #[test] - fn parse_directives_ralith_mixed() { - let dirs = parse_directives("common=iNfo,server=dEbUg"); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("common".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("server".to_string())); - assert_eq!(dirs[1].level, LevelFilter::DEBUG); - assert_eq!(dirs[1].in_span, None); - } - - #[test] - fn parse_directives_valid() { - let dirs = parse_directives("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off"); - assert_eq!(dirs.len(), 4, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::TRACE); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[2].target, Some("crate2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::DEBUG); - assert_eq!(dirs[2].in_span, None); - - assert_eq!(dirs[3].target, Some("crate3".to_string())); - assert_eq!(dirs[3].level, LevelFilter::OFF); - assert_eq!(dirs[3].in_span, None); - } - - #[test] - - fn parse_level_directives() { - let dirs = parse_directives( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off", - ); - assert_eq!(dirs.len(), 6, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::WARN); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[2].target, Some("crate1::mod2::mod3".to_string())); - assert_eq!(dirs[2].level, LevelFilter::INFO); - assert_eq!(dirs[2].in_span, None); - - assert_eq!(dirs[3].target, Some("crate2".to_string())); - assert_eq!(dirs[3].level, LevelFilter::DEBUG); - assert_eq!(dirs[3].in_span, None); - - assert_eq!(dirs[4].target, Some("crate3".to_string())); - assert_eq!(dirs[4].level, LevelFilter::TRACE); - assert_eq!(dirs[4].in_span, None); - - assert_eq!(dirs[5].target, Some("crate3::mod2::mod1".to_string())); - assert_eq!(dirs[5].level, LevelFilter::OFF); - assert_eq!(dirs[5].in_span, None); - } - - #[test] - fn parse_uppercase_level_directives() { - let dirs = parse_directives( - "crate1::mod1=ERROR,crate1::mod2=WARN,crate1::mod2::mod3=INFO,\ - crate2=DEBUG,crate3=TRACE,crate3::mod2::mod1=OFF", - ); - assert_eq!(dirs.len(), 6, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::WARN); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[2].target, Some("crate1::mod2::mod3".to_string())); - assert_eq!(dirs[2].level, LevelFilter::INFO); - assert_eq!(dirs[2].in_span, None); - - assert_eq!(dirs[3].target, Some("crate2".to_string())); - assert_eq!(dirs[3].level, LevelFilter::DEBUG); - assert_eq!(dirs[3].in_span, None); - - assert_eq!(dirs[4].target, Some("crate3".to_string())); - assert_eq!(dirs[4].level, LevelFilter::TRACE); - assert_eq!(dirs[4].in_span, None); - - assert_eq!(dirs[5].target, Some("crate3::mod2::mod1".to_string())); - assert_eq!(dirs[5].level, LevelFilter::OFF); - assert_eq!(dirs[5].in_span, None); - } - - #[test] - fn parse_numeric_level_directives() { - let dirs = parse_directives( - "crate1::mod1=1,crate1::mod2=2,crate1::mod2::mod3=3,crate2=4,\ - crate3=5,crate3::mod2::mod1=0", - ); - assert_eq!(dirs.len(), 6, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, None); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::WARN); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[2].target, Some("crate1::mod2::mod3".to_string())); - assert_eq!(dirs[2].level, LevelFilter::INFO); - assert_eq!(dirs[2].in_span, None); - - assert_eq!(dirs[3].target, Some("crate2".to_string())); - assert_eq!(dirs[3].level, LevelFilter::DEBUG); - assert_eq!(dirs[3].in_span, None); - - assert_eq!(dirs[4].target, Some("crate3".to_string())); - assert_eq!(dirs[4].level, LevelFilter::TRACE); - assert_eq!(dirs[4].in_span, None); - - assert_eq!(dirs[5].target, Some("crate3::mod2::mod1".to_string())); - assert_eq!(dirs[5].level, LevelFilter::OFF); - assert_eq!(dirs[5].in_span, None); - } - - #[test] - fn parse_directives_invalid_crate() { - // test parse_directives with multiple = in specification - let dirs = parse_directives("crate1::mod1=warn=info,crate2=debug"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::DEBUG); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_invalid_level() { - // test parse_directives with 'noNumber' as log level - let dirs = parse_directives("crate1::mod1=noNumber,crate2=debug"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::DEBUG); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_string_level() { - // test parse_directives with 'warn' as log level - let dirs = parse_directives("crate1::mod1=wrong,crate2=warn"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::WARN); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_empty_level() { - // test parse_directives with '' as log level - let dirs = parse_directives("crate1::mod1=wrong,crate2="); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::TRACE); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_global() { - // test parse_directives with no crate - let dirs = parse_directives("warn,crate2=debug"); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, None); - assert_eq!(dirs[0].level, LevelFilter::WARN); - assert_eq!(dirs[1].in_span, None); - - assert_eq!(dirs[1].target, Some("crate2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::DEBUG); - assert_eq!(dirs[1].in_span, None); - } - - // helper function for tests below - fn test_parse_bare_level(directive_to_test: &str, level_expected: LevelFilter) { - let dirs = parse_directives(directive_to_test); - assert_eq!( - dirs.len(), - 1, - "\ninput: \"{}\"; parsed: {:#?}", - directive_to_test, - dirs - ); - assert_eq!(dirs[0].target, None); - assert_eq!(dirs[0].level, level_expected); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_global_bare_warn_lc() { - // test parse_directives with no crate, in isolation, all lowercase - test_parse_bare_level("warn", LevelFilter::WARN); - } - - #[test] - fn parse_directives_global_bare_warn_uc() { - // test parse_directives with no crate, in isolation, all uppercase - test_parse_bare_level("WARN", LevelFilter::WARN); - } - - #[test] - fn parse_directives_global_bare_warn_mixed() { - // test parse_directives with no crate, in isolation, mixed case - test_parse_bare_level("wArN", LevelFilter::WARN); - } - - #[test] - fn parse_directives_valid_with_spans() { - let dirs = parse_directives("crate1::mod1[foo]=error,crate1::mod2[bar],crate2[baz]=debug"); - assert_eq!(dirs.len(), 3, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::ERROR); - assert_eq!(dirs[0].in_span, Some("foo".to_string())); - - assert_eq!(dirs[1].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::TRACE); - assert_eq!(dirs[1].in_span, Some("bar".to_string())); - - assert_eq!(dirs[2].target, Some("crate2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::DEBUG); - assert_eq!(dirs[2].in_span, Some("baz".to_string())); - } - - #[test] - fn parse_directives_with_dash_in_target_name() { - let dirs = parse_directives("target-name=info"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("target-name".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, None); - } - - #[test] - fn parse_directives_with_dash_in_span_name() { - // Reproduces https://github.com/tokio-rs/tracing/issues/1367 - - let dirs = parse_directives("target[span-name]=info"); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("target".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, Some("span-name".to_string())); - } - - #[test] - fn parse_directives_with_special_characters_in_span_name() { - let span_name = "!\"#$%&'()*+-./:;<=>?@^_`|~[}"; - - let dirs = parse_directives(format!("target[{}]=info", span_name)); - assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("target".to_string())); - assert_eq!(dirs[0].level, LevelFilter::INFO); - assert_eq!(dirs[0].in_span, Some(span_name.to_string())); - } - - #[test] - fn parse_directives_with_invalid_span_chars() { - let invalid_span_name = "]{"; - - let dirs = parse_directives(format!("target[{}]=info", invalid_span_name)); - assert_eq!(dirs.len(), 0, "\nparsed: {:#?}", dirs); - } -} diff --git a/vendor/tracing-subscriber/src/filter/env/field.rs b/vendor/tracing-subscriber/src/filter/env/field.rs deleted file mode 100644 index 1394fd04a..000000000 --- a/vendor/tracing-subscriber/src/filter/env/field.rs +++ /dev/null @@ -1,626 +0,0 @@ -use matchers::Pattern; -use std::{ - cmp::Ordering, - error::Error, - fmt::{self, Write}, - str::FromStr, - sync::{ - atomic::{AtomicBool, Ordering::*}, - Arc, - }, -}; - -use super::{FieldMap, LevelFilter}; -use tracing_core::field::{Field, Visit}; - -#[derive(Clone, Debug, Eq, PartialEq)] -pub(crate) struct Match { - pub(crate) name: String, // TODO: allow match patterns for names? - pub(crate) value: Option<ValueMatch>, -} - -#[derive(Debug, Eq, PartialEq)] -pub(crate) struct CallsiteMatch { - pub(crate) fields: FieldMap<ValueMatch>, - pub(crate) level: LevelFilter, -} - -#[derive(Debug)] -pub(crate) struct SpanMatch { - fields: FieldMap<(ValueMatch, AtomicBool)>, - level: LevelFilter, - has_matched: AtomicBool, -} - -pub(crate) struct MatchVisitor<'a> { - inner: &'a SpanMatch, -} - -#[derive(Debug, Clone)] -pub(crate) enum ValueMatch { - /// Matches a specific `bool` value. - Bool(bool), - /// Matches a specific `f64` value. - F64(f64), - /// Matches a specific `u64` value. - U64(u64), - /// Matches a specific `i64` value. - I64(i64), - /// Matches any `NaN` `f64` value. - NaN, - /// Matches any field whose `fmt::Debug` output is equal to a fixed string. - Debug(MatchDebug), - /// Matches any field whose `fmt::Debug` output matches a regular expression - /// pattern. - Pat(Box<MatchPattern>), -} - -impl Eq for ValueMatch {} - -impl PartialEq for ValueMatch { - fn eq(&self, other: &Self) -> bool { - use ValueMatch::*; - match (self, other) { - (Bool(a), Bool(b)) => a.eq(b), - (F64(a), F64(b)) => { - debug_assert!(!a.is_nan()); - debug_assert!(!b.is_nan()); - - a.eq(b) - } - (U64(a), U64(b)) => a.eq(b), - (I64(a), I64(b)) => a.eq(b), - (NaN, NaN) => true, - (Pat(a), Pat(b)) => a.eq(b), - _ => false, - } - } -} - -impl Ord for ValueMatch { - fn cmp(&self, other: &Self) -> Ordering { - use ValueMatch::*; - match (self, other) { - (Bool(this), Bool(that)) => this.cmp(that), - (Bool(_), _) => Ordering::Less, - - (F64(this), F64(that)) => this - .partial_cmp(that) - .expect("`ValueMatch::F64` may not contain `NaN` values"), - (F64(_), Bool(_)) => Ordering::Greater, - (F64(_), _) => Ordering::Less, - - (NaN, NaN) => Ordering::Equal, - (NaN, Bool(_)) | (NaN, F64(_)) => Ordering::Greater, - (NaN, _) => Ordering::Less, - - (U64(this), U64(that)) => this.cmp(that), - (U64(_), Bool(_)) | (U64(_), F64(_)) | (U64(_), NaN) => Ordering::Greater, - (U64(_), _) => Ordering::Less, - - (I64(this), I64(that)) => this.cmp(that), - (I64(_), Bool(_)) | (I64(_), F64(_)) | (I64(_), NaN) | (I64(_), U64(_)) => { - Ordering::Greater - } - (I64(_), _) => Ordering::Less, - - (Pat(this), Pat(that)) => this.cmp(that), - (Pat(_), _) => Ordering::Greater, - - (Debug(this), Debug(that)) => this.cmp(that), - (Debug(_), _) => Ordering::Greater, - } - } -} - -impl PartialOrd for ValueMatch { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -/// Matches a field's `fmt::Debug` output against a regular expression pattern. -/// -/// This is used for matching all non-literal field value filters when regular -/// expressions are enabled. -#[derive(Debug, Clone)] -pub(crate) struct MatchPattern { - pub(crate) matcher: Pattern, - pattern: Arc<str>, -} - -/// Matches a field's `fmt::Debug` output against a fixed string pattern. -/// -/// This is used for matching all non-literal field value filters when regular -/// expressions are disabled. -#[derive(Debug, Clone)] -pub(crate) struct MatchDebug { - pattern: Arc<str>, -} - -/// Indicates that a field name specified in a filter directive was invalid. -#[derive(Clone, Debug)] -#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))] -pub struct BadName { - name: String, -} - -// === impl Match === - -impl Match { - pub(crate) fn has_value(&self) -> bool { - self.value.is_some() - } - - // TODO: reference count these strings? - pub(crate) fn name(&self) -> String { - self.name.clone() - } - - pub(crate) fn parse(s: &str, regex: bool) -> Result<Self, Box<dyn Error + Send + Sync>> { - let mut parts = s.split('='); - let name = parts - .next() - .ok_or_else(|| BadName { - name: "".to_string(), - })? - // TODO: validate field name - .to_string(); - let value = parts - .next() - .map(|part| match regex { - true => ValueMatch::parse_regex(part), - false => Ok(ValueMatch::parse_non_regex(part)), - }) - .transpose()?; - Ok(Match { name, value }) - } -} - -impl fmt::Display for Match { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.name, f)?; - if let Some(ref value) = self.value { - write!(f, "={}", value)?; - } - Ok(()) - } -} - -impl Ord for Match { - fn cmp(&self, other: &Self) -> Ordering { - // Ordering for `Match` directives is based first on _whether_ a value - // is matched or not. This is semantically meaningful --- we would - // prefer to check directives that match values first as they are more - // specific. - let has_value = match (self.value.as_ref(), other.value.as_ref()) { - (Some(_), None) => Ordering::Greater, - (None, Some(_)) => Ordering::Less, - _ => Ordering::Equal, - }; - // If both directives match a value, we fall back to the field names in - // length + lexicographic ordering, and if these are equal as well, we - // compare the match directives. - // - // This ordering is no longer semantically meaningful but is necessary - // so that the directives can be stored in the `BTreeMap` in a defined - // order. - has_value - .then_with(|| self.name.cmp(&other.name)) - .then_with(|| self.value.cmp(&other.value)) - } -} - -impl PartialOrd for Match { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -// === impl ValueMatch === - -fn value_match_f64(v: f64) -> ValueMatch { - if v.is_nan() { - ValueMatch::NaN - } else { - ValueMatch::F64(v) - } -} - -impl ValueMatch { - /// Parse a `ValueMatch` that will match `fmt::Debug` fields using regular - /// expressions. - /// - /// This returns an error if the string didn't contain a valid `bool`, - /// `u64`, `i64`, or `f64` literal, and couldn't be parsed as a regular - /// expression. - fn parse_regex(s: &str) -> Result<Self, matchers::Error> { - s.parse::<bool>() - .map(ValueMatch::Bool) - .or_else(|_| s.parse::<u64>().map(ValueMatch::U64)) - .or_else(|_| s.parse::<i64>().map(ValueMatch::I64)) - .or_else(|_| s.parse::<f64>().map(value_match_f64)) - .or_else(|_| { - s.parse::<MatchPattern>() - .map(|p| ValueMatch::Pat(Box::new(p))) - }) - } - - /// Parse a `ValueMatch` that will match `fmt::Debug` against a fixed - /// string. - /// - /// This does *not* return an error, because any string that isn't a valid - /// `bool`, `u64`, `i64`, or `f64` literal is treated as expected - /// `fmt::Debug` output. - fn parse_non_regex(s: &str) -> Self { - s.parse::<bool>() - .map(ValueMatch::Bool) - .or_else(|_| s.parse::<u64>().map(ValueMatch::U64)) - .or_else(|_| s.parse::<i64>().map(ValueMatch::I64)) - .or_else(|_| s.parse::<f64>().map(value_match_f64)) - .unwrap_or_else(|_| ValueMatch::Debug(MatchDebug::new(s))) - } -} - -impl fmt::Display for ValueMatch { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ValueMatch::Bool(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::F64(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::NaN => fmt::Display::fmt(&std::f64::NAN, f), - ValueMatch::I64(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::U64(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::Debug(ref inner) => fmt::Display::fmt(inner, f), - ValueMatch::Pat(ref inner) => fmt::Display::fmt(inner, f), - } - } -} - -// === impl MatchPattern === - -impl FromStr for MatchPattern { - type Err = matchers::Error; - fn from_str(s: &str) -> Result<Self, Self::Err> { - let matcher = s.parse::<Pattern>()?; - Ok(Self { - matcher, - pattern: s.to_owned().into(), - }) - } -} - -impl fmt::Display for MatchPattern { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&*self.pattern, f) - } -} - -impl AsRef<str> for MatchPattern { - #[inline] - fn as_ref(&self) -> &str { - self.pattern.as_ref() - } -} - -impl MatchPattern { - #[inline] - fn str_matches(&self, s: &impl AsRef<str>) -> bool { - self.matcher.matches(s) - } - - #[inline] - fn debug_matches(&self, d: &impl fmt::Debug) -> bool { - self.matcher.debug_matches(d) - } - - pub(super) fn into_debug_match(self) -> MatchDebug { - MatchDebug { - pattern: self.pattern, - } - } -} - -impl PartialEq for MatchPattern { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.pattern == other.pattern - } -} - -impl Eq for MatchPattern {} - -impl PartialOrd for MatchPattern { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.pattern.cmp(&other.pattern)) - } -} - -impl Ord for MatchPattern { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - self.pattern.cmp(&other.pattern) - } -} - -// === impl MatchDebug === - -impl MatchDebug { - fn new(s: &str) -> Self { - Self { - pattern: s.to_owned().into(), - } - } - - #[inline] - fn debug_matches(&self, d: &impl fmt::Debug) -> bool { - // Naively, we would probably match a value's `fmt::Debug` output by - // formatting it to a string, and then checking if the string is equal - // to the expected pattern. However, this would require allocating every - // time we want to match a field value against a `Debug` matcher, which - // can be avoided. - // - // Instead, we implement `fmt::Write` for a type that, rather than - // actually _writing_ the strings to something, matches them against the - // expected pattern, and returns an error if the pattern does not match. - struct Matcher<'a> { - pattern: &'a str, - } - - impl fmt::Write for Matcher<'_> { - fn write_str(&mut self, s: &str) -> fmt::Result { - // If the string is longer than the remaining expected string, - // we know it won't match, so bail. - if s.len() > self.pattern.len() { - return Err(fmt::Error); - } - - // If the expected string begins with the string that was - // written, we are still potentially a match. Advance the - // position in the expected pattern to chop off the matched - // output, and continue. - if self.pattern.starts_with(s) { - self.pattern = &self.pattern[s.len()..]; - return Ok(()); - } - - // Otherwise, the expected string doesn't include the string - // that was written at the current position, so the `fmt::Debug` - // output doesn't match! Return an error signalling that this - // doesn't match. - Err(fmt::Error) - } - } - let mut matcher = Matcher { - pattern: &self.pattern, - }; - - // Try to "write" the value's `fmt::Debug` output to a `Matcher`. This - // returns an error if the `fmt::Debug` implementation wrote any - // characters that did not match the expected pattern. - write!(matcher, "{:?}", d).is_ok() - } -} - -impl fmt::Display for MatchDebug { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&*self.pattern, f) - } -} - -impl AsRef<str> for MatchDebug { - #[inline] - fn as_ref(&self) -> &str { - self.pattern.as_ref() - } -} - -impl PartialEq for MatchDebug { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.pattern == other.pattern - } -} - -impl Eq for MatchDebug {} - -impl PartialOrd for MatchDebug { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.pattern.cmp(&other.pattern)) - } -} - -impl Ord for MatchDebug { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - self.pattern.cmp(&other.pattern) - } -} - -// === impl BadName === - -impl Error for BadName {} - -impl fmt::Display for BadName { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "invalid field name `{}`", self.name) - } -} - -impl CallsiteMatch { - pub(crate) fn to_span_match(&self) -> SpanMatch { - let fields = self - .fields - .iter() - .map(|(k, v)| (k.clone(), (v.clone(), AtomicBool::new(false)))) - .collect(); - SpanMatch { - fields, - level: self.level, - has_matched: AtomicBool::new(false), - } - } -} - -impl SpanMatch { - pub(crate) fn visitor(&self) -> MatchVisitor<'_> { - MatchVisitor { inner: self } - } - - #[inline] - pub(crate) fn is_matched(&self) -> bool { - if self.has_matched.load(Acquire) { - return true; - } - self.is_matched_slow() - } - - #[inline(never)] - fn is_matched_slow(&self) -> bool { - let matched = self - .fields - .values() - .all(|(_, matched)| matched.load(Acquire)); - if matched { - self.has_matched.store(true, Release); - } - matched - } - - #[inline] - pub(crate) fn filter(&self) -> Option<LevelFilter> { - if self.is_matched() { - Some(self.level) - } else { - None - } - } -} - -impl<'a> Visit for MatchVisitor<'a> { - fn record_f64(&mut self, field: &Field, value: f64) { - match self.inner.fields.get(field) { - Some((ValueMatch::NaN, ref matched)) if value.is_nan() => { - matched.store(true, Release); - } - Some((ValueMatch::F64(ref e), ref matched)) - if (value - *e).abs() < std::f64::EPSILON => - { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_i64(&mut self, field: &Field, value: i64) { - use std::convert::TryInto; - - match self.inner.fields.get(field) { - Some((ValueMatch::I64(ref e), ref matched)) if value == *e => { - matched.store(true, Release); - } - Some((ValueMatch::U64(ref e), ref matched)) if Ok(value) == (*e).try_into() => { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_u64(&mut self, field: &Field, value: u64) { - match self.inner.fields.get(field) { - Some((ValueMatch::U64(ref e), ref matched)) if value == *e => { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_bool(&mut self, field: &Field, value: bool) { - match self.inner.fields.get(field) { - Some((ValueMatch::Bool(ref e), ref matched)) if value == *e => { - matched.store(true, Release); - } - _ => {} - } - } - - fn record_str(&mut self, field: &Field, value: &str) { - match self.inner.fields.get(field) { - Some((ValueMatch::Pat(ref e), ref matched)) if e.str_matches(&value) => { - matched.store(true, Release); - } - Some((ValueMatch::Debug(ref e), ref matched)) if e.debug_matches(&value) => { - matched.store(true, Release) - } - _ => {} - } - } - - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - match self.inner.fields.get(field) { - Some((ValueMatch::Pat(ref e), ref matched)) if e.debug_matches(&value) => { - matched.store(true, Release); - } - Some((ValueMatch::Debug(ref e), ref matched)) if e.debug_matches(&value) => { - matched.store(true, Release) - } - _ => {} - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[derive(Debug)] - #[allow(dead_code)] - struct MyStruct { - answer: usize, - question: &'static str, - } - - #[test] - fn debug_struct_match() { - let my_struct = MyStruct { - answer: 42, - question: "life, the universe, and everything", - }; - - let pattern = "MyStruct { answer: 42, question: \"life, the universe, and everything\" }"; - - assert_eq!( - format!("{:?}", my_struct), - pattern, - "`MyStruct`'s `Debug` impl doesn't output the expected string" - ); - - let matcher = MatchDebug { - pattern: pattern.into(), - }; - assert!(matcher.debug_matches(&my_struct)) - } - - #[test] - fn debug_struct_not_match() { - let my_struct = MyStruct { - answer: 42, - question: "what shall we have for lunch?", - }; - - let pattern = "MyStruct { answer: 42, question: \"life, the universe, and everything\" }"; - - assert_eq!( - format!("{:?}", my_struct), - "MyStruct { answer: 42, question: \"what shall we have for lunch?\" }", - "`MyStruct`'s `Debug` impl doesn't output the expected string" - ); - - let matcher = MatchDebug { - pattern: pattern.into(), - }; - assert!(!matcher.debug_matches(&my_struct)) - } -} diff --git a/vendor/tracing-subscriber/src/filter/env/mod.rs b/vendor/tracing-subscriber/src/filter/env/mod.rs deleted file mode 100644 index 81a9ae2bd..000000000 --- a/vendor/tracing-subscriber/src/filter/env/mod.rs +++ /dev/null @@ -1,991 +0,0 @@ -//! A `Layer` that enables or disables spans and events based on a set of -//! filtering directives. - -// these are publicly re-exported, but the compiler doesn't realize -// that for some reason. -#[allow(unreachable_pub)] -pub use self::{builder::Builder, directive::Directive, field::BadName as BadFieldName}; -mod builder; -mod directive; -mod field; - -use crate::{ - filter::LevelFilter, - layer::{Context, Layer}, - sync::RwLock, -}; -use directive::ParseError; -use std::{cell::RefCell, collections::HashMap, env, error::Error, fmt, str::FromStr}; -use thread_local::ThreadLocal; -use tracing_core::{ - callsite, - field::Field, - span, - subscriber::{Interest, Subscriber}, - Metadata, -}; - -/// A [`Layer`] which filters spans and events based on a set of filter -/// directives. -/// -/// `EnvFilter` implements both the [`Layer`](#impl-Layer<S>) and [`Filter`] traits, so it may -/// be used for both [global filtering][global] and [per-layer filtering][plf], -/// respectively. See [the documentation on filtering with `Layer`s][filtering] -/// for details. -/// -/// The [`Targets`] type implements a similar form of filtering, but without the -/// ability to dynamically enable events based on the current span context, and -/// without filtering on field values. When these features are not required, -/// [`Targets`] provides a lighter-weight alternative to [`EnvFilter`]. -/// -/// # Directives -/// -/// A filter consists of one or more comma-separated directives which match on [`Span`]s and [`Event`]s. -/// Each directive may have a corresponding maximum verbosity [`level`] which -/// enables (e.g., _selects for_) spans and events that match. Like `log`, -/// `tracing` considers less exclusive levels (like `trace` or `info`) to be more -/// verbose than more exclusive levels (like `error` or `warn`). -/// -/// The directive syntax is similar to that of [`env_logger`]'s. At a high level, the syntax for directives -/// consists of several parts: -/// -/// ```text -/// target[span{field=value}]=level -/// ``` -/// -/// Each component (`target`, `span`, `field`, `value`, and `level`) will be covered in turn. -/// -/// - `target` matches the event or span's target. In general, this is the module path and/or crate name. -/// Examples of targets `h2`, `tokio::net`, or `tide::server`. For more information on targets, -/// please refer to [`Metadata`]'s documentation. -/// - `span` matches on the span's name. If a `span` directive is provided alongside a `target`, -/// the `span` directive will match on spans _within_ the `target`. -/// - `field` matches on [fields] within spans. Field names can also be supplied without a `value` -/// and will match on any [`Span`] or [`Event`] that has a field with that name. -/// For example: `[span{field=\"value\"}]=debug`, `[{field}]=trace`. -/// - `value` matches on the value of a span's field. If a value is a numeric literal or a bool, -/// it will match _only_ on that value. Otherwise, this filter matches the -/// [`std::fmt::Debug`] output from the value. -/// - `level` sets a maximum verbosity level accepted by this directive. -/// -/// When a field value directive (`[{<FIELD NAME>=<FIELD_VALUE>}]=...`) matches a -/// value's [`std::fmt::Debug`] output (i.e., the field value in the directive -/// is not a `bool`, `i64`, `u64`, or `f64` literal), the matched pattern may be -/// interpreted as either a regular expression or as the precise expected -/// output of the field's [`std::fmt::Debug`] implementation. By default, these -/// filters are interpreted as regular expressions, but this can be disabled -/// using the [`Builder::with_regex`] builder method to use precise matching -/// instead. -/// -/// When field value filters are interpreted as regular expressions, the -/// [`regex-automata` crate's regular expression syntax][re-syntax] is -/// supported. -/// -/// **Note**: When filters are constructed from potentially untrusted inputs, -/// [disabling regular expression matching](Builder::with_regex) is strongly -/// recommended. -/// -/// ## Usage Notes -/// -/// - The portion of the directive which is included within the square brackets is `tracing`-specific. -/// - Any portion of the directive can be omitted. -/// - The sole exception are the `field` and `value` directives. If a `value` is provided, -/// a `field` must _also_ be provided. However, the converse does not hold, as fields can -/// be matched without a value. -/// - If only a level is provided, it will set the maximum level for all `Span`s and `Event`s -/// that are not enabled by other filters. -/// - A directive without a level will enable anything that it matches. This is equivalent to `=trace`. -/// - When a crate has a dash in its name, the default target for events will be the -/// crate's module path as it appears in Rust. This means every dash will be replaced -/// with an underscore. -/// - A dash in a target will only appear when being specified explicitly: -/// `tracing::info!(target: "target-name", ...);` -/// -/// ## Example Syntax -/// -/// - `tokio::net=info` will enable all spans or events that: -/// - have the `tokio::net` target, -/// - at the level `info` or above. -/// - `warn,tokio::net=info` will enable all spans and events that: -/// - are at the level `warn` or above, *or* -/// - have the `tokio::net` target at the level `info` or above. -/// - `my_crate[span_a]=trace` will enable all spans and events that: -/// - are within the `span_a` span or named `span_a` _if_ `span_a` has the target `my_crate`, -/// - at the level `trace` or above. -/// - `[span_b{name=\"bob\"}]` will enable all spans or event that: -/// - have _any_ target, -/// - are inside a span named `span_b`, -/// - which has a field named `name` with value `bob`, -/// - at _any_ level. -/// -/// # Examples -/// -/// Parsing an `EnvFilter` from the [default environment -/// variable](EnvFilter::from_default_env) (`RUST_LOG`): -/// -/// ``` -/// use tracing_subscriber::{EnvFilter, fmt, prelude::*}; -/// -/// tracing_subscriber::registry() -/// .with(fmt::layer()) -/// .with(EnvFilter::from_default_env()) -/// .init(); -/// ``` -/// -/// Parsing an `EnvFilter` [from a user-provided environment -/// variable](EnvFilter::from_env): -/// -/// ``` -/// use tracing_subscriber::{EnvFilter, fmt, prelude::*}; -/// -/// tracing_subscriber::registry() -/// .with(fmt::layer()) -/// .with(EnvFilter::from_env("MYAPP_LOG")) -/// .init(); -/// ``` -/// -/// Using `EnvFilter` as a [per-layer filter][plf] to filter only a single -/// [`Layer`]: -/// -/// ``` -/// use tracing_subscriber::{EnvFilter, fmt, prelude::*}; -/// -/// // Parse an `EnvFilter` configuration from the `RUST_LOG` -/// // environment variable. -/// let filter = EnvFilter::from_default_env(); -/// -/// // Apply the filter to this layer *only*. -/// let filtered_layer = fmt::layer().with_filter(filter); -/// -/// // Some other layer, whose output we don't want to filter. -/// let unfiltered_layer = // ... -/// # fmt::layer(); -/// -/// tracing_subscriber::registry() -/// .with(filtered_layer) -/// .with(unfiltered_layer) -/// .init(); -/// ``` -/// # Constructing `EnvFilter`s -/// -/// An `EnvFilter` is be constructed by parsing a string containing one or more -/// directives. The [`EnvFilter::new`] constructor parses an `EnvFilter` from a -/// string, ignoring any invalid directives, while [`EnvFilter::try_new`] -/// returns an error if invalid directives are encountered. Similarly, the -/// [`EnvFilter::from_env`] and [`EnvFilter::try_from_env`] constructors parse -/// an `EnvFilter` from the value of the provided environment variable, with -/// lossy and strict validation, respectively. -/// -/// A [builder](EnvFilter::builder) interface is available to set additional -/// configuration options prior to parsing an `EnvFilter`. See the [`Builder` -/// type's documentation](Builder) for details on the options that can be -/// configured using the builder. -/// -/// [`Span`]: tracing_core::span -/// [fields]: tracing_core::Field -/// [`Event`]: tracing_core::Event -/// [`level`]: tracing_core::Level -/// [`Metadata`]: tracing_core::Metadata -/// [`Targets`]: crate::filter::Targets -/// [`env_logger`]: https://crates.io/crates/env_logger -/// [`Filter`]: #impl-Filter<S> -/// [global]: crate::layer#global-filtering -/// [plf]: crate::layer#per-layer-filtering -/// [filtering]: crate::layer#filtering-with-layers -#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))] -#[derive(Debug)] -pub struct EnvFilter { - statics: directive::Statics, - dynamics: directive::Dynamics, - has_dynamics: bool, - by_id: RwLock<HashMap<span::Id, directive::SpanMatcher>>, - by_cs: RwLock<HashMap<callsite::Identifier, directive::CallsiteMatcher>>, - scope: ThreadLocal<RefCell<Vec<LevelFilter>>>, - regex: bool, -} - -type FieldMap<T> = HashMap<Field, T>; - -/// Indicates that an error occurred while parsing a `EnvFilter` from an -/// environment variable. -#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))] -#[derive(Debug)] -pub struct FromEnvError { - kind: ErrorKind, -} - -#[derive(Debug)] -enum ErrorKind { - Parse(ParseError), - Env(env::VarError), -} - -impl EnvFilter { - /// `RUST_LOG` is the default environment variable used by - /// [`EnvFilter::from_default_env`] and [`EnvFilter::try_from_default_env`]. - /// - /// [`EnvFilter::from_default_env`]: EnvFilter::from_default_env() - /// [`EnvFilter::try_from_default_env`]: EnvFilter::try_from_default_env() - pub const DEFAULT_ENV: &'static str = "RUST_LOG"; - - // === constructors, etc === - - /// Returns a [builder] that can be used to configure a new [`EnvFilter`] - /// instance. - /// - /// The [`Builder`] type is used to set additional configurations, such as - /// [whether regular expressions are enabled](Builder::with_regex) or [the - /// default directive](Builder::with_default_directive) before parsing an - /// [`EnvFilter`] from a string or environment variable. - /// - /// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html - pub fn builder() -> Builder { - Builder::default() - } - - /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment - /// variable, ignoring any invalid filter directives. - /// - /// If the environment variable is empty or not set, or if it contains only - /// invalid directives, a default directive enabling the [`ERROR`] level is - /// added. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// # fn docs() -> EnvFilter { - /// EnvFilter::builder() - /// .with_default_directive(LevelFilter::ERROR.into()) - /// .from_env_lossy() - /// # } - /// ``` - /// - /// [`ERROR`]: tracing::Level::ERROR - pub fn from_default_env() -> Self { - Self::builder() - .with_default_directive(LevelFilter::ERROR.into()) - .from_env_lossy() - } - - /// Returns a new `EnvFilter` from the value of the given environment - /// variable, ignoring any invalid filter directives. - /// - /// If the environment variable is empty or not set, or if it contains only - /// invalid directives, a default directive enabling the [`ERROR`] level is - /// added. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// # fn docs() -> EnvFilter { - /// # let env = ""; - /// EnvFilter::builder() - /// .with_default_directive(LevelFilter::ERROR.into()) - /// .with_env_var(env) - /// .from_env_lossy() - /// # } - /// ``` - /// - /// [`ERROR`]: tracing::Level::ERROR - pub fn from_env<A: AsRef<str>>(env: A) -> Self { - Self::builder() - .with_default_directive(LevelFilter::ERROR.into()) - .with_env_var(env.as_ref()) - .from_env_lossy() - } - - /// Returns a new `EnvFilter` from the directives in the given string, - /// ignoring any that are invalid. - /// - /// If the string is empty or contains only invalid directives, a default - /// directive enabling the [`ERROR`] level is added. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// # fn docs() -> EnvFilter { - /// # let directives = ""; - /// EnvFilter::builder() - /// .with_default_directive(LevelFilter::ERROR.into()) - /// .parse_lossy(directives) - /// # } - /// ``` - /// - /// [`ERROR`]: tracing::Level::ERROR - pub fn new<S: AsRef<str>>(directives: S) -> Self { - Self::builder() - .with_default_directive(LevelFilter::ERROR.into()) - .parse_lossy(directives) - } - - /// Returns a new `EnvFilter` from the directives in the given string, - /// or an error if any are invalid. - /// - /// If the string is empty, a default directive enabling the [`ERROR`] level - /// is added. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::ParseError> { - /// # let directives = ""; - /// EnvFilter::builder() - /// .with_default_directive(LevelFilter::ERROR.into()) - /// .parse(directives) - /// # } - /// ``` - /// - /// [`ERROR`]: tracing::Level::ERROR - pub fn try_new<S: AsRef<str>>(dirs: S) -> Result<Self, directive::ParseError> { - Self::builder().parse(dirs) - } - - /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment - /// variable, or an error if the environment variable is unset or contains - /// any invalid filter directives. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::EnvFilter; - /// - /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> { - /// EnvFilter::builder().try_from_env() - /// # } - /// ``` - pub fn try_from_default_env() -> Result<Self, FromEnvError> { - Self::builder().try_from_env() - } - - /// Returns a new `EnvFilter` from the value of the given environment - /// variable, or an error if the environment variable is unset or contains - /// any invalid filter directives. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::EnvFilter; - /// - /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> { - /// # let env = ""; - /// EnvFilter::builder().with_env_var(env).try_from_env() - /// # } - /// ``` - pub fn try_from_env<A: AsRef<str>>(env: A) -> Result<Self, FromEnvError> { - Self::builder().with_env_var(env.as_ref()).try_from_env() - } - - /// Add a filtering directive to this `EnvFilter`. - /// - /// The added directive will be used in addition to any previously set - /// directives, either added using this method or provided when the filter - /// is constructed. - /// - /// Filters may be created from [`LevelFilter`] or [`Level`], which will - /// enable all traces at or below a certain verbosity level, or - /// parsed from a string specifying a directive. - /// - /// If a filter directive is inserted that matches exactly the same spans - /// and events as a previous filter, but sets a different level for those - /// spans and events, the previous directive is overwritten. - /// - /// [`LevelFilter`]: super::LevelFilter - /// [`Level`]: tracing_core::Level - /// - /// # Examples - /// - /// From [`LevelFilter`]: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// let mut filter = EnvFilter::from_default_env() - /// .add_directive(LevelFilter::INFO.into()); - /// ``` - /// - /// Or from [`Level`]: - /// - /// ```rust - /// # use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// # use tracing::Level; - /// let mut filter = EnvFilter::from_default_env() - /// .add_directive(Level::INFO.into()); - /// ``` - /// - /// Parsed from a string: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, Directive}; - /// - /// # fn try_mk_filter() -> Result<(), Box<dyn ::std::error::Error>> { - /// let mut filter = EnvFilter::try_from_default_env()? - /// .add_directive("my_crate::module=trace".parse()?) - /// .add_directive("my_crate::my_other_module::something=info".parse()?); - /// # Ok(()) - /// # } - /// ``` - /// In the above example, substitute `my_crate`, `module`, etc. with the - /// name your target crate/module is imported with. This might be - /// different from the package name in Cargo.toml (`-` is replaced by `_`). - /// Example, if the package name in your Cargo.toml is `MY-FANCY-LIB`, then - /// the corresponding Rust identifier would be `MY_FANCY_LIB`: - pub fn add_directive(mut self, mut directive: Directive) -> Self { - if !self.regex { - directive.deregexify(); - } - if let Some(stat) = directive.to_static() { - self.statics.add(stat) - } else { - self.has_dynamics = true; - self.dynamics.add(directive); - } - self - } - - // === filtering methods === - - /// Returns `true` if this `EnvFilter` would enable the provided `metadata` - /// in the current context. - /// - /// This is equivalent to calling the [`Layer::enabled`] or - /// [`Filter::enabled`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn enabled<S>(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { - let level = metadata.level(); - - // is it possible for a dynamic filter directive to enable this event? - // if not, we can avoid the thread loca'l access + iterating over the - // spans in the current scope. - if self.has_dynamics && self.dynamics.max_level >= *level { - if metadata.is_span() { - // If the metadata is a span, see if we care about its callsite. - let enabled_by_cs = self - .by_cs - .read() - .ok() - .map(|by_cs| by_cs.contains_key(&metadata.callsite())) - .unwrap_or(false); - if enabled_by_cs { - return true; - } - } - - let enabled_by_scope = { - let scope = self.scope.get_or_default().borrow(); - for filter in &*scope { - if filter >= level { - return true; - } - } - false - }; - if enabled_by_scope { - return true; - } - } - - // is it possible for a static filter directive to enable this event? - if self.statics.max_level >= *level { - // Otherwise, fall back to checking if the callsite is - // statically enabled. - return self.statics.enabled(metadata); - } - - false - } - - /// Returns an optional hint of the highest [verbosity level][level] that - /// this `EnvFilter` will enable. - /// - /// This is equivalent to calling the [`Layer::max_level_hint`] or - /// [`Filter::max_level_hint`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - /// - /// [level]: tracing_core::metadata::Level - pub fn max_level_hint(&self) -> Option<LevelFilter> { - if self.dynamics.has_value_filters() { - // If we perform any filtering on span field *values*, we will - // enable *all* spans, because their field values are not known - // until recording. - return Some(LevelFilter::TRACE); - } - std::cmp::max( - self.statics.max_level.into(), - self.dynamics.max_level.into(), - ) - } - - /// Informs the filter that a new span was created. - /// - /// This is equivalent to calling the [`Layer::on_new_span`] or - /// [`Filter::on_new_span`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn on_new_span<S>(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) { - let by_cs = try_lock!(self.by_cs.read()); - if let Some(cs) = by_cs.get(&attrs.metadata().callsite()) { - let span = cs.to_span_match(attrs); - try_lock!(self.by_id.write()).insert(id.clone(), span); - } - } - - /// Informs the filter that the span with the provided `id` was entered. - /// - /// This is equivalent to calling the [`Layer::on_enter`] or - /// [`Filter::on_enter`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn on_enter<S>(&self, id: &span::Id, _: Context<'_, S>) { - // XXX: This is where _we_ could push IDs to the stack instead, and use - // that to allow changing the filter while a span is already entered. - // But that might be much less efficient... - if let Some(span) = try_lock!(self.by_id.read()).get(id) { - self.scope.get_or_default().borrow_mut().push(span.level()); - } - } - - /// Informs the filter that the span with the provided `id` was exited. - /// - /// This is equivalent to calling the [`Layer::on_exit`] or - /// [`Filter::on_exit`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn on_exit<S>(&self, id: &span::Id, _: Context<'_, S>) { - if self.cares_about_span(id) { - self.scope.get_or_default().borrow_mut().pop(); - } - } - - /// Informs the filter that the span with the provided `id` was closed. - /// - /// This is equivalent to calling the [`Layer::on_close`] or - /// [`Filter::on_close`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn on_close<S>(&self, id: span::Id, _: Context<'_, S>) { - // If we don't need to acquire a write lock, avoid doing so. - if !self.cares_about_span(&id) { - return; - } - - let mut spans = try_lock!(self.by_id.write()); - spans.remove(&id); - } - - /// Informs the filter that the span with the provided `id` recorded the - /// provided field `values`. - /// - /// This is equivalent to calling the [`Layer::on_record`] or - /// [`Filter::on_record`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope - pub fn on_record<S>(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) { - if let Some(span) = try_lock!(self.by_id.read()).get(id) { - span.record_update(values); - } - } - - fn cares_about_span(&self, span: &span::Id) -> bool { - let spans = try_lock!(self.by_id.read(), else return false); - spans.contains_key(span) - } - - fn base_interest(&self) -> Interest { - if self.has_dynamics { - Interest::sometimes() - } else { - Interest::never() - } - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - if self.has_dynamics && metadata.is_span() { - // If this metadata describes a span, first, check if there is a - // dynamic filter that should be constructed for it. If so, it - // should always be enabled, since it influences filtering. - if let Some(matcher) = self.dynamics.matcher(metadata) { - let mut by_cs = try_lock!(self.by_cs.write(), else return self.base_interest()); - by_cs.insert(metadata.callsite(), matcher); - return Interest::always(); - } - } - - // Otherwise, check if any of our static filters enable this metadata. - if self.statics.enabled(metadata) { - Interest::always() - } else { - self.base_interest() - } - } -} - -impl<S: Subscriber> Layer<S> for EnvFilter { - #[inline] - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - EnvFilter::register_callsite(self, metadata) - } - - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - EnvFilter::max_level_hint(self) - } - - #[inline] - fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { - self.enabled(metadata, ctx) - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - self.on_new_span(attrs, id, ctx) - } - - #[inline] - fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - self.on_record(id, values, ctx); - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - self.on_enter(id, ctx); - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - self.on_exit(id, ctx); - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - self.on_close(id, ctx); - } -} - -feature! { - #![all(feature = "registry", feature = "std")] - use crate::layer::Filter; - - impl<S> Filter<S> for EnvFilter { - #[inline] - fn enabled(&self, meta: &Metadata<'_>, ctx: &Context<'_, S>) -> bool { - self.enabled(meta, ctx.clone()) - } - - #[inline] - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - self.register_callsite(meta) - } - - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - EnvFilter::max_level_hint(self) - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - self.on_new_span(attrs, id, ctx) - } - - #[inline] - fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - self.on_record(id, values, ctx); - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - self.on_enter(id, ctx); - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - self.on_exit(id, ctx); - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - self.on_close(id, ctx); - } - } -} - -impl FromStr for EnvFilter { - type Err = directive::ParseError; - - fn from_str(spec: &str) -> Result<Self, Self::Err> { - Self::try_new(spec) - } -} - -impl<S> From<S> for EnvFilter -where - S: AsRef<str>, -{ - fn from(s: S) -> Self { - Self::new(s) - } -} - -impl Default for EnvFilter { - fn default() -> Self { - Builder::default().from_directives(std::iter::empty()) - } -} - -impl fmt::Display for EnvFilter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut statics = self.statics.iter(); - let wrote_statics = if let Some(next) = statics.next() { - fmt::Display::fmt(next, f)?; - for directive in statics { - write!(f, ",{}", directive)?; - } - true - } else { - false - }; - - let mut dynamics = self.dynamics.iter(); - if let Some(next) = dynamics.next() { - if wrote_statics { - f.write_str(",")?; - } - fmt::Display::fmt(next, f)?; - for directive in dynamics { - write!(f, ",{}", directive)?; - } - } - Ok(()) - } -} - -// ===== impl FromEnvError ===== - -impl From<directive::ParseError> for FromEnvError { - fn from(p: directive::ParseError) -> Self { - Self { - kind: ErrorKind::Parse(p), - } - } -} - -impl From<env::VarError> for FromEnvError { - fn from(v: env::VarError) -> Self { - Self { - kind: ErrorKind::Env(v), - } - } -} - -impl fmt::Display for FromEnvError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - ErrorKind::Parse(ref p) => p.fmt(f), - ErrorKind::Env(ref e) => e.fmt(f), - } - } -} - -impl Error for FromEnvError { - fn source(&self) -> Option<&(dyn Error + 'static)> { - match self.kind { - ErrorKind::Parse(ref p) => Some(p), - ErrorKind::Env(ref e) => Some(e), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use tracing_core::field::FieldSet; - use tracing_core::*; - - struct NoSubscriber; - impl Subscriber for NoSubscriber { - #[inline] - fn register_callsite(&self, _: &'static Metadata<'static>) -> subscriber::Interest { - subscriber::Interest::always() - } - fn new_span(&self, _: &span::Attributes<'_>) -> span::Id { - span::Id::from_u64(0xDEAD) - } - fn event(&self, _event: &Event<'_>) {} - fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {} - fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {} - - #[inline] - fn enabled(&self, _metadata: &Metadata<'_>) -> bool { - true - } - fn enter(&self, _span: &span::Id) {} - fn exit(&self, _span: &span::Id) {} - } - - struct Cs; - impl Callsite for Cs { - fn set_interest(&self, _interest: Interest) {} - fn metadata(&self) -> &Metadata<'_> { - unimplemented!() - } - } - - #[test] - fn callsite_enabled_no_span_directive() { - let filter = EnvFilter::new("app=debug").with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::TRACE, - None, - None, - None, - FieldSet::new(&[], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_never()); - } - - #[test] - fn callsite_off() { - let filter = EnvFilter::new("app=off").with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::ERROR, - None, - None, - None, - FieldSet::new(&[], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_never()); - } - - #[test] - fn callsite_enabled_includes_span_directive() { - let filter = EnvFilter::new("app[mySpan]=debug").with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::TRACE, - None, - None, - None, - FieldSet::new(&[], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_always()); - } - - #[test] - fn callsite_enabled_includes_span_directive_field() { - let filter = - EnvFilter::new("app[mySpan{field=\"value\"}]=debug").with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::TRACE, - None, - None, - None, - FieldSet::new(&["field"], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_always()); - } - - #[test] - fn callsite_enabled_includes_span_directive_multiple_fields() { - let filter = EnvFilter::new("app[mySpan{field=\"value\",field2=2}]=debug") - .with_subscriber(NoSubscriber); - static META: &Metadata<'static> = &Metadata::new( - "mySpan", - "app", - Level::TRACE, - None, - None, - None, - FieldSet::new(&["field"], identify_callsite!(&Cs)), - Kind::SPAN, - ); - - let interest = filter.register_callsite(META); - assert!(interest.is_never()); - } - - #[test] - fn roundtrip() { - let f1: EnvFilter = - "[span1{foo=1}]=error,[span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug" - .parse() - .unwrap(); - let f2: EnvFilter = format!("{}", f1).parse().unwrap(); - assert_eq!(f1.statics, f2.statics); - assert_eq!(f1.dynamics, f2.dynamics); - } - - #[test] - fn size_of_filters() { - fn print_sz(s: &str) { - let filter = s.parse::<EnvFilter>().expect("filter should parse"); - println!( - "size_of_val({:?})\n -> {}B", - s, - std::mem::size_of_val(&filter) - ); - } - - print_sz("info"); - - print_sz("foo=debug"); - - print_sz( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off", - ); - - print_sz("[span1{foo=1}]=error,[span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug"); - - print_sz( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off,[span1{foo=1}]=error,\ - [span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug", - ); - } - - #[test] - fn parse_empty_string() { - // There is no corresponding test for [`Builder::parse_lossy`] as failed - // parsing does not produce any observable side effects. If this test fails - // check that [`Builder::parse_lossy`] is behaving correctly as well. - assert!(EnvFilter::builder().parse("").is_ok()); - } -} diff --git a/vendor/tracing-subscriber/src/filter/filter_fn.rs b/vendor/tracing-subscriber/src/filter/filter_fn.rs deleted file mode 100644 index 332bf860a..000000000 --- a/vendor/tracing-subscriber/src/filter/filter_fn.rs +++ /dev/null @@ -1,749 +0,0 @@ -use crate::{ - filter::LevelFilter, - layer::{Context, Layer}, -}; -use core::{any::type_name, fmt, marker::PhantomData}; -use tracing_core::{Interest, Metadata, Subscriber}; - -/// A filter implemented by a closure or function pointer that -/// determines whether a given span or event is enabled, based on its -/// [`Metadata`]. -/// -/// This type can be used for both [per-layer filtering][plf] (using its -/// [`Filter`] implementation) and [global filtering][global] (using its -/// [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// [`Metadata`]: tracing_core::Metadata -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -#[derive(Clone)] -pub struct FilterFn<F = fn(&Metadata<'_>) -> bool> { - enabled: F, - max_level_hint: Option<LevelFilter>, -} - -/// A filter implemented by a closure or function pointer that -/// determines whether a given span or event is enabled _dynamically_, -/// potentially based on the current [span context]. -/// -/// This type can be used for both [per-layer filtering][plf] (using its -/// [`Filter`] implementation) and [global filtering][global] (using its -/// [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// [span context]: crate::layer::Context -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -pub struct DynFilterFn< - S, - // TODO(eliza): should these just be boxed functions? - F = fn(&Metadata<'_>, &Context<'_, S>) -> bool, - R = fn(&'static Metadata<'static>) -> Interest, -> { - enabled: F, - register_callsite: Option<R>, - max_level_hint: Option<LevelFilter>, - _s: PhantomData<fn(S)>, -} - -// === impl FilterFn === - -/// Constructs a [`FilterFn`], from a function or closure that returns `true` if -/// a span or event should be enabled, based on its [`Metadata`]. -/// -/// The returned [`FilterFn`] can be used for both [per-layer filtering][plf] -/// (using its [`Filter`] implementation) and [global filtering][global] (using -/// its [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// This is equivalent to calling [`FilterFn::new`]. -/// -/// [`Metadata`]: tracing_core::Metadata -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -/// -/// # Examples -/// -/// ``` -/// use tracing_subscriber::{ -/// layer::{Layer, SubscriberExt}, -/// filter, -/// util::SubscriberInitExt, -/// }; -/// -/// let my_filter = filter::filter_fn(|metadata| { -/// // Only enable spans or events with the target "interesting_things" -/// metadata.target() == "interesting_things" -/// }); -/// -/// let my_layer = tracing_subscriber::fmt::layer(); -/// -/// tracing_subscriber::registry() -/// .with(my_layer.with_filter(my_filter)) -/// .init(); -/// -/// // This event will not be enabled. -/// tracing::warn!("something important but uninteresting happened!"); -/// -/// // This event will be enabled. -/// tracing::debug!(target: "interesting_things", "an interesting minor detail..."); -/// ``` -pub fn filter_fn<F>(f: F) -> FilterFn<F> -where - F: Fn(&Metadata<'_>) -> bool, -{ - FilterFn::new(f) -} - -/// Constructs a [`DynFilterFn`] from a function or closure that returns `true` -/// if a span or event should be enabled within a particular [span context][`Context`]. -/// -/// This is equivalent to calling [`DynFilterFn::new`]. -/// -/// Unlike [`filter_fn`], this function takes a closure or function pointer -/// taking the [`Metadata`] for a span or event *and* the current [`Context`]. -/// This means that a [`DynFilterFn`] can choose whether to enable spans or -/// events based on information about the _current_ span (or its parents). -/// -/// If this is *not* necessary, use [`filter_fn`] instead. -/// -/// The returned [`DynFilterFn`] can be used for both [per-layer filtering][plf] -/// (using its [`Filter`] implementation) and [global filtering][global] (using -/// its [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// # Examples -/// -/// ``` -/// use tracing_subscriber::{ -/// layer::{Layer, SubscriberExt}, -/// filter, -/// util::SubscriberInitExt, -/// }; -/// -/// // Only enable spans or events within a span named "interesting_span". -/// let my_filter = filter::dynamic_filter_fn(|metadata, cx| { -/// // If this *is* "interesting_span", make sure to enable it. -/// if metadata.is_span() && metadata.name() == "interesting_span" { -/// return true; -/// } -/// -/// // Otherwise, are we in an interesting span? -/// if let Some(current_span) = cx.lookup_current() { -/// return current_span.name() == "interesting_span"; -/// } -/// -/// false -/// }); -/// -/// let my_layer = tracing_subscriber::fmt::layer(); -/// -/// tracing_subscriber::registry() -/// .with(my_layer.with_filter(my_filter)) -/// .init(); -/// -/// // This event will not be enabled. -/// tracing::info!("something happened"); -/// -/// tracing::info_span!("interesting_span").in_scope(|| { -/// // This event will be enabled. -/// tracing::debug!("something else happened"); -/// }); -/// ``` -/// -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -/// [`Context`]: crate::layer::Context -/// [`Metadata`]: tracing_core::Metadata -pub fn dynamic_filter_fn<S, F>(f: F) -> DynFilterFn<S, F> -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, -{ - DynFilterFn::new(f) -} - -impl<F> FilterFn<F> -where - F: Fn(&Metadata<'_>) -> bool, -{ - /// Constructs a [`FilterFn`] from a function or closure that returns `true` - /// if a span or event should be enabled, based on its [`Metadata`]. - /// - /// If determining whether a span or event should be enabled also requires - /// information about the current span context, use [`DynFilterFn`] instead. - /// - /// See the [documentation on per-layer filtering][plf] for details on using - /// [`Filter`]s. - /// - /// [`Filter`]: crate::layer::Filter - /// [plf]: crate::layer#per-layer-filtering - /// [`Metadata`]: tracing_core::Metadata - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::FilterFn, - /// util::SubscriberInitExt, - /// }; - /// - /// let my_filter = FilterFn::new(|metadata| { - /// // Only enable spans or events with the target "interesting_things" - /// metadata.target() == "interesting_things" - /// }); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// - /// // This event will not be enabled. - /// tracing::warn!("something important but uninteresting happened!"); - /// - /// // This event will be enabled. - /// tracing::debug!(target: "interesting_things", "an interesting minor detail..."); - /// ``` - pub fn new(enabled: F) -> Self { - Self { - enabled, - max_level_hint: None, - } - } - - /// Sets the highest verbosity [`Level`] the filter function will enable. - /// - /// The value passed to this method will be returned by this `FilterFn`'s - /// [`Filter::max_level_hint`] method. - /// - /// If the provided function will not enable all levels, it is recommended - /// to call this method to configure it with the most verbose level it will - /// enable. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::{filter_fn, LevelFilter}, - /// util::SubscriberInitExt, - /// }; - /// use tracing_core::Level; - /// - /// let my_filter = filter_fn(|metadata| { - /// // Only enable spans or events with targets starting with `my_crate` - /// // and levels at or below `INFO`. - /// metadata.level() <= &Level::INFO && metadata.target().starts_with("my_crate") - /// }) - /// // Since the filter closure will only enable the `INFO` level and - /// // below, set the max level hint - /// .with_max_level_hint(LevelFilter::INFO); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// ``` - /// - /// [`Level`]: tracing_core::Level - /// [`Filter::max_level_hint`]: crate::layer::Filter::max_level_hint - pub fn with_max_level_hint(self, max_level_hint: impl Into<LevelFilter>) -> Self { - Self { - max_level_hint: Some(max_level_hint.into()), - ..self - } - } - - #[inline] - pub(in crate::filter) fn is_enabled(&self, metadata: &Metadata<'_>) -> bool { - let enabled = (self.enabled)(metadata); - debug_assert!( - !enabled || self.is_below_max_level(metadata), - "FilterFn<{}> claimed it would only enable {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::<F>(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - - enabled - } - - #[inline] - pub(in crate::filter) fn is_callsite_enabled( - &self, - metadata: &'static Metadata<'static>, - ) -> Interest { - // Because `self.enabled` takes a `Metadata` only (and no `Context` - // parameter), we can reasonably assume its results are cachable, and - // just return `Interest::always`/`Interest::never`. - if (self.enabled)(metadata) { - debug_assert!( - self.is_below_max_level(metadata), - "FilterFn<{}> claimed it was only interested in {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::<F>(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - return Interest::always(); - } - - Interest::never() - } - - fn is_below_max_level(&self, metadata: &Metadata<'_>) -> bool { - self.max_level_hint - .as_ref() - .map(|hint| metadata.level() <= hint) - .unwrap_or(true) - } -} - -impl<S, F> Layer<S> for FilterFn<F> -where - F: Fn(&Metadata<'_>) -> bool + 'static, - S: Subscriber, -{ - fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { - self.is_enabled(metadata) - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.is_callsite_enabled(metadata) - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - self.max_level_hint - } -} - -impl<F> From<F> for FilterFn<F> -where - F: Fn(&Metadata<'_>) -> bool, -{ - fn from(enabled: F) -> Self { - Self::new(enabled) - } -} - -impl<F> fmt::Debug for FilterFn<F> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FilterFn") - .field("enabled", &format_args!("{}", type_name::<F>())) - .field("max_level_hint", &self.max_level_hint) - .finish() - } -} - -// === impl DynFilterFn == - -impl<S, F> DynFilterFn<S, F> -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, -{ - /// Constructs a [`Filter`] from a function or closure that returns `true` - /// if a span or event should be enabled in the current [span - /// context][`Context`]. - /// - /// Unlike [`FilterFn`], a `DynFilterFn` is constructed from a closure or - /// function pointer that takes both the [`Metadata`] for a span or event - /// *and* the current [`Context`]. This means that a [`DynFilterFn`] can - /// choose whether to enable spans or events based on information about the - /// _current_ span (or its parents). - /// - /// If this is *not* necessary, use [`FilterFn`] instead. - /// - /// See the [documentation on per-layer filtering][plf] for details on using - /// [`Filter`]s. - /// - /// [`Filter`]: crate::layer::Filter - /// [plf]: crate::layer#per-layer-filtering - /// [`Context`]: crate::layer::Context - /// [`Metadata`]: tracing_core::Metadata - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::DynFilterFn, - /// util::SubscriberInitExt, - /// }; - /// - /// // Only enable spans or events within a span named "interesting_span". - /// let my_filter = DynFilterFn::new(|metadata, cx| { - /// // If this *is* "interesting_span", make sure to enable it. - /// if metadata.is_span() && metadata.name() == "interesting_span" { - /// return true; - /// } - /// - /// // Otherwise, are we in an interesting span? - /// if let Some(current_span) = cx.lookup_current() { - /// return current_span.name() == "interesting_span"; - /// } - /// - /// false - /// }); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// - /// // This event will not be enabled. - /// tracing::info!("something happened"); - /// - /// tracing::info_span!("interesting_span").in_scope(|| { - /// // This event will be enabled. - /// tracing::debug!("something else happened"); - /// }); - /// ``` - pub fn new(enabled: F) -> Self { - Self { - enabled, - register_callsite: None, - max_level_hint: None, - _s: PhantomData, - } - } -} - -impl<S, F, R> DynFilterFn<S, F, R> -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, -{ - /// Sets the highest verbosity [`Level`] the filter function will enable. - /// - /// The value passed to this method will be returned by this `DynFilterFn`'s - /// [`Filter::max_level_hint`] method. - /// - /// If the provided function will not enable all levels, it is recommended - /// to call this method to configure it with the most verbose level it will - /// enable. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::{DynFilterFn, LevelFilter}, - /// util::SubscriberInitExt, - /// }; - /// use tracing_core::Level; - /// - /// // Only enable spans or events with levels at or below `INFO`, if - /// // we are inside a span called "interesting_span". - /// let my_filter = DynFilterFn::new(|metadata, cx| { - /// // If the level is greater than INFO, disable it. - /// if metadata.level() > &Level::INFO { - /// return false; - /// } - /// - /// // If any span in the current scope is named "interesting_span", - /// // enable this span or event. - /// for span in cx.lookup_current().iter().flat_map(|span| span.scope()) { - /// if span.name() == "interesting_span" { - /// return true; - /// } - /// } - /// - /// // Otherwise, disable it. - /// false - /// }) - /// // Since the filter closure will only enable the `INFO` level and - /// // below, set the max level hint - /// .with_max_level_hint(LevelFilter::INFO); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// ``` - /// - /// [`Level`]: tracing_core::Level - /// [`Filter::max_level_hint`]: crate::layer::Filter::max_level_hint - pub fn with_max_level_hint(self, max_level_hint: impl Into<LevelFilter>) -> Self { - Self { - max_level_hint: Some(max_level_hint.into()), - ..self - } - } - - /// Adds a function for filtering callsites to this filter. - /// - /// When this filter's [`Filter::callsite_enabled`][cse] method is called, - /// the provided function will be used rather than the default. - /// - /// By default, `DynFilterFn` assumes that, because the filter _may_ depend - /// dynamically on the current [span context], its result should never be - /// cached. However, some filtering strategies may require dynamic information - /// from the current span context in *some* cases, but are able to make - /// static filtering decisions from [`Metadata`] alone in others. - /// - /// For example, consider the filter given in the example for - /// [`DynFilterFn::new`]. That filter enables all spans named - /// "interesting_span", and any events and spans that occur inside of an - /// interesting span. Since the span's name is part of its static - /// [`Metadata`], the "interesting_span" can be enabled in - /// [`callsite_enabled`][cse]: - /// - /// ``` - /// use tracing_subscriber::{ - /// layer::{Layer, SubscriberExt}, - /// filter::DynFilterFn, - /// util::SubscriberInitExt, - /// }; - /// use tracing_core::subscriber::Interest; - /// - /// // Only enable spans or events within a span named "interesting_span". - /// let my_filter = DynFilterFn::new(|metadata, cx| { - /// // If this *is* "interesting_span", make sure to enable it. - /// if metadata.is_span() && metadata.name() == "interesting_span" { - /// return true; - /// } - /// - /// // Otherwise, are we in an interesting span? - /// if let Some(current_span) = cx.lookup_current() { - /// return current_span.name() == "interesting_span"; - /// } - /// - /// false - /// }).with_callsite_filter(|metadata| { - /// // If this is an "interesting_span", we know we will always - /// // enable it. - /// if metadata.is_span() && metadata.name() == "interesting_span" { - /// return Interest::always(); - /// } - /// - /// // Otherwise, it depends on whether or not we're in an interesting - /// // span. You'll have to ask us again for each span/event! - /// Interest::sometimes() - /// }); - /// - /// let my_layer = tracing_subscriber::fmt::layer(); - /// - /// tracing_subscriber::registry() - /// .with(my_layer.with_filter(my_filter)) - /// .init(); - /// ``` - /// - /// [cse]: crate::layer::Filter::callsite_enabled - /// [`enabled`]: crate::layer::Filter::enabled - /// [`Metadata`]: tracing_core::Metadata - /// [span context]: crate::layer::Context - pub fn with_callsite_filter<R2>(self, callsite_enabled: R2) -> DynFilterFn<S, F, R2> - where - R2: Fn(&'static Metadata<'static>) -> Interest, - { - let register_callsite = Some(callsite_enabled); - let DynFilterFn { - enabled, - max_level_hint, - _s, - .. - } = self; - DynFilterFn { - enabled, - register_callsite, - max_level_hint, - _s, - } - } - - fn default_callsite_enabled(&self, metadata: &Metadata<'_>) -> Interest { - // If it's below the configured max level, assume that `enabled` will - // never enable it... - if !is_below_max_level(&self.max_level_hint, metadata) { - debug_assert!( - !(self.enabled)(metadata, &Context::none()), - "DynFilterFn<{}> claimed it would only enable {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::<F>(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - return Interest::never(); - } - - // Otherwise, since this `enabled` function is dynamic and depends on - // the current context, we don't know whether this span or event will be - // enabled or not. Ask again every time it's recorded! - Interest::sometimes() - } -} - -impl<S, F, R> DynFilterFn<S, F, R> -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, - R: Fn(&'static Metadata<'static>) -> Interest, -{ - #[inline] - fn is_enabled(&self, metadata: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - let enabled = (self.enabled)(metadata, cx); - debug_assert!( - !enabled || is_below_max_level(&self.max_level_hint, metadata), - "DynFilterFn<{}> claimed it would only enable {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::<F>(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - - enabled - } - - #[inline] - fn is_callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - let interest = self - .register_callsite - .as_ref() - .map(|callsite_enabled| callsite_enabled(metadata)) - .unwrap_or_else(|| self.default_callsite_enabled(metadata)); - debug_assert!( - interest.is_never() || is_below_max_level(&self.max_level_hint, metadata), - "DynFilterFn<{}, {}> claimed it was only interested in {:?} and below, \ - but it enabled metadata with the {:?} level\nmetadata={:#?}", - type_name::<F>(), - type_name::<R>(), - self.max_level_hint.unwrap(), - metadata.level(), - metadata, - ); - - interest - } -} - -impl<S, F, R> Layer<S> for DynFilterFn<S, F, R> -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool + 'static, - R: Fn(&'static Metadata<'static>) -> Interest + 'static, - S: Subscriber, -{ - fn enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool { - self.is_enabled(metadata, &cx) - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.is_callsite_enabled(metadata) - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - self.max_level_hint - } -} - -impl<S, F, R> fmt::Debug for DynFilterFn<S, F, R> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut s = f.debug_struct("DynFilterFn"); - s.field("enabled", &format_args!("{}", type_name::<F>())); - if self.register_callsite.is_some() { - s.field( - "register_callsite", - &format_args!("Some({})", type_name::<R>()), - ); - } else { - s.field("register_callsite", &format_args!("None")); - } - - s.field("max_level_hint", &self.max_level_hint).finish() - } -} - -impl<S, F, R> Clone for DynFilterFn<S, F, R> -where - F: Clone, - R: Clone, -{ - fn clone(&self) -> Self { - Self { - enabled: self.enabled.clone(), - register_callsite: self.register_callsite.clone(), - max_level_hint: self.max_level_hint, - _s: PhantomData, - } - } -} - -impl<F, S> From<F> for DynFilterFn<S, F> -where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, -{ - fn from(f: F) -> Self { - Self::new(f) - } -} - -// === PLF impls === - -feature! { - #![all(feature = "registry", feature = "std")] - use crate::layer::Filter; - - impl<S, F> Filter<S> for FilterFn<F> - where - F: Fn(&Metadata<'_>) -> bool, - { - fn enabled(&self, metadata: &Metadata<'_>, _: &Context<'_, S>) -> bool { - self.is_enabled(metadata) - } - - fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - self.is_callsite_enabled(metadata) - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - self.max_level_hint - } - } - - impl<S, F, R> Filter<S> for DynFilterFn<S, F, R> - where - F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, - R: Fn(&'static Metadata<'static>) -> Interest, - { - fn enabled(&self, metadata: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - self.is_enabled(metadata, cx) - } - - fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - self.is_callsite_enabled(metadata) - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - self.max_level_hint - } - } -} - -fn is_below_max_level(hint: &Option<LevelFilter>, metadata: &Metadata<'_>) -> bool { - hint.as_ref() - .map(|hint| metadata.level() <= hint) - .unwrap_or(true) -} diff --git a/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs b/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs deleted file mode 100644 index e79de2087..000000000 --- a/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs +++ /dev/null @@ -1,469 +0,0 @@ -//! Filter combinators -use crate::layer::{Context, Filter}; -use std::{cmp, fmt, marker::PhantomData}; -use tracing_core::{ - span::{Attributes, Id, Record}, - subscriber::Interest, - LevelFilter, Metadata, -}; - -/// Combines two [`Filter`]s so that spans and events are enabled if and only if -/// *both* filters return `true`. -/// -/// This type is typically returned by the [`FilterExt::and`] method. See that -/// method's documentation for details. -/// -/// [`Filter`]: crate::layer::Filter -/// [`FilterExt::and`]: crate::filter::FilterExt::and -pub struct And<A, B, S> { - a: A, - b: B, - _s: PhantomData<fn(S)>, -} - -/// Combines two [`Filter`]s so that spans and events are enabled if *either* filter -/// returns `true`. -/// -/// This type is typically returned by the [`FilterExt::or`] method. See that -/// method's documentation for details. -/// -/// [`Filter`]: crate::layer::Filter -/// [`FilterExt::or`]: crate::filter::FilterExt::or -pub struct Or<A, B, S> { - a: A, - b: B, - _s: PhantomData<fn(S)>, -} - -/// Inverts the result of a [`Filter`]. -/// -/// If the wrapped filter would enable a span or event, it will be disabled. If -/// it would disable a span or event, that span or event will be enabled. -/// -/// This type is typically returned by the [`FilterExt::or`] method. See that -/// method's documentation for details. -/// -/// [`Filter`]: crate::layer::Filter -/// [`FilterExt::or`]: crate::filter::FilterExt::or -pub struct Not<A, S> { - a: A, - _s: PhantomData<fn(S)>, -} - -// === impl And === - -impl<A, B, S> And<A, B, S> -where - A: Filter<S>, - B: Filter<S>, -{ - /// Combines two [`Filter`]s so that spans and events are enabled if and only if - /// *both* filters return `true`. - /// - /// # Examples - /// - /// Enabling spans or events if they have both a particular target *and* are - /// above a certain level: - /// - /// ```ignore - /// use tracing_subscriber::{ - /// filter::{filter_fn, LevelFilter, combinator::And}, - /// prelude::*, - /// }; - /// - /// // Enables spans and events with targets starting with `interesting_target`: - /// let target_filter = filter_fn(|meta| { - /// meta.target().starts_with("interesting_target") - /// }); - /// - /// // Enables spans and events with levels `INFO` and below: - /// let level_filter = LevelFilter::INFO; - /// - /// // Combine the two filters together so that a span or event is only enabled - /// // if *both* filters would enable it: - /// let filter = And::new(level_filter, target_filter); - /// - /// tracing_subscriber::registry() - /// .with(tracing_subscriber::fmt::layer().with_filter(filter)) - /// .init(); - /// - /// // This event will *not* be enabled: - /// tracing::info!("an event with an uninteresting target"); - /// - /// // This event *will* be enabled: - /// tracing::info!(target: "interesting_target", "a very interesting event"); - /// - /// // This event will *not* be enabled: - /// tracing::debug!(target: "interesting_target", "interesting debug event..."); - /// ``` - /// - /// [`Filter`]: crate::layer::Filter - pub(crate) fn new(a: A, b: B) -> Self { - Self { - a, - b, - _s: PhantomData, - } - } -} - -impl<A, B, S> Filter<S> for And<A, B, S> -where - A: Filter<S>, - B: Filter<S>, -{ - #[inline] - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - self.a.enabled(meta, cx) && self.b.enabled(meta, cx) - } - - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - let a = self.a.callsite_enabled(meta); - if a.is_never() { - return a; - } - - let b = self.b.callsite_enabled(meta); - - if !b.is_always() { - return b; - } - - a - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - // If either hint is `None`, return `None`. Otherwise, return the most restrictive. - cmp::min(self.a.max_level_hint(), self.b.max_level_hint()) - } - - #[inline] - fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { - self.a.on_new_span(attrs, id, ctx.clone()); - self.b.on_new_span(attrs, id, ctx) - } - - #[inline] - fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) { - self.a.on_record(id, values, ctx.clone()); - self.b.on_record(id, values, ctx); - } - - #[inline] - fn on_enter(&self, id: &Id, ctx: Context<'_, S>) { - self.a.on_enter(id, ctx.clone()); - self.b.on_enter(id, ctx); - } - - #[inline] - fn on_exit(&self, id: &Id, ctx: Context<'_, S>) { - self.a.on_exit(id, ctx.clone()); - self.b.on_exit(id, ctx); - } - - #[inline] - fn on_close(&self, id: Id, ctx: Context<'_, S>) { - self.a.on_close(id.clone(), ctx.clone()); - self.b.on_close(id, ctx); - } -} - -impl<A, B, S> Clone for And<A, B, S> -where - A: Clone, - B: Clone, -{ - fn clone(&self) -> Self { - Self { - a: self.a.clone(), - b: self.b.clone(), - _s: PhantomData, - } - } -} - -impl<A, B, S> fmt::Debug for And<A, B, S> -where - A: fmt::Debug, - B: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("And") - .field("a", &self.a) - .field("b", &self.b) - .finish() - } -} - -// === impl Or === - -impl<A, B, S> Or<A, B, S> -where - A: Filter<S>, - B: Filter<S>, -{ - /// Combines two [`Filter`]s so that spans and events are enabled if *either* filter - /// returns `true`. - /// - /// # Examples - /// - /// Enabling spans and events at the `INFO` level and above, and all spans - /// and events with a particular target: - /// - /// ```ignore - /// use tracing_subscriber::{ - /// filter::{filter_fn, LevelFilter, combinator::Or}, - /// prelude::*, - /// }; - /// - /// // Enables spans and events with targets starting with `interesting_target`: - /// let target_filter = filter_fn(|meta| { - /// meta.target().starts_with("interesting_target") - /// }); - /// - /// // Enables spans and events with levels `INFO` and below: - /// let level_filter = LevelFilter::INFO; - /// - /// // Combine the two filters together so that a span or event is enabled - /// // if it is at INFO or lower, or if it has a target starting with - /// // `interesting_target`. - /// let filter = Or::new(level_filter, target_filter); - /// - /// tracing_subscriber::registry() - /// .with(tracing_subscriber::fmt::layer().with_filter(filter)) - /// .init(); - /// - /// // This event will *not* be enabled: - /// tracing::debug!("an uninteresting event"); - /// - /// // This event *will* be enabled: - /// tracing::info!("an uninteresting INFO event"); - /// - /// // This event *will* be enabled: - /// tracing::info!(target: "interesting_target", "a very interesting event"); - /// - /// // This event *will* be enabled: - /// tracing::debug!(target: "interesting_target", "interesting debug event..."); - /// ``` - /// - /// Enabling a higher level for a particular target by using `Or` in - /// conjunction with the [`And`] combinator: - /// - /// ```ignore - /// use tracing_subscriber::{ - /// filter::{filter_fn, LevelFilter, combinator}, - /// prelude::*, - /// }; - /// - /// // This filter will enable spans and events with targets beginning with - /// // `my_crate`: - /// let my_crate = filter_fn(|meta| { - /// meta.target().starts_with("my_crate") - /// }); - /// - /// // Combine the `my_crate` filter with a `LevelFilter` to produce a filter - /// // that will enable the `INFO` level and lower for spans and events with - /// // `my_crate` targets: - /// let filter = combinator::And::new(my_crate, LevelFilter::INFO); - /// - /// // If a span or event *doesn't* have a target beginning with - /// // `my_crate`, enable it if it has the `WARN` level or lower: - /// // let filter = combinator::Or::new(filter, LevelFilter::WARN); - /// - /// tracing_subscriber::registry() - /// .with(tracing_subscriber::fmt::layer().with_filter(filter)) - /// .init(); - /// ``` - /// - /// [`Filter`]: crate::layer::Filter - pub(crate) fn new(a: A, b: B) -> Self { - Self { - a, - b, - _s: PhantomData, - } - } -} - -impl<A, B, S> Filter<S> for Or<A, B, S> -where - A: Filter<S>, - B: Filter<S>, -{ - #[inline] - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - self.a.enabled(meta, cx) || self.b.enabled(meta, cx) - } - - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - let a = self.a.callsite_enabled(meta); - let b = self.b.callsite_enabled(meta); - - // If either filter will always enable the span or event, return `always`. - if a.is_always() || b.is_always() { - return Interest::always(); - } - - // Okay, if either filter will sometimes enable the span or event, - // return `sometimes`. - if a.is_sometimes() || b.is_sometimes() { - return Interest::sometimes(); - } - - debug_assert!( - a.is_never() && b.is_never(), - "if neither filter was `always` or `sometimes`, both must be `never` (a={:?}; b={:?})", - a, - b, - ); - Interest::never() - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - // If either hint is `None`, return `None`. Otherwise, return the less restrictive. - Some(cmp::max(self.a.max_level_hint()?, self.b.max_level_hint()?)) - } - - #[inline] - fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { - self.a.on_new_span(attrs, id, ctx.clone()); - self.b.on_new_span(attrs, id, ctx) - } - - #[inline] - fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) { - self.a.on_record(id, values, ctx.clone()); - self.b.on_record(id, values, ctx); - } - - #[inline] - fn on_enter(&self, id: &Id, ctx: Context<'_, S>) { - self.a.on_enter(id, ctx.clone()); - self.b.on_enter(id, ctx); - } - - #[inline] - fn on_exit(&self, id: &Id, ctx: Context<'_, S>) { - self.a.on_exit(id, ctx.clone()); - self.b.on_exit(id, ctx); - } - - #[inline] - fn on_close(&self, id: Id, ctx: Context<'_, S>) { - self.a.on_close(id.clone(), ctx.clone()); - self.b.on_close(id, ctx); - } -} - -impl<A, B, S> Clone for Or<A, B, S> -where - A: Clone, - B: Clone, -{ - fn clone(&self) -> Self { - Self { - a: self.a.clone(), - b: self.b.clone(), - _s: PhantomData, - } - } -} - -impl<A, B, S> fmt::Debug for Or<A, B, S> -where - A: fmt::Debug, - B: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Or") - .field("a", &self.a) - .field("b", &self.b) - .finish() - } -} - -// === impl Not === - -impl<A, S> Not<A, S> -where - A: Filter<S>, -{ - /// Inverts the result of a [`Filter`]. - /// - /// If the wrapped filter would enable a span or event, it will be disabled. If - /// it would disable a span or event, that span or event will be enabled. - /// - /// [`Filter`]: crate::layer::Filter - pub(crate) fn new(a: A) -> Self { - Self { a, _s: PhantomData } - } -} - -impl<A, S> Filter<S> for Not<A, S> -where - A: Filter<S>, -{ - #[inline] - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - !self.a.enabled(meta, cx) - } - - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - match self.a.callsite_enabled(meta) { - i if i.is_always() => Interest::never(), - i if i.is_never() => Interest::always(), - _ => Interest::sometimes(), - } - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - // TODO(eliza): figure this out??? - None - } - - #[inline] - fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { - self.a.on_new_span(attrs, id, ctx); - } - - #[inline] - fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) { - self.a.on_record(id, values, ctx.clone()); - } - - #[inline] - fn on_enter(&self, id: &Id, ctx: Context<'_, S>) { - self.a.on_enter(id, ctx); - } - - #[inline] - fn on_exit(&self, id: &Id, ctx: Context<'_, S>) { - self.a.on_exit(id, ctx); - } - - #[inline] - fn on_close(&self, id: Id, ctx: Context<'_, S>) { - self.a.on_close(id, ctx); - } -} - -impl<A, S> Clone for Not<A, S> -where - A: Clone, -{ - fn clone(&self) -> Self { - Self { - a: self.a.clone(), - _s: PhantomData, - } - } -} - -impl<A, S> fmt::Debug for Not<A, S> -where - A: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Not").field(&self.a).finish() - } -} diff --git a/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs b/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs deleted file mode 100644 index 8949cfb5a..000000000 --- a/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs +++ /dev/null @@ -1,1135 +0,0 @@ -//! ## Per-Layer Filtering -//! -//! Per-layer filters permit individual `Layer`s to have their own filter -//! configurations without interfering with other `Layer`s. -//! -//! This module is not public; the public APIs defined in this module are -//! re-exported in the top-level `filter` module. Therefore, this documentation -//! primarily concerns the internal implementation details. For the user-facing -//! public API documentation, see the individual public types in this module, as -//! well as the, see the `Layer` trait documentation's [per-layer filtering -//! section]][1]. -//! -//! ## How does per-layer filtering work? -//! -//! As described in the API documentation, the [`Filter`] trait defines a -//! filtering strategy for a per-layer filter. We expect there will be a variety -//! of implementations of [`Filter`], both in `tracing-subscriber` and in user -//! code. -//! -//! To actually *use* a [`Filter`] implementation, it is combined with a -//! [`Layer`] by the [`Filtered`] struct defined in this module. [`Filtered`] -//! implements [`Layer`] by calling into the wrapped [`Layer`], or not, based on -//! the filtering strategy. While there will be a variety of types that implement -//! [`Filter`], all actual *uses* of per-layer filtering will occur through the -//! [`Filtered`] struct. Therefore, most of the implementation details live -//! there. -//! -//! [1]: crate::layer#per-layer-filtering -//! [`Filter`]: crate::layer::Filter -use crate::{ - filter::LevelFilter, - layer::{self, Context, Layer}, - registry, -}; -use std::{ - any::TypeId, - cell::{Cell, RefCell}, - fmt, - marker::PhantomData, - ops::Deref, - sync::Arc, - thread_local, -}; -use tracing_core::{ - span, - subscriber::{Interest, Subscriber}, - Event, Metadata, -}; -pub mod combinator; - -/// A [`Layer`] that wraps an inner [`Layer`] and adds a [`Filter`] which -/// controls what spans and events are enabled for that layer. -/// -/// This is returned by the [`Layer::with_filter`] method. See the -/// [documentation on per-layer filtering][plf] for details. -/// -/// [`Filter`]: crate::layer::Filter -/// [plf]: crate::layer#per-layer-filtering -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -#[derive(Clone)] -pub struct Filtered<L, F, S> { - filter: F, - layer: L, - id: MagicPlfDowncastMarker, - _s: PhantomData<fn(S)>, -} - -/// Uniquely identifies an individual [`Filter`] instance in the context of -/// a [`Subscriber`]. -/// -/// When adding a [`Filtered`] [`Layer`] to a [`Subscriber`], the [`Subscriber`] -/// generates a `FilterId` for that [`Filtered`] layer. The [`Filtered`] layer -/// will then use the generated ID to query whether a particular span was -/// previously enabled by that layer's [`Filter`]. -/// -/// **Note**: Currently, the [`Registry`] type provided by this crate is the -/// **only** [`Subscriber`] implementation capable of participating in per-layer -/// filtering. Therefore, the `FilterId` type cannot currently be constructed by -/// code outside of `tracing-subscriber`. In the future, new APIs will be added to `tracing-subscriber` to -/// allow non-Registry [`Subscriber`]s to also participate in per-layer -/// filtering. When those APIs are added, subscribers will be responsible -/// for generating and assigning `FilterId`s. -/// -/// [`Filter`]: crate::layer::Filter -/// [`Subscriber`]: tracing_core::Subscriber -/// [`Layer`]: crate::layer::Layer -/// [`Registry`]: crate::registry::Registry -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -#[derive(Copy, Clone)] -pub struct FilterId(u64); - -/// A bitmap tracking which [`FilterId`]s have enabled a given span or -/// event. -/// -/// This is currently a private type that's used exclusively by the -/// [`Registry`]. However, in the future, this may become a public API, in order -/// to allow user subscribers to host [`Filter`]s. -/// -/// [`Registry`]: crate::Registry -/// [`Filter`]: crate::layer::Filter -#[derive(Default, Copy, Clone, Eq, PartialEq)] -pub(crate) struct FilterMap { - bits: u64, -} - -/// The current state of `enabled` calls to per-layer filters on this -/// thread. -/// -/// When `Filtered::enabled` is called, the filter will set the bit -/// corresponding to its ID if the filter will disable the event/span being -/// filtered. When the event or span is recorded, the per-layer filter will -/// check its bit to determine if it disabled that event or span, and skip -/// forwarding the event or span to the inner layer if the bit is set. Once -/// a span or event has been skipped by a per-layer filter, it unsets its -/// bit, so that the `FilterMap` has been cleared for the next set of -/// `enabled` calls. -/// -/// FilterState is also read by the `Registry`, for two reasons: -/// -/// 1. When filtering a span, the Registry must store the `FilterMap` -/// generated by `Filtered::enabled` calls for that span as part of the -/// span's per-span data. This allows `Filtered` layers to determine -/// whether they had previously disabled a given span, and avoid showing it -/// to the wrapped layer if it was disabled. -/// -/// This allows `Filtered` layers to also filter out the spans they -/// disable from span traversals (such as iterating over parents, etc). -/// 2. If all the bits are set, then every per-layer filter has decided it -/// doesn't want to enable that span or event. In that case, the -/// `Registry`'s `enabled` method will return `false`, so that -/// recording a span or event can be skipped entirely. -#[derive(Debug)] -pub(crate) struct FilterState { - enabled: Cell<FilterMap>, - // TODO(eliza): `Interest`s should _probably_ be `Copy`. The only reason - // they're not is our Obsessive Commitment to Forwards-Compatibility. If - // this changes in tracing-core`, we can make this a `Cell` rather than - // `RefCell`... - interest: RefCell<Option<Interest>>, - - #[cfg(debug_assertions)] - counters: DebugCounters, -} - -/// Extra counters added to `FilterState` used only to make debug assertions. -#[cfg(debug_assertions)] -#[derive(Debug, Default)] -struct DebugCounters { - /// How many per-layer filters have participated in the current `enabled` - /// call? - in_filter_pass: Cell<usize>, - - /// How many per-layer filters have participated in the current `register_callsite` - /// call? - in_interest_pass: Cell<usize>, -} - -thread_local! { - pub(crate) static FILTERING: FilterState = FilterState::new(); -} - -/// Extension trait adding [combinators] for combining [`Filter`]. -/// -/// [combinators]: crate::filter::combinator -/// [`Filter`]: crate::layer::Filter -pub trait FilterExt<S>: layer::Filter<S> { - /// Combines this [`Filter`] with another [`Filter`] s so that spans and - /// events are enabled if and only if *both* filters return `true`. - /// - /// # Examples - /// - /// Enabling spans or events if they have both a particular target *and* are - /// above a certain level: - /// - /// ``` - /// use tracing_subscriber::{ - /// filter::{filter_fn, LevelFilter, FilterExt}, - /// prelude::*, - /// }; - /// - /// // Enables spans and events with targets starting with `interesting_target`: - /// let target_filter = filter_fn(|meta| { - /// meta.target().starts_with("interesting_target") - /// }); - /// - /// // Enables spans and events with levels `INFO` and below: - /// let level_filter = LevelFilter::INFO; - /// - /// // Combine the two filters together, returning a filter that only enables - /// // spans and events that *both* filters will enable: - /// let filter = target_filter.and(level_filter); - /// - /// tracing_subscriber::registry() - /// .with(tracing_subscriber::fmt::layer().with_filter(filter)) - /// .init(); - /// - /// // This event will *not* be enabled: - /// tracing::info!("an event with an uninteresting target"); - /// - /// // This event *will* be enabled: - /// tracing::info!(target: "interesting_target", "a very interesting event"); - /// - /// // This event will *not* be enabled: - /// tracing::debug!(target: "interesting_target", "interesting debug event..."); - /// ``` - /// - /// [`Filter`]: crate::layer::Filter - fn and<B>(self, other: B) -> combinator::And<Self, B, S> - where - Self: Sized, - B: layer::Filter<S>, - { - combinator::And::new(self, other) - } - - /// Combines two [`Filter`]s so that spans and events are enabled if *either* filter - /// returns `true`. - /// - /// # Examples - /// - /// Enabling spans and events at the `INFO` level and above, and all spans - /// and events with a particular target: - /// ``` - /// use tracing_subscriber::{ - /// filter::{filter_fn, LevelFilter, FilterExt}, - /// prelude::*, - /// }; - /// - /// // Enables spans and events with targets starting with `interesting_target`: - /// let target_filter = filter_fn(|meta| { - /// meta.target().starts_with("interesting_target") - /// }); - /// - /// // Enables spans and events with levels `INFO` and below: - /// let level_filter = LevelFilter::INFO; - /// - /// // Combine the two filters together so that a span or event is enabled - /// // if it is at INFO or lower, or if it has a target starting with - /// // `interesting_target`. - /// let filter = level_filter.or(target_filter); - /// - /// tracing_subscriber::registry() - /// .with(tracing_subscriber::fmt::layer().with_filter(filter)) - /// .init(); - /// - /// // This event will *not* be enabled: - /// tracing::debug!("an uninteresting event"); - /// - /// // This event *will* be enabled: - /// tracing::info!("an uninteresting INFO event"); - /// - /// // This event *will* be enabled: - /// tracing::info!(target: "interesting_target", "a very interesting event"); - /// - /// // This event *will* be enabled: - /// tracing::debug!(target: "interesting_target", "interesting debug event..."); - /// ``` - /// - /// Enabling a higher level for a particular target by using `or` in - /// conjunction with the [`and`] combinator: - /// - /// ``` - /// use tracing_subscriber::{ - /// filter::{filter_fn, LevelFilter, FilterExt}, - /// prelude::*, - /// }; - /// - /// // This filter will enable spans and events with targets beginning with - /// // `my_crate`: - /// let my_crate = filter_fn(|meta| { - /// meta.target().starts_with("my_crate") - /// }); - /// - /// let filter = my_crate - /// // Combine the `my_crate` filter with a `LevelFilter` to produce a - /// // filter that will enable the `INFO` level and lower for spans and - /// // events with `my_crate` targets: - /// .and(LevelFilter::INFO) - /// // If a span or event *doesn't* have a target beginning with - /// // `my_crate`, enable it if it has the `WARN` level or lower: - /// .or(LevelFilter::WARN); - /// - /// tracing_subscriber::registry() - /// .with(tracing_subscriber::fmt::layer().with_filter(filter)) - /// .init(); - /// ``` - /// - /// [`Filter`]: crate::layer::Filter - /// [`and`]: FilterExt::and - fn or<B>(self, other: B) -> combinator::Or<Self, B, S> - where - Self: Sized, - B: layer::Filter<S>, - { - combinator::Or::new(self, other) - } - - /// Inverts `self`, returning a filter that enables spans and events only if - /// `self` would *not* enable them. - fn not(self) -> combinator::Not<Self, S> - where - Self: Sized, - { - combinator::Not::new(self) - } - - /// [Boxes] `self`, erasing its concrete type. - /// - /// This is equivalent to calling [`Box::new`], but in method form, so that - /// it can be used when chaining combinator methods. - /// - /// # Examples - /// - /// When different combinations of filters are used conditionally, they may - /// have different types. For example, the following code won't compile, - /// since the `if` and `else` clause produce filters of different types: - /// - /// ```compile_fail - /// use tracing_subscriber::{ - /// filter::{filter_fn, LevelFilter, FilterExt}, - /// prelude::*, - /// }; - /// - /// let enable_bar_target: bool = // ... - /// # false; - /// - /// let filter = if enable_bar_target { - /// filter_fn(|meta| meta.target().starts_with("foo")) - /// // If `enable_bar_target` is true, add a `filter_fn` enabling - /// // spans and events with the target `bar`: - /// .or(filter_fn(|meta| meta.target().starts_with("bar"))) - /// .and(LevelFilter::INFO) - /// } else { - /// filter_fn(|meta| meta.target().starts_with("foo")) - /// .and(LevelFilter::INFO) - /// }; - /// - /// tracing_subscriber::registry() - /// .with(tracing_subscriber::fmt::layer().with_filter(filter)) - /// .init(); - /// ``` - /// - /// By using `boxed`, the types of the two different branches can be erased, - /// so the assignment to the `filter` variable is valid (as both branches - /// have the type `Box<dyn Filter<S> + Send + Sync + 'static>`). The - /// following code *does* compile: - /// - /// ``` - /// use tracing_subscriber::{ - /// filter::{filter_fn, LevelFilter, FilterExt}, - /// prelude::*, - /// }; - /// - /// let enable_bar_target: bool = // ... - /// # false; - /// - /// let filter = if enable_bar_target { - /// filter_fn(|meta| meta.target().starts_with("foo")) - /// .or(filter_fn(|meta| meta.target().starts_with("bar"))) - /// .and(LevelFilter::INFO) - /// // Boxing the filter erases its type, so both branches now - /// // have the same type. - /// .boxed() - /// } else { - /// filter_fn(|meta| meta.target().starts_with("foo")) - /// .and(LevelFilter::INFO) - /// .boxed() - /// }; - /// - /// tracing_subscriber::registry() - /// .with(tracing_subscriber::fmt::layer().with_filter(filter)) - /// .init(); - /// ``` - /// - /// [Boxes]: std::boxed - /// [`Box::new`]: std::boxed::Box::new - fn boxed(self) -> Box<dyn layer::Filter<S> + Send + Sync + 'static> - where - Self: Sized + Send + Sync + 'static, - { - Box::new(self) - } -} - -// === impl Filter === - -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -impl<S> layer::Filter<S> for LevelFilter { - fn enabled(&self, meta: &Metadata<'_>, _: &Context<'_, S>) -> bool { - meta.level() <= self - } - - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - if meta.level() <= self { - Interest::always() - } else { - Interest::never() - } - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - Some(*self) - } -} - -macro_rules! filter_impl_body { - () => { - #[inline] - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - self.deref().enabled(meta, cx) - } - - #[inline] - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - self.deref().callsite_enabled(meta) - } - - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - self.deref().max_level_hint() - } - }; -} - -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -impl<S> layer::Filter<S> for Arc<dyn layer::Filter<S> + Send + Sync + 'static> { - filter_impl_body!(); -} - -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -impl<S> layer::Filter<S> for Box<dyn layer::Filter<S> + Send + Sync + 'static> { - filter_impl_body!(); -} - -// === impl Filtered === - -impl<L, F, S> Filtered<L, F, S> { - /// Wraps the provided [`Layer`] so that it is filtered by the given - /// [`Filter`]. - /// - /// This is equivalent to calling the [`Layer::with_filter`] method. - /// - /// See the [documentation on per-layer filtering][plf] for details. - /// - /// [`Filter`]: crate::layer::Filter - /// [plf]: crate::layer#per-layer-filtering - pub fn new(layer: L, filter: F) -> Self { - Self { - layer, - filter, - id: MagicPlfDowncastMarker(FilterId::disabled()), - _s: PhantomData, - } - } - - #[inline(always)] - fn id(&self) -> FilterId { - debug_assert!( - !self.id.0.is_disabled(), - "a `Filtered` layer was used, but it had no `FilterId`; \ - was it registered with the subscriber?" - ); - self.id.0 - } - - fn did_enable(&self, f: impl FnOnce()) { - FILTERING.with(|filtering| filtering.did_enable(self.id(), f)) - } - - /// Borrows the [`Filter`](crate::layer::Filter) used by this layer. - pub fn filter(&self) -> &F { - &self.filter - } - - /// Mutably borrows the [`Filter`](crate::layer::Filter) used by this layer. - /// - /// When this layer can be mutably borrowed, this may be used to mutate the filter. - /// Generally, this will primarily be used with the - /// [`reload::Handle::modify`](crate::reload::Handle::modify) method. - /// - /// # Examples - /// - /// ``` - /// # use tracing::info; - /// # use tracing_subscriber::{filter,fmt,reload,Registry,prelude::*}; - /// # fn main() { - /// let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN); - /// let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer); - /// # - /// # // specifying the Registry type is required - /// # let _: &reload::Handle<filter::Filtered<fmt::Layer<Registry>, - /// # filter::LevelFilter, Registry>,Registry> - /// # = &reload_handle; - /// # - /// info!("This will be ignored"); - /// reload_handle.modify(|layer| *layer.filter_mut() = filter::LevelFilter::INFO); - /// info!("This will be logged"); - /// # } - /// ``` - pub fn filter_mut(&mut self) -> &mut F { - &mut self.filter - } - - /// Borrows the inner [`Layer`] wrapped by this `Filtered` layer. - pub fn inner(&self) -> &L { - &self.layer - } - - /// Mutably borrows the inner [`Layer`] wrapped by this `Filtered` layer. - /// - /// This method is primarily expected to be used with the - /// [`reload::Handle::modify`](crate::reload::Handle::modify) method. - /// - /// # Examples - /// - /// ``` - /// # use tracing::info; - /// # use tracing_subscriber::{filter,fmt,reload,Registry,prelude::*}; - /// # fn non_blocking<T: std::io::Write>(writer: T) -> (fn() -> std::io::Stdout) { - /// # std::io::stdout - /// # } - /// # fn main() { - /// let filtered_layer = fmt::layer().with_writer(non_blocking(std::io::stderr())).with_filter(filter::LevelFilter::INFO); - /// let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer); - /// # - /// # // specifying the Registry type is required - /// # let _: &reload::Handle<filter::Filtered<fmt::Layer<Registry, _, _, fn() -> std::io::Stdout>, - /// # filter::LevelFilter, Registry>, Registry> - /// # = &reload_handle; - /// # - /// info!("This will be logged to stderr"); - /// reload_handle.modify(|layer| *layer.inner_mut().writer_mut() = non_blocking(std::io::stdout())); - /// info!("This will be logged to stdout"); - /// # } - /// ``` - /// - /// [subscriber]: Subscribe - pub fn inner_mut(&mut self) -> &mut L { - &mut self.layer - } -} - -impl<S, L, F> Layer<S> for Filtered<L, F, S> -where - S: Subscriber + for<'span> registry::LookupSpan<'span> + 'static, - F: layer::Filter<S> + 'static, - L: Layer<S>, -{ - fn on_layer(&mut self, subscriber: &mut S) { - self.id = MagicPlfDowncastMarker(subscriber.register_filter()); - self.layer.on_layer(subscriber); - } - - // TODO(eliza): can we figure out a nice way to make the `Filtered` layer - // not call `is_enabled_for` in hooks that the inner layer doesn't actually - // have real implementations of? probably not... - // - // it would be cool if there was some wild rust reflection way of checking - // if a trait impl has the default impl of a trait method or not, but that's - // almsot certainly impossible...right? - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - let interest = self.filter.callsite_enabled(metadata); - - // If the filter didn't disable the callsite, allow the inner layer to - // register it — since `register_callsite` is also used for purposes - // such as reserving/caching per-callsite data, we want the inner layer - // to be able to perform any other registration steps. However, we'll - // ignore its `Interest`. - if !interest.is_never() { - self.layer.register_callsite(metadata); - } - - // Add our `Interest` to the current sum of per-layer filter `Interest`s - // for this callsite. - FILTERING.with(|filtering| filtering.add_interest(interest)); - - // don't short circuit! if the stack consists entirely of `Layer`s with - // per-layer filters, the `Registry` will return the actual `Interest` - // value that's the sum of all the `register_callsite` calls to those - // per-layer filters. if we returned an actual `never` interest here, a - // `Layered` layer would short-circuit and not allow any `Filtered` - // layers below us if _they_ are interested in the callsite. - Interest::always() - } - - fn enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool { - let cx = cx.with_filter(self.id()); - let enabled = self.filter.enabled(metadata, &cx); - FILTERING.with(|filtering| filtering.set(self.id(), enabled)); - - if enabled { - // If the filter enabled this metadata, ask the wrapped layer if - // _it_ wants it --- it might have a global filter. - self.layer.enabled(metadata, cx) - } else { - // Otherwise, return `true`. The _per-layer_ filter disabled this - // metadata, but returning `false` in `Layer::enabled` will - // short-circuit and globally disable the span or event. This is - // *not* what we want for per-layer filters, as other layers may - // still want this event. Returning `true` here means we'll continue - // asking the next layer in the stack. - // - // Once all per-layer filters have been evaluated, the `Registry` - // at the root of the stack will return `false` from its `enabled` - // method if *every* per-layer filter disabled this metadata. - // Otherwise, the individual per-layer filters will skip the next - // `new_span` or `on_event` call for their layer if *they* disabled - // the span or event, but it was not globally disabled. - true - } - } - - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, cx: Context<'_, S>) { - self.did_enable(|| { - let cx = cx.with_filter(self.id()); - self.filter.on_new_span(attrs, id, cx.clone()); - self.layer.on_new_span(attrs, id, cx); - }) - } - - #[doc(hidden)] - fn max_level_hint(&self) -> Option<LevelFilter> { - self.filter.max_level_hint() - } - - fn on_record(&self, span: &span::Id, values: &span::Record<'_>, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(span, self.id()) { - self.filter.on_record(span, values, cx.clone()); - self.layer.on_record(span, values, cx) - } - } - - fn on_follows_from(&self, span: &span::Id, follows: &span::Id, cx: Context<'_, S>) { - // only call `on_follows_from` if both spans are enabled by us - if cx.is_enabled_for(span, self.id()) && cx.is_enabled_for(follows, self.id()) { - self.layer - .on_follows_from(span, follows, cx.with_filter(self.id())) - } - } - - fn on_event(&self, event: &Event<'_>, cx: Context<'_, S>) { - self.did_enable(|| { - self.layer.on_event(event, cx.with_filter(self.id())); - }) - } - - fn on_enter(&self, id: &span::Id, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(id, self.id()) { - self.filter.on_enter(id, cx.clone()); - self.layer.on_enter(id, cx); - } - } - - fn on_exit(&self, id: &span::Id, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(id, self.id()) { - self.filter.on_exit(id, cx.clone()); - self.layer.on_exit(id, cx); - } - } - - fn on_close(&self, id: span::Id, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(&id, self.id()) { - self.filter.on_close(id.clone(), cx.clone()); - self.layer.on_close(id, cx); - } - } - - // XXX(eliza): the existence of this method still makes me sad... - fn on_id_change(&self, old: &span::Id, new: &span::Id, cx: Context<'_, S>) { - if let Some(cx) = cx.if_enabled_for(old, self.id()) { - self.layer.on_id_change(old, new, cx) - } - } - - #[doc(hidden)] - #[inline] - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - match id { - id if id == TypeId::of::<Self>() => Some(self as *const _ as *const ()), - id if id == TypeId::of::<L>() => Some(&self.layer as *const _ as *const ()), - id if id == TypeId::of::<F>() => Some(&self.filter as *const _ as *const ()), - id if id == TypeId::of::<MagicPlfDowncastMarker>() => { - Some(&self.id as *const _ as *const ()) - } - _ => self.layer.downcast_raw(id), - } - } -} - -impl<F, L, S> fmt::Debug for Filtered<F, L, S> -where - F: fmt::Debug, - L: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Filtered") - .field("filter", &self.filter) - .field("layer", &self.layer) - .field("id", &self.id) - .finish() - } -} - -// === impl FilterId === - -impl FilterId { - const fn disabled() -> Self { - Self(std::u64::MAX) - } - - /// Returns a `FilterId` that will consider _all_ spans enabled. - pub(crate) const fn none() -> Self { - Self(0) - } - - pub(crate) fn new(id: u8) -> Self { - assert!(id < 64, "filter IDs may not be greater than 64"); - Self(1 << id as usize) - } - - /// Combines two `FilterId`s, returning a new `FilterId` that will match a - /// [`FilterMap`] where the span was disabled by _either_ this `FilterId` - /// *or* the combined `FilterId`. - /// - /// This method is called by [`Context`]s when adding the `FilterId` of a - /// [`Filtered`] layer to the context. - /// - /// This is necessary for cases where we have a tree of nested [`Filtered`] - /// layers, like this: - /// - /// ```text - /// Filtered { - /// filter1, - /// Layered { - /// layer1, - /// Filtered { - /// filter2, - /// layer2, - /// }, - /// } - /// ``` - /// - /// We want `layer2` to be affected by both `filter1` _and_ `filter2`. - /// Without combining `FilterId`s, this works fine when filtering - /// `on_event`/`new_span`, because the outer `Filtered` layer (`filter1`) - /// won't call the inner layer's `on_event` or `new_span` callbacks if it - /// disabled the event/span. - /// - /// However, it _doesn't_ work when filtering span lookups and traversals - /// (e.g. `scope`). This is because the [`Context`] passed to `layer2` - /// would set its filter ID to the filter ID of `filter2`, and would skip - /// spans that were disabled by `filter2`. However, what if a span was - /// disabled by `filter1`? We wouldn't see it in `new_span`, but we _would_ - /// see it in lookups and traversals...which we don't want. - /// - /// When a [`Filtered`] layer adds its ID to a [`Context`], it _combines_ it - /// with any previous filter ID that the context had, rather than replacing - /// it. That way, `layer2`'s context will check if a span was disabled by - /// `filter1` _or_ `filter2`. The way we do this, instead of representing - /// `FilterId`s as a number number that we shift a 1 over by to get a mask, - /// we just store the actual mask,so we can combine them with a bitwise-OR. - /// - /// For example, if we consider the following case (pretending that the - /// masks are 8 bits instead of 64 just so i don't have to write out a bunch - /// of extra zeroes): - /// - /// - `filter1` has the filter id 1 (`0b0000_0001`) - /// - `filter2` has the filter id 2 (`0b0000_0010`) - /// - /// A span that gets disabled by filter 1 would have the [`FilterMap`] with - /// bits `0b0000_0001`. - /// - /// If the `FilterId` was internally represented as `(bits to shift + 1), - /// when `layer2`'s [`Context`] checked if it enabled the span, it would - /// make the mask `0b0000_0010` (`1 << 1`). That bit would not be set in the - /// [`FilterMap`], so it would see that it _didn't_ disable the span. Which - /// is *true*, it just doesn't reflect the tree-like shape of the actual - /// subscriber. - /// - /// By having the IDs be masks instead of shifts, though, when the - /// [`Filtered`] with `filter2` gets the [`Context`] with `filter1`'s filter ID, - /// instead of replacing it, it ors them together: - /// - /// ```ignore - /// 0b0000_0001 | 0b0000_0010 == 0b0000_0011; - /// ``` - /// - /// We then test if the span was disabled by seeing if _any_ bits in the - /// mask are `1`: - /// - /// ```ignore - /// filtermap & mask != 0; - /// 0b0000_0001 & 0b0000_0011 != 0; - /// 0b0000_0001 != 0; - /// true; - /// ``` - /// - /// [`Context`]: crate::layer::Context - pub(crate) fn and(self, FilterId(other): Self) -> Self { - // If this mask is disabled, just return the other --- otherwise, we - // would always see that every span is disabled. - if self.0 == Self::disabled().0 { - return Self(other); - } - - Self(self.0 | other) - } - - fn is_disabled(self) -> bool { - self.0 == Self::disabled().0 - } -} - -impl fmt::Debug for FilterId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // don't print a giant set of the numbers 0..63 if the filter ID is disabled. - if self.0 == Self::disabled().0 { - return f - .debug_tuple("FilterId") - .field(&format_args!("DISABLED")) - .finish(); - } - - if f.alternate() { - f.debug_struct("FilterId") - .field("ids", &format_args!("{:?}", FmtBitset(self.0))) - .field("bits", &format_args!("{:b}", self.0)) - .finish() - } else { - f.debug_tuple("FilterId").field(&FmtBitset(self.0)).finish() - } - } -} - -impl fmt::Binary for FilterId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("FilterId") - .field(&format_args!("{:b}", self.0)) - .finish() - } -} - -// === impl FilterExt === - -impl<F, S> FilterExt<S> for F where F: layer::Filter<S> {} - -// === impl FilterMap === - -impl FilterMap { - pub(crate) fn set(self, FilterId(mask): FilterId, enabled: bool) -> Self { - if mask == std::u64::MAX { - return self; - } - - if enabled { - Self { - bits: self.bits & (!mask), - } - } else { - Self { - bits: self.bits | mask, - } - } - } - - #[inline] - pub(crate) fn is_enabled(self, FilterId(mask): FilterId) -> bool { - self.bits & mask == 0 - } - - #[inline] - pub(crate) fn any_enabled(self) -> bool { - self.bits != std::u64::MAX - } -} - -impl fmt::Debug for FilterMap { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let alt = f.alternate(); - let mut s = f.debug_struct("FilterMap"); - s.field("disabled_by", &format_args!("{:?}", &FmtBitset(self.bits))); - - if alt { - s.field("bits", &format_args!("{:b}", self.bits)); - } - - s.finish() - } -} - -impl fmt::Binary for FilterMap { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FilterMap") - .field("bits", &format_args!("{:b}", self.bits)) - .finish() - } -} - -// === impl FilterState === - -impl FilterState { - fn new() -> Self { - Self { - enabled: Cell::new(FilterMap::default()), - interest: RefCell::new(None), - - #[cfg(debug_assertions)] - counters: DebugCounters::default(), - } - } - - fn set(&self, filter: FilterId, enabled: bool) { - #[cfg(debug_assertions)] - { - let in_current_pass = self.counters.in_filter_pass.get(); - if in_current_pass == 0 { - debug_assert_eq!(self.enabled.get(), FilterMap::default()); - } - self.counters.in_filter_pass.set(in_current_pass + 1); - debug_assert_eq!( - self.counters.in_interest_pass.get(), - 0, - "if we are in or starting a filter pass, we must not be in an interest pass." - ) - } - - self.enabled.set(self.enabled.get().set(filter, enabled)) - } - - fn add_interest(&self, interest: Interest) { - let mut curr_interest = self.interest.borrow_mut(); - - #[cfg(debug_assertions)] - { - let in_current_pass = self.counters.in_interest_pass.get(); - if in_current_pass == 0 { - debug_assert!(curr_interest.is_none()); - } - self.counters.in_interest_pass.set(in_current_pass + 1); - } - - if let Some(curr_interest) = curr_interest.as_mut() { - if (curr_interest.is_always() && !interest.is_always()) - || (curr_interest.is_never() && !interest.is_never()) - { - *curr_interest = Interest::sometimes(); - } - // If the two interests are the same, do nothing. If the current - // interest is `sometimes`, stay sometimes. - } else { - *curr_interest = Some(interest); - } - } - - pub(crate) fn event_enabled() -> bool { - FILTERING - .try_with(|this| { - let enabled = this.enabled.get().any_enabled(); - #[cfg(debug_assertions)] - { - if this.counters.in_filter_pass.get() == 0 { - debug_assert_eq!(this.enabled.get(), FilterMap::default()); - } - - // Nothing enabled this event, we won't tick back down the - // counter in `did_enable`. Reset it. - if !enabled { - this.counters.in_filter_pass.set(0); - } - } - enabled - }) - .unwrap_or(true) - } - - /// Executes a closure if the filter with the provided ID did not disable - /// the current span/event. - /// - /// This is used to implement the `on_event` and `new_span` methods for - /// `Filtered`. - fn did_enable(&self, filter: FilterId, f: impl FnOnce()) { - let map = self.enabled.get(); - if map.is_enabled(filter) { - // If the filter didn't disable the current span/event, run the - // callback. - f(); - } else { - // Otherwise, if this filter _did_ disable the span or event - // currently being processed, clear its bit from this thread's - // `FilterState`. The bit has already been "consumed" by skipping - // this callback, and we need to ensure that the `FilterMap` for - // this thread is reset when the *next* `enabled` call occurs. - self.enabled.set(map.set(filter, true)); - } - #[cfg(debug_assertions)] - { - let in_current_pass = self.counters.in_filter_pass.get(); - if in_current_pass <= 1 { - debug_assert_eq!(self.enabled.get(), FilterMap::default()); - } - self.counters - .in_filter_pass - .set(in_current_pass.saturating_sub(1)); - debug_assert_eq!( - self.counters.in_interest_pass.get(), - 0, - "if we are in a filter pass, we must not be in an interest pass." - ) - } - } - - /// Clears the current in-progress filter state. - /// - /// This resets the [`FilterMap`] and current [`Interest`] as well as - /// clearing the debug counters. - pub(crate) fn clear_enabled() { - // Drop the `Result` returned by `try_with` --- if we are in the middle - // a panic and the thread-local has been torn down, that's fine, just - // ignore it ratehr than panicking. - let _ = FILTERING.try_with(|filtering| { - filtering.enabled.set(FilterMap::default()); - - #[cfg(debug_assertions)] - filtering.counters.in_filter_pass.set(0); - }); - } - - pub(crate) fn take_interest() -> Option<Interest> { - FILTERING - .try_with(|filtering| { - #[cfg(debug_assertions)] - { - if filtering.counters.in_interest_pass.get() == 0 { - debug_assert!(filtering.interest.try_borrow().ok()?.is_none()); - } - filtering.counters.in_interest_pass.set(0); - } - filtering.interest.try_borrow_mut().ok()?.take() - }) - .ok()? - } - - pub(crate) fn filter_map(&self) -> FilterMap { - let map = self.enabled.get(); - #[cfg(debug_assertions)] - { - if self.counters.in_filter_pass.get() == 0 { - debug_assert_eq!(map, FilterMap::default()); - } - } - - map - } -} -/// This is a horrible and bad abuse of the downcasting system to expose -/// *internally* whether a layer has per-layer filtering, within -/// `tracing-subscriber`, without exposing a public API for it. -/// -/// If a `Layer` has per-layer filtering, it will downcast to a -/// `MagicPlfDowncastMarker`. Since layers which contain other layers permit -/// downcasting to recurse to their children, this will do the Right Thing with -/// layers like Reload, Option, etc. -/// -/// Why is this a wrapper around the `FilterId`, you may ask? Because -/// downcasting works by returning a pointer, and we don't want to risk -/// introducing UB by constructing pointers that _don't_ point to a valid -/// instance of the type they claim to be. In this case, we don't _intend_ for -/// this pointer to be dereferenced, so it would actually be fine to return one -/// that isn't a valid pointer...but we can't guarantee that the caller won't -/// (accidentally) dereference it, so it's better to be safe than sorry. We -/// could, alternatively, add an additional field to the type that's used only -/// for returning pointers to as as part of the evil downcasting hack, but I -/// thought it was nicer to just add a `repr(transparent)` wrapper to the -/// existing `FilterId` field, since it won't make the struct any bigger. -/// -/// Don't worry, this isn't on the test. :) -#[derive(Clone, Copy)] -#[repr(transparent)] -struct MagicPlfDowncastMarker(FilterId); -impl fmt::Debug for MagicPlfDowncastMarker { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Just pretend that `MagicPlfDowncastMarker` doesn't exist for - // `fmt::Debug` purposes...if no one *sees* it in their `Debug` output, - // they don't have to know I thought this code would be a good idea. - fmt::Debug::fmt(&self.0, f) - } -} - -pub(crate) fn is_plf_downcast_marker(type_id: TypeId) -> bool { - type_id == TypeId::of::<MagicPlfDowncastMarker>() -} - -/// Does a type implementing `Subscriber` contain any per-layer filters? -pub(crate) fn subscriber_has_plf<S>(subscriber: &S) -> bool -where - S: Subscriber, -{ - (subscriber as &dyn Subscriber).is::<MagicPlfDowncastMarker>() -} - -/// Does a type implementing `Layer` contain any per-layer filters? -pub(crate) fn layer_has_plf<L, S>(layer: &L) -> bool -where - L: Layer<S>, - S: Subscriber, -{ - unsafe { - // Safety: we're not actually *doing* anything with this pointer --- we - // only care about the `Option`, which we're turning into a `bool`. So - // even if the layer decides to be evil and give us some kind of invalid - // pointer, we don't ever dereference it, so this is always safe. - layer.downcast_raw(TypeId::of::<MagicPlfDowncastMarker>()) - } - .is_some() -} - -struct FmtBitset(u64); - -impl fmt::Debug for FmtBitset { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut set = f.debug_set(); - for bit in 0..64 { - // if the `bit`-th bit is set, add it to the debug set - if self.0 & (1 << bit) != 0 { - set.entry(&bit); - } - } - set.finish() - } -} diff --git a/vendor/tracing-subscriber/src/filter/level.rs b/vendor/tracing-subscriber/src/filter/level.rs deleted file mode 100644 index 0fa601260..000000000 --- a/vendor/tracing-subscriber/src/filter/level.rs +++ /dev/null @@ -1,27 +0,0 @@ -use tracing_core::{ - subscriber::{Interest, Subscriber}, - Metadata, -}; - -#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 -pub use tracing_core::metadata::{LevelFilter, ParseLevelFilterError as ParseError}; - -// === impl LevelFilter === - -impl<S: Subscriber> crate::Layer<S> for LevelFilter { - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - if self >= metadata.level() { - Interest::always() - } else { - Interest::never() - } - } - - fn enabled(&self, metadata: &Metadata<'_>, _: crate::layer::Context<'_, S>) -> bool { - self >= metadata.level() - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - Some(*self) - } -} diff --git a/vendor/tracing-subscriber/src/filter/mod.rs b/vendor/tracing-subscriber/src/filter/mod.rs deleted file mode 100644 index 000a27195..000000000 --- a/vendor/tracing-subscriber/src/filter/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! [`Layer`]s that control which spans and events are enabled by the wrapped -//! subscriber. -//! -//! This module contains a number of types that provide implementations of -//! various strategies for filtering which spans and events are enabled. For -//! details on filtering spans and events using [`Layer`]s, see the -//! [`layer` module's documentation]. -//! -//! [`layer` module's documentation]: crate::layer#filtering-with-layers -//! [`Layer`]: crate::layer -mod filter_fn; - -feature! { - #![all(feature = "env-filter", feature = "std")] - mod env; - pub use self::env::*; -} - -feature! { - #![all(feature = "registry", feature = "std")] - mod layer_filters; - pub use self::layer_filters::*; -} - -mod level; - -pub use self::filter_fn::*; -pub use self::level::{LevelFilter, ParseError as LevelParseError}; - -#[cfg(not(all(feature = "registry", feature = "std")))] -pub(crate) use self::has_plf_stubs::*; - -feature! { - #![any(feature = "std", feature = "alloc")] - pub mod targets; - pub use self::targets::Targets; - - mod directive; - pub use self::directive::ParseError; -} - -/// Stub implementations of the per-layer-fitler detection functions for when the -/// `registry` feature is disabled. -#[cfg(not(all(feature = "registry", feature = "std")))] -mod has_plf_stubs { - pub(crate) fn is_plf_downcast_marker(_: core::any::TypeId) -> bool { - false - } - - /// Does a type implementing `Subscriber` contain any per-layer filters? - pub(crate) fn subscriber_has_plf<S>(_: &S) -> bool - where - S: tracing_core::Subscriber, - { - false - } - - /// Does a type implementing `Layer` contain any per-layer filters? - pub(crate) fn layer_has_plf<L, S>(_: &L) -> bool - where - L: crate::Layer<S>, - S: tracing_core::Subscriber, - { - false - } -} diff --git a/vendor/tracing-subscriber/src/filter/targets.rs b/vendor/tracing-subscriber/src/filter/targets.rs deleted file mode 100644 index 2a30d2db6..000000000 --- a/vendor/tracing-subscriber/src/filter/targets.rs +++ /dev/null @@ -1,710 +0,0 @@ -//! A [filter] that enables or disables spans and events based on their [target] and [level]. -//! -//! See [`Targets`] for details. -//! -//! [target]: tracing_core::Metadata::target -//! [level]: tracing_core::Level -//! [filter]: crate::layer#filtering-with-layers - -use crate::{ - filter::{ - directive::{DirectiveSet, ParseError, StaticDirective}, - LevelFilter, - }, - layer, -}; -#[cfg(not(feature = "std"))] -use alloc::string::String; -use core::{ - iter::{Extend, FilterMap, FromIterator}, - slice, - str::FromStr, -}; -use tracing_core::{Interest, Level, Metadata, Subscriber}; - -/// A filter that enables or disables spans and events based on their [target] -/// and [level]. -/// -/// Targets are typically equal to the Rust module path of the code where the -/// span or event was recorded, although they may be overridden. -/// -/// This type can be used for both [per-layer filtering][plf] (using its -/// [`Filter`] implementation) and [global filtering][global] (using its -/// [`Layer`] implementation). -/// -/// See the [documentation on filtering with layers][filtering] for details. -/// -/// # Filtering With `Targets` -/// -/// A `Targets` filter consists of one or more [target] prefixes, paired with -/// [`LevelFilter`]s. If a span or event's [target] begins with one of those -/// prefixes, and its [level] is at or below the [`LevelFilter`] enabled for -/// that prefix, then the span or event will be enabled. -/// -/// This is similar to the behavior implemented by the [`env_logger` crate] in -/// the `log` ecosystem. -/// -/// The [`EnvFilter`] type also provided by this crate is very similar to `Targets`, -/// but is capable of a more sophisticated form of filtering where events may -/// also be enabled or disabled based on the span they are recorded in. -/// `Targets` can be thought of as a lighter-weight form of [`EnvFilter`] that -/// can be used instead when this dynamic filtering is not required. -/// -/// # Examples -/// -/// A `Targets` filter can be constructed by programmatically adding targets and -/// levels to enable: -/// -/// ``` -/// use tracing_subscriber::{filter, prelude::*}; -/// use tracing_core::Level; -/// -/// let filter = filter::Targets::new() -/// // Enable the `INFO` level for anything in `my_crate` -/// .with_target("my_crate", Level::INFO) -/// // Enable the `DEBUG` level for a specific module. -/// .with_target("my_crate::interesting_module", Level::DEBUG); -/// -/// // Build a new subscriber with the `fmt` layer using the `Targets` -/// // filter we constructed above. -/// tracing_subscriber::registry() -/// .with(tracing_subscriber::fmt::layer()) -/// .with(filter) -/// .init(); -/// ``` -/// -/// [`LevelFilter::OFF`] can be used to disable a particular target: -/// ``` -/// use tracing_subscriber::filter::{Targets, LevelFilter}; -/// use tracing_core::Level; -/// -/// let filter = Targets::new() -/// .with_target("my_crate", Level::INFO) -/// // Disable all traces from `annoying_module`. -/// .with_target("my_crate::annoying_module", LevelFilter::OFF); -/// # drop(filter); -/// ``` -/// -/// Alternatively, `Targets` implements [`std::str::FromStr`], allowing it to be -/// parsed from a comma-delimited list of `target=level` pairs. For example: -/// -/// ```rust -/// # fn main() -> Result<(), Box<dyn std::error::Error>> { -/// use tracing_subscriber::filter; -/// use tracing_core::Level; -/// -/// let filter = "my_crate=info,my_crate::interesting_module=trace,other_crate=debug" -/// .parse::<filter::Targets>()?; -/// -/// // The parsed filter is identical to a filter constructed using `with_target`: -/// assert_eq!( -/// filter, -/// filter::Targets::new() -/// .with_target("my_crate", Level::INFO) -/// .with_target("my_crate::interesting_module", Level::TRACE) -/// .with_target("other_crate", Level::DEBUG) -/// ); -/// # Ok(()) } -/// ``` -/// -/// This is particularly useful when the list of enabled targets is configurable -/// by the user at runtime. -/// -/// The `Targets` filter can be used as a [per-layer filter][plf] *and* as a -/// [global filter][global]: -/// -/// ```rust -/// use tracing_subscriber::{ -/// fmt, -/// filter::{Targets, LevelFilter}, -/// prelude::*, -/// }; -/// use tracing_core::Level; -/// use std::{sync::Arc, fs::File}; -/// # fn docs() -> Result<(), Box<dyn std::error::Error>> { -/// -/// // A layer that logs events to stdout using the human-readable "pretty" -/// // format. -/// let stdout_log = fmt::layer().pretty(); -/// -/// // A layer that logs events to a file, using the JSON format. -/// let file = File::create("debug_log.json")?; -/// let debug_log = fmt::layer() -/// .with_writer(Arc::new(file)) -/// .json(); -/// -/// tracing_subscriber::registry() -/// // Only log INFO and above to stdout, unless the span or event -/// // has the `my_crate::cool_module` target prefix. -/// .with(stdout_log -/// .with_filter( -/// Targets::default() -/// .with_target("my_crate::cool_module", Level::DEBUG) -/// .with_default(Level::INFO) -/// ) -/// ) -/// // Log everything enabled by the global filter to `debug_log.json`. -/// .with(debug_log) -/// // Configure a global filter for the whole subscriber stack. This will -/// // control what spans and events are recorded by both the `debug_log` -/// // and the `stdout_log` layers, and `stdout_log` will *additionally* be -/// // filtered by its per-layer filter. -/// .with( -/// Targets::default() -/// .with_target("my_crate", Level::TRACE) -/// .with_target("other_crate", Level::INFO) -/// .with_target("other_crate::annoying_module", LevelFilter::OFF) -/// .with_target("third_crate", Level::DEBUG) -/// ).init(); -/// # Ok(()) } -///``` -/// -/// [target]: tracing_core::Metadata::target -/// [level]: tracing_core::Level -/// [`Filter`]: crate::layer::Filter -/// [`Layer`]: crate::layer::Layer -/// [plf]: crate::layer#per-layer-filtering -/// [global]: crate::layer#global-filtering -/// [filtering]: crate::layer#filtering-with-layers -/// [`env_logger` crate]: https://docs.rs/env_logger/0.9.0/env_logger/index.html#enabling-logging -/// [`EnvFilter`]: crate::filter::EnvFilter -#[derive(Debug, Default, Clone, PartialEq)] -pub struct Targets(DirectiveSet<StaticDirective>); - -impl Targets { - /// Returns a new `Targets` filter. - /// - /// This filter will enable no targets. Call [`with_target`] or [`with_targets`] - /// to add enabled targets, and [`with_default`] to change the default level - /// enabled for spans and events that didn't match any of the provided targets. - /// - /// [`with_target`]: Targets::with_target - /// [`with_targets`]: Targets::with_targets - /// [`with_default`]: Targets::with_default - pub fn new() -> Self { - Self::default() - } - - /// Enables spans and events with [target]s starting with the provided target - /// prefix if they are at or below the provided [`LevelFilter`]. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::filter; - /// use tracing_core::Level; - /// - /// let filter = filter::Targets::new() - /// // Enable the `INFO` level for anything in `my_crate` - /// .with_target("my_crate", Level::INFO) - /// // Enable the `DEBUG` level for a specific module. - /// .with_target("my_crate::interesting_module", Level::DEBUG); - /// # drop(filter); - /// ``` - /// - /// [`LevelFilter::OFF`] can be used to disable a particular target: - /// ``` - /// use tracing_subscriber::filter::{Targets, LevelFilter}; - /// use tracing_core::Level; - /// - /// let filter = Targets::new() - /// .with_target("my_crate", Level::INFO) - /// // Disable all traces from `annoying_module`. - /// .with_target("my_crate::interesting_module", LevelFilter::OFF); - /// # drop(filter); - /// ``` - /// - /// [target]: tracing_core::Metadata::target - pub fn with_target(mut self, target: impl Into<String>, level: impl Into<LevelFilter>) -> Self { - self.0.add(StaticDirective::new( - Some(target.into()), - Default::default(), - level.into(), - )); - self - } - /// Adds [target]s from an iterator of [target]-[`LevelFilter`] pairs to this filter. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::filter; - /// use tracing_core::Level; - /// - /// let filter = filter::Targets::new() - /// .with_targets(vec![ - /// ("my_crate", Level::INFO), - /// ("my_crate::some_module", Level::DEBUG), - /// ("my_crate::other_module::cool_stuff", Level::TRACE), - /// ("other_crate", Level::WARN) - /// ]); - /// # drop(filter); - /// ``` - /// - /// [`LevelFilter::OFF`] can be used to disable a particular target: - /// ``` - /// use tracing_subscriber::filter::{Targets, LevelFilter}; - /// use tracing_core::Level; - /// - /// let filter = Targets::new() - /// .with_target("my_crate", Level::INFO) - /// // Disable all traces from `annoying_module`. - /// .with_target("my_crate::interesting_module", LevelFilter::OFF); - /// # drop(filter); - /// ``` - /// - /// [target]: tracing_core::Metadata::target - pub fn with_targets<T, L>(mut self, targets: impl IntoIterator<Item = (T, L)>) -> Self - where - String: From<T>, - LevelFilter: From<L>, - { - self.extend(targets); - self - } - - /// Sets the default level to enable for spans and events whose targets did - /// not match any of the configured prefixes. - /// - /// By default, this is [`LevelFilter::OFF`]. This means that spans and - /// events will only be enabled if they match one of the configured target - /// prefixes. If this is changed to a different [`LevelFilter`], spans and - /// events with targets that did not match any of the configured prefixes - /// will be enabled if their level is at or below the provided level. - pub fn with_default(mut self, level: impl Into<LevelFilter>) -> Self { - self.0 - .add(StaticDirective::new(None, Default::default(), level.into())); - self - } - - /// Returns an iterator over the [target]-[`LevelFilter`] pairs in this filter. - /// - /// The order of iteration is undefined. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::filter::{Targets, LevelFilter}; - /// use tracing_core::Level; - /// - /// let filter = Targets::new() - /// .with_target("my_crate", Level::INFO) - /// .with_target("my_crate::interesting_module", Level::DEBUG); - /// - /// let mut targets: Vec<_> = filter.iter().collect(); - /// targets.sort(); - /// - /// assert_eq!(targets, vec![ - /// ("my_crate", LevelFilter::INFO), - /// ("my_crate::interesting_module", LevelFilter::DEBUG), - /// ]); - /// ``` - /// - /// [target]: tracing_core::Metadata::target - pub fn iter(&self) -> Iter<'_> { - self.into_iter() - } - - #[inline] - fn interested(&self, metadata: &'static Metadata<'static>) -> Interest { - if self.0.enabled(metadata) { - Interest::always() - } else { - Interest::never() - } - } - - /// Returns whether a [target]-[`Level`] pair would be enabled - /// by this `Targets`. - /// - /// This method can be used with [`module_path!`] from `std` as the target - /// in order to emulate the behavior of the [`tracing::event!`] and [`tracing::span!`] - /// macros. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::filter::{Targets, LevelFilter}; - /// use tracing_core::Level; - /// - /// let filter = Targets::new() - /// .with_target("my_crate", Level::INFO) - /// .with_target("my_crate::interesting_module", Level::DEBUG); - /// - /// assert!(filter.would_enable("my_crate", &Level::INFO)); - /// assert!(!filter.would_enable("my_crate::interesting_module", &Level::TRACE)); - /// ``` - /// - /// [target]: tracing_core::Metadata::target - /// [`module_path!`]: std::module_path! - pub fn would_enable(&self, target: &str, level: &Level) -> bool { - // "Correct" to call because `Targets` only produces `StaticDirective`'s with NO - // fields - self.0.target_enabled(target, level) - } -} - -impl<T, L> Extend<(T, L)> for Targets -where - T: Into<String>, - L: Into<LevelFilter>, -{ - fn extend<I: IntoIterator<Item = (T, L)>>(&mut self, iter: I) { - let iter = iter.into_iter().map(|(target, level)| { - StaticDirective::new(Some(target.into()), Default::default(), level.into()) - }); - self.0.extend(iter); - } -} - -impl<T, L> FromIterator<(T, L)> for Targets -where - T: Into<String>, - L: Into<LevelFilter>, -{ - fn from_iter<I: IntoIterator<Item = (T, L)>>(iter: I) -> Self { - let mut this = Self::default(); - this.extend(iter); - this - } -} - -impl FromStr for Targets { - type Err = ParseError; - fn from_str(s: &str) -> Result<Self, Self::Err> { - s.split(',') - .map(StaticDirective::from_str) - .collect::<Result<_, _>>() - .map(Self) - } -} - -impl<S> layer::Layer<S> for Targets -where - S: Subscriber, -{ - fn enabled(&self, metadata: &Metadata<'_>, _: layer::Context<'_, S>) -> bool { - self.0.enabled(metadata) - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.interested(metadata) - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - Some(self.0.max_level) - } -} - -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(feature = "registry")))] -impl<S> layer::Filter<S> for Targets { - fn enabled(&self, metadata: &Metadata<'_>, _: &layer::Context<'_, S>) -> bool { - self.0.enabled(metadata) - } - - fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - self.interested(metadata) - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - Some(self.0.max_level) - } -} - -impl IntoIterator for Targets { - type Item = (String, LevelFilter); - - type IntoIter = IntoIter; - - fn into_iter(self) -> Self::IntoIter { - IntoIter::new(self) - } -} - -impl<'a> IntoIterator for &'a Targets { - type Item = (&'a str, LevelFilter); - - type IntoIter = Iter<'a>; - - fn into_iter(self) -> Self::IntoIter { - Iter::new(self) - } -} - -/// An owning iterator over the [target]-[level] pairs of a `Targets` filter. -/// -/// This struct is created by the `IntoIterator` trait implementation of [`Targets`]. -/// -/// # Examples -/// -/// Merge the targets from one `Targets` with another: -/// -/// ``` -/// use tracing_subscriber::filter::Targets; -/// use tracing_core::Level; -/// -/// let mut filter = Targets::new().with_target("my_crate", Level::INFO); -/// let overrides = Targets::new().with_target("my_crate::interesting_module", Level::DEBUG); -/// -/// filter.extend(overrides); -/// # drop(filter); -/// ``` -/// -/// [target]: tracing_core::Metadata::target -/// [level]: tracing_core::Level -#[derive(Debug)] -pub struct IntoIter( - #[allow(clippy::type_complexity)] // alias indirection would probably make this more confusing - FilterMap< - <DirectiveSet<StaticDirective> as IntoIterator>::IntoIter, - fn(StaticDirective) -> Option<(String, LevelFilter)>, - >, -); - -impl IntoIter { - fn new(targets: Targets) -> Self { - Self(targets.0.into_iter().filter_map(|directive| { - let level = directive.level; - directive.target.map(|target| (target, level)) - })) - } -} - -impl Iterator for IntoIter { - type Item = (String, LevelFilter); - - fn next(&mut self) -> Option<Self::Item> { - self.0.next() - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.0.size_hint() - } -} - -/// A borrowing iterator over the [target]-[level] pairs of a `Targets` filter. -/// -/// This struct is created by [`iter`] method of [`Targets`], or from the `IntoIterator` -/// implementation for `&Targets`. -/// -/// [target]: tracing_core::Metadata::target -/// [level]: tracing_core::Level -/// [`iter`]: Targets::iter -#[derive(Debug)] -pub struct Iter<'a>( - FilterMap< - slice::Iter<'a, StaticDirective>, - fn(&'a StaticDirective) -> Option<(&'a str, LevelFilter)>, - >, -); - -impl<'a> Iter<'a> { - fn new(targets: &'a Targets) -> Self { - Self(targets.0.iter().filter_map(|directive| { - directive - .target - .as_deref() - .map(|target| (target, directive.level)) - })) - } -} - -impl<'a> Iterator for Iter<'a> { - type Item = (&'a str, LevelFilter); - - fn next(&mut self) -> Option<Self::Item> { - self.0.next() - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.0.size_hint() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - feature! { - #![not(feature = "std")] - use alloc::{vec, vec::Vec, string::ToString}; - - // `dbg!` is only available with `libstd`; just nop it out when testing - // with alloc only. - macro_rules! dbg { - ($x:expr) => { $x } - } - } - - fn expect_parse(s: &str) -> Targets { - match dbg!(s).parse::<Targets>() { - Err(e) => panic!("string {:?} did not parse successfully: {}", s, e), - Ok(e) => e, - } - } - - fn expect_parse_ralith(s: &str) { - let dirs = expect_parse(s).0.into_vec(); - assert_eq!(dirs.len(), 2, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("server".to_string())); - assert_eq!(dirs[0].level, LevelFilter::DEBUG); - assert_eq!(dirs[0].field_names, Vec::<String>::new()); - - assert_eq!(dirs[1].target, Some("common".to_string())); - assert_eq!(dirs[1].level, LevelFilter::INFO); - assert_eq!(dirs[1].field_names, Vec::<String>::new()); - } - - fn expect_parse_level_directives(s: &str) { - let dirs = expect_parse(s).0.into_vec(); - assert_eq!(dirs.len(), 6, "\nparsed: {:#?}", dirs); - - assert_eq!(dirs[0].target, Some("crate3::mod2::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::OFF); - assert_eq!(dirs[0].field_names, Vec::<String>::new()); - - assert_eq!(dirs[1].target, Some("crate1::mod2::mod3".to_string())); - assert_eq!(dirs[1].level, LevelFilter::INFO); - assert_eq!(dirs[1].field_names, Vec::<String>::new()); - - assert_eq!(dirs[2].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::WARN); - assert_eq!(dirs[2].field_names, Vec::<String>::new()); - - assert_eq!(dirs[3].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[3].level, LevelFilter::ERROR); - assert_eq!(dirs[3].field_names, Vec::<String>::new()); - - assert_eq!(dirs[4].target, Some("crate3".to_string())); - assert_eq!(dirs[4].level, LevelFilter::TRACE); - assert_eq!(dirs[4].field_names, Vec::<String>::new()); - - assert_eq!(dirs[5].target, Some("crate2".to_string())); - assert_eq!(dirs[5].level, LevelFilter::DEBUG); - assert_eq!(dirs[5].field_names, Vec::<String>::new()); - } - - #[test] - fn parse_ralith() { - expect_parse_ralith("common=info,server=debug"); - } - - #[test] - fn parse_ralith_uc() { - expect_parse_ralith("common=INFO,server=DEBUG"); - } - - #[test] - fn parse_ralith_mixed() { - expect_parse("common=iNfo,server=dEbUg"); - } - - #[test] - fn expect_parse_valid() { - let dirs = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off") - .0 - .into_vec(); - assert_eq!(dirs.len(), 4, "\nparsed: {:#?}", dirs); - assert_eq!(dirs[0].target, Some("crate1::mod2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::TRACE); - assert_eq!(dirs[0].field_names, Vec::<String>::new()); - - assert_eq!(dirs[1].target, Some("crate1::mod1".to_string())); - assert_eq!(dirs[1].level, LevelFilter::ERROR); - assert_eq!(dirs[1].field_names, Vec::<String>::new()); - - assert_eq!(dirs[2].target, Some("crate3".to_string())); - assert_eq!(dirs[2].level, LevelFilter::OFF); - assert_eq!(dirs[2].field_names, Vec::<String>::new()); - - assert_eq!(dirs[3].target, Some("crate2".to_string())); - assert_eq!(dirs[3].level, LevelFilter::DEBUG); - assert_eq!(dirs[3].field_names, Vec::<String>::new()); - } - - #[test] - fn parse_level_directives() { - expect_parse_level_directives( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off", - ) - } - - #[test] - fn parse_uppercase_level_directives() { - expect_parse_level_directives( - "crate1::mod1=ERROR,crate1::mod2=WARN,crate1::mod2::mod3=INFO,\ - crate2=DEBUG,crate3=TRACE,crate3::mod2::mod1=OFF", - ) - } - - #[test] - fn parse_numeric_level_directives() { - expect_parse_level_directives( - "crate1::mod1=1,crate1::mod2=2,crate1::mod2::mod3=3,crate2=4,\ - crate3=5,crate3::mod2::mod1=0", - ) - } - - #[test] - fn targets_iter() { - let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off") - .with_default(LevelFilter::WARN); - - let mut targets: Vec<_> = filter.iter().collect(); - targets.sort(); - - assert_eq!( - targets, - vec![ - ("crate1::mod1", LevelFilter::ERROR), - ("crate1::mod2", LevelFilter::TRACE), - ("crate2", LevelFilter::DEBUG), - ("crate3", LevelFilter::OFF), - ] - ); - } - - #[test] - fn targets_into_iter() { - let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off") - .with_default(LevelFilter::WARN); - - let mut targets: Vec<_> = filter.into_iter().collect(); - targets.sort(); - - assert_eq!( - targets, - vec![ - ("crate1::mod1".to_string(), LevelFilter::ERROR), - ("crate1::mod2".to_string(), LevelFilter::TRACE), - ("crate2".to_string(), LevelFilter::DEBUG), - ("crate3".to_string(), LevelFilter::OFF), - ] - ); - } - - #[test] - // `println!` is only available with `libstd`. - #[cfg(feature = "std")] - fn size_of_filters() { - fn print_sz(s: &str) { - let filter = s.parse::<Targets>().expect("filter should parse"); - println!( - "size_of_val({:?})\n -> {}B", - s, - std::mem::size_of_val(&filter) - ); - } - - print_sz("info"); - - print_sz("foo=debug"); - - print_sz( - "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\ - crate2=debug,crate3=trace,crate3::mod2::mod1=off", - ); - } -} diff --git a/vendor/tracing-subscriber/src/fmt/fmt_layer.rs b/vendor/tracing-subscriber/src/fmt/fmt_layer.rs deleted file mode 100644 index 21992e780..000000000 --- a/vendor/tracing-subscriber/src/fmt/fmt_layer.rs +++ /dev/null @@ -1,1368 +0,0 @@ -use crate::{ - field::RecordFields, - fmt::{format, FormatEvent, FormatFields, MakeWriter, TestWriter}, - layer::{self, Context}, - registry::{self, LookupSpan, SpanRef}, -}; -use format::{FmtSpan, TimingDisplay}; -use std::{any::TypeId, cell::RefCell, fmt, io, marker::PhantomData, ops::Deref, time::Instant}; -use tracing_core::{ - field, - span::{Attributes, Current, Id, Record}, - Event, Metadata, Subscriber, -}; - -/// A [`Layer`] that logs formatted representations of `tracing` events. -/// -/// ## Examples -/// -/// Constructing a layer with the default configuration: -/// -/// ```rust -/// use tracing_subscriber::{fmt, Registry}; -/// use tracing_subscriber::prelude::*; -/// -/// let subscriber = Registry::default() -/// .with(fmt::Layer::default()); -/// -/// tracing::subscriber::set_global_default(subscriber).unwrap(); -/// ``` -/// -/// Overriding the layer's behavior: -/// -/// ```rust -/// use tracing_subscriber::{fmt, Registry}; -/// use tracing_subscriber::prelude::*; -/// -/// let fmt_layer = fmt::layer() -/// .with_target(false) // don't include event targets when logging -/// .with_level(false); // don't include event levels when logging -/// -/// let subscriber = Registry::default().with(fmt_layer); -/// # tracing::subscriber::set_global_default(subscriber).unwrap(); -/// ``` -/// -/// Setting a custom event formatter: -/// -/// ```rust -/// use tracing_subscriber::fmt::{self, format, time}; -/// use tracing_subscriber::prelude::*; -/// -/// let fmt = format().with_timer(time::Uptime::default()); -/// let fmt_layer = fmt::layer() -/// .event_format(fmt) -/// .with_target(false); -/// # let subscriber = fmt_layer.with_subscriber(tracing_subscriber::registry::Registry::default()); -/// # tracing::subscriber::set_global_default(subscriber).unwrap(); -/// ``` -/// -/// [`Layer`]: super::layer::Layer -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -#[derive(Debug)] -pub struct Layer< - S, - N = format::DefaultFields, - E = format::Format<format::Full>, - W = fn() -> io::Stdout, -> { - make_writer: W, - fmt_fields: N, - fmt_event: E, - fmt_span: format::FmtSpanConfig, - is_ansi: bool, - _inner: PhantomData<fn(S)>, -} - -impl<S> Layer<S> { - /// Returns a new [`Layer`][self::Layer] with the default configuration. - pub fn new() -> Self { - Self::default() - } -} - -// This needs to be a seperate impl block because they place different bounds on the type parameters. -impl<S, N, E, W> Layer<S, N, E, W> -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'writer> FormatFields<'writer> + 'static, - W: for<'writer> MakeWriter<'writer> + 'static, -{ - /// Sets the [event formatter][`FormatEvent`] that the layer being built will - /// use to format events. - /// - /// The event formatter may be any type implementing the [`FormatEvent`] - /// trait, which is implemented for all functions taking a [`FmtContext`], a - /// [`Writer`], and an [`Event`]. - /// - /// # Examples - /// - /// Setting a type implementing [`FormatEvent`] as the formatter: - /// ```rust - /// use tracing_subscriber::fmt::{self, format}; - /// - /// let layer = fmt::layer() - /// .event_format(format().compact()); - /// # // this is necessary for type inference. - /// # use tracing_subscriber::Layer as _; - /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); - /// ``` - /// [`FormatEvent`]: format::FormatEvent - /// [`Event`]: tracing::Event - /// [`Writer`]: format::Writer - pub fn event_format<E2>(self, e: E2) -> Layer<S, N, E2, W> - where - E2: FormatEvent<S, N> + 'static, - { - Layer { - fmt_fields: self.fmt_fields, - fmt_event: e, - fmt_span: self.fmt_span, - make_writer: self.make_writer, - is_ansi: self.is_ansi, - _inner: self._inner, - } - } - - /// Updates the event formatter by applying a function to the existing event formatter. - /// - /// This sets the event formatter that the layer being built will use to record fields. - /// - /// # Examples - /// - /// Updating an event formatter: - /// - /// ```rust - /// let layer = tracing_subscriber::fmt::layer() - /// .map_event_format(|e| e.compact()); - /// # // this is necessary for type inference. - /// # use tracing_subscriber::Layer as _; - /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); - /// ``` - pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> Layer<S, N, E2, W> - where - E2: FormatEvent<S, N> + 'static, - { - Layer { - fmt_fields: self.fmt_fields, - fmt_event: f(self.fmt_event), - fmt_span: self.fmt_span, - make_writer: self.make_writer, - is_ansi: self.is_ansi, - _inner: self._inner, - } - } -} - -// This needs to be a seperate impl block because they place different bounds on the type parameters. -impl<S, N, E, W> Layer<S, N, E, W> { - /// Sets the [`MakeWriter`] that the layer being built will use to write events. - /// - /// # Examples - /// - /// Using `stderr` rather than `stdout`: - /// - /// ```rust - /// use std::io; - /// use tracing_subscriber::fmt; - /// - /// let layer = fmt::layer() - /// .with_writer(io::stderr); - /// # // this is necessary for type inference. - /// # use tracing_subscriber::Layer as _; - /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); - /// ``` - pub fn with_writer<W2>(self, make_writer: W2) -> Layer<S, N, E, W2> - where - W2: for<'writer> MakeWriter<'writer> + 'static, - { - Layer { - fmt_fields: self.fmt_fields, - fmt_event: self.fmt_event, - fmt_span: self.fmt_span, - is_ansi: self.is_ansi, - make_writer, - _inner: self._inner, - } - } - - /// Borrows the [writer] for this [`Layer`]. - /// - /// [writer]: MakeWriter - pub fn writer(&self) -> &W { - &self.make_writer - } - - /// Mutably borrows the [writer] for this [`Layer`]. - /// - /// This method is primarily expected to be used with the - /// [`reload::Handle::modify`](crate::reload::Handle::modify) method. - /// - /// # Examples - /// - /// ``` - /// # use tracing::info; - /// # use tracing_subscriber::{fmt,reload,Registry,prelude::*}; - /// # fn non_blocking<T: std::io::Write>(writer: T) -> (fn() -> std::io::Stdout) { - /// # std::io::stdout - /// # } - /// # fn main() { - /// let layer = fmt::layer().with_writer(non_blocking(std::io::stderr())); - /// let (layer, reload_handle) = reload::Layer::new(layer); - /// # - /// # // specifying the Registry type is required - /// # let _: &reload::Handle<fmt::Layer<Registry, _, _, _>, Registry> = &reload_handle; - /// # - /// info!("This will be logged to stderr"); - /// reload_handle.modify(|layer| *layer.writer_mut() = non_blocking(std::io::stdout())); - /// info!("This will be logged to stdout"); - /// # } - /// ``` - /// - /// [writer]: MakeWriter - pub fn writer_mut(&mut self) -> &mut W { - &mut self.make_writer - } - - /// Sets whether this layer should use ANSI terminal formatting - /// escape codes (such as colors). - /// - /// This method is primarily expected to be used with the - /// [`reload::Handle::modify`](crate::reload::Handle::modify) method when changing - /// the writer. - #[cfg(feature = "ansi")] - #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))] - pub fn set_ansi(&mut self, ansi: bool) { - self.is_ansi = ansi; - } - - /// Configures the layer to support [`libtest`'s output capturing][capturing] when used in - /// unit tests. - /// - /// See [`TestWriter`] for additional details. - /// - /// # Examples - /// - /// Using [`TestWriter`] to let `cargo test` capture test output: - /// - /// ```rust - /// use std::io; - /// use tracing_subscriber::fmt; - /// - /// let layer = fmt::layer() - /// .with_test_writer(); - /// # // this is necessary for type inference. - /// # use tracing_subscriber::Layer as _; - /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); - /// ``` - /// [capturing]: - /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output - /// [`TestWriter`]: super::writer::TestWriter - pub fn with_test_writer(self) -> Layer<S, N, E, TestWriter> { - Layer { - fmt_fields: self.fmt_fields, - fmt_event: self.fmt_event, - fmt_span: self.fmt_span, - is_ansi: self.is_ansi, - make_writer: TestWriter::default(), - _inner: self._inner, - } - } - - /// Enable ANSI terminal colors for formatted output. - #[cfg(feature = "ansi")] - #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))] - pub fn with_ansi(self, ansi: bool) -> Self { - Self { - is_ansi: ansi, - ..self - } - } - - /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`]. - /// - /// This sets the [`MakeWriter`] that the layer being built will use to write events. - /// - /// # Examples - /// - /// Redirect output to stderr if level is <= WARN: - /// - /// ```rust - /// use tracing::Level; - /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt}; - /// - /// let stderr = std::io::stderr.with_max_level(Level::WARN); - /// let layer = fmt::layer() - /// .map_writer(move |w| stderr.or_else(w)); - /// # // this is necessary for type inference. - /// # use tracing_subscriber::Layer as _; - /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); - /// ``` - pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> Layer<S, N, E, W2> - where - W2: for<'writer> MakeWriter<'writer> + 'static, - { - Layer { - fmt_fields: self.fmt_fields, - fmt_event: self.fmt_event, - fmt_span: self.fmt_span, - is_ansi: self.is_ansi, - make_writer: f(self.make_writer), - _inner: self._inner, - } - } -} - -impl<S, N, L, T, W> Layer<S, N, format::Format<L, T>, W> -where - N: for<'writer> FormatFields<'writer> + 'static, -{ - /// Use the given [`timer`] for span and event timestamps. - /// - /// See the [`time` module] for the provided timer implementations. - /// - /// Note that using the `"time`"" feature flag enables the - /// additional time formatters [`UtcTime`] and [`LocalTime`], which use the - /// [`time` crate] to provide more sophisticated timestamp formatting - /// options. - /// - /// [`timer`]: super::time::FormatTime - /// [`time` module]: mod@super::time - /// [`UtcTime`]: super::time::UtcTime - /// [`LocalTime`]: super::time::LocalTime - /// [`time` crate]: https://docs.rs/time/0.3 - pub fn with_timer<T2>(self, timer: T2) -> Layer<S, N, format::Format<L, T2>, W> { - Layer { - fmt_event: self.fmt_event.with_timer(timer), - fmt_fields: self.fmt_fields, - fmt_span: self.fmt_span, - make_writer: self.make_writer, - is_ansi: self.is_ansi, - _inner: self._inner, - } - } - - /// Do not emit timestamps with spans and event. - pub fn without_time(self) -> Layer<S, N, format::Format<L, ()>, W> { - Layer { - fmt_event: self.fmt_event.without_time(), - fmt_fields: self.fmt_fields, - fmt_span: self.fmt_span.without_time(), - make_writer: self.make_writer, - is_ansi: self.is_ansi, - _inner: self._inner, - } - } - - /// Configures how synthesized events are emitted at points in the [span - /// lifecycle][lifecycle]. - /// - /// The following options are available: - /// - /// - `FmtSpan::NONE`: No events will be synthesized when spans are - /// created, entered, exited, or closed. Data from spans will still be - /// included as the context for formatted events. This is the default. - /// - `FmtSpan::NEW`: An event will be synthesized when spans are created. - /// - `FmtSpan::ENTER`: An event will be synthesized when spans are entered. - /// - `FmtSpan::EXIT`: An event will be synthesized when spans are exited. - /// - `FmtSpan::CLOSE`: An event will be synthesized when a span closes. If - /// [timestamps are enabled][time] for this formatter, the generated - /// event will contain fields with the span's _busy time_ (the total - /// time for which it was entered) and _idle time_ (the total time that - /// the span existed but was not entered). - /// - `FmtSpan::ACTIVE`: Events will be synthesized when spans are entered - /// or exited. - /// - `FmtSpan::FULL`: Events will be synthesized whenever a span is - /// created, entered, exited, or closed. If timestamps are enabled, the - /// close event will contain the span's busy and idle time, as - /// described above. - /// - /// The options can be enabled in any combination. For instance, the following - /// will synthesize events whenever spans are created and closed: - /// - /// ```rust - /// use tracing_subscriber::fmt; - /// use tracing_subscriber::fmt::format::FmtSpan; - /// - /// let subscriber = fmt() - /// .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE) - /// .finish(); - /// ``` - /// - /// Note that the generated events will only be part of the log output by - /// this formatter; they will not be recorded by other `Subscriber`s or by - /// `Layer`s added to this subscriber. - /// - /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle - /// [time]: Layer::without_time() - pub fn with_span_events(self, kind: FmtSpan) -> Self { - Layer { - fmt_span: self.fmt_span.with_kind(kind), - ..self - } - } - - /// Sets whether or not an event's target is displayed. - pub fn with_target(self, display_target: bool) -> Layer<S, N, format::Format<L, T>, W> { - Layer { - fmt_event: self.fmt_event.with_target(display_target), - ..self - } - } - /// Sets whether or not an event's [source code file path][file] is - /// displayed. - /// - /// [file]: tracing_core::Metadata::file - pub fn with_file(self, display_filename: bool) -> Layer<S, N, format::Format<L, T>, W> { - Layer { - fmt_event: self.fmt_event.with_file(display_filename), - ..self - } - } - - /// Sets whether or not an event's [source code line number][line] is - /// displayed. - /// - /// [line]: tracing_core::Metadata::line - pub fn with_line_number( - self, - display_line_number: bool, - ) -> Layer<S, N, format::Format<L, T>, W> { - Layer { - fmt_event: self.fmt_event.with_line_number(display_line_number), - ..self - } - } - - /// Sets whether or not an event's level is displayed. - pub fn with_level(self, display_level: bool) -> Layer<S, N, format::Format<L, T>, W> { - Layer { - fmt_event: self.fmt_event.with_level(display_level), - ..self - } - } - - /// Sets whether or not the [thread ID] of the current thread is displayed - /// when formatting events. - /// - /// [thread ID]: std::thread::ThreadId - pub fn with_thread_ids(self, display_thread_ids: bool) -> Layer<S, N, format::Format<L, T>, W> { - Layer { - fmt_event: self.fmt_event.with_thread_ids(display_thread_ids), - ..self - } - } - - /// Sets whether or not the [name] of the current thread is displayed - /// when formatting events. - /// - /// [name]: std::thread#naming-threads - pub fn with_thread_names( - self, - display_thread_names: bool, - ) -> Layer<S, N, format::Format<L, T>, W> { - Layer { - fmt_event: self.fmt_event.with_thread_names(display_thread_names), - ..self - } - } - - /// Sets the layer being built to use a [less verbose formatter][super::format::Compact]. - pub fn compact(self) -> Layer<S, N, format::Format<format::Compact, T>, W> - where - N: for<'writer> FormatFields<'writer> + 'static, - { - Layer { - fmt_event: self.fmt_event.compact(), - fmt_fields: self.fmt_fields, - fmt_span: self.fmt_span, - make_writer: self.make_writer, - is_ansi: self.is_ansi, - _inner: self._inner, - } - } - - /// Sets the layer being built to use an [excessively pretty, human-readable formatter](crate::fmt::format::Pretty). - #[cfg(feature = "ansi")] - #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))] - pub fn pretty(self) -> Layer<S, format::Pretty, format::Format<format::Pretty, T>, W> { - Layer { - fmt_event: self.fmt_event.pretty(), - fmt_fields: format::Pretty::default(), - fmt_span: self.fmt_span, - make_writer: self.make_writer, - is_ansi: self.is_ansi, - _inner: self._inner, - } - } - - /// Sets the layer being built to use a [JSON formatter][super::format::Json]. - /// - /// The full format includes fields from all entered spans. - /// - /// # Example Output - /// - /// ```ignore,json - /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate","fields":{"message":"some message", "key": "value"}} - /// ``` - /// - /// # Options - /// - /// - [`Layer::flatten_event`] can be used to enable flattening event fields into the root - /// object. - /// - /// [`Layer::flatten_event`]: Layer::flatten_event() - #[cfg(feature = "json")] - #[cfg_attr(docsrs, doc(cfg(feature = "json")))] - pub fn json(self) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { - Layer { - fmt_event: self.fmt_event.json(), - fmt_fields: format::JsonFields::new(), - fmt_span: self.fmt_span, - make_writer: self.make_writer, - // always disable ANSI escapes in JSON mode! - is_ansi: false, - _inner: self._inner, - } - } -} - -#[cfg(feature = "json")] -#[cfg_attr(docsrs, doc(cfg(feature = "json")))] -impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { - /// Sets the JSON layer being built to flatten event metadata. - /// - /// See [`format::Json`][super::format::Json] - pub fn flatten_event( - self, - flatten_event: bool, - ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { - Layer { - fmt_event: self.fmt_event.flatten_event(flatten_event), - fmt_fields: format::JsonFields::new(), - ..self - } - } - - /// Sets whether or not the formatter will include the current span in - /// formatted events. - /// - /// See [`format::Json`][super::format::Json] - pub fn with_current_span( - self, - display_current_span: bool, - ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { - Layer { - fmt_event: self.fmt_event.with_current_span(display_current_span), - fmt_fields: format::JsonFields::new(), - ..self - } - } - - /// Sets whether or not the formatter will include a list (from root to leaf) - /// of all currently entered spans in formatted events. - /// - /// See [`format::Json`][super::format::Json] - pub fn with_span_list( - self, - display_span_list: bool, - ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { - Layer { - fmt_event: self.fmt_event.with_span_list(display_span_list), - fmt_fields: format::JsonFields::new(), - ..self - } - } -} - -impl<S, N, E, W> Layer<S, N, E, W> { - /// Sets the field formatter that the layer being built will use to record - /// fields. - pub fn fmt_fields<N2>(self, fmt_fields: N2) -> Layer<S, N2, E, W> - where - N2: for<'writer> FormatFields<'writer> + 'static, - { - Layer { - fmt_event: self.fmt_event, - fmt_fields, - fmt_span: self.fmt_span, - make_writer: self.make_writer, - is_ansi: self.is_ansi, - _inner: self._inner, - } - } - - /// Updates the field formatter by applying a function to the existing field formatter. - /// - /// This sets the field formatter that the layer being built will use to record fields. - /// - /// # Examples - /// - /// Updating a field formatter: - /// - /// ```rust - /// use tracing_subscriber::field::MakeExt; - /// let layer = tracing_subscriber::fmt::layer() - /// .map_fmt_fields(|f| f.debug_alt()); - /// # // this is necessary for type inference. - /// # use tracing_subscriber::Layer as _; - /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); - /// ``` - pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> Layer<S, N2, E, W> - where - N2: for<'writer> FormatFields<'writer> + 'static, - { - Layer { - fmt_event: self.fmt_event, - fmt_fields: f(self.fmt_fields), - fmt_span: self.fmt_span, - make_writer: self.make_writer, - is_ansi: self.is_ansi, - _inner: self._inner, - } - } -} - -impl<S> Default for Layer<S> { - fn default() -> Self { - Layer { - fmt_fields: format::DefaultFields::default(), - fmt_event: format::Format::default(), - fmt_span: format::FmtSpanConfig::default(), - make_writer: io::stdout, - is_ansi: cfg!(feature = "ansi"), - _inner: PhantomData, - } - } -} - -impl<S, N, E, W> Layer<S, N, E, W> -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'writer> FormatFields<'writer> + 'static, - E: FormatEvent<S, N> + 'static, - W: for<'writer> MakeWriter<'writer> + 'static, -{ - #[inline] - fn make_ctx<'a>(&'a self, ctx: Context<'a, S>, event: &'a Event<'a>) -> FmtContext<'a, S, N> { - FmtContext { - ctx, - fmt_fields: &self.fmt_fields, - event, - } - } -} - -/// A formatted representation of a span's fields stored in its [extensions]. -/// -/// Because `FormattedFields` is generic over the type of the formatter that -/// produced it, multiple versions of a span's formatted fields can be stored in -/// the [`Extensions`][extensions] type-map. This means that when multiple -/// formatters are in use, each can store its own formatted representation -/// without conflicting. -/// -/// [extensions]: crate::registry::Extensions -#[derive(Default)] -pub struct FormattedFields<E: ?Sized> { - _format_fields: PhantomData<fn(E)>, - was_ansi: bool, - /// The formatted fields of a span. - pub fields: String, -} - -impl<E: ?Sized> FormattedFields<E> { - /// Returns a new `FormattedFields`. - pub fn new(fields: String) -> Self { - Self { - fields, - was_ansi: false, - _format_fields: PhantomData, - } - } - - /// Returns a new [`format::Writer`] for writing to this `FormattedFields`. - /// - /// The returned [`format::Writer`] can be used with the - /// [`FormatFields::format_fields`] method. - pub fn as_writer(&mut self) -> format::Writer<'_> { - format::Writer::new(&mut self.fields).with_ansi(self.was_ansi) - } -} - -impl<E: ?Sized> fmt::Debug for FormattedFields<E> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FormattedFields") - .field("fields", &self.fields) - .field("formatter", &format_args!("{}", std::any::type_name::<E>())) - .field("was_ansi", &self.was_ansi) - .finish() - } -} - -impl<E: ?Sized> fmt::Display for FormattedFields<E> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.fields, f) - } -} - -impl<E: ?Sized> Deref for FormattedFields<E> { - type Target = String; - fn deref(&self) -> &Self::Target { - &self.fields - } -} - -// === impl FmtLayer === - -macro_rules! with_event_from_span { - ($id:ident, $span:ident, $($field:literal = $value:expr),*, |$event:ident| $code:block) => { - let meta = $span.metadata(); - let cs = meta.callsite(); - let fs = field::FieldSet::new(&[$($field),*], cs); - #[allow(unused)] - let mut iter = fs.iter(); - let v = [$( - (&iter.next().unwrap(), Some(&$value as &dyn field::Value)), - )*]; - let vs = fs.value_set(&v); - let $event = Event::new_child_of($id, meta, &vs); - $code - }; -} - -impl<S, N, E, W> layer::Layer<S> for Layer<S, N, E, W> -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'writer> FormatFields<'writer> + 'static, - E: FormatEvent<S, N> + 'static, - W: for<'writer> MakeWriter<'writer> + 'static, -{ - fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { - let span = ctx.span(id).expect("Span not found, this is a bug"); - let mut extensions = span.extensions_mut(); - - if extensions.get_mut::<FormattedFields<N>>().is_none() { - let mut fields = FormattedFields::<N>::new(String::new()); - if self - .fmt_fields - .format_fields(fields.as_writer().with_ansi(self.is_ansi), attrs) - .is_ok() - { - fields.was_ansi = self.is_ansi; - extensions.insert(fields); - } - } - - if self.fmt_span.fmt_timing - && self.fmt_span.trace_close() - && extensions.get_mut::<Timings>().is_none() - { - extensions.insert(Timings::new()); - } - - if self.fmt_span.trace_new() { - with_event_from_span!(id, span, "message" = "new", |event| { - drop(extensions); - drop(span); - self.on_event(&event, ctx); - }); - } - } - - fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) { - let span = ctx.span(id).expect("Span not found, this is a bug"); - let mut extensions = span.extensions_mut(); - if let Some(fields) = extensions.get_mut::<FormattedFields<N>>() { - let _ = self.fmt_fields.add_fields(fields, values); - return; - } - - let mut fields = FormattedFields::<N>::new(String::new()); - if self - .fmt_fields - .format_fields(fields.as_writer().with_ansi(self.is_ansi), values) - .is_ok() - { - fields.was_ansi = self.is_ansi; - extensions.insert(fields); - } - } - - fn on_enter(&self, id: &Id, ctx: Context<'_, S>) { - if self.fmt_span.trace_enter() || self.fmt_span.trace_close() && self.fmt_span.fmt_timing { - let span = ctx.span(id).expect("Span not found, this is a bug"); - let mut extensions = span.extensions_mut(); - if let Some(timings) = extensions.get_mut::<Timings>() { - let now = Instant::now(); - timings.idle += (now - timings.last).as_nanos() as u64; - timings.last = now; - } - - if self.fmt_span.trace_enter() { - with_event_from_span!(id, span, "message" = "enter", |event| { - drop(extensions); - drop(span); - self.on_event(&event, ctx); - }); - } - } - } - - fn on_exit(&self, id: &Id, ctx: Context<'_, S>) { - if self.fmt_span.trace_exit() || self.fmt_span.trace_close() && self.fmt_span.fmt_timing { - let span = ctx.span(id).expect("Span not found, this is a bug"); - let mut extensions = span.extensions_mut(); - if let Some(timings) = extensions.get_mut::<Timings>() { - let now = Instant::now(); - timings.busy += (now - timings.last).as_nanos() as u64; - timings.last = now; - } - - if self.fmt_span.trace_exit() { - with_event_from_span!(id, span, "message" = "exit", |event| { - drop(extensions); - drop(span); - self.on_event(&event, ctx); - }); - } - } - } - - fn on_close(&self, id: Id, ctx: Context<'_, S>) { - if self.fmt_span.trace_close() { - let span = ctx.span(&id).expect("Span not found, this is a bug"); - let extensions = span.extensions(); - if let Some(timing) = extensions.get::<Timings>() { - let Timings { - busy, - mut idle, - last, - } = *timing; - idle += (Instant::now() - last).as_nanos() as u64; - - let t_idle = field::display(TimingDisplay(idle)); - let t_busy = field::display(TimingDisplay(busy)); - - with_event_from_span!( - id, - span, - "message" = "close", - "time.busy" = t_busy, - "time.idle" = t_idle, - |event| { - drop(extensions); - drop(span); - self.on_event(&event, ctx); - } - ); - } else { - with_event_from_span!(id, span, "message" = "close", |event| { - drop(extensions); - drop(span); - self.on_event(&event, ctx); - }); - } - } - } - - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { - thread_local! { - static BUF: RefCell<String> = RefCell::new(String::new()); - } - - BUF.with(|buf| { - let borrow = buf.try_borrow_mut(); - let mut a; - let mut b; - let mut buf = match borrow { - Ok(buf) => { - a = buf; - &mut *a - } - _ => { - b = String::new(); - &mut b - } - }; - - let ctx = self.make_ctx(ctx, event); - if self - .fmt_event - .format_event( - &ctx, - format::Writer::new(&mut buf).with_ansi(self.is_ansi), - event, - ) - .is_ok() - { - let mut writer = self.make_writer.make_writer_for(event.metadata()); - let _ = io::Write::write_all(&mut writer, buf.as_bytes()); - } - - buf.clear(); - }); - } - - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - // This `downcast_raw` impl allows downcasting a `fmt` layer to any of - // its components (event formatter, field formatter, and `MakeWriter`) - // as well as to the layer's type itself. The potential use-cases for - // this *may* be somewhat niche, though... - match () { - _ if id == TypeId::of::<Self>() => Some(self as *const Self as *const ()), - _ if id == TypeId::of::<E>() => Some(&self.fmt_event as *const E as *const ()), - _ if id == TypeId::of::<N>() => Some(&self.fmt_fields as *const N as *const ()), - _ if id == TypeId::of::<W>() => Some(&self.make_writer as *const W as *const ()), - _ => None, - } - } -} - -/// Provides the current span context to a formatter. -pub struct FmtContext<'a, S, N> { - pub(crate) ctx: Context<'a, S>, - pub(crate) fmt_fields: &'a N, - pub(crate) event: &'a Event<'a>, -} - -impl<'a, S, N> fmt::Debug for FmtContext<'a, S, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FmtContext").finish() - } -} - -impl<'cx, 'writer, S, N> FormatFields<'writer> for FmtContext<'cx, S, N> -where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - N: FormatFields<'writer> + 'static, -{ - fn format_fields<R: RecordFields>( - &self, - writer: format::Writer<'writer>, - fields: R, - ) -> fmt::Result { - self.fmt_fields.format_fields(writer, fields) - } -} - -impl<'a, S, N> FmtContext<'a, S, N> -where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static, -{ - /// Visits every span in the current context with a closure. - /// - /// The provided closure will be called first with the current span, - /// and then with that span's parent, and then that span's parent, - /// and so on until a root span is reached. - pub fn visit_spans<E, F>(&self, mut f: F) -> Result<(), E> - where - F: FnMut(&SpanRef<'_, S>) -> Result<(), E>, - { - // visit all the current spans - if let Some(scope) = self.event_scope() { - for span in scope.from_root() { - f(&span)?; - } - } - Ok(()) - } - - /// Returns metadata for the span with the given `id`, if it exists. - /// - /// If this returns `None`, then no span exists for that ID (either it has - /// closed or the ID is invalid). - #[inline] - pub fn metadata(&self, id: &Id) -> Option<&'static Metadata<'static>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - self.ctx.metadata(id) - } - - /// Returns [stored data] for the span with the given `id`, if it exists. - /// - /// If this returns `None`, then no span exists for that ID (either it has - /// closed or the ID is invalid). - /// - /// [stored data]: crate::registry::SpanRef - #[inline] - pub fn span(&self, id: &Id) -> Option<SpanRef<'_, S>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - self.ctx.span(id) - } - - /// Returns `true` if an active span exists for the given `Id`. - #[inline] - pub fn exists(&self, id: &Id) -> bool - where - S: for<'lookup> LookupSpan<'lookup>, - { - self.ctx.exists(id) - } - - /// Returns [stored data] for the span that the wrapped subscriber considers - /// to be the current. - /// - /// If this returns `None`, then we are not currently within a span. - /// - /// [stored data]: crate::registry::SpanRef - #[inline] - pub fn lookup_current(&self) -> Option<SpanRef<'_, S>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - self.ctx.lookup_current() - } - - /// Returns the current span for this formatter. - pub fn current_span(&self) -> Current { - self.ctx.current_span() - } - - /// Returns [stored data] for the parent span of the event currently being - /// formatted. - /// - /// If the event has a contextual parent, this will return the current span. If - /// the event has an explicit parent span, this will return that span. If - /// the event does not have a parent span, this will return `None`. - /// - /// [stored data]: SpanRef - pub fn parent_span(&self) -> Option<SpanRef<'_, S>> { - self.ctx.event_span(self.event) - } - - /// Returns an iterator over the [stored data] for all the spans in the - /// current context, starting with the specified span and ending with the - /// root of the trace tree and ending with the current span. - /// - /// This is equivalent to the [`Context::span_scope`] method. - /// - /// <div class="information"> - /// <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div> - /// </div> - /// <div class="example-wrap" style="display:inline-block"> - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this - /// returns the spans in reverse order (from leaf to root). Use - /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a> - /// in case root-to-leaf ordering is desired. - /// </pre></div> - /// - /// <div class="example-wrap" style="display:inline-block"> - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This requires the wrapped subscriber to implement the - /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait. - /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s - /// declaration</a> for details. - /// </pre></div> - /// - /// [stored data]: crate::registry::SpanRef - pub fn span_scope(&self, id: &Id) -> Option<registry::Scope<'_, S>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - self.ctx.span_scope(id) - } - - /// Returns an iterator over the [stored data] for all the spans in the - /// event's span context, starting with its parent span and ending with the - /// root of the trace tree. - /// - /// This is equivalent to calling the [`Context::event_scope`] method and - /// passing the event currently being formatted. - /// - /// <div class="example-wrap" style="display:inline-block"> - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this - /// returns the spans in reverse order (from leaf to root). Use - /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a> - /// in case root-to-leaf ordering is desired. - /// </pre></div> - /// - /// <div class="example-wrap" style="display:inline-block"> - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This requires the wrapped subscriber to implement the - /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait. - /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s - /// declaration</a> for details. - /// </pre></div> - /// - /// [stored data]: crate::registry::SpanRef - pub fn event_scope(&self) -> Option<registry::Scope<'_, S>> - where - S: for<'lookup> registry::LookupSpan<'lookup>, - { - self.ctx.event_scope(self.event) - } - - /// Returns the [field formatter] configured by the subscriber invoking - /// `format_event`. - /// - /// The event formatter may use the returned field formatter to format the - /// fields of any events it records. - /// - /// [field formatter]: FormatFields - pub fn field_format(&self) -> &N { - self.fmt_fields - } -} - -struct Timings { - idle: u64, - busy: u64, - last: Instant, -} - -impl Timings { - fn new() -> Self { - Self { - idle: 0, - busy: 0, - last: Instant::now(), - } - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::fmt::{ - self, - format::{self, test::MockTime, Format}, - layer::Layer as _, - test::{MockMakeWriter, MockWriter}, - time, - }; - use crate::Registry; - use format::FmtSpan; - use regex::Regex; - use tracing::subscriber::with_default; - use tracing_core::dispatcher::Dispatch; - - #[test] - fn impls() { - let f = Format::default().with_timer(time::Uptime::default()); - let fmt = fmt::Layer::default().event_format(f); - let subscriber = fmt.with_subscriber(Registry::default()); - let _dispatch = Dispatch::new(subscriber); - - let f = format::Format::default(); - let fmt = fmt::Layer::default().event_format(f); - let subscriber = fmt.with_subscriber(Registry::default()); - let _dispatch = Dispatch::new(subscriber); - - let f = format::Format::default().compact(); - let fmt = fmt::Layer::default().event_format(f); - let subscriber = fmt.with_subscriber(Registry::default()); - let _dispatch = Dispatch::new(subscriber); - } - - #[test] - fn fmt_layer_downcasts() { - let f = format::Format::default(); - let fmt = fmt::Layer::default().event_format(f); - let subscriber = fmt.with_subscriber(Registry::default()); - - let dispatch = Dispatch::new(subscriber); - assert!(dispatch.downcast_ref::<fmt::Layer<Registry>>().is_some()); - } - - #[test] - fn fmt_layer_downcasts_to_parts() { - let f = format::Format::default(); - let fmt = fmt::Layer::default().event_format(f); - let subscriber = fmt.with_subscriber(Registry::default()); - let dispatch = Dispatch::new(subscriber); - assert!(dispatch.downcast_ref::<format::DefaultFields>().is_some()); - assert!(dispatch.downcast_ref::<format::Format>().is_some()) - } - - #[test] - fn is_lookup_span() { - fn assert_lookup_span<T: for<'a> crate::registry::LookupSpan<'a>>(_: T) {} - let fmt = fmt::Layer::default(); - let subscriber = fmt.with_subscriber(Registry::default()); - assert_lookup_span(subscriber) - } - - fn sanitize_timings(s: String) -> String { - let re = Regex::new("time\\.(idle|busy)=([0-9.]+)[mµn]s").unwrap(); - re.replace_all(s.as_str(), "timing").to_string() - } - - #[test] - fn synthesize_span_none() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime) - // check that FmtSpan::NONE is the default - .finish(); - - with_default(subscriber, || { - let span1 = tracing::info_span!("span1", x = 42); - let _e = span1.enter(); - }); - let actual = sanitize_timings(make_writer.get_string()); - assert_eq!("", actual.as_str()); - } - - #[test] - fn synthesize_span_active() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime) - .with_span_events(FmtSpan::ACTIVE) - .finish(); - - with_default(subscriber, || { - let span1 = tracing::info_span!("span1", x = 42); - let _e = span1.enter(); - }); - let actual = sanitize_timings(make_writer.get_string()); - assert_eq!( - "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: enter\n\ - fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: exit\n", - actual.as_str() - ); - } - - #[test] - fn synthesize_span_close() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime) - .with_span_events(FmtSpan::CLOSE) - .finish(); - - with_default(subscriber, || { - let span1 = tracing::info_span!("span1", x = 42); - let _e = span1.enter(); - }); - let actual = sanitize_timings(make_writer.get_string()); - assert_eq!( - "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close timing timing\n", - actual.as_str() - ); - } - - #[test] - fn synthesize_span_close_no_timing() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime) - .without_time() - .with_span_events(FmtSpan::CLOSE) - .finish(); - - with_default(subscriber, || { - let span1 = tracing::info_span!("span1", x = 42); - let _e = span1.enter(); - }); - let actual = sanitize_timings(make_writer.get_string()); - assert_eq!( - "span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close\n", - actual.as_str() - ); - } - - #[test] - fn synthesize_span_full() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime) - .with_span_events(FmtSpan::FULL) - .finish(); - - with_default(subscriber, || { - let span1 = tracing::info_span!("span1", x = 42); - let _e = span1.enter(); - }); - let actual = sanitize_timings(make_writer.get_string()); - assert_eq!( - "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: new\n\ - fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: enter\n\ - fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: exit\n\ - fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close timing timing\n", - actual.as_str() - ); - } - - #[test] - fn make_writer_based_on_meta() { - struct MakeByTarget { - make_writer1: MockMakeWriter, - make_writer2: MockMakeWriter, - } - - impl<'a> MakeWriter<'a> for MakeByTarget { - type Writer = MockWriter; - - fn make_writer(&'a self) -> Self::Writer { - self.make_writer1.make_writer() - } - - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - if meta.target() == "writer2" { - return self.make_writer2.make_writer(); - } - self.make_writer() - } - } - - let make_writer1 = MockMakeWriter::default(); - let make_writer2 = MockMakeWriter::default(); - - let make_writer = MakeByTarget { - make_writer1: make_writer1.clone(), - make_writer2: make_writer2.clone(), - }; - - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer) - .with_level(false) - .with_target(false) - .with_ansi(false) - .with_timer(MockTime) - .with_span_events(FmtSpan::CLOSE) - .finish(); - - with_default(subscriber, || { - let span1 = tracing::info_span!("writer1_span", x = 42); - let _e = span1.enter(); - tracing::info!(target: "writer2", "hello writer2!"); - let span2 = tracing::info_span!(target: "writer2", "writer2_span"); - let _e = span2.enter(); - tracing::warn!(target: "writer1", "hello writer1!"); - }); - - let actual = sanitize_timings(make_writer1.get_string()); - assert_eq!( - "fake time writer1_span{x=42}:writer2_span: hello writer1!\n\ - fake time writer1_span{x=42}: close timing timing\n", - actual.as_str() - ); - let actual = sanitize_timings(make_writer2.get_string()); - assert_eq!( - "fake time writer1_span{x=42}: hello writer2!\n\ - fake time writer1_span{x=42}:writer2_span: close timing timing\n", - actual.as_str() - ); - } -} diff --git a/vendor/tracing-subscriber/src/fmt/format/json.rs b/vendor/tracing-subscriber/src/fmt/format/json.rs deleted file mode 100644 index c2f4d3755..000000000 --- a/vendor/tracing-subscriber/src/fmt/format/json.rs +++ /dev/null @@ -1,885 +0,0 @@ -use super::{Format, FormatEvent, FormatFields, FormatTime, Writer}; -use crate::{ - field::{RecordFields, VisitOutput}, - fmt::{ - fmt_layer::{FmtContext, FormattedFields}, - writer::WriteAdaptor, - }, - registry::LookupSpan, -}; -use serde::ser::{SerializeMap, Serializer as _}; -use serde_json::Serializer; -use std::{ - collections::BTreeMap, - fmt::{self, Write}, -}; -use tracing_core::{ - field::{self, Field}, - span::Record, - Event, Subscriber, -}; -use tracing_serde::AsSerde; - -#[cfg(feature = "tracing-log")] -use tracing_log::NormalizeEvent; - -/// Marker for [`Format`] that indicates that the newline-delimited JSON log -/// format should be used. -/// -/// This formatter is intended for production use with systems where structured -/// logs are consumed as JSON by analysis and viewing tools. The JSON output is -/// not optimized for human readability; instead, it should be pretty-printed -/// using external JSON tools such as `jq`, or using a JSON log viewer. -/// -/// # Example Output -/// -/// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt-json -/// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s -/// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-json` -/// {"timestamp":"2022-02-15T18:47:10.821315Z","level":"INFO","fields":{"message":"preparing to shave yaks","number_of_yaks":3},"target":"fmt_json"} -/// {"timestamp":"2022-02-15T18:47:10.821422Z","level":"INFO","fields":{"message":"shaving yaks"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -/// {"timestamp":"2022-02-15T18:47:10.821495Z","level":"TRACE","fields":{"message":"hello! I'm gonna shave a yak","excitement":"yay!"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":1,"name":"shave"}]} -/// {"timestamp":"2022-02-15T18:47:10.821546Z","level":"TRACE","fields":{"message":"yak shaved successfully"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":1,"name":"shave"}]} -/// {"timestamp":"2022-02-15T18:47:10.821598Z","level":"DEBUG","fields":{"yak":1,"shaved":true},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]} -/// {"timestamp":"2022-02-15T18:47:10.821637Z","level":"TRACE","fields":{"yaks_shaved":1},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -/// {"timestamp":"2022-02-15T18:47:10.821684Z","level":"TRACE","fields":{"message":"hello! I'm gonna shave a yak","excitement":"yay!"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":2,"name":"shave"}]} -/// {"timestamp":"2022-02-15T18:47:10.821727Z","level":"TRACE","fields":{"message":"yak shaved successfully"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":2,"name":"shave"}]} -/// {"timestamp":"2022-02-15T18:47:10.821773Z","level":"DEBUG","fields":{"yak":2,"shaved":true},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]} -/// {"timestamp":"2022-02-15T18:47:10.821806Z","level":"TRACE","fields":{"yaks_shaved":2},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -/// {"timestamp":"2022-02-15T18:47:10.821909Z","level":"TRACE","fields":{"message":"hello! I'm gonna shave a yak","excitement":"yay!"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":3,"name":"shave"}]} -/// {"timestamp":"2022-02-15T18:47:10.821956Z","level":"WARN","fields":{"message":"could not locate yak"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":3,"name":"shave"}]} -/// {"timestamp":"2022-02-15T18:47:10.822006Z","level":"DEBUG","fields":{"yak":3,"shaved":false},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]} -/// {"timestamp":"2022-02-15T18:47:10.822041Z","level":"ERROR","fields":{"message":"failed to shave yak","yak":3,"error":"missing yak"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -/// {"timestamp":"2022-02-15T18:47:10.822079Z","level":"TRACE","fields":{"yaks_shaved":2},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -/// {"timestamp":"2022-02-15T18:47:10.822117Z","level":"INFO","fields":{"message":"yak shaving completed","all_yaks_shaved":false},"target":"fmt_json"} -/// </pre> -/// -/// # Options -/// -/// This formatter exposes additional options to configure the structure of the -/// output JSON objects: -/// -/// - [`Json::flatten_event`] can be used to enable flattening event fields into -/// the root -/// - [`Json::with_current_span`] can be used to control logging of the current -/// span -/// - [`Json::with_span_list`] can be used to control logging of the span list -/// object. -/// -/// By default, event fields are not flattened, and both current span and span -/// list are logged. -/// -/// # Valuable Support -/// -/// Experimental support is available for using the [`valuable`] crate to record -/// user-defined values as structured JSON. When the ["valuable" unstable -/// feature][unstable] is enabled, types implementing [`valuable::Valuable`] will -/// be recorded as structured JSON, rather than -/// using their [`std::fmt::Debug`] implementations. -/// -/// **Note**: This is an experimental feature. [Unstable features][unstable] -/// must be enabled in order to use `valuable` support. -/// -/// [`Json::flatten_event`]: Json::flatten_event() -/// [`Json::with_current_span`]: Json::with_current_span() -/// [`Json::with_span_list`]: Json::with_span_list() -/// [`valuable`]: https://crates.io/crates/valuable -/// [unstable]: crate#unstable-features -/// [`valuable::Valuable`]: https://docs.rs/valuable/latest/valuable/trait.Valuable.html -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct Json { - pub(crate) flatten_event: bool, - pub(crate) display_current_span: bool, - pub(crate) display_span_list: bool, -} - -impl Json { - /// If set to `true` event metadata will be flattened into the root object. - pub fn flatten_event(&mut self, flatten_event: bool) { - self.flatten_event = flatten_event; - } - - /// If set to `false`, formatted events won't contain a field for the current span. - pub fn with_current_span(&mut self, display_current_span: bool) { - self.display_current_span = display_current_span; - } - - /// If set to `false`, formatted events won't contain a list of all currently - /// entered spans. Spans are logged in a list from root to leaf. - pub fn with_span_list(&mut self, display_span_list: bool) { - self.display_span_list = display_span_list; - } -} - -struct SerializableContext<'a, 'b, Span, N>( - &'b crate::layer::Context<'a, Span>, - std::marker::PhantomData<N>, -) -where - Span: Subscriber + for<'lookup> crate::registry::LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static; - -impl<'a, 'b, Span, N> serde::ser::Serialize for SerializableContext<'a, 'b, Span, N> -where - Span: Subscriber + for<'lookup> crate::registry::LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static, -{ - fn serialize<Ser>(&self, serializer_o: Ser) -> Result<Ser::Ok, Ser::Error> - where - Ser: serde::ser::Serializer, - { - use serde::ser::SerializeSeq; - let mut serializer = serializer_o.serialize_seq(None)?; - - if let Some(leaf_span) = self.0.lookup_current() { - for span in leaf_span.scope().from_root() { - serializer.serialize_element(&SerializableSpan(&span, self.1))?; - } - } - - serializer.end() - } -} - -struct SerializableSpan<'a, 'b, Span, N>( - &'b crate::registry::SpanRef<'a, Span>, - std::marker::PhantomData<N>, -) -where - Span: for<'lookup> crate::registry::LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static; - -impl<'a, 'b, Span, N> serde::ser::Serialize for SerializableSpan<'a, 'b, Span, N> -where - Span: for<'lookup> crate::registry::LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static, -{ - fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> - where - Ser: serde::ser::Serializer, - { - let mut serializer = serializer.serialize_map(None)?; - - let ext = self.0.extensions(); - let data = ext - .get::<FormattedFields<N>>() - .expect("Unable to find FormattedFields in extensions; this is a bug"); - - // TODO: let's _not_ do this, but this resolves - // https://github.com/tokio-rs/tracing/issues/391. - // We should probably rework this to use a `serde_json::Value` or something - // similar in a JSON-specific layer, but I'd (david) - // rather have a uglier fix now rather than shipping broken JSON. - match serde_json::from_str::<serde_json::Value>(data) { - Ok(serde_json::Value::Object(fields)) => { - for field in fields { - serializer.serialize_entry(&field.0, &field.1)?; - } - } - // We have fields for this span which are valid JSON but not an object. - // This is probably a bug, so panic if we're in debug mode - Ok(_) if cfg!(debug_assertions) => panic!( - "span '{}' had malformed fields! this is a bug.\n error: invalid JSON object\n fields: {:?}", - self.0.metadata().name(), - data - ), - // If we *aren't* in debug mode, it's probably best not to - // crash the program, let's log the field found but also an - // message saying it's type is invalid - Ok(value) => { - serializer.serialize_entry("field", &value)?; - serializer.serialize_entry("field_error", "field was no a valid object")? - } - // We have previously recorded fields for this span - // should be valid JSON. However, they appear to *not* - // be valid JSON. This is almost certainly a bug, so - // panic if we're in debug mode - Err(e) if cfg!(debug_assertions) => panic!( - "span '{}' had malformed fields! this is a bug.\n error: {}\n fields: {:?}", - self.0.metadata().name(), - e, - data - ), - // If we *aren't* in debug mode, it's probably best not - // crash the program, but let's at least make sure it's clear - // that the fields are not supposed to be missing. - Err(e) => serializer.serialize_entry("field_error", &format!("{}", e))?, - }; - serializer.serialize_entry("name", self.0.metadata().name())?; - serializer.end() - } -} - -impl<S, N, T> FormatEvent<S, N> for Format<Json, T> -where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static, - T: FormatTime, -{ - fn format_event( - &self, - ctx: &FmtContext<'_, S, N>, - mut writer: Writer<'_>, - event: &Event<'_>, - ) -> fmt::Result - where - S: Subscriber + for<'a> LookupSpan<'a>, - { - let mut timestamp = String::new(); - self.timer.format_time(&mut Writer::new(&mut timestamp))?; - - #[cfg(feature = "tracing-log")] - let normalized_meta = event.normalized_metadata(); - #[cfg(feature = "tracing-log")] - let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); - #[cfg(not(feature = "tracing-log"))] - let meta = event.metadata(); - - let mut visit = || { - let mut serializer = Serializer::new(WriteAdaptor::new(&mut writer)); - - let mut serializer = serializer.serialize_map(None)?; - - if self.display_timestamp { - serializer.serialize_entry("timestamp", ×tamp)?; - } - - if self.display_level { - serializer.serialize_entry("level", &meta.level().as_serde())?; - } - - let format_field_marker: std::marker::PhantomData<N> = std::marker::PhantomData; - - let current_span = if self.format.display_current_span || self.format.display_span_list - { - event - .parent() - .and_then(|id| ctx.span(id)) - .or_else(|| ctx.lookup_current()) - } else { - None - }; - - if self.format.flatten_event { - let mut visitor = tracing_serde::SerdeMapVisitor::new(serializer); - event.record(&mut visitor); - - serializer = visitor.take_serializer()?; - } else { - use tracing_serde::fields::AsMap; - serializer.serialize_entry("fields", &event.field_map())?; - }; - - if self.display_target { - serializer.serialize_entry("target", meta.target())?; - } - - if self.display_filename { - if let Some(filename) = meta.file() { - serializer.serialize_entry("filename", filename)?; - } - } - - if self.display_line_number { - if let Some(line_number) = meta.line() { - serializer.serialize_entry("line_number", &line_number)?; - } - } - - if self.format.display_current_span { - if let Some(ref span) = current_span { - serializer - .serialize_entry("span", &SerializableSpan(span, format_field_marker)) - .unwrap_or(()); - } - } - - if self.format.display_span_list && current_span.is_some() { - serializer.serialize_entry( - "spans", - &SerializableContext(&ctx.ctx, format_field_marker), - )?; - } - - if self.display_thread_name { - let current_thread = std::thread::current(); - match current_thread.name() { - Some(name) => { - serializer.serialize_entry("threadName", name)?; - } - // fall-back to thread id when name is absent and ids are not enabled - None if !self.display_thread_id => { - serializer - .serialize_entry("threadName", &format!("{:?}", current_thread.id()))?; - } - _ => {} - } - } - - if self.display_thread_id { - serializer - .serialize_entry("threadId", &format!("{:?}", std::thread::current().id()))?; - } - - serializer.end() - }; - - visit().map_err(|_| fmt::Error)?; - writeln!(writer) - } -} - -impl Default for Json { - fn default() -> Json { - Json { - flatten_event: false, - display_current_span: true, - display_span_list: true, - } - } -} - -/// The JSON [`FormatFields`] implementation. -/// -#[derive(Debug)] -pub struct JsonFields { - // reserve the ability to add fields to this without causing a breaking - // change in the future. - _private: (), -} - -impl JsonFields { - /// Returns a new JSON [`FormatFields`] implementation. - /// - pub fn new() -> Self { - Self { _private: () } - } -} - -impl Default for JsonFields { - fn default() -> Self { - Self::new() - } -} - -impl<'a> FormatFields<'a> for JsonFields { - /// Format the provided `fields` to the provided `writer`, returning a result. - fn format_fields<R: RecordFields>(&self, mut writer: Writer<'_>, fields: R) -> fmt::Result { - let mut v = JsonVisitor::new(&mut writer); - fields.record(&mut v); - v.finish() - } - - /// Record additional field(s) on an existing span. - /// - /// By default, this appends a space to the current set of fields if it is - /// non-empty, and then calls `self.format_fields`. If different behavior is - /// required, the default implementation of this method can be overridden. - fn add_fields( - &self, - current: &'a mut FormattedFields<Self>, - fields: &Record<'_>, - ) -> fmt::Result { - if current.is_empty() { - // If there are no previously recorded fields, we can just reuse the - // existing string. - let mut writer = current.as_writer(); - let mut v = JsonVisitor::new(&mut writer); - fields.record(&mut v); - v.finish()?; - return Ok(()); - } - - // If fields were previously recorded on this span, we need to parse - // the current set of fields as JSON, add the new fields, and - // re-serialize them. Otherwise, if we just appended the new fields - // to a previously serialized JSON object, we would end up with - // malformed JSON. - // - // XXX(eliza): this is far from efficient, but unfortunately, it is - // necessary as long as the JSON formatter is implemented on top of - // an interface that stores all formatted fields as strings. - // - // We should consider reimplementing the JSON formatter as a - // separate layer, rather than a formatter for the `fmt` layer — - // then, we could store fields as JSON values, and add to them - // without having to parse and re-serialize. - let mut new = String::new(); - let map: BTreeMap<&'_ str, serde_json::Value> = - serde_json::from_str(current).map_err(|_| fmt::Error)?; - let mut v = JsonVisitor::new(&mut new); - v.values = map; - fields.record(&mut v); - v.finish()?; - current.fields = new; - - Ok(()) - } -} - -/// The [visitor] produced by [`JsonFields`]'s [`MakeVisitor`] implementation. -/// -/// [visitor]: crate::field::Visit -/// [`MakeVisitor`]: crate::field::MakeVisitor -pub struct JsonVisitor<'a> { - values: BTreeMap<&'a str, serde_json::Value>, - writer: &'a mut dyn Write, -} - -impl<'a> fmt::Debug for JsonVisitor<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!("JsonVisitor {{ values: {:?} }}", self.values)) - } -} - -impl<'a> JsonVisitor<'a> { - /// Returns a new default visitor that formats to the provided `writer`. - /// - /// # Arguments - /// - `writer`: the writer to format to. - /// - `is_empty`: whether or not any fields have been previously written to - /// that writer. - pub fn new(writer: &'a mut dyn Write) -> Self { - Self { - values: BTreeMap::new(), - writer, - } - } -} - -impl<'a> crate::field::VisitFmt for JsonVisitor<'a> { - fn writer(&mut self) -> &mut dyn fmt::Write { - self.writer - } -} - -impl<'a> crate::field::VisitOutput<fmt::Result> for JsonVisitor<'a> { - fn finish(self) -> fmt::Result { - let inner = || { - let mut serializer = Serializer::new(WriteAdaptor::new(self.writer)); - let mut ser_map = serializer.serialize_map(None)?; - - for (k, v) in self.values { - ser_map.serialize_entry(k, &v)?; - } - - ser_map.end() - }; - - if inner().is_err() { - Err(fmt::Error) - } else { - Ok(()) - } - } -} - -impl<'a> field::Visit for JsonVisitor<'a> { - #[cfg(all(tracing_unstable, feature = "valuable"))] - fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) { - let value = match serde_json::to_value(valuable_serde::Serializable::new(value)) { - Ok(value) => value, - Err(_e) => { - #[cfg(debug_assertions)] - unreachable!( - "`valuable::Valuable` implementations should always serialize \ - successfully, but an error occurred: {}", - _e, - ); - - #[cfg(not(debug_assertions))] - return; - } - }; - - self.values.insert(field.name(), value); - } - - /// Visit a double precision floating point value. - fn record_f64(&mut self, field: &Field, value: f64) { - self.values - .insert(field.name(), serde_json::Value::from(value)); - } - - /// Visit a signed 64-bit integer value. - fn record_i64(&mut self, field: &Field, value: i64) { - self.values - .insert(field.name(), serde_json::Value::from(value)); - } - - /// Visit an unsigned 64-bit integer value. - fn record_u64(&mut self, field: &Field, value: u64) { - self.values - .insert(field.name(), serde_json::Value::from(value)); - } - - /// Visit a boolean value. - fn record_bool(&mut self, field: &Field, value: bool) { - self.values - .insert(field.name(), serde_json::Value::from(value)); - } - - /// Visit a string value. - fn record_str(&mut self, field: &Field, value: &str) { - self.values - .insert(field.name(), serde_json::Value::from(value)); - } - - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - match field.name() { - // Skip fields that are actually log metadata that have already been handled - #[cfg(feature = "tracing-log")] - name if name.starts_with("log.") => (), - name if name.starts_with("r#") => { - self.values - .insert(&name[2..], serde_json::Value::from(format!("{:?}", value))); - } - name => { - self.values - .insert(name, serde_json::Value::from(format!("{:?}", value))); - } - }; - } -} -#[cfg(test)] -mod test { - use super::*; - use crate::fmt::{format::FmtSpan, test::MockMakeWriter, time::FormatTime, SubscriberBuilder}; - use tracing::{self, subscriber::with_default}; - - use std::fmt; - use std::path::Path; - - struct MockTime; - impl FormatTime for MockTime { - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - write!(w, "fake time") - } - } - - fn subscriber() -> SubscriberBuilder<JsonFields, Format<Json>> { - SubscriberBuilder::default().json() - } - - #[test] - fn json() { - let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n"; - let subscriber = subscriber() - .flatten_event(false) - .with_current_span(true) - .with_span_list(true); - test_json(expected, subscriber, || { - let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); - let _guard = span.enter(); - tracing::info!("some json test"); - }); - } - - #[test] - fn json_filename() { - let current_path = Path::new("tracing-subscriber") - .join("src") - .join("fmt") - .join("format") - .join("json.rs") - .to_str() - .expect("path must be valid unicode") - // escape windows backslashes - .replace('\\', "\\\\"); - let expected = - &format!("{}{}{}", - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"filename\":\"", - current_path, - "\",\"fields\":{\"message\":\"some json test\"}}\n"); - let subscriber = subscriber() - .flatten_event(false) - .with_current_span(true) - .with_file(true) - .with_span_list(true); - test_json(expected, subscriber, || { - let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); - let _guard = span.enter(); - tracing::info!("some json test"); - }); - } - - #[test] - fn json_line_number() { - let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"line_number\":42,\"fields\":{\"message\":\"some json test\"}}\n"; - let subscriber = subscriber() - .flatten_event(false) - .with_current_span(true) - .with_line_number(true) - .with_span_list(true); - test_json_with_line_number(expected, subscriber, || { - let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); - let _guard = span.enter(); - tracing::info!("some json test"); - }); - } - - #[test] - fn json_flattened_event() { - let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"message\":\"some json test\"}\n"; - - let subscriber = subscriber() - .flatten_event(true) - .with_current_span(true) - .with_span_list(true); - test_json(expected, subscriber, || { - let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); - let _guard = span.enter(); - tracing::info!("some json test"); - }); - } - - #[test] - fn json_disabled_current_span_event() { - let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n"; - let subscriber = subscriber() - .flatten_event(false) - .with_current_span(false) - .with_span_list(true); - test_json(expected, subscriber, || { - let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); - let _guard = span.enter(); - tracing::info!("some json test"); - }); - } - - #[test] - fn json_disabled_span_list_event() { - let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n"; - let subscriber = subscriber() - .flatten_event(false) - .with_current_span(true) - .with_span_list(false); - test_json(expected, subscriber, || { - let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); - let _guard = span.enter(); - tracing::info!("some json test"); - }); - } - - #[test] - fn json_nested_span() { - let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":43,\"name\":\"nested_json_span\",\"number\":4},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3},{\"answer\":43,\"name\":\"nested_json_span\",\"number\":4}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n"; - let subscriber = subscriber() - .flatten_event(false) - .with_current_span(true) - .with_span_list(true); - test_json(expected, subscriber, || { - let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3); - let _guard = span.enter(); - let span = tracing::span!( - tracing::Level::INFO, - "nested_json_span", - answer = 43, - number = 4 - ); - let _guard = span.enter(); - tracing::info!("some json test"); - }); - } - - #[test] - fn json_no_span() { - let expected = - "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"target\":\"tracing_subscriber::fmt::format::json::test\",\"fields\":{\"message\":\"some json test\"}}\n"; - let subscriber = subscriber() - .flatten_event(false) - .with_current_span(true) - .with_span_list(true); - test_json(expected, subscriber, || { - tracing::info!("some json test"); - }); - } - - #[test] - fn record_works() { - // This test reproduces issue #707, where using `Span::record` causes - // any events inside the span to be ignored. - - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt() - .json() - .with_writer(make_writer.clone()) - .finish(); - - with_default(subscriber, || { - tracing::info!("an event outside the root span"); - assert_eq!( - parse_as_json(&make_writer)["fields"]["message"], - "an event outside the root span" - ); - - let span = tracing::info_span!("the span", na = tracing::field::Empty); - span.record("na", &"value"); - let _enter = span.enter(); - - tracing::info!("an event inside the root span"); - assert_eq!( - parse_as_json(&make_writer)["fields"]["message"], - "an event inside the root span" - ); - }); - } - - #[test] - fn json_span_event_show_correct_context() { - let buffer = MockMakeWriter::default(); - let subscriber = subscriber() - .with_writer(buffer.clone()) - .flatten_event(false) - .with_current_span(true) - .with_span_list(false) - .with_span_events(FmtSpan::FULL) - .finish(); - - with_default(subscriber, || { - let context = "parent"; - let parent_span = tracing::info_span!("parent_span", context); - - let event = parse_as_json(&buffer); - assert_eq!(event["fields"]["message"], "new"); - assert_eq!(event["span"]["context"], "parent"); - - let _parent_enter = parent_span.enter(); - let event = parse_as_json(&buffer); - assert_eq!(event["fields"]["message"], "enter"); - assert_eq!(event["span"]["context"], "parent"); - - let context = "child"; - let child_span = tracing::info_span!("child_span", context); - let event = parse_as_json(&buffer); - assert_eq!(event["fields"]["message"], "new"); - assert_eq!(event["span"]["context"], "child"); - - let _child_enter = child_span.enter(); - let event = parse_as_json(&buffer); - assert_eq!(event["fields"]["message"], "enter"); - assert_eq!(event["span"]["context"], "child"); - - drop(_child_enter); - let event = parse_as_json(&buffer); - assert_eq!(event["fields"]["message"], "exit"); - assert_eq!(event["span"]["context"], "child"); - - drop(child_span); - let event = parse_as_json(&buffer); - assert_eq!(event["fields"]["message"], "close"); - assert_eq!(event["span"]["context"], "child"); - - drop(_parent_enter); - let event = parse_as_json(&buffer); - assert_eq!(event["fields"]["message"], "exit"); - assert_eq!(event["span"]["context"], "parent"); - - drop(parent_span); - let event = parse_as_json(&buffer); - assert_eq!(event["fields"]["message"], "close"); - assert_eq!(event["span"]["context"], "parent"); - }); - } - - #[test] - fn json_span_event_with_no_fields() { - // Check span events serialize correctly. - // Discussion: https://github.com/tokio-rs/tracing/issues/829#issuecomment-661984255 - let buffer = MockMakeWriter::default(); - let subscriber = subscriber() - .with_writer(buffer.clone()) - .flatten_event(false) - .with_current_span(false) - .with_span_list(false) - .with_span_events(FmtSpan::FULL) - .finish(); - - with_default(subscriber, || { - let span = tracing::info_span!("valid_json"); - assert_eq!(parse_as_json(&buffer)["fields"]["message"], "new"); - - let _enter = span.enter(); - assert_eq!(parse_as_json(&buffer)["fields"]["message"], "enter"); - - drop(_enter); - assert_eq!(parse_as_json(&buffer)["fields"]["message"], "exit"); - - drop(span); - assert_eq!(parse_as_json(&buffer)["fields"]["message"], "close"); - }); - } - - fn parse_as_json(buffer: &MockMakeWriter) -> serde_json::Value { - let buf = String::from_utf8(buffer.buf().to_vec()).unwrap(); - let json = buf - .lines() - .last() - .expect("expected at least one line to be written!"); - match serde_json::from_str(json) { - Ok(v) => v, - Err(e) => panic!( - "assertion failed: JSON shouldn't be malformed\n error: {}\n json: {}", - e, json - ), - } - } - - fn test_json<T>( - expected: &str, - builder: crate::fmt::SubscriberBuilder<JsonFields, Format<Json>>, - producer: impl FnOnce() -> T, - ) { - let make_writer = MockMakeWriter::default(); - let subscriber = builder - .with_writer(make_writer.clone()) - .with_timer(MockTime) - .finish(); - - with_default(subscriber, producer); - - let buf = make_writer.buf(); - let actual = std::str::from_utf8(&buf[..]).unwrap(); - assert_eq!( - serde_json::from_str::<std::collections::HashMap<&str, serde_json::Value>>(expected) - .unwrap(), - serde_json::from_str(actual).unwrap() - ); - } - - fn test_json_with_line_number<T>( - expected: &str, - builder: crate::fmt::SubscriberBuilder<JsonFields, Format<Json>>, - producer: impl FnOnce() -> T, - ) { - let make_writer = MockMakeWriter::default(); - let subscriber = builder - .with_writer(make_writer.clone()) - .with_timer(MockTime) - .finish(); - - with_default(subscriber, producer); - - let buf = make_writer.buf(); - let actual = std::str::from_utf8(&buf[..]).unwrap(); - let mut expected = - serde_json::from_str::<std::collections::HashMap<&str, serde_json::Value>>(expected) - .unwrap(); - let expect_line_number = expected.remove("line_number").is_some(); - let mut actual: std::collections::HashMap<&str, serde_json::Value> = - serde_json::from_str(actual).unwrap(); - let line_number = actual.remove("line_number"); - if expect_line_number { - assert_eq!(line_number.map(|x| x.is_number()), Some(true)); - } else { - assert!(line_number.is_none()); - } - assert_eq!(actual, expected); - } -} diff --git a/vendor/tracing-subscriber/src/fmt/format/mod.rs b/vendor/tracing-subscriber/src/fmt/format/mod.rs deleted file mode 100644 index ec79ac140..000000000 --- a/vendor/tracing-subscriber/src/fmt/format/mod.rs +++ /dev/null @@ -1,2161 +0,0 @@ -//! Formatters for logging `tracing` events. -//! -//! This module provides several formatter implementations, as well as utilities -//! for implementing custom formatters. -//! -//! # Formatters -//! This module provides a number of formatter implementations: -//! -//! * [`Full`]: The default formatter. This emits human-readable, -//! single-line logs for each event that occurs, with the current span context -//! displayed before the formatted representation of the event. See -//! [here](Full#example-output) for sample output. -//! -//! * [`Compact`]: A variant of the default formatter, optimized for -//! short line lengths. Fields from the current span context are appended to -//! the fields of the formatted event, and span names are not shown; the -//! verbosity level is abbreviated to a single character. See -//! [here](Compact#example-output) for sample output. -//! -//! * [`Pretty`]: Emits excessively pretty, multi-line logs, optimized -//! for human readability. This is primarily intended to be used in local -//! development and debugging, or for command-line applications, where -//! automated analysis and compact storage of logs is less of a priority than -//! readability and visual appeal. See [here](Pretty#example-output) -//! for sample output. -//! -//! * [`Json`]: Outputs newline-delimited JSON logs. This is intended -//! for production use with systems where structured logs are consumed as JSON -//! by analysis and viewing tools. The JSON output is not optimized for human -//! readability. See [here](Json#example-output) for sample output. -use super::time::{FormatTime, SystemTime}; -use crate::{ - field::{MakeOutput, MakeVisitor, RecordFields, VisitFmt, VisitOutput}, - fmt::fmt_layer::FmtContext, - fmt::fmt_layer::FormattedFields, - registry::LookupSpan, -}; - -use std::fmt::{self, Debug, Display, Write}; -use tracing_core::{ - field::{self, Field, Visit}, - span, Event, Level, Subscriber, -}; - -#[cfg(feature = "tracing-log")] -use tracing_log::NormalizeEvent; - -#[cfg(feature = "ansi")] -use ansi_term::{Colour, Style}; - -#[cfg(feature = "json")] -mod json; -#[cfg(feature = "json")] -#[cfg_attr(docsrs, doc(cfg(feature = "json")))] -pub use json::*; - -#[cfg(feature = "ansi")] -mod pretty; -#[cfg(feature = "ansi")] -#[cfg_attr(docsrs, doc(cfg(feature = "ansi")))] -pub use pretty::*; - -/// A type that can format a tracing [`Event`] to a [`Writer`]. -/// -/// `FormatEvent` is primarily used in the context of [`fmt::Subscriber`] or -/// [`fmt::Layer`]. Each time an event is dispatched to [`fmt::Subscriber`] or -/// [`fmt::Layer`], the subscriber or layer -/// forwards it to its associated `FormatEvent` to emit a log message. -/// -/// This trait is already implemented for function pointers with the same -/// signature as `format_event`. -/// -/// # Arguments -/// -/// The following arguments are passed to `FormatEvent::format_event`: -/// -/// * A [`FmtContext`]. This is an extension of the [`layer::Context`] type, -/// which can be used for accessing stored information such as the current -/// span context an event occurred in. -/// -/// In addition, [`FmtContext`] exposes access to the [`FormatFields`] -/// implementation that the subscriber was configured to use via the -/// [`FmtContext::field_format`] method. This can be used when the -/// [`FormatEvent`] implementation needs to format the event's fields. -/// -/// For convenience, [`FmtContext`] also [implements `FormatFields`], -/// forwarding to the configured [`FormatFields`] type. -/// -/// * A [`Writer`] to which the formatted representation of the event is -/// written. This type implements the [`std::fmt::Write`] trait, and therefore -/// can be used with the [`std::write!`] and [`std::writeln!`] macros, as well -/// as calling [`std::fmt::Write`] methods directly. -/// -/// The [`Writer`] type also implements additional methods that provide -/// information about how the event should be formatted. The -/// [`Writer::has_ansi_escapes`] method indicates whether [ANSI terminal -/// escape codes] are supported by the underlying I/O writer that the event -/// will be written to. If this returns `true`, the formatter is permitted to -/// use ANSI escape codes to add colors and other text formatting to its -/// output. If it returns `false`, the event will be written to an output that -/// does not support ANSI escape codes (such as a log file), and they should -/// not be emitted. -/// -/// Crates like [`ansi_term`] and [`owo-colors`] can be used to add ANSI -/// escape codes to formatted output. -/// -/// * The actual [`Event`] to be formatted. -/// -/// # Examples -/// -/// This example re-implements a simiplified version of this crate's [default -/// formatter]: -/// -/// ```rust -/// use std::fmt; -/// use tracing_core::{Subscriber, Event}; -/// use tracing_subscriber::fmt::{ -/// format::{self, FormatEvent, FormatFields}, -/// FmtContext, -/// FormattedFields, -/// }; -/// use tracing_subscriber::registry::LookupSpan; -/// -/// struct MyFormatter; -/// -/// impl<S, N> FormatEvent<S, N> for MyFormatter -/// where -/// S: Subscriber + for<'a> LookupSpan<'a>, -/// N: for<'a> FormatFields<'a> + 'static, -/// { -/// fn format_event( -/// &self, -/// ctx: &FmtContext<'_, S, N>, -/// mut writer: format::Writer<'_>, -/// event: &Event<'_>, -/// ) -> fmt::Result { -/// // Format values from the event's's metadata: -/// let metadata = event.metadata(); -/// write!(&mut writer, "{} {}: ", metadata.level(), metadata.target())?; -/// -/// // Format all the spans in the event's span context. -/// if let Some(scope) = ctx.event_scope() { -/// for span in scope.from_root() { -/// write!(writer, "{}", span.name())?; -/// -/// // `FormattedFields` is a formatted representation of the span's -/// // fields, which is stored in its extensions by the `fmt` layer's -/// // `new_span` method. The fields will have been formatted -/// // by the same field formatter that's provided to the event -/// // formatter in the `FmtContext`. -/// let ext = span.extensions(); -/// let fields = &ext -/// .get::<FormattedFields<N>>() -/// .expect("will never be `None`"); -/// -/// // Skip formatting the fields if the span had no fields. -/// if !fields.is_empty() { -/// write!(writer, "{{{}}}", fields)?; -/// } -/// write!(writer, ": ")?; -/// } -/// } -/// -/// // Write fields on the event -/// ctx.field_format().format_fields(writer.by_ref(), event)?; -/// -/// writeln!(writer) -/// } -/// } -/// -/// let _subscriber = tracing_subscriber::fmt() -/// .event_format(MyFormatter) -/// .init(); -/// -/// let _span = tracing::info_span!("my_span", answer = 42).entered(); -/// tracing::info!(question = "life, the universe, and everything", "hello world"); -/// ``` -/// -/// This formatter will print events like this: -/// -/// ```text -/// DEBUG yak_shaving::shaver: some-span{field-on-span=foo}: started shaving yak -/// ``` -/// -/// [`layer::Context`]: crate::layer::Context -/// [`fmt::Layer`]: super::Layer -/// [`fmt::Subscriber`]: super::Subscriber -/// [`Event`]: tracing::Event -/// [implements `FormatFields`]: super::FmtContext#impl-FormatFields<'writer> -/// [ANSI terminal escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code -/// [`Writer::has_ansi_escapes`]: Writer::has_ansi_escapes -/// [`ansi_term`]: https://crates.io/crates/ansi_term -/// [`owo-colors`]: https://crates.io/crates/owo-colors -/// [default formatter]: Full -pub trait FormatEvent<S, N> -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, -{ - /// Write a log message for `Event` in `Context` to the given [`Writer`]. - fn format_event( - &self, - ctx: &FmtContext<'_, S, N>, - writer: Writer<'_>, - event: &Event<'_>, - ) -> fmt::Result; -} - -impl<S, N> FormatEvent<S, N> - for fn(ctx: &FmtContext<'_, S, N>, Writer<'_>, &Event<'_>) -> fmt::Result -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, -{ - fn format_event( - &self, - ctx: &FmtContext<'_, S, N>, - writer: Writer<'_>, - event: &Event<'_>, - ) -> fmt::Result { - (*self)(ctx, writer, event) - } -} -/// A type that can format a [set of fields] to a [`Writer`]. -/// -/// `FormatFields` is primarily used in the context of [`FmtSubscriber`]. Each -/// time a span or event with fields is recorded, the subscriber will format -/// those fields with its associated `FormatFields` implementation. -/// -/// [set of fields]: crate::field::RecordFields -/// [`FmtSubscriber`]: super::Subscriber -pub trait FormatFields<'writer> { - /// Format the provided `fields` to the provided [`Writer`], returning a result. - fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result; - - /// Record additional field(s) on an existing span. - /// - /// By default, this appends a space to the current set of fields if it is - /// non-empty, and then calls `self.format_fields`. If different behavior is - /// required, the default implementation of this method can be overridden. - fn add_fields( - &self, - current: &'writer mut FormattedFields<Self>, - fields: &span::Record<'_>, - ) -> fmt::Result { - if !current.fields.is_empty() { - current.fields.push(' '); - } - self.format_fields(current.as_writer(), fields) - } -} - -/// Returns the default configuration for an [event formatter]. -/// -/// Methods on the returned event formatter can be used for further -/// configuration. For example: -/// -/// ```rust -/// let format = tracing_subscriber::fmt::format() -/// .without_time() // Don't include timestamps -/// .with_target(false) // Don't include event targets. -/// .with_level(false) // Don't include event levels. -/// .compact(); // Use a more compact, abbreviated format. -/// -/// // Use the configured formatter when building a new subscriber. -/// tracing_subscriber::fmt() -/// .event_format(format) -/// .init(); -/// ``` -pub fn format() -> Format { - Format::default() -} - -/// Returns the default configuration for a JSON [event formatter]. -#[cfg(feature = "json")] -#[cfg_attr(docsrs, doc(cfg(feature = "json")))] -pub fn json() -> Format<Json> { - format().json() -} - -/// Returns a [`FormatFields`] implementation that formats fields using the -/// provided function or closure. -/// -pub fn debug_fn<F>(f: F) -> FieldFn<F> -where - F: Fn(&mut Writer<'_>, &Field, &dyn fmt::Debug) -> fmt::Result + Clone, -{ - FieldFn(f) -} - -/// A writer to which formatted representations of spans and events are written. -/// -/// This type is provided as input to the [`FormatEvent::format_event`] and -/// [`FormatFields::format_fields`] methods, which will write formatted -/// representations of [`Event`]s and [fields] to the `Writer`. -/// -/// This type implements the [`std::fmt::Write`] trait, allowing it to be used -/// with any function that takes an instance of [`std::fmt::Write`]. -/// Additionally, it can be used with the standard library's [`std::write!`] and -/// [`std::writeln!`] macros. -/// -/// Additionally, a `Writer` may expose additional `tracing`-specific -/// information to the formatter implementation. -/// -/// [fields]: tracing_core::field -pub struct Writer<'writer> { - writer: &'writer mut dyn fmt::Write, - // TODO(eliza): add ANSI support - is_ansi: bool, -} - -/// A [`FormatFields`] implementation that formats fields by calling a function -/// or closure. -/// -#[derive(Debug, Clone)] -pub struct FieldFn<F>(F); -/// The [visitor] produced by [`FieldFn`]'s [`MakeVisitor`] implementation. -/// -/// [visitor]: super::super::field::Visit -/// [`MakeVisitor`]: super::super::field::MakeVisitor -pub struct FieldFnVisitor<'a, F> { - f: F, - writer: Writer<'a>, - result: fmt::Result, -} -/// Marker for [`Format`] that indicates that the compact log format should be used. -/// -/// The compact format includes fields from all currently entered spans, after -/// the event's fields. Span names are listed in order before fields are -/// displayed. -/// -/// # Example Output -/// -/// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt-compact -/// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s -/// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-compact` -/// <font color="#AAAAAA">2022-02-17T19:51:05.809287Z </font><font color="#4E9A06"> INFO</font> <b>fmt_compact</b><font color="#AAAAAA">: preparing to shave yaks </font><i>number_of_yaks</i><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809367Z </font><font color="#4E9A06"> INFO</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: shaving yaks </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809414Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: hello! I'm gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">="yay!" </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=1</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809443Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: yak shaved successfully </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=1</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809477Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks</b>: <b>yak_events</b><font color="#AAAAAA">: </font><i>yak</i><font color="#AAAAAA">=1 </font><i>shaved</i><font color="#AAAAAA">=true </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809500Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: </font><i>yaks_shaved</i><font color="#AAAAAA">=1 </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809531Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: hello! I'm gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">="yay!" </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=2</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809554Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: yak shaved successfully </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=2</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809581Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks</b>: <b>yak_events</b><font color="#AAAAAA">: </font><i>yak</i><font color="#AAAAAA">=2 </font><i>shaved</i><font color="#AAAAAA">=true </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809606Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: </font><i>yaks_shaved</i><font color="#AAAAAA">=2 </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809635Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: hello! I'm gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">="yay!" </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809664Z </font><font color="#C4A000"> WARN</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: could not locate yak </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809693Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks</b>: <b>yak_events</b><font color="#AAAAAA">: </font><i>yak</i><font color="#AAAAAA">=3 </font><i>shaved</i><font color="#AAAAAA">=false </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809717Z </font><font color="#CC0000">ERROR</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: failed to shave yak </font><i>yak</i><font color="#AAAAAA">=3 </font><i>error</i><font color="#AAAAAA">=missing yak </font><i>error.sources</i><font color="#AAAAAA">=[out of space, out of cash] </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809743Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: </font><i>yaks_shaved</i><font color="#AAAAAA">=2 </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-17T19:51:05.809768Z </font><font color="#4E9A06"> INFO</font> <b>fmt_compact</b><font color="#AAAAAA">: yak shaving completed </font><i>all_yaks_shaved</i><font color="#AAAAAA">=false</font> -/// -/// </pre> -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] -pub struct Compact; - -/// Marker for [`Format`] that indicates that the default log format should be used. -/// -/// This formatter shows the span context before printing event data. Spans are -/// displayed including their names and fields. -/// -/// # Example Output -/// -/// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt -/// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s -/// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt` -/// <font color="#AAAAAA">2022-02-15T18:40:14.289898Z </font><font color="#4E9A06"> INFO</font> fmt: preparing to shave yaks <i>number_of_yaks</i><font color="#AAAAAA">=3</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.289974Z </font><font color="#4E9A06"> INFO</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: shaving yaks</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290011Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=1</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: hello! I'm gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">="yay!"</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290038Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=1</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: yak shaved successfully</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290070Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: yak_events: </font><i>yak</i><font color="#AAAAAA">=1 </font><i>shaved</i><font color="#AAAAAA">=true</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290089Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: </font><i>yaks_shaved</i><font color="#AAAAAA">=1</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290114Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=2</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: hello! I'm gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">="yay!"</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290134Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=2</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: yak shaved successfully</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290157Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: yak_events: </font><i>yak</i><font color="#AAAAAA">=2 </font><i>shaved</i><font color="#AAAAAA">=true</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290174Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: </font><i>yaks_shaved</i><font color="#AAAAAA">=2</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290198Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: hello! I'm gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">="yay!"</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290222Z </font><font color="#C4A000"> WARN</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: could not locate yak</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290247Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: yak_events: </font><i>yak</i><font color="#AAAAAA">=3 </font><i>shaved</i><font color="#AAAAAA">=false</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290268Z </font><font color="#CC0000">ERROR</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: failed to shave yak </font><i>yak</i><font color="#AAAAAA">=3 </font><i>error</i><font color="#AAAAAA">=missing yak </font><i>error.sources</i><font color="#AAAAAA">=[out of space, out of cash]</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290287Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: </font><i>yaks_shaved</i><font color="#AAAAAA">=2</font> -/// <font color="#AAAAAA">2022-02-15T18:40:14.290309Z </font><font color="#4E9A06"> INFO</font> fmt: yak shaving completed. <i>all_yaks_shaved</i><font color="#AAAAAA">=false</font> -/// </pre> -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] -pub struct Full; - -/// A pre-configured event formatter. -/// -/// You will usually want to use this as the `FormatEvent` for a `FmtSubscriber`. -/// -/// The default logging format, [`Full`] includes all fields in each event and its containing -/// spans. The [`Compact`] logging format is intended to produce shorter log -/// lines; it displays each event's fields, along with fields from the current -/// span context, but other information is abbreviated. The [`Pretty`] logging -/// format is an extra-verbose, multi-line human-readable logging format -/// intended for use in development. -#[derive(Debug, Clone)] -pub struct Format<F = Full, T = SystemTime> { - format: F, - pub(crate) timer: T, - pub(crate) ansi: Option<bool>, - pub(crate) display_timestamp: bool, - pub(crate) display_target: bool, - pub(crate) display_level: bool, - pub(crate) display_thread_id: bool, - pub(crate) display_thread_name: bool, - pub(crate) display_filename: bool, - pub(crate) display_line_number: bool, -} - -// === impl Writer === - -impl<'writer> Writer<'writer> { - // TODO(eliza): consider making this a public API? - // We may not want to do that if we choose to expose specialized - // constructors instead (e.g. `from_string` that stores whether the string - // is empty...?) - pub(crate) fn new(writer: &'writer mut impl fmt::Write) -> Self { - Self { - writer: writer as &mut dyn fmt::Write, - is_ansi: false, - } - } - - // TODO(eliza): consider making this a public API? - pub(crate) fn with_ansi(self, is_ansi: bool) -> Self { - Self { is_ansi, ..self } - } - - /// Return a new `Writer` that mutably borrows `self`. - /// - /// This can be used to temporarily borrow a `Writer` to pass a new `Writer` - /// to a function that takes a `Writer` by value, allowing the original writer - /// to still be used once that function returns. - pub fn by_ref(&mut self) -> Writer<'_> { - let is_ansi = self.is_ansi; - Writer { - writer: self as &mut dyn fmt::Write, - is_ansi, - } - } - - /// Writes a string slice into this `Writer`, returning whether the write succeeded. - /// - /// This method can only succeed if the entire string slice was successfully - /// written, and this method will not return until all data has been written - /// or an error occurs. - /// - /// This is identical to calling the [`write_str` method] from the `Writer`'s - /// [`std::fmt::Write`] implementation. However, it is also provided as an - /// inherent method, so that `Writer`s can be used without needing to import the - /// [`std::fmt::Write`] trait. - /// - /// # Errors - /// - /// This function will return an instance of [`std::fmt::Error`] on error. - /// - /// [`write_str` method]: std::fmt::Write::write_str - #[inline] - pub fn write_str(&mut self, s: &str) -> fmt::Result { - self.writer.write_str(s) - } - - /// Writes a [`char`] into this writer, returning whether the write succeeded. - /// - /// A single [`char`] may be encoded as more than one byte. - /// This method can only succeed if the entire byte sequence was successfully - /// written, and this method will not return until all data has been - /// written or an error occurs. - /// - /// This is identical to calling the [`write_char` method] from the `Writer`'s - /// [`std::fmt::Write`] implementation. However, it is also provided as an - /// inherent method, so that `Writer`s can be used without needing to import the - /// [`std::fmt::Write`] trait. - /// - /// # Errors - /// - /// This function will return an instance of [`std::fmt::Error`] on error. - /// - /// [`write_char` method]: std::fmt::Write::write_char - #[inline] - pub fn write_char(&mut self, c: char) -> fmt::Result { - self.writer.write_char(c) - } - - /// Glue for usage of the [`write!`] macro with `Writer`s. - /// - /// This method should generally not be invoked manually, but rather through - /// the [`write!`] macro itself. - /// - /// This is identical to calling the [`write_fmt` method] from the `Writer`'s - /// [`std::fmt::Write`] implementation. However, it is also provided as an - /// inherent method, so that `Writer`s can be used with the [`write!` macro] - /// without needing to import the - /// [`std::fmt::Write`] trait. - /// - /// [`write_fmt` method]: std::fmt::Write::write_fmt - pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { - self.writer.write_fmt(args) - } - - /// Returns `true` if [ANSI escape codes] may be used to add colors - /// and other formatting when writing to this `Writer`. - /// - /// If this returns `false`, formatters should not emit ANSI escape codes. - /// - /// [ANSI escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code - pub fn has_ansi_escapes(&self) -> bool { - self.is_ansi - } - - pub(in crate::fmt::format) fn bold(&self) -> Style { - #[cfg(feature = "ansi")] - { - if self.is_ansi { - return Style::new().bold(); - } - } - - Style::new() - } - - pub(in crate::fmt::format) fn dimmed(&self) -> Style { - #[cfg(feature = "ansi")] - { - if self.is_ansi { - return Style::new().dimmed(); - } - } - - Style::new() - } - - pub(in crate::fmt::format) fn italic(&self) -> Style { - #[cfg(feature = "ansi")] - { - if self.is_ansi { - return Style::new().italic(); - } - } - - Style::new() - } -} - -impl fmt::Write for Writer<'_> { - #[inline] - fn write_str(&mut self, s: &str) -> fmt::Result { - Writer::write_str(self, s) - } - - #[inline] - fn write_char(&mut self, c: char) -> fmt::Result { - Writer::write_char(self, c) - } - - #[inline] - fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { - Writer::write_fmt(self, args) - } -} - -impl fmt::Debug for Writer<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Writer") - .field("writer", &format_args!("<&mut dyn fmt::Write>")) - .field("is_ansi", &self.is_ansi) - .finish() - } -} - -// === impl Format === - -impl Default for Format<Full, SystemTime> { - fn default() -> Self { - Format { - format: Full, - timer: SystemTime, - ansi: None, - display_timestamp: true, - display_target: true, - display_level: true, - display_thread_id: false, - display_thread_name: false, - display_filename: false, - display_line_number: false, - } - } -} - -impl<F, T> Format<F, T> { - /// Use a less verbose output format. - /// - /// See [`Compact`]. - pub fn compact(self) -> Format<Compact, T> { - Format { - format: Compact, - timer: self.timer, - ansi: self.ansi, - display_target: self.display_target, - display_timestamp: self.display_timestamp, - display_level: self.display_level, - display_thread_id: self.display_thread_id, - display_thread_name: self.display_thread_name, - display_filename: self.display_filename, - display_line_number: self.display_line_number, - } - } - - /// Use an excessively pretty, human-readable output format. - /// - /// See [`Pretty`]. - /// - /// Note that this requires the "ansi" feature to be enabled. - /// - /// # Options - /// - /// [`Format::with_ansi`] can be used to disable ANSI terminal escape codes (which enable - /// formatting such as colors, bold, italic, etc) in event formatting. However, a field - /// formatter must be manually provided to avoid ANSI in the formatting of parent spans, like - /// so: - /// - /// ``` - /// # use tracing_subscriber::fmt::format; - /// tracing_subscriber::fmt() - /// .pretty() - /// .with_ansi(false) - /// .fmt_fields(format::PrettyFields::new().with_ansi(false)) - /// // ... other settings ... - /// .init(); - /// ``` - #[cfg(feature = "ansi")] - #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))] - pub fn pretty(self) -> Format<Pretty, T> { - Format { - format: Pretty::default(), - timer: self.timer, - ansi: self.ansi, - display_target: self.display_target, - display_timestamp: self.display_timestamp, - display_level: self.display_level, - display_thread_id: self.display_thread_id, - display_thread_name: self.display_thread_name, - display_filename: true, - display_line_number: true, - } - } - - /// Use the full JSON format. - /// - /// The full format includes fields from all entered spans. - /// - /// # Example Output - /// - /// ```ignore,json - /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate","fields":{"message":"some message", "key": "value"}} - /// ``` - /// - /// # Options - /// - /// - [`Format::flatten_event`] can be used to enable flattening event fields into the root - /// object. - #[cfg(feature = "json")] - #[cfg_attr(docsrs, doc(cfg(feature = "json")))] - pub fn json(self) -> Format<Json, T> { - Format { - format: Json::default(), - timer: self.timer, - ansi: self.ansi, - display_target: self.display_target, - display_timestamp: self.display_timestamp, - display_level: self.display_level, - display_thread_id: self.display_thread_id, - display_thread_name: self.display_thread_name, - display_filename: self.display_filename, - display_line_number: self.display_line_number, - } - } - - /// Use the given [`timer`] for log message timestamps. - /// - /// See [`time` module] for the provided timer implementations. - /// - /// Note that using the `"time"` feature flag enables the - /// additional time formatters [`UtcTime`] and [`LocalTime`], which use the - /// [`time` crate] to provide more sophisticated timestamp formatting - /// options. - /// - /// [`timer`]: super::time::FormatTime - /// [`time` module]: mod@super::time - /// [`UtcTime`]: super::time::UtcTime - /// [`LocalTime`]: super::time::LocalTime - /// [`time` crate]: https://docs.rs/time/0.3 - pub fn with_timer<T2>(self, timer: T2) -> Format<F, T2> { - Format { - format: self.format, - timer, - ansi: self.ansi, - display_target: self.display_target, - display_timestamp: self.display_timestamp, - display_level: self.display_level, - display_thread_id: self.display_thread_id, - display_thread_name: self.display_thread_name, - display_filename: self.display_filename, - display_line_number: self.display_line_number, - } - } - - /// Do not emit timestamps with log messages. - pub fn without_time(self) -> Format<F, ()> { - Format { - format: self.format, - timer: (), - ansi: self.ansi, - display_timestamp: false, - display_target: self.display_target, - display_level: self.display_level, - display_thread_id: self.display_thread_id, - display_thread_name: self.display_thread_name, - display_filename: self.display_filename, - display_line_number: self.display_line_number, - } - } - - /// Enable ANSI terminal colors for formatted output. - pub fn with_ansi(self, ansi: bool) -> Format<F, T> { - Format { - ansi: Some(ansi), - ..self - } - } - - /// Sets whether or not an event's target is displayed. - pub fn with_target(self, display_target: bool) -> Format<F, T> { - Format { - display_target, - ..self - } - } - - /// Sets whether or not an event's level is displayed. - pub fn with_level(self, display_level: bool) -> Format<F, T> { - Format { - display_level, - ..self - } - } - - /// Sets whether or not the [thread ID] of the current thread is displayed - /// when formatting events. - /// - /// [thread ID]: std::thread::ThreadId - pub fn with_thread_ids(self, display_thread_id: bool) -> Format<F, T> { - Format { - display_thread_id, - ..self - } - } - - /// Sets whether or not the [name] of the current thread is displayed - /// when formatting events. - /// - /// [name]: std::thread#naming-threads - pub fn with_thread_names(self, display_thread_name: bool) -> Format<F, T> { - Format { - display_thread_name, - ..self - } - } - - /// Sets whether or not an event's [source code file path][file] is - /// displayed. - /// - /// [file]: tracing_core::Metadata::file - pub fn with_file(self, display_filename: bool) -> Format<F, T> { - Format { - display_filename, - ..self - } - } - - /// Sets whether or not an event's [source code line number][line] is - /// displayed. - /// - /// [line]: tracing_core::Metadata::line - pub fn with_line_number(self, display_line_number: bool) -> Format<F, T> { - Format { - display_line_number, - ..self - } - } - - /// Sets whether or not the source code location from which an event - /// originated is displayed. - /// - /// This is equivalent to calling [`Format::with_file`] and - /// [`Format::with_line_number`] with the same value. - pub fn with_source_location(self, display_location: bool) -> Self { - self.with_line_number(display_location) - .with_file(display_location) - } - - #[inline] - fn format_timestamp(&self, writer: &mut Writer<'_>) -> fmt::Result - where - T: FormatTime, - { - // If timestamps are disabled, do nothing. - if !self.display_timestamp { - return Ok(()); - } - - // If ANSI color codes are enabled, format the timestamp with ANSI - // colors. - #[cfg(feature = "ansi")] - { - if writer.has_ansi_escapes() { - let style = Style::new().dimmed(); - write!(writer, "{}", style.prefix())?; - - // If getting the timestamp failed, don't bail --- only bail on - // formatting errors. - if self.timer.format_time(writer).is_err() { - writer.write_str("<unknown time>")?; - } - - write!(writer, "{} ", style.suffix())?; - return Ok(()); - } - } - - // Otherwise, just format the timestamp without ANSI formatting. - // If getting the timestamp failed, don't bail --- only bail on - // formatting errors. - if self.timer.format_time(writer).is_err() { - writer.write_str("<unknown time>")?; - } - writer.write_char(' ') - } -} - -#[cfg(feature = "json")] -#[cfg_attr(docsrs, doc(cfg(feature = "json")))] -impl<T> Format<Json, T> { - /// Use the full JSON format with the event's event fields flattened. - /// - /// # Example Output - /// - /// ```ignore,json - /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate", "message":"some message", "key": "value"} - /// ``` - /// See [`Json`][super::format::Json]. - #[cfg(feature = "json")] - #[cfg_attr(docsrs, doc(cfg(feature = "json")))] - pub fn flatten_event(mut self, flatten_event: bool) -> Format<Json, T> { - self.format.flatten_event(flatten_event); - self - } - - /// Sets whether or not the formatter will include the current span in - /// formatted events. - /// - /// See [`format::Json`][Json] - #[cfg(feature = "json")] - #[cfg_attr(docsrs, doc(cfg(feature = "json")))] - pub fn with_current_span(mut self, display_current_span: bool) -> Format<Json, T> { - self.format.with_current_span(display_current_span); - self - } - - /// Sets whether or not the formatter will include a list (from root to - /// leaf) of all currently entered spans in formatted events. - /// - /// See [`format::Json`][Json] - #[cfg(feature = "json")] - #[cfg_attr(docsrs, doc(cfg(feature = "json")))] - pub fn with_span_list(mut self, display_span_list: bool) -> Format<Json, T> { - self.format.with_span_list(display_span_list); - self - } -} - -impl<S, N, T> FormatEvent<S, N> for Format<Full, T> -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, - T: FormatTime, -{ - fn format_event( - &self, - ctx: &FmtContext<'_, S, N>, - mut writer: Writer<'_>, - event: &Event<'_>, - ) -> fmt::Result { - #[cfg(feature = "tracing-log")] - let normalized_meta = event.normalized_metadata(); - #[cfg(feature = "tracing-log")] - let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); - #[cfg(not(feature = "tracing-log"))] - let meta = event.metadata(); - - // if the `Format` struct *also* has an ANSI color configuration, - // override the writer...the API for configuring ANSI color codes on the - // `Format` struct is deprecated, but we still need to honor those - // configurations. - if let Some(ansi) = self.ansi { - writer = writer.with_ansi(ansi); - } - - self.format_timestamp(&mut writer)?; - - if self.display_level { - let fmt_level = { - #[cfg(feature = "ansi")] - { - FmtLevel::new(meta.level(), writer.has_ansi_escapes()) - } - #[cfg(not(feature = "ansi"))] - { - FmtLevel::new(meta.level()) - } - }; - write!(writer, "{} ", fmt_level)?; - } - - if self.display_thread_name { - let current_thread = std::thread::current(); - match current_thread.name() { - Some(name) => { - write!(writer, "{} ", FmtThreadName::new(name))?; - } - // fall-back to thread id when name is absent and ids are not enabled - None if !self.display_thread_id => { - write!(writer, "{:0>2?} ", current_thread.id())?; - } - _ => {} - } - } - - if self.display_thread_id { - write!(writer, "{:0>2?} ", std::thread::current().id())?; - } - - let dimmed = writer.dimmed(); - - if let Some(scope) = ctx.event_scope() { - let bold = writer.bold(); - - let mut seen = false; - - for span in scope.from_root() { - write!(writer, "{}", bold.paint(span.metadata().name()))?; - seen = true; - - let ext = span.extensions(); - if let Some(fields) = &ext.get::<FormattedFields<N>>() { - if !fields.is_empty() { - write!(writer, "{}{}{}", bold.paint("{"), fields, bold.paint("}"))?; - } - } - write!(writer, "{}", dimmed.paint(":"))?; - } - - if seen { - writer.write_char(' ')?; - } - }; - - if self.display_target { - write!( - writer, - "{}{} ", - dimmed.paint(meta.target()), - dimmed.paint(":") - )?; - } - - let line_number = if self.display_line_number { - meta.line() - } else { - None - }; - - if self.display_filename { - if let Some(filename) = meta.file() { - write!( - writer, - "{}{}{}", - dimmed.paint(filename), - dimmed.paint(":"), - if line_number.is_some() { "" } else { " " } - )?; - } - } - - if let Some(line_number) = line_number { - write!( - writer, - "{}{}:{} ", - dimmed.prefix(), - line_number, - dimmed.suffix() - )?; - } - - ctx.format_fields(writer.by_ref(), event)?; - writeln!(writer) - } -} - -impl<S, N, T> FormatEvent<S, N> for Format<Compact, T> -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, - T: FormatTime, -{ - fn format_event( - &self, - ctx: &FmtContext<'_, S, N>, - mut writer: Writer<'_>, - event: &Event<'_>, - ) -> fmt::Result { - #[cfg(feature = "tracing-log")] - let normalized_meta = event.normalized_metadata(); - #[cfg(feature = "tracing-log")] - let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); - #[cfg(not(feature = "tracing-log"))] - let meta = event.metadata(); - - // if the `Format` struct *also* has an ANSI color configuration, - // override the writer...the API for configuring ANSI color codes on the - // `Format` struct is deprecated, but we still need to honor those - // configurations. - if let Some(ansi) = self.ansi { - writer = writer.with_ansi(ansi); - } - - self.format_timestamp(&mut writer)?; - - if self.display_level { - let fmt_level = { - #[cfg(feature = "ansi")] - { - FmtLevel::new(meta.level(), writer.has_ansi_escapes()) - } - #[cfg(not(feature = "ansi"))] - { - FmtLevel::new(meta.level()) - } - }; - write!(writer, "{} ", fmt_level)?; - } - - if self.display_thread_name { - let current_thread = std::thread::current(); - match current_thread.name() { - Some(name) => { - write!(writer, "{} ", FmtThreadName::new(name))?; - } - // fall-back to thread id when name is absent and ids are not enabled - None if !self.display_thread_id => { - write!(writer, "{:0>2?} ", current_thread.id())?; - } - _ => {} - } - } - - if self.display_thread_id { - write!(writer, "{:0>2?} ", std::thread::current().id())?; - } - - let fmt_ctx = { - #[cfg(feature = "ansi")] - { - FmtCtx::new(ctx, event.parent(), writer.has_ansi_escapes()) - } - #[cfg(not(feature = "ansi"))] - { - FmtCtx::new(&ctx, event.parent()) - } - }; - write!(writer, "{}", fmt_ctx)?; - - let bold = writer.bold(); - let dimmed = writer.dimmed(); - - let mut needs_space = false; - if self.display_target { - write!(writer, "{}{}", bold.paint(meta.target()), dimmed.paint(":"))?; - needs_space = true; - } - - if self.display_filename { - if let Some(filename) = meta.file() { - if self.display_target { - writer.write_char(' ')?; - } - write!(writer, "{}{}", bold.paint(filename), dimmed.paint(":"))?; - needs_space = true; - } - } - - if self.display_line_number { - if let Some(line_number) = meta.line() { - write!( - writer, - "{}{}{}{}", - bold.prefix(), - line_number, - bold.suffix(), - dimmed.paint(":") - )?; - needs_space = true; - } - } - - if needs_space { - writer.write_char(' ')?; - } - - ctx.format_fields(writer.by_ref(), event)?; - - for span in ctx - .event_scope() - .into_iter() - .flat_map(crate::registry::Scope::from_root) - { - let exts = span.extensions(); - if let Some(fields) = exts.get::<FormattedFields<N>>() { - if !fields.is_empty() { - write!(writer, " {}", dimmed.paint(&fields.fields))?; - } - } - } - writeln!(writer) - } -} - -// === impl FormatFields === -impl<'writer, M> FormatFields<'writer> for M -where - M: MakeOutput<Writer<'writer>, fmt::Result>, - M::Visitor: VisitFmt + VisitOutput<fmt::Result>, -{ - fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result { - let mut v = self.make_visitor(writer); - fields.record(&mut v); - v.finish() - } -} - -/// The default [`FormatFields`] implementation. -/// -#[derive(Debug)] -pub struct DefaultFields { - // reserve the ability to add fields to this without causing a breaking - // change in the future. - _private: (), -} - -/// The [visitor] produced by [`DefaultFields`]'s [`MakeVisitor`] implementation. -/// -/// [visitor]: super::super::field::Visit -/// [`MakeVisitor`]: super::super::field::MakeVisitor -#[derive(Debug)] -pub struct DefaultVisitor<'a> { - writer: Writer<'a>, - is_empty: bool, - result: fmt::Result, -} - -impl DefaultFields { - /// Returns a new default [`FormatFields`] implementation. - /// - pub fn new() -> Self { - Self { _private: () } - } -} - -impl Default for DefaultFields { - fn default() -> Self { - Self::new() - } -} - -impl<'a> MakeVisitor<Writer<'a>> for DefaultFields { - type Visitor = DefaultVisitor<'a>; - - #[inline] - fn make_visitor(&self, target: Writer<'a>) -> Self::Visitor { - DefaultVisitor::new(target, true) - } -} - -// === impl DefaultVisitor === - -impl<'a> DefaultVisitor<'a> { - /// Returns a new default visitor that formats to the provided `writer`. - /// - /// # Arguments - /// - `writer`: the writer to format to. - /// - `is_empty`: whether or not any fields have been previously written to - /// that writer. - pub fn new(writer: Writer<'a>, is_empty: bool) -> Self { - Self { - writer, - is_empty, - result: Ok(()), - } - } - - fn maybe_pad(&mut self) { - if self.is_empty { - self.is_empty = false; - } else { - self.result = write!(self.writer, " "); - } - } -} - -impl<'a> field::Visit for DefaultVisitor<'a> { - fn record_str(&mut self, field: &Field, value: &str) { - if self.result.is_err() { - return; - } - - if field.name() == "message" { - self.record_debug(field, &format_args!("{}", value)) - } else { - self.record_debug(field, &value) - } - } - - fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) { - if let Some(source) = value.source() { - let italic = self.writer.italic(); - self.record_debug( - field, - &format_args!( - "{} {}{}{}{}", - value, - italic.paint(field.name()), - italic.paint(".sources"), - self.writer.dimmed().paint("="), - ErrorSourceList(source) - ), - ) - } else { - self.record_debug(field, &format_args!("{}", value)) - } - } - - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - if self.result.is_err() { - return; - } - - self.maybe_pad(); - self.result = match field.name() { - "message" => write!(self.writer, "{:?}", value), - // Skip fields that are actually log metadata that have already been handled - #[cfg(feature = "tracing-log")] - name if name.starts_with("log.") => Ok(()), - name if name.starts_with("r#") => write!( - self.writer, - "{}{}{:?}", - self.writer.italic().paint(&name[2..]), - self.writer.dimmed().paint("="), - value - ), - name => write!( - self.writer, - "{}{}{:?}", - self.writer.italic().paint(name), - self.writer.dimmed().paint("="), - value - ), - }; - } -} - -impl<'a> crate::field::VisitOutput<fmt::Result> for DefaultVisitor<'a> { - fn finish(self) -> fmt::Result { - self.result - } -} - -impl<'a> crate::field::VisitFmt for DefaultVisitor<'a> { - fn writer(&mut self) -> &mut dyn fmt::Write { - &mut self.writer - } -} - -/// Renders an error into a list of sources, *including* the error -struct ErrorSourceList<'a>(&'a (dyn std::error::Error + 'static)); - -impl<'a> Display for ErrorSourceList<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut list = f.debug_list(); - let mut curr = Some(self.0); - while let Some(curr_err) = curr { - list.entry(&format_args!("{}", curr_err)); - curr = curr_err.source(); - } - list.finish() - } -} - -struct FmtCtx<'a, S, N> { - ctx: &'a FmtContext<'a, S, N>, - span: Option<&'a span::Id>, - #[cfg(feature = "ansi")] - ansi: bool, -} - -impl<'a, S, N: 'a> FmtCtx<'a, S, N> -where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static, -{ - #[cfg(feature = "ansi")] - pub(crate) fn new( - ctx: &'a FmtContext<'_, S, N>, - span: Option<&'a span::Id>, - ansi: bool, - ) -> Self { - Self { ctx, span, ansi } - } - - #[cfg(not(feature = "ansi"))] - pub(crate) fn new(ctx: &'a FmtContext<'_, S, N>, span: Option<&'a span::Id>) -> Self { - Self { ctx, span } - } - - fn bold(&self) -> Style { - #[cfg(feature = "ansi")] - { - if self.ansi { - return Style::new().bold(); - } - } - - Style::new() - } -} - -impl<'a, S, N: 'a> fmt::Display for FmtCtx<'a, S, N> -where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - N: for<'writer> FormatFields<'writer> + 'static, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let bold = self.bold(); - let mut seen = false; - - let span = self - .span - .and_then(|id| self.ctx.ctx.span(id)) - .or_else(|| self.ctx.ctx.lookup_current()); - - let scope = span.into_iter().flat_map(|span| span.scope().from_root()); - - for span in scope { - seen = true; - write!(f, "{}:", bold.paint(span.metadata().name()))?; - } - - if seen { - f.write_char(' ')?; - } - Ok(()) - } -} - -#[cfg(not(feature = "ansi"))] -struct Style; - -#[cfg(not(feature = "ansi"))] -impl Style { - fn new() -> Self { - Style - } - - fn bold(self) -> Self { - self - } - - fn paint(&self, d: impl fmt::Display) -> impl fmt::Display { - d - } - - fn prefix(&self) -> impl fmt::Display { - "" - } - - fn suffix(&self) -> impl fmt::Display { - "" - } -} - -struct FmtThreadName<'a> { - name: &'a str, -} - -impl<'a> FmtThreadName<'a> { - pub(crate) fn new(name: &'a str) -> Self { - Self { name } - } -} - -impl<'a> fmt::Display for FmtThreadName<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use std::sync::atomic::{ - AtomicUsize, - Ordering::{AcqRel, Acquire, Relaxed}, - }; - - // Track the longest thread name length we've seen so far in an atomic, - // so that it can be updated by any thread. - static MAX_LEN: AtomicUsize = AtomicUsize::new(0); - let len = self.name.len(); - // Snapshot the current max thread name length. - let mut max_len = MAX_LEN.load(Relaxed); - - while len > max_len { - // Try to set a new max length, if it is still the value we took a - // snapshot of. - match MAX_LEN.compare_exchange(max_len, len, AcqRel, Acquire) { - // We successfully set the new max value - Ok(_) => break, - // Another thread set a new max value since we last observed - // it! It's possible that the new length is actually longer than - // ours, so we'll loop again and check whether our length is - // still the longest. If not, we'll just use the newer value. - Err(actual) => max_len = actual, - } - } - - // pad thread name using `max_len` - write!(f, "{:>width$}", self.name, width = max_len) - } -} - -struct FmtLevel<'a> { - level: &'a Level, - #[cfg(feature = "ansi")] - ansi: bool, -} - -impl<'a> FmtLevel<'a> { - #[cfg(feature = "ansi")] - pub(crate) fn new(level: &'a Level, ansi: bool) -> Self { - Self { level, ansi } - } - - #[cfg(not(feature = "ansi"))] - pub(crate) fn new(level: &'a Level) -> Self { - Self { level } - } -} - -const TRACE_STR: &str = "TRACE"; -const DEBUG_STR: &str = "DEBUG"; -const INFO_STR: &str = " INFO"; -const WARN_STR: &str = " WARN"; -const ERROR_STR: &str = "ERROR"; - -#[cfg(not(feature = "ansi"))] -impl<'a> fmt::Display for FmtLevel<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self.level { - Level::TRACE => f.pad(TRACE_STR), - Level::DEBUG => f.pad(DEBUG_STR), - Level::INFO => f.pad(INFO_STR), - Level::WARN => f.pad(WARN_STR), - Level::ERROR => f.pad(ERROR_STR), - } - } -} - -#[cfg(feature = "ansi")] -impl<'a> fmt::Display for FmtLevel<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.ansi { - match *self.level { - Level::TRACE => write!(f, "{}", Colour::Purple.paint(TRACE_STR)), - Level::DEBUG => write!(f, "{}", Colour::Blue.paint(DEBUG_STR)), - Level::INFO => write!(f, "{}", Colour::Green.paint(INFO_STR)), - Level::WARN => write!(f, "{}", Colour::Yellow.paint(WARN_STR)), - Level::ERROR => write!(f, "{}", Colour::Red.paint(ERROR_STR)), - } - } else { - match *self.level { - Level::TRACE => f.pad(TRACE_STR), - Level::DEBUG => f.pad(DEBUG_STR), - Level::INFO => f.pad(INFO_STR), - Level::WARN => f.pad(WARN_STR), - Level::ERROR => f.pad(ERROR_STR), - } - } - } -} - -// === impl FieldFn === - -impl<'a, F> MakeVisitor<Writer<'a>> for FieldFn<F> -where - F: Fn(&mut Writer<'a>, &Field, &dyn fmt::Debug) -> fmt::Result + Clone, -{ - type Visitor = FieldFnVisitor<'a, F>; - - fn make_visitor(&self, writer: Writer<'a>) -> Self::Visitor { - FieldFnVisitor { - writer, - f: self.0.clone(), - result: Ok(()), - } - } -} - -impl<'a, F> Visit for FieldFnVisitor<'a, F> -where - F: Fn(&mut Writer<'a>, &Field, &dyn fmt::Debug) -> fmt::Result, -{ - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - if self.result.is_ok() { - self.result = (self.f)(&mut self.writer, field, value) - } - } -} - -impl<'a, F> VisitOutput<fmt::Result> for FieldFnVisitor<'a, F> -where - F: Fn(&mut Writer<'a>, &Field, &dyn fmt::Debug) -> fmt::Result, -{ - fn finish(self) -> fmt::Result { - self.result - } -} - -impl<'a, F> VisitFmt for FieldFnVisitor<'a, F> -where - F: Fn(&mut Writer<'a>, &Field, &dyn fmt::Debug) -> fmt::Result, -{ - fn writer(&mut self) -> &mut dyn fmt::Write { - &mut self.writer - } -} - -impl<'a, F> fmt::Debug for FieldFnVisitor<'a, F> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FieldFnVisitor") - .field("f", &format_args!("{}", std::any::type_name::<F>())) - .field("writer", &self.writer) - .field("result", &self.result) - .finish() - } -} - -// === printing synthetic Span events === - -/// Configures what points in the span lifecycle are logged as events. -/// -/// See also [`with_span_events`](super::SubscriberBuilder.html::with_span_events). -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)] -pub struct FmtSpan(u8); - -impl FmtSpan { - /// one event when span is created - pub const NEW: FmtSpan = FmtSpan(1 << 0); - /// one event per enter of a span - pub const ENTER: FmtSpan = FmtSpan(1 << 1); - /// one event per exit of a span - pub const EXIT: FmtSpan = FmtSpan(1 << 2); - /// one event when the span is dropped - pub const CLOSE: FmtSpan = FmtSpan(1 << 3); - - /// spans are ignored (this is the default) - pub const NONE: FmtSpan = FmtSpan(0); - /// one event per enter/exit of a span - pub const ACTIVE: FmtSpan = FmtSpan(FmtSpan::ENTER.0 | FmtSpan::EXIT.0); - /// events at all points (new, enter, exit, drop) - pub const FULL: FmtSpan = - FmtSpan(FmtSpan::NEW.0 | FmtSpan::ENTER.0 | FmtSpan::EXIT.0 | FmtSpan::CLOSE.0); - - /// Check whether or not a certain flag is set for this [`FmtSpan`] - fn contains(&self, other: FmtSpan) -> bool { - self.clone() & other.clone() == other - } -} - -macro_rules! impl_fmt_span_bit_op { - ($trait:ident, $func:ident, $op:tt) => { - impl std::ops::$trait for FmtSpan { - type Output = FmtSpan; - - fn $func(self, rhs: Self) -> Self::Output { - FmtSpan(self.0 $op rhs.0) - } - } - }; -} - -macro_rules! impl_fmt_span_bit_assign_op { - ($trait:ident, $func:ident, $op:tt) => { - impl std::ops::$trait for FmtSpan { - fn $func(&mut self, rhs: Self) { - *self = FmtSpan(self.0 $op rhs.0) - } - } - }; -} - -impl_fmt_span_bit_op!(BitAnd, bitand, &); -impl_fmt_span_bit_op!(BitOr, bitor, |); -impl_fmt_span_bit_op!(BitXor, bitxor, ^); - -impl_fmt_span_bit_assign_op!(BitAndAssign, bitand_assign, &); -impl_fmt_span_bit_assign_op!(BitOrAssign, bitor_assign, |); -impl_fmt_span_bit_assign_op!(BitXorAssign, bitxor_assign, ^); - -impl Debug for FmtSpan { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut wrote_flag = false; - let mut write_flags = |flag, flag_str| -> fmt::Result { - if self.contains(flag) { - if wrote_flag { - f.write_str(" | ")?; - } - - f.write_str(flag_str)?; - wrote_flag = true; - } - - Ok(()) - }; - - if FmtSpan::NONE | self.clone() == FmtSpan::NONE { - f.write_str("FmtSpan::NONE")?; - } else { - write_flags(FmtSpan::NEW, "FmtSpan::NEW")?; - write_flags(FmtSpan::ENTER, "FmtSpan::ENTER")?; - write_flags(FmtSpan::EXIT, "FmtSpan::EXIT")?; - write_flags(FmtSpan::CLOSE, "FmtSpan::CLOSE")?; - } - - Ok(()) - } -} - -pub(super) struct FmtSpanConfig { - pub(super) kind: FmtSpan, - pub(super) fmt_timing: bool, -} - -impl FmtSpanConfig { - pub(super) fn without_time(self) -> Self { - Self { - kind: self.kind, - fmt_timing: false, - } - } - pub(super) fn with_kind(self, kind: FmtSpan) -> Self { - Self { - kind, - fmt_timing: self.fmt_timing, - } - } - pub(super) fn trace_new(&self) -> bool { - self.kind.contains(FmtSpan::NEW) - } - pub(super) fn trace_enter(&self) -> bool { - self.kind.contains(FmtSpan::ENTER) - } - pub(super) fn trace_exit(&self) -> bool { - self.kind.contains(FmtSpan::EXIT) - } - pub(super) fn trace_close(&self) -> bool { - self.kind.contains(FmtSpan::CLOSE) - } -} - -impl Debug for FmtSpanConfig { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.kind.fmt(f) - } -} - -impl Default for FmtSpanConfig { - fn default() -> Self { - Self { - kind: FmtSpan::NONE, - fmt_timing: true, - } - } -} - -pub(super) struct TimingDisplay(pub(super) u64); -impl Display for TimingDisplay { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut t = self.0 as f64; - for unit in ["ns", "µs", "ms", "s"].iter() { - if t < 10.0 { - return write!(f, "{:.2}{}", t, unit); - } else if t < 100.0 { - return write!(f, "{:.1}{}", t, unit); - } else if t < 1000.0 { - return write!(f, "{:.0}{}", t, unit); - } - t /= 1000.0; - } - write!(f, "{:.0}s", t * 1000.0) - } -} - -#[cfg(test)] -pub(super) mod test { - use crate::fmt::{test::MockMakeWriter, time::FormatTime}; - use tracing::{ - self, - dispatcher::{set_default, Dispatch}, - subscriber::with_default, - }; - - use super::*; - - use regex::Regex; - use std::{fmt, path::Path}; - - pub(crate) struct MockTime; - impl FormatTime for MockTime { - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - write!(w, "fake time") - } - } - - #[test] - fn disable_everything() { - // This test reproduces https://github.com/tokio-rs/tracing/issues/1354 - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .without_time() - .with_level(false) - .with_target(false) - .with_thread_ids(false) - .with_thread_names(false); - #[cfg(feature = "ansi")] - let subscriber = subscriber.with_ansi(false); - assert_info_hello(subscriber, make_writer, "hello\n") - } - - fn test_ansi<T>( - is_ansi: bool, - expected: &str, - builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, - ) where - Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, - T: Send + Sync + 'static, - { - let make_writer = MockMakeWriter::default(); - let subscriber = builder - .with_writer(make_writer.clone()) - .with_ansi(is_ansi) - .with_timer(MockTime); - run_test(subscriber, make_writer, expected) - } - - #[cfg(not(feature = "ansi"))] - fn test_without_ansi<T>( - expected: &str, - builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, - ) where - Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, - T: Send + Sync, - { - let make_writer = MockMakeWriter::default(); - let subscriber = builder.with_writer(make_writer).with_timer(MockTime); - run_test(subscriber, make_writer, expected) - } - - fn test_without_level<T>( - expected: &str, - builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, - ) where - Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, - T: Send + Sync + 'static, - { - let make_writer = MockMakeWriter::default(); - let subscriber = builder - .with_writer(make_writer.clone()) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime); - run_test(subscriber, make_writer, expected); - } - - #[test] - fn with_line_number_and_file_name() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_file(true) - .with_line_number(true) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime); - - let expected = Regex::new(&format!( - "^fake time tracing_subscriber::fmt::format::test: {}:[0-9]+: hello\n$", - current_path() - // if we're on Windows, the path might contain backslashes, which - // have to be escpaed before compiling the regex. - .replace('\\', "\\\\") - )) - .unwrap(); - let _default = set_default(&subscriber.into()); - tracing::info!("hello"); - let res = make_writer.get_string(); - assert!(expected.is_match(&res)); - } - - #[test] - fn with_line_number() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_line_number(true) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime); - - let expected = - Regex::new("^fake time tracing_subscriber::fmt::format::test: [0-9]+: hello\n$") - .unwrap(); - let _default = set_default(&subscriber.into()); - tracing::info!("hello"); - let res = make_writer.get_string(); - assert!(expected.is_match(&res)); - } - - #[test] - fn with_filename() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_file(true) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime); - let expected = &format!( - "fake time tracing_subscriber::fmt::format::test: {}: hello\n", - current_path(), - ); - assert_info_hello(subscriber, make_writer, expected); - } - - #[test] - fn with_thread_ids() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_thread_ids(true) - .with_ansi(false) - .with_timer(MockTime); - let expected = - "fake time INFO ThreadId(NUMERIC) tracing_subscriber::fmt::format::test: hello\n"; - - assert_info_hello_ignore_numeric(subscriber, make_writer, expected); - } - - #[test] - fn pretty_default() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .pretty() - .with_writer(make_writer.clone()) - .with_ansi(false) - .with_timer(MockTime); - let expected = format!( - r#" fake time INFO tracing_subscriber::fmt::format::test: hello - at {}:NUMERIC - -"#, - file!() - ); - - assert_info_hello_ignore_numeric(subscriber, make_writer, &expected) - } - - fn assert_info_hello(subscriber: impl Into<Dispatch>, buf: MockMakeWriter, expected: &str) { - let _default = set_default(&subscriber.into()); - tracing::info!("hello"); - let result = buf.get_string(); - - assert_eq!(expected, result) - } - - // When numeric characters are used they often form a non-deterministic value as they usually represent things like a thread id or line number. - // This assert method should be used when non-deterministic numeric characters are present. - fn assert_info_hello_ignore_numeric( - subscriber: impl Into<Dispatch>, - buf: MockMakeWriter, - expected: &str, - ) { - let _default = set_default(&subscriber.into()); - tracing::info!("hello"); - - let regex = Regex::new("[0-9]+").unwrap(); - let result = buf.get_string(); - let result_cleaned = regex.replace_all(&result, "NUMERIC"); - - assert_eq!(expected, result_cleaned) - } - - fn test_overridden_parents<T>( - expected: &str, - builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, - ) where - Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, - T: Send + Sync + 'static, - { - let make_writer = MockMakeWriter::default(); - let subscriber = builder - .with_writer(make_writer.clone()) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime) - .finish(); - - with_default(subscriber, || { - let span1 = tracing::info_span!("span1", span = 1); - let span2 = tracing::info_span!(parent: &span1, "span2", span = 2); - tracing::info!(parent: &span2, "hello"); - }); - assert_eq!(expected, make_writer.get_string()); - } - - fn test_overridden_parents_in_scope<T>( - expected1: &str, - expected2: &str, - builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, - ) where - Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, - T: Send + Sync + 'static, - { - let make_writer = MockMakeWriter::default(); - let subscriber = builder - .with_writer(make_writer.clone()) - .with_level(false) - .with_ansi(false) - .with_timer(MockTime) - .finish(); - - with_default(subscriber, || { - let span1 = tracing::info_span!("span1", span = 1); - let span2 = tracing::info_span!(parent: &span1, "span2", span = 2); - let span3 = tracing::info_span!("span3", span = 3); - let _e3 = span3.enter(); - - tracing::info!("hello"); - assert_eq!(expected1, make_writer.get_string().as_str()); - - tracing::info!(parent: &span2, "hello"); - assert_eq!(expected2, make_writer.get_string().as_str()); - }); - } - - fn run_test(subscriber: impl Into<Dispatch>, buf: MockMakeWriter, expected: &str) { - let _default = set_default(&subscriber.into()); - tracing::info!("hello"); - assert_eq!(expected, buf.get_string()) - } - - mod default { - use super::*; - - #[test] - fn with_thread_ids() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .with_writer(make_writer.clone()) - .with_thread_ids(true) - .with_ansi(false) - .with_timer(MockTime); - let expected = - "fake time INFO ThreadId(NUMERIC) tracing_subscriber::fmt::format::test: hello\n"; - - assert_info_hello_ignore_numeric(subscriber, make_writer, expected); - } - - #[cfg(feature = "ansi")] - #[test] - fn with_ansi_true() { - let expected = "\u{1b}[2mfake time\u{1b}[0m \u{1b}[32m INFO\u{1b}[0m \u{1b}[2mtracing_subscriber::fmt::format::test\u{1b}[0m\u{1b}[2m:\u{1b}[0m hello\n"; - test_ansi(true, expected, crate::fmt::Subscriber::builder()); - } - - #[cfg(feature = "ansi")] - #[test] - fn with_ansi_false() { - let expected = "fake time INFO tracing_subscriber::fmt::format::test: hello\n"; - test_ansi(false, expected, crate::fmt::Subscriber::builder()); - } - - #[cfg(not(feature = "ansi"))] - #[test] - fn without_ansi() { - let expected = "fake time INFO tracing_subscriber::fmt::format::test: hello\n"; - test_without_ansi(expected, crate::fmt::Subscriber::builder()) - } - - #[test] - fn without_level() { - let expected = "fake time tracing_subscriber::fmt::format::test: hello\n"; - test_without_level(expected, crate::fmt::Subscriber::builder()) - } - - #[test] - fn overridden_parents() { - let expected = "fake time span1{span=1}:span2{span=2}: tracing_subscriber::fmt::format::test: hello\n"; - test_overridden_parents(expected, crate::fmt::Subscriber::builder()) - } - - #[test] - fn overridden_parents_in_scope() { - test_overridden_parents_in_scope( - "fake time span3{span=3}: tracing_subscriber::fmt::format::test: hello\n", - "fake time span1{span=1}:span2{span=2}: tracing_subscriber::fmt::format::test: hello\n", - crate::fmt::Subscriber::builder(), - ) - } - } - - mod compact { - use super::*; - - #[cfg(feature = "ansi")] - #[test] - fn with_ansi_true() { - let expected = "\u{1b}[2mfake time\u{1b}[0m \u{1b}[32m INFO\u{1b}[0m \u{1b}[1mtracing_subscriber::fmt::format::test\u{1b}[0m\u{1b}[2m:\u{1b}[0m hello\n"; - test_ansi(true, expected, crate::fmt::Subscriber::builder().compact()) - } - - #[cfg(feature = "ansi")] - #[test] - fn with_ansi_false() { - let expected = "fake time INFO tracing_subscriber::fmt::format::test: hello\n"; - test_ansi(false, expected, crate::fmt::Subscriber::builder().compact()); - } - - #[cfg(not(feature = "ansi"))] - #[test] - fn without_ansi() { - let expected = "fake time INFO tracing_subscriber::fmt::format::test: hello\n"; - test_without_ansi(expected, crate::fmt::Subscriber::builder().compact()) - } - - #[test] - fn without_level() { - let expected = "fake time tracing_subscriber::fmt::format::test: hello\n"; - test_without_level(expected, crate::fmt::Subscriber::builder().compact()); - } - - #[test] - fn overridden_parents() { - let expected = "fake time span1:span2: tracing_subscriber::fmt::format::test: hello span=1 span=2\n"; - test_overridden_parents(expected, crate::fmt::Subscriber::builder().compact()) - } - - #[test] - fn overridden_parents_in_scope() { - test_overridden_parents_in_scope( - "fake time span3: tracing_subscriber::fmt::format::test: hello span=3\n", - "fake time span1:span2: tracing_subscriber::fmt::format::test: hello span=1 span=2\n", - crate::fmt::Subscriber::builder().compact(), - ) - } - } - - mod pretty { - use super::*; - - #[test] - fn pretty_default() { - let make_writer = MockMakeWriter::default(); - let subscriber = crate::fmt::Subscriber::builder() - .pretty() - .with_writer(make_writer.clone()) - .with_ansi(false) - .with_timer(MockTime); - let expected = format!( - " fake time INFO tracing_subscriber::fmt::format::test: hello\n at {}:NUMERIC\n\n", - file!() - ); - - assert_info_hello_ignore_numeric(subscriber, make_writer, &expected) - } - } - - #[test] - fn format_nanos() { - fn fmt(t: u64) -> String { - TimingDisplay(t).to_string() - } - - assert_eq!(fmt(1), "1.00ns"); - assert_eq!(fmt(12), "12.0ns"); - assert_eq!(fmt(123), "123ns"); - assert_eq!(fmt(1234), "1.23µs"); - assert_eq!(fmt(12345), "12.3µs"); - assert_eq!(fmt(123456), "123µs"); - assert_eq!(fmt(1234567), "1.23ms"); - assert_eq!(fmt(12345678), "12.3ms"); - assert_eq!(fmt(123456789), "123ms"); - assert_eq!(fmt(1234567890), "1.23s"); - assert_eq!(fmt(12345678901), "12.3s"); - assert_eq!(fmt(123456789012), "123s"); - assert_eq!(fmt(1234567890123), "1235s"); - } - - #[test] - fn fmt_span_combinations() { - let f = FmtSpan::NONE; - assert!(!f.contains(FmtSpan::NEW)); - assert!(!f.contains(FmtSpan::ENTER)); - assert!(!f.contains(FmtSpan::EXIT)); - assert!(!f.contains(FmtSpan::CLOSE)); - - let f = FmtSpan::ACTIVE; - assert!(!f.contains(FmtSpan::NEW)); - assert!(f.contains(FmtSpan::ENTER)); - assert!(f.contains(FmtSpan::EXIT)); - assert!(!f.contains(FmtSpan::CLOSE)); - - let f = FmtSpan::FULL; - assert!(f.contains(FmtSpan::NEW)); - assert!(f.contains(FmtSpan::ENTER)); - assert!(f.contains(FmtSpan::EXIT)); - assert!(f.contains(FmtSpan::CLOSE)); - - let f = FmtSpan::NEW | FmtSpan::CLOSE; - assert!(f.contains(FmtSpan::NEW)); - assert!(!f.contains(FmtSpan::ENTER)); - assert!(!f.contains(FmtSpan::EXIT)); - assert!(f.contains(FmtSpan::CLOSE)); - } - - /// Returns the test's module path. - fn current_path() -> String { - Path::new("tracing-subscriber") - .join("src") - .join("fmt") - .join("format") - .join("mod.rs") - .to_str() - .expect("path must not contain invalid unicode") - .to_owned() - } -} diff --git a/vendor/tracing-subscriber/src/fmt/format/pretty.rs b/vendor/tracing-subscriber/src/fmt/format/pretty.rs deleted file mode 100644 index a50d08ba7..000000000 --- a/vendor/tracing-subscriber/src/fmt/format/pretty.rs +++ /dev/null @@ -1,511 +0,0 @@ -use super::*; -use crate::{ - field::{VisitFmt, VisitOutput}, - fmt::fmt_layer::{FmtContext, FormattedFields}, - registry::LookupSpan, -}; - -use std::fmt; -use tracing_core::{ - field::{self, Field}, - Event, Level, Subscriber, -}; - -#[cfg(feature = "tracing-log")] -use tracing_log::NormalizeEvent; - -use ansi_term::{Colour, Style}; - -/// An excessively pretty, human-readable event formatter. -/// -/// Unlike the [`Full`], [`Compact`], and [`Json`] formatters, this is a -/// multi-line output format. Each individual event may output multiple lines of -/// text. -/// -/// # Example Output -/// -/// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt-pretty -/// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s -/// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-pretty` -/// 2022-02-15T18:44:24.535324Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: preparing to shave yaks, </font><font color="#4E9A06"><b>number_of_yaks</b></font><font color="#4E9A06">: 3</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:16 <font color="#AAAAAA"><i>on</i></font> main -/// -/// 2022-02-15T18:44:24.535403Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty::yak_shave</b></font><font color="#4E9A06">: shaving yaks</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:41 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535442Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1 -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535469Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:25 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1 -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535502Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 1, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535524Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 1</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535551Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2 -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535573Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:25 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2 -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535600Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 2, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535618Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535644Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3 -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535670Z <font color="#C4A000"> WARN</font> <font color="#C4A000"><b>fmt_pretty::yak_shave</b></font><font color="#C4A000">: could not locate yak</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:18 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3 -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535698Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 3, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: false</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535720Z <font color="#CC0000">ERROR</font> <font color="#CC0000"><b>fmt_pretty::yak_shave</b></font><font color="#CC0000">: failed to shave yak, </font><font color="#CC0000"><b>yak</b></font><font color="#CC0000">: 3, </font><font color="#CC0000"><b>error</b></font><font color="#CC0000">: missing yak, </font><font color="#CC0000"><b>error.sources</b></font><font color="#CC0000">: [out of space, out of cash]</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:51 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535742Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main -/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 -/// -/// 2022-02-15T18:44:24.535765Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: yak shaving completed, </font><font color="#4E9A06"><b>all_yaks_shaved</b></font><font color="#4E9A06">: false</font> -/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:19 <font color="#AAAAAA"><i>on</i></font> main -/// </pre> -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct Pretty { - display_location: bool, -} - -/// The [visitor] produced by [`Pretty`]'s [`MakeVisitor`] implementation. -/// -/// [visitor]: field::Visit -/// [`MakeVisitor`]: crate::field::MakeVisitor -#[derive(Debug)] -pub struct PrettyVisitor<'a> { - writer: Writer<'a>, - is_empty: bool, - style: Style, - result: fmt::Result, -} - -/// An excessively pretty, human-readable [`MakeVisitor`] implementation. -/// -/// [`MakeVisitor`]: crate::field::MakeVisitor -#[derive(Debug)] -pub struct PrettyFields { - /// A value to override the provided `Writer`'s ANSI formatting - /// configuration. - /// - /// If this is `Some`, we override the `Writer`'s ANSI setting. This is - /// necessary in order to continue supporting the deprecated - /// `PrettyFields::with_ansi` method. If it is `None`, we don't override the - /// ANSI formatting configuration (because the deprecated method was not - /// called). - // TODO: when `PrettyFields::with_ansi` is removed, we can get rid - // of this entirely. - ansi: Option<bool>, -} - -// === impl Pretty === - -impl Default for Pretty { - fn default() -> Self { - Self { - display_location: true, - } - } -} - -impl Pretty { - fn style_for(level: &Level) -> Style { - match *level { - Level::TRACE => Style::new().fg(Colour::Purple), - Level::DEBUG => Style::new().fg(Colour::Blue), - Level::INFO => Style::new().fg(Colour::Green), - Level::WARN => Style::new().fg(Colour::Yellow), - Level::ERROR => Style::new().fg(Colour::Red), - } - } - - /// Sets whether the event's source code location is displayed. - /// - /// This defaults to `true`. - #[deprecated( - since = "0.3.6", - note = "all formatters now support configurable source locations. Use `Format::with_source_location` instead." - )] - pub fn with_source_location(self, display_location: bool) -> Self { - Self { - display_location, - ..self - } - } -} - -impl<C, N, T> FormatEvent<C, N> for Format<Pretty, T> -where - C: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, - T: FormatTime, -{ - fn format_event( - &self, - ctx: &FmtContext<'_, C, N>, - mut writer: Writer<'_>, - event: &Event<'_>, - ) -> fmt::Result { - #[cfg(feature = "tracing-log")] - let normalized_meta = event.normalized_metadata(); - #[cfg(feature = "tracing-log")] - let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); - #[cfg(not(feature = "tracing-log"))] - let meta = event.metadata(); - write!(&mut writer, " ")?; - - // if the `Format` struct *also* has an ANSI color configuration, - // override the writer...the API for configuring ANSI color codes on the - // `Format` struct is deprecated, but we still need to honor those - // configurations. - if let Some(ansi) = self.ansi { - writer = writer.with_ansi(ansi); - } - - self.format_timestamp(&mut writer)?; - - let style = if self.display_level && writer.has_ansi_escapes() { - Pretty::style_for(meta.level()) - } else { - Style::new() - }; - - if self.display_level { - write!( - writer, - "{} ", - super::FmtLevel::new(meta.level(), writer.has_ansi_escapes()) - )?; - } - - if self.display_target { - let target_style = if writer.has_ansi_escapes() { - style.bold() - } else { - style - }; - write!( - writer, - "{}{}{}:", - target_style.prefix(), - meta.target(), - target_style.infix(style) - )?; - } - let line_number = if self.display_line_number { - meta.line() - } else { - None - }; - - // If the file name is disabled, format the line number right after the - // target. Otherwise, if we also display the file, it'll go on a - // separate line. - if let (Some(line_number), false, true) = ( - line_number, - self.display_filename, - self.format.display_location, - ) { - write!( - writer, - "{}{}{}:", - style.prefix(), - line_number, - style.infix(style) - )?; - } - - writer.write_char(' ')?; - - let mut v = PrettyVisitor::new(writer.by_ref(), true).with_style(style); - event.record(&mut v); - v.finish()?; - writer.write_char('\n')?; - - let dimmed = if writer.has_ansi_escapes() { - Style::new().dimmed().italic() - } else { - Style::new() - }; - let thread = self.display_thread_name || self.display_thread_id; - - if let (Some(file), true, true) = ( - meta.file(), - self.format.display_location, - self.display_filename, - ) { - write!(writer, " {} {}", dimmed.paint("at"), file,)?; - - if let Some(line) = line_number { - write!(writer, ":{}", line)?; - } - writer.write_char(if thread { ' ' } else { '\n' })?; - } else if thread { - write!(writer, " ")?; - }; - - if thread { - write!(writer, "{} ", dimmed.paint("on"))?; - let thread = std::thread::current(); - if self.display_thread_name { - if let Some(name) = thread.name() { - write!(writer, "{}", name)?; - if self.display_thread_id { - writer.write_char(' ')?; - } - } - } - if self.display_thread_id { - write!(writer, "{:?}", thread.id())?; - } - writer.write_char('\n')?; - } - - let bold = writer.bold(); - let span = event - .parent() - .and_then(|id| ctx.span(id)) - .or_else(|| ctx.lookup_current()); - - let scope = span.into_iter().flat_map(|span| span.scope()); - - for span in scope { - let meta = span.metadata(); - if self.display_target { - write!( - writer, - " {} {}::{}", - dimmed.paint("in"), - meta.target(), - bold.paint(meta.name()), - )?; - } else { - write!( - writer, - " {} {}", - dimmed.paint("in"), - bold.paint(meta.name()), - )?; - } - - let ext = span.extensions(); - let fields = &ext - .get::<FormattedFields<N>>() - .expect("Unable to find FormattedFields in extensions; this is a bug"); - if !fields.is_empty() { - write!(writer, " {} {}", dimmed.paint("with"), fields)?; - } - writer.write_char('\n')?; - } - - writer.write_char('\n') - } -} - -impl<'writer> FormatFields<'writer> for Pretty { - fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result { - let mut v = PrettyVisitor::new(writer, true); - fields.record(&mut v); - v.finish() - } - - fn add_fields( - &self, - current: &'writer mut FormattedFields<Self>, - fields: &span::Record<'_>, - ) -> fmt::Result { - let empty = current.is_empty(); - let writer = current.as_writer(); - let mut v = PrettyVisitor::new(writer, empty); - fields.record(&mut v); - v.finish() - } -} - -// === impl PrettyFields === - -impl Default for PrettyFields { - fn default() -> Self { - Self::new() - } -} - -impl PrettyFields { - /// Returns a new default [`PrettyFields`] implementation. - pub fn new() -> Self { - // By default, don't override the `Writer`'s ANSI colors - // configuration. We'll only do this if the user calls the - // deprecated `PrettyFields::with_ansi` method. - Self { ansi: None } - } - - /// Enable ANSI encoding for formatted fields. - #[deprecated( - since = "0.3.3", - note = "Use `fmt::Subscriber::with_ansi` or `fmt::Layer::with_ansi` instead." - )] - pub fn with_ansi(self, ansi: bool) -> Self { - Self { - ansi: Some(ansi), - ..self - } - } -} - -impl<'a> MakeVisitor<Writer<'a>> for PrettyFields { - type Visitor = PrettyVisitor<'a>; - - #[inline] - fn make_visitor(&self, mut target: Writer<'a>) -> Self::Visitor { - if let Some(ansi) = self.ansi { - target = target.with_ansi(ansi); - } - PrettyVisitor::new(target, true) - } -} - -// === impl PrettyVisitor === - -impl<'a> PrettyVisitor<'a> { - /// Returns a new default visitor that formats to the provided `writer`. - /// - /// # Arguments - /// - `writer`: the writer to format to. - /// - `is_empty`: whether or not any fields have been previously written to - /// that writer. - pub fn new(writer: Writer<'a>, is_empty: bool) -> Self { - Self { - writer, - is_empty, - style: Style::default(), - result: Ok(()), - } - } - - pub(crate) fn with_style(self, style: Style) -> Self { - Self { style, ..self } - } - - fn write_padded(&mut self, value: &impl fmt::Debug) { - let padding = if self.is_empty { - self.is_empty = false; - "" - } else { - ", " - }; - self.result = write!(self.writer, "{}{:?}", padding, value); - } - - fn bold(&self) -> Style { - if self.writer.has_ansi_escapes() { - self.style.bold() - } else { - Style::new() - } - } -} - -impl<'a> field::Visit for PrettyVisitor<'a> { - fn record_str(&mut self, field: &Field, value: &str) { - if self.result.is_err() { - return; - } - - if field.name() == "message" { - self.record_debug(field, &format_args!("{}", value)) - } else { - self.record_debug(field, &value) - } - } - - fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) { - if let Some(source) = value.source() { - let bold = self.bold(); - self.record_debug( - field, - &format_args!( - "{}, {}{}.sources{}: {}", - value, - bold.prefix(), - field, - bold.infix(self.style), - ErrorSourceList(source), - ), - ) - } else { - self.record_debug(field, &format_args!("{}", value)) - } - } - - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - if self.result.is_err() { - return; - } - let bold = self.bold(); - match field.name() { - "message" => self.write_padded(&format_args!("{}{:?}", self.style.prefix(), value,)), - // Skip fields that are actually log metadata that have already been handled - #[cfg(feature = "tracing-log")] - name if name.starts_with("log.") => self.result = Ok(()), - name if name.starts_with("r#") => self.write_padded(&format_args!( - "{}{}{}: {:?}", - bold.prefix(), - &name[2..], - bold.infix(self.style), - value - )), - name => self.write_padded(&format_args!( - "{}{}{}: {:?}", - bold.prefix(), - name, - bold.infix(self.style), - value - )), - }; - } -} - -impl<'a> VisitOutput<fmt::Result> for PrettyVisitor<'a> { - fn finish(mut self) -> fmt::Result { - write!(&mut self.writer, "{}", self.style.suffix())?; - self.result - } -} - -impl<'a> VisitFmt for PrettyVisitor<'a> { - fn writer(&mut self) -> &mut dyn fmt::Write { - &mut self.writer - } -} diff --git a/vendor/tracing-subscriber/src/fmt/mod.rs b/vendor/tracing-subscriber/src/fmt/mod.rs deleted file mode 100644 index 3c6a6ac40..000000000 --- a/vendor/tracing-subscriber/src/fmt/mod.rs +++ /dev/null @@ -1,1324 +0,0 @@ -//! A `Subscriber` for formatting and logging `tracing` data. -//! -//! # Overview -//! -//! [`tracing`] is a framework for instrumenting Rust programs with context-aware, -//! structured, event-based diagnostic information. This crate provides an -//! implementation of the [`Subscriber`] trait that records `tracing`'s `Event`s -//! and `Span`s by formatting them as text and logging them to stdout. -//! -//! # Usage -//! -//! First, add this to your `Cargo.toml` file: -//! -//! ```toml -//! [dependencies] -//! tracing-subscriber = "0.3" -//! ``` -//! -//! *Compiler support: [requires `rustc` 1.49+][msrv]* -//! -//! [msrv]: super#supported-rust-versions -//! -//! Add the following to your executable to initialize the default subscriber: -//! ```rust -//! use tracing_subscriber; -//! -//! tracing_subscriber::fmt::init(); -//! ``` -//! -//! ## Filtering Events with Environment Variables -//! -//! The default subscriber installed by `init` enables you to filter events -//! at runtime using environment variables (using the [`EnvFilter`]). -//! -//! The filter syntax is a superset of the [`env_logger`] syntax. -//! -//! For example: -//! - Setting `RUST_LOG=debug` enables all `Span`s and `Event`s -//! set to the log level `DEBUG` or higher -//! - Setting `RUST_LOG=my_crate=trace` enables `Span`s and `Event`s -//! in `my_crate` at all log levels -//! -//! **Note**: This should **not** be called by libraries. Libraries should use -//! [`tracing`] to publish `tracing` `Event`s. -//! -//! # Configuration -//! -//! You can configure a subscriber instead of using the defaults with -//! the following functions: -//! -//! ### Subscriber -//! -//! The [`FmtSubscriber`] formats and records `tracing` events as line-oriented logs. -//! You can create one by calling: -//! -//! ```rust -//! let subscriber = tracing_subscriber::fmt() -//! // ... add configuration -//! .finish(); -//! ``` -//! -//! You can find the configuration methods for [`FmtSubscriber`] in -//! [`SubscriberBuilder`]. -//! -//! ## Formatters -//! -//! The output format used by the layer and subscriber in this module is -//! represented by implementing the [`FormatEvent`] trait, and can be -//! customized. This module provides a number of formatter implementations: -//! -//! * [`format::Full`]: The default formatter. This emits human-readable, -//! single-line logs for each event that occurs, with the current span context -//! displayed before the formatted representation of the event. See -//! [here](format::Full#example-output) for sample output. -//! -//! * [`format::Compact`]: A variant of the default formatter, optimized for -//! short line lengths. Fields from the current span context are appended to -//! the fields of the formatted event. See -//! [here](format::Compact#example-output) for sample output. -//! -//! * [`format::Pretty`]: Emits excessively pretty, multi-line logs, optimized -//! for human readability. This is primarily intended to be used in local -//! development and debugging, or for command-line applications, where -//! automated analysis and compact storage of logs is less of a priority than -//! readability and visual appeal. See [here](format::Pretty#example-output) -//! for sample output. -//! -//! * [`format::Json`]: Outputs newline-delimited JSON logs. This is intended -//! for production use with systems where structured logs are consumed as JSON -//! by analysis and viewing tools. The JSON output is not optimized for human -//! readability. See [here](format::Json#example-output) for sample output. -//! -//! ### Customizing Formatters -//! -//! The formatting of log lines for spans and events is controlled by two -//! traits, [`FormatEvent`] and [`FormatFields`]. The [`FormatEvent`] trait -//! determines the overall formatting of the log line, such as what information -//! from the event's metadata and span context is included and in what order. -//! The [`FormatFields`] trait determines how fields — both the event's -//! fields and fields on spans — are formatted. -//! -//! The [`fmt::format`] module provides several types which implement these traits, -//! many of which expose additional configuration options to customize their -//! output. The [`format::Format`] type implements common configuration used by -//! all the formatters provided in this crate, and can be used as a builder to -//! set specific formatting settings. For example: -//! -//! ``` -//! use tracing_subscriber::fmt; -//! -//! // Configure a custom event formatter -//! let format = fmt::format() -//! .with_level(false) // don't include levels in formatted output -//! .with_target(false) // don't include targets -//! .with_thread_ids(true) // include the thread ID of the current thread -//! .with_thread_names(true) // include the name of the current thread -//! .compact(); // use the `Compact` formatting style. -//! -//! // Create a `fmt` subscriber that uses our custom event format, and set it -//! // as the default. -//! tracing_subscriber::fmt() -//! .event_format(format) -//! .init(); -//! ``` -//! -//! However, if a specific output format is needed, other crates can -//! also implement [`FormatEvent`] and [`FormatFields`]. See those traits' -//! documentation for details on how to implement them. -//! -//! ## Filters -//! -//! If you want to filter the `tracing` `Events` based on environment -//! variables, you can use the [`EnvFilter`] as follows: -//! -//! ```rust -//! use tracing_subscriber::EnvFilter; -//! -//! let filter = EnvFilter::from_default_env(); -//! ``` -//! -//! As mentioned above, the [`EnvFilter`] allows `Span`s and `Event`s to -//! be filtered at runtime by setting the `RUST_LOG` environment variable. -//! -//! You can find the other available [`filter`]s in the documentation. -//! -//! ### Using Your Subscriber -//! -//! Finally, once you have configured your `Subscriber`, you need to -//! configure your executable to use it. -//! -//! A subscriber can be installed globally using: -//! ```rust -//! use tracing; -//! use tracing_subscriber::FmtSubscriber; -//! -//! let subscriber = FmtSubscriber::new(); -//! -//! tracing::subscriber::set_global_default(subscriber) -//! .map_err(|_err| eprintln!("Unable to set global default subscriber")); -//! // Note this will only fail if you try to set the global default -//! // subscriber multiple times -//! ``` -//! -//! ### Composing Layers -//! -//! Composing an [`EnvFilter`] `Layer` and a [format `Layer`][super::fmt::Layer]: -//! -//! ```rust -//! use tracing_subscriber::{fmt, EnvFilter}; -//! use tracing_subscriber::prelude::*; -//! -//! let fmt_layer = fmt::layer() -//! .with_target(false); -//! let filter_layer = EnvFilter::try_from_default_env() -//! .or_else(|_| EnvFilter::try_new("info")) -//! .unwrap(); -//! -//! tracing_subscriber::registry() -//! .with(filter_layer) -//! .with(fmt_layer) -//! .init(); -//! ``` -//! -//! [`EnvFilter`]: super::filter::EnvFilter -//! [`env_logger`]: https://docs.rs/env_logger/ -//! [`filter`]: super::filter -//! [`FmtSubscriber`]: Subscriber -//! [`Subscriber`]: -//! https://docs.rs/tracing/latest/tracing/trait.Subscriber.html -//! [`tracing`]: https://crates.io/crates/tracing -//! [`fmt::format`]: mod@crate::fmt::format -use std::{any::TypeId, error::Error, io}; -use tracing_core::{span, subscriber::Interest, Event, Metadata}; - -mod fmt_layer; -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -pub mod format; -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -pub mod time; -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -pub mod writer; - -pub use fmt_layer::{FmtContext, FormattedFields, Layer}; - -use crate::layer::Layer as _; -use crate::util::SubscriberInitExt; -use crate::{ - filter::LevelFilter, - layer, - registry::{LookupSpan, Registry}, -}; - -#[doc(inline)] -pub use self::{ - format::{format, FormatEvent, FormatFields}, - time::time, - writer::{MakeWriter, TestWriter}, -}; - -/// A `Subscriber` that logs formatted representations of `tracing` events. -/// -/// This consists of an inner `Formatter` wrapped in a layer that performs filtering. -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -#[derive(Debug)] -pub struct Subscriber< - N = format::DefaultFields, - E = format::Format<format::Full>, - F = LevelFilter, - W = fn() -> io::Stdout, -> { - inner: layer::Layered<F, Formatter<N, E, W>>, -} - -/// A `Subscriber` that logs formatted representations of `tracing` events. -/// This type only logs formatted events; it does not perform any filtering. -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -pub type Formatter< - N = format::DefaultFields, - E = format::Format<format::Full>, - W = fn() -> io::Stdout, -> = layer::Layered<fmt_layer::Layer<Registry, N, E, W>, Registry>; - -/// Configures and constructs `Subscriber`s. -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -#[derive(Debug)] -pub struct SubscriberBuilder< - N = format::DefaultFields, - E = format::Format<format::Full>, - F = LevelFilter, - W = fn() -> io::Stdout, -> { - filter: F, - inner: Layer<Registry, N, E, W>, -} - -/// Returns a new [`SubscriberBuilder`] for configuring a [formatting subscriber]. -/// -/// This is essentially shorthand for [`SubscriberBuilder::default()]`. -/// -/// # Examples -/// -/// Using [`init`] to set the default subscriber: -/// -/// ```rust -/// tracing_subscriber::fmt().init(); -/// ``` -/// -/// Configuring the output format: -/// -/// ```rust -/// -/// tracing_subscriber::fmt() -/// // Configure formatting settings. -/// .with_target(false) -/// .with_timer(tracing_subscriber::fmt::time::uptime()) -/// .with_level(true) -/// // Set the subscriber as the default. -/// .init(); -/// ``` -/// -/// [`try_init`] returns an error if the default subscriber could not be set: -/// -/// ```rust -/// use std::error::Error; -/// -/// fn init_subscriber() -> Result<(), Box<dyn Error + Send + Sync + 'static>> { -/// tracing_subscriber::fmt() -/// // Configure the subscriber to emit logs in JSON format. -/// .json() -/// // Configure the subscriber to flatten event fields in the output JSON objects. -/// .flatten_event(true) -/// // Set the subscriber as the default, returning an error if this fails. -/// .try_init()?; -/// -/// Ok(()) -/// } -/// ``` -/// -/// Rather than setting the subscriber as the default, [`finish`] _returns_ the -/// constructed subscriber, which may then be passed to other functions: -/// -/// ```rust -/// let subscriber = tracing_subscriber::fmt() -/// .with_max_level(tracing::Level::DEBUG) -/// .compact() -/// .finish(); -/// -/// tracing::subscriber::with_default(subscriber, || { -/// // the subscriber will only be set as the default -/// // inside this closure... -/// }) -/// ``` -/// -/// [formatting subscriber]: Subscriber -/// [`SubscriberBuilder::default()`]: SubscriberBuilder::default -/// [`init`]: SubscriberBuilder::init() -/// [`try_init`]: SubscriberBuilder::try_init() -/// [`finish`]: SubscriberBuilder::finish() -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -pub fn fmt() -> SubscriberBuilder { - SubscriberBuilder::default() -} - -/// Returns a new [formatting layer] that can be [composed] with other layers to -/// construct a [`Subscriber`]. -/// -/// This is a shorthand for the equivalent [`Layer::default()`] function. -/// -/// [formatting layer]: Layer -/// [composed]: crate::layer -/// [`Layer::default()`]: Layer::default -#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] -pub fn layer<S>() -> Layer<S> { - Layer::default() -} - -impl Subscriber { - /// The maximum [verbosity level] that is enabled by a `Subscriber` by - /// default. - /// - /// This can be overridden with the [`SubscriberBuilder::with_max_level`] method. - /// - /// [verbosity level]: tracing_core::Level - /// [`SubscriberBuilder::with_max_level`]: SubscriberBuilder::with_max_level - pub const DEFAULT_MAX_LEVEL: LevelFilter = LevelFilter::INFO; - - /// Returns a new `SubscriberBuilder` for configuring a format subscriber. - pub fn builder() -> SubscriberBuilder { - SubscriberBuilder::default() - } - - /// Returns a new format subscriber with the default configuration. - pub fn new() -> Self { - Default::default() - } -} - -impl Default for Subscriber { - fn default() -> Self { - SubscriberBuilder::default().finish() - } -} - -// === impl Subscriber === - -impl<N, E, F, W> tracing_core::Subscriber for Subscriber<N, E, F, W> -where - N: for<'writer> FormatFields<'writer> + 'static, - E: FormatEvent<Registry, N> + 'static, - F: layer::Layer<Formatter<N, E, W>> + 'static, - W: for<'writer> MakeWriter<'writer> + 'static, - layer::Layered<F, Formatter<N, E, W>>: tracing_core::Subscriber, - fmt_layer::Layer<Registry, N, E, W>: layer::Layer<Registry>, -{ - #[inline] - fn register_callsite(&self, meta: &'static Metadata<'static>) -> Interest { - self.inner.register_callsite(meta) - } - - #[inline] - fn enabled(&self, meta: &Metadata<'_>) -> bool { - self.inner.enabled(meta) - } - - #[inline] - fn new_span(&self, attrs: &span::Attributes<'_>) -> span::Id { - self.inner.new_span(attrs) - } - - #[inline] - fn record(&self, span: &span::Id, values: &span::Record<'_>) { - self.inner.record(span, values) - } - - #[inline] - fn record_follows_from(&self, span: &span::Id, follows: &span::Id) { - self.inner.record_follows_from(span, follows) - } - - #[inline] - fn event_enabled(&self, event: &Event<'_>) -> bool { - self.inner.event_enabled(event) - } - - #[inline] - fn event(&self, event: &Event<'_>) { - self.inner.event(event); - } - - #[inline] - fn enter(&self, id: &span::Id) { - // TODO: add on_enter hook - self.inner.enter(id); - } - - #[inline] - fn exit(&self, id: &span::Id) { - self.inner.exit(id); - } - - #[inline] - fn current_span(&self) -> span::Current { - self.inner.current_span() - } - - #[inline] - fn clone_span(&self, id: &span::Id) -> span::Id { - self.inner.clone_span(id) - } - - #[inline] - fn try_close(&self, id: span::Id) -> bool { - self.inner.try_close(id) - } - - #[inline] - fn max_level_hint(&self) -> Option<tracing_core::LevelFilter> { - self.inner.max_level_hint() - } - - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - if id == TypeId::of::<Self>() { - Some(self as *const Self as *const ()) - } else { - self.inner.downcast_raw(id) - } - } -} - -impl<'a, N, E, F, W> LookupSpan<'a> for Subscriber<N, E, F, W> -where - layer::Layered<F, Formatter<N, E, W>>: LookupSpan<'a>, -{ - type Data = <layer::Layered<F, Formatter<N, E, W>> as LookupSpan<'a>>::Data; - - fn span_data(&'a self, id: &span::Id) -> Option<Self::Data> { - self.inner.span_data(id) - } -} - -// ===== impl SubscriberBuilder ===== - -impl Default for SubscriberBuilder { - fn default() -> Self { - SubscriberBuilder { - filter: Subscriber::DEFAULT_MAX_LEVEL, - inner: Default::default(), - } - } -} - -impl<N, E, F, W> SubscriberBuilder<N, E, F, W> -where - N: for<'writer> FormatFields<'writer> + 'static, - E: FormatEvent<Registry, N> + 'static, - W: for<'writer> MakeWriter<'writer> + 'static, - F: layer::Layer<Formatter<N, E, W>> + Send + Sync + 'static, - fmt_layer::Layer<Registry, N, E, W>: layer::Layer<Registry> + Send + Sync + 'static, -{ - /// Finish the builder, returning a new `FmtSubscriber`. - pub fn finish(self) -> Subscriber<N, E, F, W> { - let subscriber = self.inner.with_subscriber(Registry::default()); - Subscriber { - inner: self.filter.with_subscriber(subscriber), - } - } - - /// Install this Subscriber as the global default if one is - /// not already set. - /// - /// If the `tracing-log` feature is enabled, this will also install - /// the LogTracer to convert `Log` records into `tracing` `Event`s. - /// - /// # Errors - /// Returns an Error if the initialization was unsuccessful, likely - /// because a global subscriber was already installed by another - /// call to `try_init`. - pub fn try_init(self) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { - use crate::util::SubscriberInitExt; - self.finish().try_init()?; - - Ok(()) - } - - /// Install this Subscriber as the global default. - /// - /// If the `tracing-log` feature is enabled, this will also install - /// the LogTracer to convert `Log` records into `tracing` `Event`s. - /// - /// # Panics - /// Panics if the initialization was unsuccessful, likely because a - /// global subscriber was already installed by another call to `try_init`. - pub fn init(self) { - self.try_init() - .expect("Unable to install global subscriber") - } -} - -impl<N, E, F, W> From<SubscriberBuilder<N, E, F, W>> for tracing_core::Dispatch -where - N: for<'writer> FormatFields<'writer> + 'static, - E: FormatEvent<Registry, N> + 'static, - W: for<'writer> MakeWriter<'writer> + 'static, - F: layer::Layer<Formatter<N, E, W>> + Send + Sync + 'static, - fmt_layer::Layer<Registry, N, E, W>: layer::Layer<Registry> + Send + Sync + 'static, -{ - fn from(builder: SubscriberBuilder<N, E, F, W>) -> tracing_core::Dispatch { - tracing_core::Dispatch::new(builder.finish()) - } -} - -impl<N, L, T, F, W> SubscriberBuilder<N, format::Format<L, T>, F, W> -where - N: for<'writer> FormatFields<'writer> + 'static, -{ - /// Use the given [`timer`] for log message timestamps. - /// - /// See the [`time` module] for the provided timer implementations. - /// - /// Note that using the `"time`"" feature flag enables the - /// additional time formatters [`UtcTime`] and [`LocalTime`], which use the - /// [`time` crate] to provide more sophisticated timestamp formatting - /// options. - /// - /// [`timer`]: time::FormatTime - /// [`time` module]: mod@time - /// [`UtcTime`]: time::UtcTime - /// [`LocalTime`]: time::LocalTime - /// [`time` crate]: https://docs.rs/time/0.3 - pub fn with_timer<T2>(self, timer: T2) -> SubscriberBuilder<N, format::Format<L, T2>, F, W> { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.with_timer(timer), - } - } - - /// Do not emit timestamps with log messages. - pub fn without_time(self) -> SubscriberBuilder<N, format::Format<L, ()>, F, W> { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.without_time(), - } - } - - /// Configures how synthesized events are emitted at points in the [span - /// lifecycle][lifecycle]. - /// - /// The following options are available: - /// - /// - `FmtSpan::NONE`: No events will be synthesized when spans are - /// created, entered, exited, or closed. Data from spans will still be - /// included as the context for formatted events. This is the default. - /// - `FmtSpan::NEW`: An event will be synthesized when spans are created. - /// - `FmtSpan::ENTER`: An event will be synthesized when spans are entered. - /// - `FmtSpan::EXIT`: An event will be synthesized when spans are exited. - /// - `FmtSpan::CLOSE`: An event will be synthesized when a span closes. If - /// [timestamps are enabled][time] for this formatter, the generated - /// event will contain fields with the span's _busy time_ (the total - /// time for which it was entered) and _idle time_ (the total time that - /// the span existed but was not entered). - /// - `FmtSpan::ACTIVE`: An event will be synthesized when spans are entered - /// or exited. - /// - `FmtSpan::FULL`: Events will be synthesized whenever a span is - /// created, entered, exited, or closed. If timestamps are enabled, the - /// close event will contain the span's busy and idle time, as - /// described above. - /// - /// The options can be enabled in any combination. For instance, the following - /// will synthesize events whenever spans are created and closed: - /// - /// ```rust - /// use tracing_subscriber::fmt::format::FmtSpan; - /// use tracing_subscriber::fmt; - /// - /// let subscriber = fmt() - /// .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE) - /// .finish(); - /// ``` - /// - /// Note that the generated events will only be part of the log output by - /// this formatter; they will not be recorded by other `Subscriber`s or by - /// `Layer`s added to this subscriber. - /// - /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle - /// [time]: SubscriberBuilder::without_time() - pub fn with_span_events(self, kind: format::FmtSpan) -> Self { - SubscriberBuilder { - inner: self.inner.with_span_events(kind), - ..self - } - } - - /// Enable ANSI encoding for formatted events. - #[cfg(feature = "ansi")] - #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))] - pub fn with_ansi(self, ansi: bool) -> SubscriberBuilder<N, format::Format<L, T>, F, W> { - SubscriberBuilder { - inner: self.inner.with_ansi(ansi), - ..self - } - } - - /// Sets whether or not an event's target is displayed. - pub fn with_target( - self, - display_target: bool, - ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> { - SubscriberBuilder { - inner: self.inner.with_target(display_target), - ..self - } - } - - /// Sets whether or not an event's [source code file path][file] is - /// displayed. - /// - /// [file]: tracing_core::Metadata::file - pub fn with_file( - self, - display_filename: bool, - ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> { - SubscriberBuilder { - inner: self.inner.with_file(display_filename), - ..self - } - } - - /// Sets whether or not an event's [source code line number][line] is - /// displayed. - /// - /// [line]: tracing_core::Metadata::line - pub fn with_line_number( - self, - display_line_number: bool, - ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> { - SubscriberBuilder { - inner: self.inner.with_line_number(display_line_number), - ..self - } - } - - /// Sets whether or not an event's level is displayed. - pub fn with_level( - self, - display_level: bool, - ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> { - SubscriberBuilder { - inner: self.inner.with_level(display_level), - ..self - } - } - - /// Sets whether or not the [name] of the current thread is displayed - /// when formatting events. - /// - /// [name]: std::thread#naming-threads - pub fn with_thread_names( - self, - display_thread_names: bool, - ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> { - SubscriberBuilder { - inner: self.inner.with_thread_names(display_thread_names), - ..self - } - } - - /// Sets whether or not the [thread ID] of the current thread is displayed - /// when formatting events. - /// - /// [thread ID]: std::thread::ThreadId - pub fn with_thread_ids( - self, - display_thread_ids: bool, - ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> { - SubscriberBuilder { - inner: self.inner.with_thread_ids(display_thread_ids), - ..self - } - } - - /// Sets the subscriber being built to use a less verbose formatter. - /// - /// See [`format::Compact`]. - pub fn compact(self) -> SubscriberBuilder<N, format::Format<format::Compact, T>, F, W> - where - N: for<'writer> FormatFields<'writer> + 'static, - { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.compact(), - } - } - - /// Sets the subscriber being built to use an [excessively pretty, human-readable formatter](crate::fmt::format::Pretty). - #[cfg(feature = "ansi")] - #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))] - pub fn pretty( - self, - ) -> SubscriberBuilder<format::Pretty, format::Format<format::Pretty, T>, F, W> { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.pretty(), - } - } - - /// Sets the subscriber being built to use a JSON formatter. - /// - /// See [`format::Json`][super::fmt::format::Json] - #[cfg(feature = "json")] - #[cfg_attr(docsrs, doc(cfg(feature = "json")))] - pub fn json( - self, - ) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> - where - N: for<'writer> FormatFields<'writer> + 'static, - { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.json(), - } - } -} - -#[cfg(feature = "json")] -#[cfg_attr(docsrs, doc(cfg(feature = "json")))] -impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> { - /// Sets the json subscriber being built to flatten event metadata. - /// - /// See [`format::Json`][super::fmt::format::Json] - pub fn flatten_event( - self, - flatten_event: bool, - ) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.flatten_event(flatten_event), - } - } - - /// Sets whether or not the JSON subscriber being built will include the current span - /// in formatted events. - /// - /// See [`format::Json`][super::fmt::format::Json] - pub fn with_current_span( - self, - display_current_span: bool, - ) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.with_current_span(display_current_span), - } - } - - /// Sets whether or not the JSON subscriber being built will include a list (from - /// root to leaf) of all currently entered spans in formatted events. - /// - /// See [`format::Json`][super::fmt::format::Json] - pub fn with_span_list( - self, - display_span_list: bool, - ) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.with_span_list(display_span_list), - } - } -} - -#[cfg(feature = "env-filter")] -#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))] -impl<N, E, W> SubscriberBuilder<N, E, crate::EnvFilter, W> -where - Formatter<N, E, W>: tracing_core::Subscriber + 'static, -{ - /// Configures the subscriber being built to allow filter reloading at - /// runtime. - pub fn with_filter_reloading( - self, - ) -> SubscriberBuilder<N, E, crate::reload::Layer<crate::EnvFilter, Formatter<N, E, W>>, W> - { - let (filter, _) = crate::reload::Layer::new(self.filter); - SubscriberBuilder { - filter, - inner: self.inner, - } - } -} - -#[cfg(feature = "env-filter")] -#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))] -impl<N, E, W> SubscriberBuilder<N, E, crate::reload::Layer<crate::EnvFilter, Formatter<N, E, W>>, W> -where - Formatter<N, E, W>: tracing_core::Subscriber + 'static, -{ - /// Returns a `Handle` that may be used to reload the constructed subscriber's - /// filter. - pub fn reload_handle(&self) -> crate::reload::Handle<crate::EnvFilter, Formatter<N, E, W>> { - self.filter.handle() - } -} - -impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { - /// Sets the field formatter that the subscriber being built will use to record - /// fields. - /// - /// For example: - /// ```rust - /// use tracing_subscriber::fmt::format; - /// use tracing_subscriber::prelude::*; - /// - /// let formatter = - /// // Construct a custom formatter for `Debug` fields - /// format::debug_fn(|writer, field, value| write!(writer, "{}: {:?}", field, value)) - /// // Use the `tracing_subscriber::MakeFmtExt` trait to wrap the - /// // formatter so that a delimiter is added between fields. - /// .delimited(", "); - /// - /// let subscriber = tracing_subscriber::fmt() - /// .fmt_fields(formatter) - /// .finish(); - /// # drop(subscriber) - /// ``` - pub fn fmt_fields<N2>(self, fmt_fields: N2) -> SubscriberBuilder<N2, E, F, W> - where - N2: for<'writer> FormatFields<'writer> + 'static, - { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.fmt_fields(fmt_fields), - } - } - - /// Sets the [`EnvFilter`] that the subscriber will use to determine if - /// a span or event is enabled. - /// - /// Note that this method requires the "env-filter" feature flag to be enabled. - /// - /// If a filter was previously set, or a maximum level was set by the - /// [`with_max_level`] method, that value is replaced by the new filter. - /// - /// # Examples - /// - /// Setting a filter based on the value of the `RUST_LOG` environment - /// variable: - /// ```rust - /// use tracing_subscriber::{fmt, EnvFilter}; - /// - /// fmt() - /// .with_env_filter(EnvFilter::from_default_env()) - /// .init(); - /// ``` - /// - /// Setting a filter based on a pre-set filter directive string: - /// ```rust - /// use tracing_subscriber::fmt; - /// - /// fmt() - /// .with_env_filter("my_crate=info,my_crate::my_mod=debug,[my_span]=trace") - /// .init(); - /// ``` - /// - /// Adding additional directives to a filter constructed from an env var: - /// ```rust - /// use tracing_subscriber::{fmt, filter::{EnvFilter, LevelFilter}}; - /// - /// # fn filter() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { - /// let filter = EnvFilter::try_from_env("MY_CUSTOM_FILTER_ENV_VAR")? - /// // Set the base level when not matched by other directives to WARN. - /// .add_directive(LevelFilter::WARN.into()) - /// // Set the max level for `my_crate::my_mod` to DEBUG, overriding - /// // any directives parsed from the env variable. - /// .add_directive("my_crate::my_mod=debug".parse()?); - /// - /// fmt() - /// .with_env_filter(filter) - /// .try_init()?; - /// # Ok(())} - /// ``` - /// [`EnvFilter`]: super::filter::EnvFilter - /// [`with_max_level`]: SubscriberBuilder::with_max_level() - #[cfg(feature = "env-filter")] - #[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))] - pub fn with_env_filter( - self, - filter: impl Into<crate::EnvFilter>, - ) -> SubscriberBuilder<N, E, crate::EnvFilter, W> - where - Formatter<N, E, W>: tracing_core::Subscriber + 'static, - { - let filter = filter.into(); - SubscriberBuilder { - filter, - inner: self.inner, - } - } - - /// Sets the maximum [verbosity level] that will be enabled by the - /// subscriber. - /// - /// If the max level has already been set, or a [`EnvFilter`] was added by - /// [`with_env_filter`], this replaces that configuration with the new - /// maximum level. - /// - /// # Examples - /// - /// Enable up to the `DEBUG` verbosity level: - /// ```rust - /// use tracing_subscriber::fmt; - /// use tracing::Level; - /// - /// fmt() - /// .with_max_level(Level::DEBUG) - /// .init(); - /// ``` - /// This subscriber won't record any spans or events! - /// ```rust - /// use tracing_subscriber::{fmt, filter::LevelFilter}; - /// - /// let subscriber = fmt() - /// .with_max_level(LevelFilter::OFF) - /// .finish(); - /// ``` - /// [verbosity level]: tracing_core::Level - /// [`EnvFilter`]: struct@crate::filter::EnvFilter - /// [`with_env_filter`]: fn@Self::with_env_filter - pub fn with_max_level( - self, - filter: impl Into<LevelFilter>, - ) -> SubscriberBuilder<N, E, LevelFilter, W> { - let filter = filter.into(); - SubscriberBuilder { - filter, - inner: self.inner, - } - } - - /// Sets the [event formatter][`FormatEvent`] that the subscriber being built - /// will use to format events that occur. - /// - /// The event formatter may be any type implementing the [`FormatEvent`] - /// trait, which is implemented for all functions taking a [`FmtContext`], a - /// [`Writer`], and an [`Event`]. - /// - /// # Examples - /// - /// Setting a type implementing [`FormatEvent`] as the formatter: - /// - /// ```rust - /// use tracing_subscriber::fmt::format; - /// - /// let subscriber = tracing_subscriber::fmt() - /// .event_format(format().compact()) - /// .finish(); - /// ``` - /// - /// [`Writer`]: struct@self::format::Writer - pub fn event_format<E2>(self, fmt_event: E2) -> SubscriberBuilder<N, E2, F, W> - where - E2: FormatEvent<Registry, N> + 'static, - N: for<'writer> FormatFields<'writer> + 'static, - W: for<'writer> MakeWriter<'writer> + 'static, - { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.event_format(fmt_event), - } - } - - /// Sets the [`MakeWriter`] that the subscriber being built will use to write events. - /// - /// # Examples - /// - /// Using `stderr` rather than `stdout`: - /// - /// ```rust - /// use tracing_subscriber::fmt; - /// use std::io; - /// - /// fmt() - /// .with_writer(io::stderr) - /// .init(); - /// ``` - pub fn with_writer<W2>(self, make_writer: W2) -> SubscriberBuilder<N, E, F, W2> - where - W2: for<'writer> MakeWriter<'writer> + 'static, - { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.with_writer(make_writer), - } - } - - /// Configures the subscriber to support [`libtest`'s output capturing][capturing] when used in - /// unit tests. - /// - /// See [`TestWriter`] for additional details. - /// - /// # Examples - /// - /// Using [`TestWriter`] to let `cargo test` capture test output. Note that we do not install it - /// globally as it may cause conflicts. - /// - /// ```rust - /// use tracing_subscriber::fmt; - /// use tracing::subscriber; - /// - /// subscriber::set_default( - /// fmt() - /// .with_test_writer() - /// .finish() - /// ); - /// ``` - /// - /// [capturing]: - /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output - /// [`TestWriter`]: writer::TestWriter - pub fn with_test_writer(self) -> SubscriberBuilder<N, E, F, TestWriter> { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.with_writer(TestWriter::default()), - } - } - - /// Updates the event formatter by applying a function to the existing event formatter. - /// - /// This sets the event formatter that the subscriber being built will use to record fields. - /// - /// # Examples - /// - /// Updating an event formatter: - /// - /// ```rust - /// let subscriber = tracing_subscriber::fmt() - /// .map_event_format(|e| e.compact()) - /// .finish(); - /// ``` - pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> SubscriberBuilder<N, E2, F, W> - where - E2: FormatEvent<Registry, N> + 'static, - N: for<'writer> FormatFields<'writer> + 'static, - W: for<'writer> MakeWriter<'writer> + 'static, - { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.map_event_format(f), - } - } - - /// Updates the field formatter by applying a function to the existing field formatter. - /// - /// This sets the field formatter that the subscriber being built will use to record fields. - /// - /// # Examples - /// - /// Updating a field formatter: - /// - /// ```rust - /// use tracing_subscriber::field::MakeExt; - /// let subscriber = tracing_subscriber::fmt() - /// .map_fmt_fields(|f| f.debug_alt()) - /// .finish(); - /// ``` - pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> SubscriberBuilder<N2, E, F, W> - where - N2: for<'writer> FormatFields<'writer> + 'static, - { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.map_fmt_fields(f), - } - } - - /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`]. - /// - /// This sets the [`MakeWriter`] that the subscriber being built will use to write events. - /// - /// # Examples - /// - /// Redirect output to stderr if level is <= WARN: - /// - /// ```rust - /// use tracing::Level; - /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt}; - /// - /// let stderr = std::io::stderr.with_max_level(Level::WARN); - /// let layer = tracing_subscriber::fmt() - /// .map_writer(move |w| stderr.or_else(w)) - /// .finish(); - /// ``` - pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> SubscriberBuilder<N, E, F, W2> - where - W2: for<'writer> MakeWriter<'writer> + 'static, - { - SubscriberBuilder { - filter: self.filter, - inner: self.inner.map_writer(f), - } - } -} - -/// Install a global tracing subscriber that listens for events and -/// filters based on the value of the [`RUST_LOG` environment variable], -/// if one is not already set. -/// -/// If the `tracing-log` feature is enabled, this will also install -/// the [`LogTracer`] to convert `log` records into `tracing` `Event`s. -/// -/// This is shorthand for -/// -/// ```rust -/// # fn doc() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { -/// tracing_subscriber::fmt().try_init() -/// # } -/// ``` -/// -/// -/// # Errors -/// -/// Returns an Error if the initialization was unsuccessful, -/// likely because a global subscriber was already installed by another -/// call to `try_init`. -/// -/// [`LogTracer`]: -/// https://docs.rs/tracing-log/0.1.0/tracing_log/struct.LogTracer.html -/// [`RUST_LOG` environment variable]: crate::filter::EnvFilter::DEFAULT_ENV -pub fn try_init() -> Result<(), Box<dyn Error + Send + Sync + 'static>> { - let builder = Subscriber::builder(); - - #[cfg(feature = "env-filter")] - let builder = builder.with_env_filter(crate::EnvFilter::from_default_env()); - - // If `env-filter` is disabled, remove the default max level filter from the - // subscriber; it will be added to the `Targets` filter instead if no filter - // is set in `RUST_LOG`. - // Replacing the default `LevelFilter` with an `EnvFilter` would imply this, - // but we can't replace the builder's filter with a `Targets` filter yet. - #[cfg(not(feature = "env-filter"))] - let builder = builder.with_max_level(LevelFilter::TRACE); - - let subscriber = builder.finish(); - #[cfg(not(feature = "env-filter"))] - let subscriber = { - use crate::{filter::Targets, layer::SubscriberExt}; - use std::{env, str::FromStr}; - let targets = match env::var("RUST_LOG") { - Ok(var) => Targets::from_str(&var) - .map_err(|e| { - eprintln!("Ignoring `RUST_LOG={:?}`: {}", var, e); - }) - .unwrap_or_default(), - Err(env::VarError::NotPresent) => { - Targets::new().with_default(Subscriber::DEFAULT_MAX_LEVEL) - } - Err(e) => { - eprintln!("Ignoring `RUST_LOG`: {}", e); - Targets::new().with_default(Subscriber::DEFAULT_MAX_LEVEL) - } - }; - subscriber.with(targets) - }; - - subscriber.try_init().map_err(Into::into) -} - -/// Install a global tracing subscriber that listens for events and -/// filters based on the value of the [`RUST_LOG` environment variable]. -/// -/// If the `tracing-log` feature is enabled, this will also install -/// the LogTracer to convert `Log` records into `tracing` `Event`s. -/// -/// This is shorthand for -/// -/// ```rust -/// tracing_subscriber::fmt().init() -/// ``` -/// -/// # Panics -/// Panics if the initialization was unsuccessful, likely because a -/// global subscriber was already installed by another call to `try_init`. -/// -/// [`RUST_LOG` environment variable]: crate::filter::EnvFilter::DEFAULT_ENV -pub fn init() { - try_init().expect("Unable to install global subscriber") -} - -#[cfg(test)] -mod test { - use crate::{ - filter::LevelFilter, - fmt::{ - format::{self, Format}, - time, - writer::MakeWriter, - Subscriber, - }, - }; - use std::{ - io, - sync::{Arc, Mutex, MutexGuard, TryLockError}, - }; - use tracing_core::dispatcher::Dispatch; - - pub(crate) struct MockWriter { - buf: Arc<Mutex<Vec<u8>>>, - } - - impl MockWriter { - pub(crate) fn new(buf: Arc<Mutex<Vec<u8>>>) -> Self { - Self { buf } - } - - pub(crate) fn map_error<Guard>(err: TryLockError<Guard>) -> io::Error { - match err { - TryLockError::WouldBlock => io::Error::from(io::ErrorKind::WouldBlock), - TryLockError::Poisoned(_) => io::Error::from(io::ErrorKind::Other), - } - } - - pub(crate) fn buf(&self) -> io::Result<MutexGuard<'_, Vec<u8>>> { - self.buf.try_lock().map_err(Self::map_error) - } - } - - impl io::Write for MockWriter { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.buf()?.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - self.buf()?.flush() - } - } - - #[derive(Clone, Default)] - pub(crate) struct MockMakeWriter { - buf: Arc<Mutex<Vec<u8>>>, - } - - impl MockMakeWriter { - pub(crate) fn new(buf: Arc<Mutex<Vec<u8>>>) -> Self { - Self { buf } - } - - #[cfg(feature = "json")] - pub(crate) fn buf(&self) -> MutexGuard<'_, Vec<u8>> { - self.buf.lock().unwrap() - } - - pub(crate) fn get_string(&self) -> String { - let mut buf = self.buf.lock().expect("lock shouldn't be poisoned"); - let string = std::str::from_utf8(&buf[..]) - .expect("formatter should not have produced invalid utf-8") - .to_owned(); - buf.clear(); - string - } - } - - impl<'a> MakeWriter<'a> for MockMakeWriter { - type Writer = MockWriter; - - fn make_writer(&'a self) -> Self::Writer { - MockWriter::new(self.buf.clone()) - } - } - - #[test] - fn impls() { - let f = Format::default().with_timer(time::Uptime::default()); - let subscriber = Subscriber::builder().event_format(f).finish(); - let _dispatch = Dispatch::new(subscriber); - - let f = format::Format::default(); - let subscriber = Subscriber::builder().event_format(f).finish(); - let _dispatch = Dispatch::new(subscriber); - - let f = format::Format::default().compact(); - let subscriber = Subscriber::builder().event_format(f).finish(); - let _dispatch = Dispatch::new(subscriber); - } - - #[test] - fn subscriber_downcasts() { - let subscriber = Subscriber::builder().finish(); - let dispatch = Dispatch::new(subscriber); - assert!(dispatch.downcast_ref::<Subscriber>().is_some()); - } - - #[test] - fn subscriber_downcasts_to_parts() { - let subscriber = Subscriber::new(); - let dispatch = Dispatch::new(subscriber); - assert!(dispatch.downcast_ref::<format::DefaultFields>().is_some()); - assert!(dispatch.downcast_ref::<LevelFilter>().is_some()); - assert!(dispatch.downcast_ref::<format::Format>().is_some()) - } - - #[test] - fn is_lookup_span() { - fn assert_lookup_span<T: for<'a> crate::registry::LookupSpan<'a>>(_: T) {} - let subscriber = Subscriber::new(); - assert_lookup_span(subscriber) - } -} diff --git a/vendor/tracing-subscriber/src/fmt/time/datetime.rs b/vendor/tracing-subscriber/src/fmt/time/datetime.rs deleted file mode 100644 index 531331687..000000000 --- a/vendor/tracing-subscriber/src/fmt/time/datetime.rs +++ /dev/null @@ -1,410 +0,0 @@ -// musl as a whole is licensed under the following standard MIT license: -// -// ---------------------------------------------------------------------- -// Copyright © 2005-2020 Rich Felker, et al. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ---------------------------------------------------------------------- -// -// Authors/contributors include: -// -// A. Wilcox -// Ada Worcester -// Alex Dowad -// Alex Suykov -// Alexander Monakov -// Andre McCurdy -// Andrew Kelley -// Anthony G. Basile -// Aric Belsito -// Arvid Picciani -// Bartosz Brachaczek -// Benjamin Peterson -// Bobby Bingham -// Boris Brezillon -// Brent Cook -// Chris Spiegel -// Clément Vasseur -// Daniel Micay -// Daniel Sabogal -// Daurnimator -// David Carlier -// David Edelsohn -// Denys Vlasenko -// Dmitry Ivanov -// Dmitry V. Levin -// Drew DeVault -// Emil Renner Berthing -// Fangrui Song -// Felix Fietkau -// Felix Janda -// Gianluca Anzolin -// Hauke Mehrtens -// He X -// Hiltjo Posthuma -// Isaac Dunham -// Jaydeep Patil -// Jens Gustedt -// Jeremy Huntwork -// Jo-Philipp Wich -// Joakim Sindholt -// John Spencer -// Julien Ramseier -// Justin Cormack -// Kaarle Ritvanen -// Khem Raj -// Kylie McClain -// Leah Neukirchen -// Luca Barbato -// Luka Perkov -// M Farkas-Dyck (Strake) -// Mahesh Bodapati -// Markus Wichmann -// Masanori Ogino -// Michael Clark -// Michael Forney -// Mikhail Kremnyov -// Natanael Copa -// Nicholas J. Kain -// orc -// Pascal Cuoq -// Patrick Oppenlander -// Petr Hosek -// Petr Skocik -// Pierre Carrier -// Reini Urban -// Rich Felker -// Richard Pennington -// Ryan Fairfax -// Samuel Holland -// Segev Finer -// Shiz -// sin -// Solar Designer -// Stefan Kristiansson -// Stefan O'Rear -// Szabolcs Nagy -// Timo Teräs -// Trutz Behn -// Valentin Ochs -// Will Dietz -// William Haddon -// William Pitcock -// -// Portions of this software are derived from third-party works licensed -// under terms compatible with the above MIT license: -// -// The TRE regular expression implementation (src/regex/reg* and -// src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed -// under a 2-clause BSD license (license text in the source files). The -// included version has been heavily modified by Rich Felker in 2012, in -// the interests of size, simplicity, and namespace cleanliness. -// -// Much of the math library code (src/math/* and src/complex/*) is -// Copyright © 1993,2004 Sun Microsystems or -// Copyright © 2003-2011 David Schultz or -// Copyright © 2003-2009 Steven G. Kargl or -// Copyright © 2003-2009 Bruce D. Evans or -// Copyright © 2008 Stephen L. Moshier or -// Copyright © 2017-2018 Arm Limited -// and labelled as such in comments in the individual source files. All -// have been licensed under extremely permissive terms. -// -// The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008 -// The Android Open Source Project and is licensed under a two-clause BSD -// license. It was taken from Bionic libc, used on Android. -// -// The AArch64 memcpy and memset code (src/string/aarch64/*) are -// Copyright © 1999-2019, Arm Limited. -// -// The implementation of DES for crypt (src/crypt/crypt_des.c) is -// Copyright © 1994 David Burren. It is licensed under a BSD license. -// -// The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was -// originally written by Solar Designer and placed into the public -// domain. The code also comes with a fallback permissive license for use -// in jurisdictions that may not recognize the public domain. -// -// The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 -// Valentin Ochs and is licensed under an MIT-style license. -// -// The x86_64 port was written by Nicholas J. Kain and is licensed under -// the standard MIT terms. -// -// The mips and microblaze ports were originally written by Richard -// Pennington for use in the ellcc project. The original code was adapted -// by Rich Felker for build system and code conventions during upstream -// integration. It is licensed under the standard MIT terms. -// -// The mips64 port was contributed by Imagination Technologies and is -// licensed under the standard MIT terms. -// -// The powerpc port was also originally written by Richard Pennington, -// and later supplemented and integrated by John Spencer. It is licensed -// under the standard MIT terms. -// -// All other files which have no copyright comments are original works -// produced specifically for use as part of this library, written either -// by Rich Felker, the main author of the library, or by one or more -// contibutors listed above. Details on authorship of individual files -// can be found in the git version control history of the project. The -// omission of copyright and license comments in each file is in the -// interest of source tree size. -// -// In addition, permission is hereby granted for all public header files -// (include/* and arch/*/bits/*) and crt files intended to be linked into -// applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit -// the copyright notice and permission notice otherwise required by the -// license, and to use these files without any requirement of -// attribution. These files include substantial contributions from: -// -// Bobby Bingham -// John Spencer -// Nicholas J. Kain -// Rich Felker -// Richard Pennington -// Stefan Kristiansson -// Szabolcs Nagy -// -// all of whom have explicitly granted such permission. -// -// This file previously contained text expressing a belief that most of -// the files covered by the above exception were sufficiently trivial not -// to be subject to copyright, resulting in confusion over whether it -// negated the permissions granted in the license. In the spirit of -// permissive licensing, and of not having licensing issues being an -// obstacle to adoption, that text has been removed. - - -use std::fmt; - -/// A date/time type which exists primarily to convert `SystemTime` timestamps into an ISO 8601 -/// formatted string. -/// -/// Yes, this exists. Before you have a heart attack, understand that the meat of this is musl's -/// [`__secs_to_tm`][1] converted to Rust via [c2rust][2] and then cleaned up by hand as part of -/// the [kudu-rs project][3], [released under MIT][4]. -/// -/// [1] http://git.musl-libc.org/cgit/musl/tree/src/time/__secs_to_tm.c -/// [2] https://c2rust.com/ -/// [3] https://github.com/danburkert/kudu-rs/blob/c9660067e5f4c1a54143f169b5eeb49446f82e54/src/timestamp.rs#L5-L18 -/// [4] https://github.com/tokio-rs/tracing/issues/1644#issuecomment-963888244 -/// -/// All existing `strftime`-like APIs I found were unable to handle the full range of timestamps representable -/// by `SystemTime`, including `strftime` itself, since tm.tm_year is an int. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub(crate) struct DateTime { - year: i64, - month: u8, - day: u8, - hour: u8, - minute: u8, - second: u8, - nanos: u32, -} - -impl fmt::Display for DateTime { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.year > 9999 { - write!(f, "+{}", self.year)?; - } else if self.year < 0 { - write!(f, "{:05}", self.year)?; - } else { - write!(f, "{:04}", self.year)?; - } - - write!( - f, - "-{:02}-{:02}T{:02}:{:02}:{:02}.{:06}Z", - self.month, - self.day, - self.hour, - self.minute, - self.second, - self.nanos / 1_000 - ) - } -} - -impl From<std::time::SystemTime> for DateTime { - fn from(timestamp: std::time::SystemTime) -> DateTime { - let (t, nanos) = match timestamp.duration_since(std::time::UNIX_EPOCH) { - Ok(duration) => { - debug_assert!(duration.as_secs() <= std::i64::MAX as u64); - (duration.as_secs() as i64, duration.subsec_nanos()) - } - Err(error) => { - let duration = error.duration(); - debug_assert!(duration.as_secs() <= std::i64::MAX as u64); - let (secs, nanos) = (duration.as_secs() as i64, duration.subsec_nanos()); - if nanos == 0 { - (-secs, 0) - } else { - (-secs - 1, 1_000_000_000 - nanos) - } - } - }; - - // 2000-03-01 (mod 400 year, immediately after feb29 - const LEAPOCH: i64 = 946_684_800 + 86400 * (31 + 29); - const DAYS_PER_400Y: i32 = 365 * 400 + 97; - const DAYS_PER_100Y: i32 = 365 * 100 + 24; - const DAYS_PER_4Y: i32 = 365 * 4 + 1; - static DAYS_IN_MONTH: [i8; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29]; - - // Note(dcb): this bit is rearranged slightly to avoid integer overflow. - let mut days: i64 = (t / 86_400) - (LEAPOCH / 86_400); - let mut remsecs: i32 = (t % 86_400) as i32; - if remsecs < 0i32 { - remsecs += 86_400; - days -= 1 - } - - let mut qc_cycles: i32 = (days / i64::from(DAYS_PER_400Y)) as i32; - let mut remdays: i32 = (days % i64::from(DAYS_PER_400Y)) as i32; - if remdays < 0 { - remdays += DAYS_PER_400Y; - qc_cycles -= 1; - } - - let mut c_cycles: i32 = remdays / DAYS_PER_100Y; - if c_cycles == 4 { - c_cycles -= 1; - } - remdays -= c_cycles * DAYS_PER_100Y; - - let mut q_cycles: i32 = remdays / DAYS_PER_4Y; - if q_cycles == 25 { - q_cycles -= 1; - } - remdays -= q_cycles * DAYS_PER_4Y; - - let mut remyears: i32 = remdays / 365; - if remyears == 4 { - remyears -= 1; - } - remdays -= remyears * 365; - - let mut years: i64 = i64::from(remyears) - + 4 * i64::from(q_cycles) - + 100 * i64::from(c_cycles) - + 400 * i64::from(qc_cycles); - - let mut months: i32 = 0; - while i32::from(DAYS_IN_MONTH[months as usize]) <= remdays { - remdays -= i32::from(DAYS_IN_MONTH[months as usize]); - months += 1 - } - - if months >= 10 { - months -= 12; - years += 1; - } - - DateTime { - year: years + 2000, - month: (months + 3) as u8, - day: (remdays + 1) as u8, - hour: (remsecs / 3600) as u8, - minute: (remsecs / 60 % 60) as u8, - second: (remsecs % 60) as u8, - nanos, - } - } -} - -#[cfg(test)] -mod tests { - use std::i32; - use std::time::{Duration, UNIX_EPOCH}; - - use super::*; - - #[test] - fn test_datetime() { - let case = |expected: &str, secs: i64, micros: u32| { - let timestamp = if secs >= 0 { - UNIX_EPOCH + Duration::new(secs as u64, micros * 1_000) - } else { - (UNIX_EPOCH - Duration::new(!secs as u64 + 1, 0)) + Duration::new(0, micros * 1_000) - }; - assert_eq!( - expected, - format!("{}", DateTime::from(timestamp)), - "secs: {}, micros: {}", - secs, - micros - ) - }; - - // Mostly generated with: - // - date -jur <secs> +"%Y-%m-%dT%H:%M:%S.000000Z" - // - http://unixtimestamp.50x.eu/ - - case("1970-01-01T00:00:00.000000Z", 0, 0); - - case("1970-01-01T00:00:00.000001Z", 0, 1); - case("1970-01-01T00:00:00.500000Z", 0, 500_000); - case("1970-01-01T00:00:01.000001Z", 1, 1); - case("1970-01-01T00:01:01.000001Z", 60 + 1, 1); - case("1970-01-01T01:01:01.000001Z", 60 * 60 + 60 + 1, 1); - case( - "1970-01-02T01:01:01.000001Z", - 24 * 60 * 60 + 60 * 60 + 60 + 1, - 1, - ); - - case("1969-12-31T23:59:59.000000Z", -1, 0); - case("1969-12-31T23:59:59.000001Z", -1, 1); - case("1969-12-31T23:59:59.500000Z", -1, 500_000); - case("1969-12-31T23:58:59.000001Z", -60 - 1, 1); - case("1969-12-31T22:58:59.000001Z", -60 * 60 - 60 - 1, 1); - case( - "1969-12-30T22:58:59.000001Z", - -24 * 60 * 60 - 60 * 60 - 60 - 1, - 1, - ); - - case("2038-01-19T03:14:07.000000Z", std::i32::MAX as i64, 0); - case("2038-01-19T03:14:08.000000Z", std::i32::MAX as i64 + 1, 0); - case("1901-12-13T20:45:52.000000Z", i32::MIN as i64, 0); - case("1901-12-13T20:45:51.000000Z", i32::MIN as i64 - 1, 0); - - // Skipping these tests on windows as std::time::SysteTime range is low - // on Windows compared with that of Unix which can cause the following - // high date value tests to panic - #[cfg(not(target_os = "windows"))] - { - case("+292277026596-12-04T15:30:07.000000Z", std::i64::MAX, 0); - case("+292277026596-12-04T15:30:06.000000Z", std::i64::MAX - 1, 0); - case("-292277022657-01-27T08:29:53.000000Z", i64::MIN + 1, 0); - } - - case("1900-01-01T00:00:00.000000Z", -2208988800, 0); - case("1899-12-31T23:59:59.000000Z", -2208988801, 0); - case("0000-01-01T00:00:00.000000Z", -62167219200, 0); - case("-0001-12-31T23:59:59.000000Z", -62167219201, 0); - - case("1234-05-06T07:08:09.000000Z", -23215049511, 0); - case("-1234-05-06T07:08:09.000000Z", -101097651111, 0); - case("2345-06-07T08:09:01.000000Z", 11847456541, 0); - case("-2345-06-07T08:09:01.000000Z", -136154620259, 0); - } -} diff --git a/vendor/tracing-subscriber/src/fmt/time/mod.rs b/vendor/tracing-subscriber/src/fmt/time/mod.rs deleted file mode 100644 index e5b7c83b0..000000000 --- a/vendor/tracing-subscriber/src/fmt/time/mod.rs +++ /dev/null @@ -1,138 +0,0 @@ -//! Formatters for event timestamps. -use crate::fmt::format::Writer; -use std::fmt; -use std::time::Instant; - -mod datetime; - -#[cfg(feature = "time")] -mod time_crate; -#[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] -pub use time_crate::UtcTime; - -#[cfg(feature = "local-time")] -#[cfg_attr(docsrs, doc(cfg(unsound_local_offset, feature = "local-time")))] -pub use time_crate::LocalTime; - -#[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] -pub use time_crate::OffsetTime; - -/// A type that can measure and format the current time. -/// -/// This trait is used by `Format` to include a timestamp with each `Event` when it is logged. -/// -/// Notable default implementations of this trait are `SystemTime` and `()`. The former prints the -/// current time as reported by `std::time::SystemTime`, and the latter does not print the current -/// time at all. `FormatTime` is also automatically implemented for any function pointer with the -/// appropriate signature. -/// -/// The full list of provided implementations can be found in [`time`]. -/// -/// [`time`]: self -pub trait FormatTime { - /// Measure and write out the current time. - /// - /// When `format_time` is called, implementors should get the current time using their desired - /// mechanism, and write it out to the given `fmt::Write`. Implementors must insert a trailing - /// space themselves if they wish to separate the time from subsequent log message text. - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result; -} - -/// Returns a new `SystemTime` timestamp provider. -/// -/// This can then be configured further to determine how timestamps should be -/// configured. -/// -/// This is equivalent to calling -/// ```rust -/// # fn timer() -> tracing_subscriber::fmt::time::SystemTime { -/// tracing_subscriber::fmt::time::SystemTime::default() -/// # } -/// ``` -pub fn time() -> SystemTime { - SystemTime::default() -} - -/// Returns a new `Uptime` timestamp provider. -/// -/// With this timer, timestamps will be formatted with the amount of time -/// elapsed since the timestamp provider was constructed. -/// -/// This can then be configured further to determine how timestamps should be -/// configured. -/// -/// This is equivalent to calling -/// ```rust -/// # fn timer() -> tracing_subscriber::fmt::time::Uptime { -/// tracing_subscriber::fmt::time::Uptime::default() -/// # } -/// ``` -pub fn uptime() -> Uptime { - Uptime::default() -} - -impl<'a, F> FormatTime for &'a F -where - F: FormatTime, -{ - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - (*self).format_time(w) - } -} - -impl FormatTime for () { - fn format_time(&self, _: &mut Writer<'_>) -> fmt::Result { - Ok(()) - } -} - -impl FormatTime for fn(&mut Writer<'_>) -> fmt::Result { - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - (*self)(w) - } -} - -/// Retrieve and print the current wall-clock time. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] -pub struct SystemTime; - -/// Retrieve and print the relative elapsed wall-clock time since an epoch. -/// -/// The `Default` implementation for `Uptime` makes the epoch the current time. -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub struct Uptime { - epoch: Instant, -} - -impl Default for Uptime { - fn default() -> Self { - Uptime { - epoch: Instant::now(), - } - } -} - -impl From<Instant> for Uptime { - fn from(epoch: Instant) -> Self { - Uptime { epoch } - } -} - -impl FormatTime for SystemTime { - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - write!( - w, - "{}", - datetime::DateTime::from(std::time::SystemTime::now()) - ) - } -} - -impl FormatTime for Uptime { - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - let e = self.epoch.elapsed(); - write!(w, "{:4}.{:09}s", e.as_secs(), e.subsec_nanos()) - } -} diff --git a/vendor/tracing-subscriber/src/fmt/time/time_crate.rs b/vendor/tracing-subscriber/src/fmt/time/time_crate.rs deleted file mode 100644 index 60d57fd0b..000000000 --- a/vendor/tracing-subscriber/src/fmt/time/time_crate.rs +++ /dev/null @@ -1,470 +0,0 @@ -use crate::fmt::{format::Writer, time::FormatTime, writer::WriteAdaptor}; -use std::fmt; -use time::{format_description::well_known, formatting::Formattable, OffsetDateTime, UtcOffset}; - -/// Formats the current [local time] using a [formatter] from the [`time` crate]. -/// -/// To format the current [UTC time] instead, use the [`UtcTime`] type. -/// -/// <div class="example-wrap" style="display:inline-block"> -/// <pre class="compile_fail" style="white-space:normal;font:inherit;"> -/// <strong>Warning</strong>: The <a href = "https://docs.rs/time/0.3/time/"><code>time</code> -/// crate</a> must be compiled with <code>--cfg unsound_local_offset</code> in order to use -/// local timestamps. When this cfg is not enabled, local timestamps cannot be recorded, and -/// events will be logged without timestamps. -/// -/// Alternatively, [`OffsetTime`] can log with a local offset if it is initialized early. -/// -/// See the <a href="https://docs.rs/time/0.3.4/time/#feature-flags"><code>time</code> -/// documentation</a> for more details. -/// </pre></div> -/// -/// [local time]: time::OffsetDateTime::now_local -/// [UTC time]: time::OffsetDateTime::now_utc -/// [formatter]: time::formatting::Formattable -/// [`time` crate]: time -#[derive(Clone, Debug)] -#[cfg_attr( - docsrs, - doc(cfg(all(unsound_local_offset, feature = "time", feature = "local-time"))) -)] -#[cfg(feature = "local-time")] -pub struct LocalTime<F> { - format: F, -} - -/// Formats the current [UTC time] using a [formatter] from the [`time` crate]. -/// -/// To format the current [local time] instead, use the [`LocalTime`] type. -/// -/// [local time]: time::OffsetDateTime::now_local -/// [UTC time]: time::OffsetDateTime::now_utc -/// [formatter]: time::formatting::Formattable -/// [`time` crate]: time -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] -#[derive(Clone, Debug)] -pub struct UtcTime<F> { - format: F, -} - -/// Formats the current time using a fixed offset and a [formatter] from the [`time` crate]. -/// -/// This is typically used as an alternative to [`LocalTime`]. `LocalTime` determines the offset -/// every time it formats a message, which may be unsound or fail. With `OffsetTime`, the offset is -/// determined once. This makes it possible to do so while the program is still single-threaded and -/// handle any errors. However, this also means the offset cannot change while the program is -/// running (the offset will not change across DST changes). -/// -/// [formatter]: time::formatting::Formattable -/// [`time` crate]: time -#[derive(Clone, Debug)] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] -pub struct OffsetTime<F> { - offset: time::UtcOffset, - format: F, -} - -// === impl LocalTime === - -#[cfg(feature = "local-time")] -impl LocalTime<well_known::Rfc3339> { - /// Returns a formatter that formats the current [local time] in the - /// [RFC 3339] format (a subset of the [ISO 8601] timestamp format). - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time}; - /// - /// let collector = tracing_subscriber::fmt() - /// .with_timer(time::LocalTime::rfc_3339()); - /// # drop(collector); - /// ``` - /// - /// [local time]: time::OffsetDateTime::now_local - /// [RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339 - /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601 - pub fn rfc_3339() -> Self { - Self::new(well_known::Rfc3339) - } -} - -#[cfg(feature = "local-time")] -impl<F: Formattable> LocalTime<F> { - /// Returns a formatter that formats the current [local time] using the - /// [`time` crate] with the provided provided format. The format may be any - /// type that implements the [`Formattable`] trait. - /// - /// - /// <div class="example-wrap" style="display:inline-block"> - /// <pre class="compile_fail" style="white-space:normal;font:inherit;"> - /// <strong>Warning</strong>: The <a href = "https://docs.rs/time/0.3/time/"> - /// <code>time</code> crate</a> must be compiled with <code>--cfg - /// unsound_local_offset</code> in order to use local timestamps. When this - /// cfg is not enabled, local timestamps cannot be recorded, and - /// events will be logged without timestamps. - /// - /// See the <a href="https://docs.rs/time/0.3.4/time/#feature-flags"> - /// <code>time</code> documentation</a> for more details. - /// </pre></div> - /// - /// Typically, the format will be a format description string, or one of the - /// `time` crate's [well-known formats]. - /// - /// If the format description is statically known, then the - /// [`format_description!`] macro should be used. This is identical to the - /// [`time::format_description::parse`] method, but runs at compile-time, - /// throwing an error if the format description is invalid. If the desired format - /// is not known statically (e.g., a user is providing a format string), then the - /// [`time::format_description::parse`] method should be used. Note that this - /// method is fallible. - /// - /// See the [`time` book] for details on the format description syntax. - /// - /// # Examples - /// - /// Using the [`format_description!`] macro: - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::LocalTime}; - /// use time::macros::format_description; - /// - /// let timer = LocalTime::new(format_description!("[hour]:[minute]:[second]")); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// Using [`time::format_description::parse`]: - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::LocalTime}; - /// - /// let time_format = time::format_description::parse("[hour]:[minute]:[second]") - /// .expect("format string should be valid!"); - /// let timer = LocalTime::new(time_format); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// Using the [`format_description!`] macro requires enabling the `time` - /// crate's "macros" feature flag. - /// - /// Using a [well-known format][well-known formats] (this is equivalent to - /// [`LocalTime::rfc_3339`]): - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::LocalTime}; - /// - /// let timer = LocalTime::new(time::format_description::well_known::Rfc3339); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// [local time]: time::OffsetDateTime::now_local() - /// [`time` crate]: time - /// [`Formattable`]: time::formatting::Formattable - /// [well-known formats]: time::format_description::well_known - /// [`format_description!`]: time::macros::format_description! - /// [`time::format_description::parse`]: time::format_description::parse() - /// [`time` book]: https://time-rs.github.io/book/api/format-description.html - pub fn new(format: F) -> Self { - Self { format } - } -} - -#[cfg(feature = "local-time")] -impl<F> FormatTime for LocalTime<F> -where - F: Formattable, -{ - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - let now = OffsetDateTime::now_local().map_err(|_| fmt::Error)?; - format_datetime(now, w, &self.format) - } -} - -#[cfg(feature = "local-time")] -impl<F> Default for LocalTime<F> -where - F: Formattable + Default, -{ - fn default() -> Self { - Self::new(F::default()) - } -} - -// === impl UtcTime === - -impl UtcTime<well_known::Rfc3339> { - /// Returns a formatter that formats the current [UTC time] in the - /// [RFC 3339] format, which is a subset of the [ISO 8601] timestamp format. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time}; - /// - /// let collector = tracing_subscriber::fmt() - /// .with_timer(time::UtcTime::rfc_3339()); - /// # drop(collector); - /// ``` - /// - /// [local time]: time::OffsetDateTime::now_utc - /// [RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339 - /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601 - pub fn rfc_3339() -> Self { - Self::new(well_known::Rfc3339) - } -} - -impl<F: Formattable> UtcTime<F> { - /// Returns a formatter that formats the current [UTC time] using the - /// [`time` crate], with the provided provided format. The format may be any - /// type that implements the [`Formattable`] trait. - /// - /// Typically, the format will be a format description string, or one of the - /// `time` crate's [well-known formats]. - /// - /// If the format description is statically known, then the - /// [`format_description!`] macro should be used. This is identical to the - /// [`time::format_description::parse`] method, but runs at compile-time, - /// failing an error if the format description is invalid. If the desired format - /// is not known statically (e.g., a user is providing a format string), then the - /// [`time::format_description::parse`] method should be used. Note that this - /// method is fallible. - /// - /// See the [`time` book] for details on the format description syntax. - /// - /// # Examples - /// - /// Using the [`format_description!`] macro: - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::UtcTime}; - /// use time::macros::format_description; - /// - /// let timer = UtcTime::new(format_description!("[hour]:[minute]:[second]")); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// Using the [`format_description!`] macro requires enabling the `time` - /// crate's "macros" feature flag. - /// - /// Using [`time::format_description::parse`]: - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::UtcTime}; - /// - /// let time_format = time::format_description::parse("[hour]:[minute]:[second]") - /// .expect("format string should be valid!"); - /// let timer = UtcTime::new(time_format); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// Using a [well-known format][well-known formats] (this is equivalent to - /// [`UtcTime::rfc_3339`]): - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::UtcTime}; - /// - /// let timer = UtcTime::new(time::format_description::well_known::Rfc3339); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// [UTC time]: time::OffsetDateTime::now_utc() - /// [`time` crate]: time - /// [`Formattable`]: time::formatting::Formattable - /// [well-known formats]: time::format_description::well_known - /// [`format_description!`]: time::macros::format_description! - /// [`time::format_description::parse`]: time::format_description::parse - /// [`time` book]: https://time-rs.github.io/book/api/format-description.html - pub fn new(format: F) -> Self { - Self { format } - } -} - -impl<F> FormatTime for UtcTime<F> -where - F: Formattable, -{ - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - format_datetime(OffsetDateTime::now_utc(), w, &self.format) - } -} - -impl<F> Default for UtcTime<F> -where - F: Formattable + Default, -{ - fn default() -> Self { - Self::new(F::default()) - } -} - -// === impl OffsetTime === - -#[cfg(feature = "local-time")] -impl OffsetTime<well_known::Rfc3339> { - /// Returns a formatter that formats the current time using the [local time offset] in the [RFC - /// 3339] format (a subset of the [ISO 8601] timestamp format). - /// - /// Returns an error if the local time offset cannot be determined. This typically occurs in - /// multithreaded programs. To avoid this problem, initialize `OffsetTime` before forking - /// threads. When using Tokio, this means initializing `OffsetTime` before the Tokio runtime. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time}; - /// - /// let collector = tracing_subscriber::fmt() - /// .with_timer(time::OffsetTime::local_rfc_3339().expect("could not get local offset!")); - /// # drop(collector); - /// ``` - /// - /// Using `OffsetTime` with Tokio: - /// - /// ``` - /// use tracing_subscriber::fmt::time::OffsetTime; - /// - /// #[tokio::main] - /// async fn run() { - /// tracing::info!("runtime initialized"); - /// - /// // At this point the Tokio runtime is initialized, and we can use both Tokio and Tracing - /// // normally. - /// } - /// - /// fn main() { - /// // Because we need to get the local offset before Tokio spawns any threads, our `main` - /// // function cannot use `tokio::main`. - /// tracing_subscriber::fmt() - /// .with_timer(OffsetTime::local_rfc_3339().expect("could not get local time offset")) - /// .init(); - /// - /// // Even though `run` is written as an `async fn`, because we used `tokio::main` on it - /// // we can call it as a synchronous function. - /// run(); - /// } - /// ``` - /// - /// [local time offset]: time::UtcOffset::current_local_offset - /// [RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339 - /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601 - pub fn local_rfc_3339() -> Result<Self, time::error::IndeterminateOffset> { - Ok(Self::new( - UtcOffset::current_local_offset()?, - well_known::Rfc3339, - )) - } -} - -impl<F: time::formatting::Formattable> OffsetTime<F> { - /// Returns a formatter that formats the current time using the [`time` crate] with the provided - /// provided format and [timezone offset]. The format may be any type that implements the - /// [`Formattable`] trait. - /// - /// - /// Typically, the offset will be the [local offset], and format will be a format description - /// string, or one of the `time` crate's [well-known formats]. - /// - /// If the format description is statically known, then the - /// [`format_description!`] macro should be used. This is identical to the - /// [`time::format_description::parse`] method, but runs at compile-time, - /// throwing an error if the format description is invalid. If the desired format - /// is not known statically (e.g., a user is providing a format string), then the - /// [`time::format_description::parse`] method should be used. Note that this - /// method is fallible. - /// - /// See the [`time` book] for details on the format description syntax. - /// - /// # Examples - /// - /// Using the [`format_description!`] macro: - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::OffsetTime}; - /// use time::macros::format_description; - /// use time::UtcOffset; - /// - /// let offset = UtcOffset::current_local_offset().expect("should get local offset!"); - /// let timer = OffsetTime::new(offset, format_description!("[hour]:[minute]:[second]")); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// Using [`time::format_description::parse`]: - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::OffsetTime}; - /// use time::UtcOffset; - /// - /// let offset = UtcOffset::current_local_offset().expect("should get local offset!"); - /// let time_format = time::format_description::parse("[hour]:[minute]:[second]") - /// .expect("format string should be valid!"); - /// let timer = OffsetTime::new(offset, time_format); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// Using the [`format_description!`] macro requires enabling the `time` - /// crate's "macros" feature flag. - /// - /// Using a [well-known format][well-known formats] (this is equivalent to - /// [`OffsetTime::local_rfc_3339`]): - /// - /// ``` - /// use tracing_subscriber::fmt::{self, time::OffsetTime}; - /// use time::UtcOffset; - /// - /// let offset = UtcOffset::current_local_offset().expect("should get local offset!"); - /// let timer = OffsetTime::new(offset, time::format_description::well_known::Rfc3339); - /// let collector = tracing_subscriber::fmt() - /// .with_timer(timer); - /// # drop(collector); - /// ``` - /// - /// [`time` crate]: time - /// [timezone offset]: time::UtcOffset - /// [`Formattable`]: time::formatting::Formattable - /// [local offset]: time::UtcOffset::current_local_offset() - /// [well-known formats]: time::format_description::well_known - /// [`format_description!`]: time::macros::format_description - /// [`time::format_description::parse`]: time::format_description::parse - /// [`time` book]: https://time-rs.github.io/book/api/format-description.html - pub fn new(offset: time::UtcOffset, format: F) -> Self { - Self { offset, format } - } -} - -impl<F> FormatTime for OffsetTime<F> -where - F: time::formatting::Formattable, -{ - fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result { - let now = OffsetDateTime::now_utc().to_offset(self.offset); - format_datetime(now, w, &self.format) - } -} - -fn format_datetime( - now: OffsetDateTime, - into: &mut Writer<'_>, - fmt: &impl Formattable, -) -> fmt::Result { - let mut into = WriteAdaptor::new(into); - now.format_into(&mut into, fmt) - .map_err(|_| fmt::Error) - .map(|_| ()) -} diff --git a/vendor/tracing-subscriber/src/fmt/writer.rs b/vendor/tracing-subscriber/src/fmt/writer.rs deleted file mode 100644 index 4aacd6d54..000000000 --- a/vendor/tracing-subscriber/src/fmt/writer.rs +++ /dev/null @@ -1,1464 +0,0 @@ -//! Abstractions for creating [`io::Write`] instances. -//! -//! [`io::Write`]: std::io::Write -use std::{ - fmt, - io::{self, Write}, - sync::{Arc, Mutex, MutexGuard}, -}; -use tracing_core::Metadata; - -/// A type that can create [`io::Write`] instances. -/// -/// `MakeWriter` is used by [`fmt::Layer`] or [`fmt::Subscriber`] to print -/// formatted text representations of [`Event`]s. -/// -/// This trait is already implemented for function pointers and -/// immutably-borrowing closures that return an instance of [`io::Write`], such -/// as [`io::stdout`] and [`io::stderr`]. Additionally, it is implemented for -/// [`std::sync::Mutex`][mutex] when the tyoe inside the mutex implements -/// [`io::Write`]. -/// -/// # Examples -/// -/// The simplest usage is to pass in a named function that returns a writer. For -/// example, to log all events to stderr, we could write: -/// ``` -/// let subscriber = tracing_subscriber::fmt() -/// .with_writer(std::io::stderr) -/// .finish(); -/// # drop(subscriber); -/// ``` -/// -/// Any function that returns a writer can be used: -/// -/// ``` -/// fn make_my_great_writer() -> impl std::io::Write { -/// // ... -/// # std::io::stdout() -/// } -/// -/// let subscriber = tracing_subscriber::fmt() -/// .with_writer(make_my_great_writer) -/// .finish(); -/// # drop(subscriber); -/// ``` -/// -/// A closure can be used to introduce arbitrary logic into how the writer is -/// created. Consider the (admittedly rather silly) example of sending every 5th -/// event to stderr, and all other events to stdout: -/// -/// ``` -/// use std::io; -/// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; -/// -/// let n = AtomicUsize::new(0); -/// let subscriber = tracing_subscriber::fmt() -/// .with_writer(move || -> Box<dyn io::Write> { -/// if n.fetch_add(1, Relaxed) % 5 == 0 { -/// Box::new(io::stderr()) -/// } else { -/// Box::new(io::stdout()) -/// } -/// }) -/// .finish(); -/// # drop(subscriber); -/// ``` -/// -/// A single instance of a type implementing [`io::Write`] may be used as a -/// `MakeWriter` by wrapping it in a [`Mutex`][mutex]. For example, we could -/// write to a file like so: -/// -/// ``` -/// use std::{fs::File, sync::Mutex}; -/// -/// # fn docs() -> Result<(), Box<dyn std::error::Error>> { -/// let log_file = File::create("my_cool_trace.log")?; -/// let subscriber = tracing_subscriber::fmt() -/// .with_writer(Mutex::new(log_file)) -/// .finish(); -/// # drop(subscriber); -/// # Ok(()) -/// # } -/// ``` -/// -/// [`io::Write`]: std::io::Write -/// [`fmt::Layer`]: crate::fmt::Layer -/// [`fmt::Subscriber`]: crate::fmt::Subscriber -/// [`Event`]: tracing_core::event::Event -/// [`io::stdout`]: std::io::stdout() -/// [`io::stderr`]: std::io::stderr() -/// [mutex]: std::sync::Mutex -/// [`MakeWriter::make_writer_for`]: MakeWriter::make_writer_for -/// [`Metadata`]: tracing_core::Metadata -/// [levels]: tracing_core::Level -/// [targets]: tracing_core::Metadata::target -pub trait MakeWriter<'a> { - /// The concrete [`io::Write`] implementation returned by [`make_writer`]. - /// - /// [`io::Write`]: std::io::Write - /// [`make_writer`]: MakeWriter::make_writer - type Writer: io::Write; - - /// Returns an instance of [`Writer`]. - /// - /// # Implementer notes - /// - /// [`fmt::Layer`] or [`fmt::Subscriber`] will call this method each time an event is recorded. Ensure any state - /// that must be saved across writes is not lost when the [`Writer`] instance is dropped. If - /// creating a [`io::Write`] instance is expensive, be sure to cache it when implementing - /// [`MakeWriter`] to improve performance. - /// - /// [`Writer`]: MakeWriter::Writer - /// [`fmt::Layer`]: crate::fmt::Layer - /// [`fmt::Subscriber`]: crate::fmt::Subscriber - /// [`io::Write`]: std::io::Write - fn make_writer(&'a self) -> Self::Writer; - - /// Returns a [`Writer`] for writing data from the span or event described - /// by the provided [`Metadata`]. - /// - /// By default, this calls [`self.make_writer()`][make_writer], ignoring - /// the provided metadata, but implementations can override this to provide - /// metadata-specific behaviors. - /// - /// This method allows `MakeWriter` implementations to implement different - /// behaviors based on the span or event being written. The `MakeWriter` - /// type might return different writers based on the provided metadata, or - /// might write some values to the writer before or after providing it to - /// the caller. - /// - /// For example, we might want to write data from spans and events at the - /// [`ERROR`] and [`WARN`] levels to `stderr`, and data from spans or events - /// at lower levels to stdout: - /// - /// ``` - /// use std::io::{self, Stdout, Stderr, StdoutLock, StderrLock}; - /// use tracing_subscriber::fmt::writer::MakeWriter; - /// use tracing_core::{Metadata, Level}; - /// - /// pub struct MyMakeWriter { - /// stdout: Stdout, - /// stderr: Stderr, - /// } - /// - /// /// A lock on either stdout or stderr, depending on the verbosity level - /// /// of the event being written. - /// pub enum StdioLock<'a> { - /// Stdout(StdoutLock<'a>), - /// Stderr(StderrLock<'a>), - /// } - /// - /// impl<'a> io::Write for StdioLock<'a> { - /// fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - /// match self { - /// StdioLock::Stdout(lock) => lock.write(buf), - /// StdioLock::Stderr(lock) => lock.write(buf), - /// } - /// } - /// - /// fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - /// // ... - /// # match self { - /// # StdioLock::Stdout(lock) => lock.write_all(buf), - /// # StdioLock::Stderr(lock) => lock.write_all(buf), - /// # } - /// } - /// - /// fn flush(&mut self) -> io::Result<()> { - /// // ... - /// # match self { - /// # StdioLock::Stdout(lock) => lock.flush(), - /// # StdioLock::Stderr(lock) => lock.flush(), - /// # } - /// } - /// } - /// - /// impl<'a> MakeWriter<'a> for MyMakeWriter { - /// type Writer = StdioLock<'a>; - /// - /// fn make_writer(&'a self) -> Self::Writer { - /// // We must have an implementation of `make_writer` that makes - /// // a "default" writer without any configuring metadata. Let's - /// // just return stdout in that case. - /// StdioLock::Stdout(self.stdout.lock()) - /// } - /// - /// fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - /// // Here's where we can implement our special behavior. We'll - /// // check if the metadata's verbosity level is WARN or ERROR, - /// // and return stderr in that case. - /// if meta.level() <= &Level::WARN { - /// return StdioLock::Stderr(self.stderr.lock()); - /// } - /// - /// // Otherwise, we'll return stdout. - /// StdioLock::Stdout(self.stdout.lock()) - /// } - /// } - /// ``` - /// - /// [`Writer`]: MakeWriter::Writer - /// [`Metadata`]: tracing_core::Metadata - /// [make_writer]: MakeWriter::make_writer - /// [`WARN`]: tracing_core::Level::WARN - /// [`ERROR`]: tracing_core::Level::ERROR - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - let _ = meta; - self.make_writer() - } -} - -/// Extension trait adding combinators for working with types implementing -/// [`MakeWriter`]. -/// -/// This is not intended to be implemented directly for user-defined -/// [`MakeWriter`]s; instead, it should be imported when the desired methods are -/// used. -pub trait MakeWriterExt<'a>: MakeWriter<'a> { - /// Wraps `self` and returns a [`MakeWriter`] that will only write output - /// for events at or below the provided verbosity [`Level`]. For instance, - /// `Level::TRACE` is considered to be _more verbose` than `Level::INFO`. - /// - /// Events whose level is more verbose than `level` will be ignored, and no - /// output will be written. - /// - /// # Examples - /// - /// ``` - /// use tracing::Level; - /// use tracing_subscriber::fmt::writer::MakeWriterExt; - /// - /// // Construct a writer that outputs events to `stderr` only if the span or - /// // event's level is >= WARN (WARN and ERROR). - /// let mk_writer = std::io::stderr.with_max_level(Level::WARN); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// ``` - /// - /// Writing the `ERROR` and `WARN` levels to `stderr`, and everything else - /// to `stdout`: - /// - /// ``` - /// # use tracing::Level; - /// # use tracing_subscriber::fmt::writer::MakeWriterExt; - /// - /// let mk_writer = std::io::stderr - /// .with_max_level(Level::WARN) - /// .or_else(std::io::stdout); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// ``` - /// - /// Writing the `ERROR` level to `stderr`, the `INFO` and `WARN` levels to - /// `stdout`, and the `INFO` and DEBUG` levels to a file: - /// - /// ``` - /// # use tracing::Level; - /// # use tracing_subscriber::fmt::writer::MakeWriterExt; - /// use std::{sync::Arc, fs::File}; - /// # // don't actually create the file when running the tests. - /// # fn docs() -> std::io::Result<()> { - /// let debug_log = Arc::new(File::create("debug.log")?); - /// - /// let mk_writer = std::io::stderr - /// .with_max_level(Level::ERROR) - /// .or_else(std::io::stdout - /// .with_max_level(Level::INFO) - /// .and(debug_log.with_max_level(Level::DEBUG)) - /// ); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// # Ok(()) } - /// ``` - /// - /// [`Level`]: tracing_core::Level - /// [`io::Write`]: std::io::Write - fn with_max_level(self, level: tracing_core::Level) -> WithMaxLevel<Self> - where - Self: Sized, - { - WithMaxLevel::new(self, level) - } - - /// Wraps `self` and returns a [`MakeWriter`] that will only write output - /// for events at or above the provided verbosity [`Level`]. - /// - /// Events whose level is less verbose than `level` will be ignored, and no - /// output will be written. - /// - /// # Examples - /// - /// ``` - /// use tracing::Level; - /// use tracing_subscriber::fmt::writer::MakeWriterExt; - /// - /// // Construct a writer that outputs events to `stdout` only if the span or - /// // event's level is <= DEBUG (DEBUG and TRACE). - /// let mk_writer = std::io::stdout.with_min_level(Level::DEBUG); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// ``` - /// This can be combined with [`MakeWriterExt::with_max_level`] to write - /// only within a range of levels: - /// - /// ``` - /// # use tracing::Level; - /// # use tracing_subscriber::fmt::writer::MakeWriterExt; - /// // Only write the `DEBUG` and `INFO` levels to stdout. - /// let mk_writer = std::io::stdout - /// .with_max_level(Level::DEBUG) - /// .with_min_level(Level::INFO) - /// // Write the `WARN` and `ERROR` levels to stderr. - /// .and(std::io::stderr.with_min_level(Level::WARN)); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// ``` - /// [`Level`]: tracing_core::Level - /// [`io::Write`]: std::io::Write - fn with_min_level(self, level: tracing_core::Level) -> WithMinLevel<Self> - where - Self: Sized, - { - WithMinLevel::new(self, level) - } - - /// Wraps `self` with a predicate that takes a span or event's [`Metadata`] - /// and returns a `bool`. The returned [`MakeWriter`]'s - /// [`MakeWriter::make_writer_for`][mwf] method will check the predicate to - /// determine if a writer should be produced for a given span or event. - /// - /// If the predicate returns `false`, the wrapped [`MakeWriter`]'s - /// [`make_writer_for`][mwf] will return [`OptionalWriter::none`][own]. - /// Otherwise, it calls the wrapped [`MakeWriter`]'s - /// [`make_writer_for`][mwf] method, and returns the produced writer. - /// - /// This can be used to filter an output based on arbitrary [`Metadata`] - /// parameters. - /// - /// # Examples - /// - /// Writing events with a specific target to an HTTP access log, and other - /// events to stdout: - /// - /// ``` - /// use tracing_subscriber::fmt::writer::MakeWriterExt; - /// use std::{sync::Arc, fs::File}; - /// # // don't actually create the file when running the tests. - /// # fn docs() -> std::io::Result<()> { - /// let access_log = Arc::new(File::create("access.log")?); - /// - /// let mk_writer = access_log - /// // Only write events with the target "http::access_log" to the - /// // access log file. - /// .with_filter(|meta| meta.target() == "http::access_log") - /// // Write events with all other targets to stdout. - /// .or_else(std::io::stdout); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// # Ok(()) - /// # } - /// ``` - /// - /// Conditionally enabling or disabling a log file: - /// ``` - /// use tracing_subscriber::fmt::writer::MakeWriterExt; - /// use std::{ - /// sync::{Arc, atomic::{AtomicBool, Ordering}}, - /// fs::File, - /// }; - /// - /// static DEBUG_LOG_ENABLED: AtomicBool = AtomicBool::new(false); - /// - /// # // don't actually create the file when running the tests. - /// # fn docs() -> std::io::Result<()> { - /// // Create the debug log file - /// let debug_file = Arc::new(File::create("debug.log")?) - /// // Enable the debug log only if the flag is enabled. - /// .with_filter(|_| DEBUG_LOG_ENABLED.load(Ordering::Acquire)); - /// - /// // Always write to stdout - /// let mk_writer = std::io::stdout - /// // Write to the debug file if it's enabled - /// .and(debug_file); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// - /// // ... - /// - /// // Later, we can toggle on or off the debug log file. - /// DEBUG_LOG_ENABLED.store(true, Ordering::Release); - /// # Ok(()) - /// # } - /// ``` - /// - /// [`Metadata`]: tracing_core::Metadata - /// [mwf]: MakeWriter::make_writer_for - /// [own]: EitherWriter::none - fn with_filter<F>(self, filter: F) -> WithFilter<Self, F> - where - Self: Sized, - F: Fn(&Metadata<'_>) -> bool, - { - WithFilter::new(self, filter) - } - - /// Combines `self` with another type implementing [`MakeWriter`], returning - /// a new [`MakeWriter`] that produces [writers] that write to *both* - /// outputs. - /// - /// If writing to either writer returns an error, the returned writer will - /// return that error. However, both writers will still be written to before - /// the error is returned, so it is possible for one writer to fail while - /// the other is written to successfully. - /// - /// # Examples - /// - /// ``` - /// use tracing_subscriber::fmt::writer::MakeWriterExt; - /// - /// // Construct a writer that outputs events to `stdout` *and* `stderr`. - /// let mk_writer = std::io::stdout.and(std::io::stderr); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// ``` - /// - /// `and` can be used in conjunction with filtering combinators. For - /// example, if we want to write to a number of outputs depending on the - /// level of an event, we could write: - /// - /// ``` - /// use tracing::Level; - /// # use tracing_subscriber::fmt::writer::MakeWriterExt; - /// use std::{sync::Arc, fs::File}; - /// # // don't actually create the file when running the tests. - /// # fn docs() -> std::io::Result<()> { - /// let debug_log = Arc::new(File::create("debug.log")?); - /// - /// // Write everything to the debug log. - /// let mk_writer = debug_log - /// // Write the `ERROR` and `WARN` levels to stderr. - /// .and(std::io::stderr.with_max_level(Level::WARN)) - /// // Write `INFO` to `stdout`. - /// .and(std::io::stdout - /// .with_max_level(Level::INFO) - /// .with_min_level(Level::INFO) - /// ); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// # Ok(()) } - /// ``` - /// - /// [writers]: std::io::Write - fn and<B>(self, other: B) -> Tee<Self, B> - where - Self: Sized, - B: MakeWriter<'a> + Sized, - { - Tee::new(self, other) - } - - /// Combines `self` with another type implementing [`MakeWriter`], returning - /// a new [`MakeWriter`] that calls `other`'s [`make_writer`] if `self`'s - /// `make_writer` returns [`OptionalWriter::none`][own]. - /// - /// # Examples - /// - /// ``` - /// use tracing::Level; - /// use tracing_subscriber::fmt::writer::MakeWriterExt; - /// - /// // Produces a writer that writes to `stderr` if the level is >= WARN, - /// // or returns `OptionalWriter::none()` otherwise. - /// let stderr = std::io::stderr.with_max_level(Level::WARN); - /// - /// // If the `stderr` `MakeWriter` is disabled by the max level filter, - /// // write to stdout instead: - /// let mk_writer = stderr.or_else(std::io::stdout); - /// - /// tracing_subscriber::fmt().with_writer(mk_writer).init(); - /// ``` - /// - /// [`make_writer`]: MakeWriter::make_writer - /// [own]: EitherWriter::none - fn or_else<W, B>(self, other: B) -> OrElse<Self, B> - where - Self: MakeWriter<'a, Writer = OptionalWriter<W>> + Sized, - B: MakeWriter<'a> + Sized, - W: Write, - { - OrElse::new(self, other) - } -} - -/// A writer intended to support [`libtest`'s output capturing][capturing] for use in unit tests. -/// -/// `TestWriter` is used by [`fmt::Subscriber`] or [`fmt::Layer`] to enable capturing support. -/// -/// `cargo test` can only capture output from the standard library's [`print!`] macro. See -/// [`libtest`'s output capturing][capturing] for more details about output capturing. -/// -/// Writing to [`io::stdout`] and [`io::stderr`] produces the same results as using -/// [`libtest`'s `--nocapture` option][nocapture] which may make the results look unreadable. -/// -/// [`fmt::Subscriber`]: super::Subscriber -/// [`fmt::Layer`]: super::Layer -/// [capturing]: https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output -/// [nocapture]: https://doc.rust-lang.org/cargo/commands/cargo-test.html -/// [`io::stdout`]: std::io::stdout -/// [`io::stderr`]: std::io::stderr -/// [`print!`]: std::print! -#[derive(Default, Debug)] -pub struct TestWriter { - _p: (), -} - -/// A writer that erases the specific [`io::Write`] and [`MakeWriter`] types being used. -/// -/// This is useful in cases where the concrete type of the writer cannot be known -/// until runtime. -/// -/// # Examples -/// -/// A function that returns a [`Subscriber`] that will write to either stdout or stderr: -/// -/// ```rust -/// # use tracing::Subscriber; -/// # use tracing_subscriber::fmt::writer::BoxMakeWriter; -/// -/// fn dynamic_writer(use_stderr: bool) -> impl Subscriber { -/// let writer = if use_stderr { -/// BoxMakeWriter::new(std::io::stderr) -/// } else { -/// BoxMakeWriter::new(std::io::stdout) -/// }; -/// -/// tracing_subscriber::fmt().with_writer(writer).finish() -/// } -/// ``` -/// -/// [`Subscriber`]: tracing::Subscriber -/// [`io::Write`]: std::io::Write -pub struct BoxMakeWriter { - inner: Box<dyn for<'a> MakeWriter<'a, Writer = Box<dyn Write + 'a>> + Send + Sync>, - name: &'static str, -} - -/// A [writer] that is one of two types implementing [`io::Write`][writer]. -/// -/// This may be used by [`MakeWriter`] implementations that may conditionally -/// return one of two writers. -/// -/// [writer]: std::io::Write -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum EitherWriter<A, B> { - /// A writer of type `A`. - A(A), - /// A writer of type `B`. - B(B), -} - -/// A [writer] which may or may not be enabled. -/// -/// This may be used by [`MakeWriter`] implementations that wish to -/// conditionally enable or disable the returned writer based on a span or -/// event's [`Metadata`]. -/// -/// [writer]: std::io::Write -pub type OptionalWriter<T> = EitherWriter<T, std::io::Sink>; - -/// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans -/// and events with metadata at or below a specified verbosity [`Level`]. -/// -/// This is returned by the [`MakeWriterExt::with_max_level`] method. See the -/// method documentation for details. -/// -/// [writer]: std::io::Write -/// [`Level`]: tracing_core::Level -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct WithMaxLevel<M> { - make: M, - level: tracing_core::Level, -} - -/// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans -/// and events with metadata at or above a specified verbosity [`Level`]. -/// -/// This is returned by the [`MakeWriterExt::with_min_level`] method. See the -/// method documentation for details. -/// -/// [writer]: std::io::Write -/// [`Level`]: tracing_core::Level -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct WithMinLevel<M> { - make: M, - level: tracing_core::Level, -} - -/// A [`MakeWriter`] combinator that wraps a [`MakeWriter`] with a predicate for -/// span and event [`Metadata`], so that the [`MakeWriter::make_writer_for`] -/// method returns [`OptionalWriter::some`][ows] when the predicate returns `true`, -/// and [`OptionalWriter::none`][own] when the predicate returns `false`. -/// -/// This is returned by the [`MakeWriterExt::with_filter`] method. See the -/// method documentation for details. -/// -/// [`Metadata`]: tracing_core::Metadata -/// [ows]: EitherWriter::some -/// [own]: EitherWriter::none -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct WithFilter<M, F> { - make: M, - filter: F, -} - -/// Combines a [`MakeWriter`] that returns an [`OptionalWriter`] with another -/// [`MakeWriter`], so that the second [`MakeWriter`] is used when the first -/// [`MakeWriter`] returns [`OptionalWriter::none`][own]. -/// -/// This is returned by the [`MakeWriterExt::or_else] method. See the -/// method documentation for details. -/// -/// [own]: EitherWriter::none -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct OrElse<A, B> { - inner: A, - or_else: B, -} - -/// Combines two types implementing [`MakeWriter`] (or [`std::io::Write`]) to -/// produce a writer that writes to both [`MakeWriter`]'s returned writers. -/// -/// This is returned by the [`MakeWriterExt::and`] method. See the method -/// documentation for details. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Tee<A, B> { - a: A, - b: B, -} - -/// A type implementing [`io::Write`] for a [`MutexGuard`] where the type -/// inside the [`Mutex`] implements [`io::Write`]. -/// -/// This is used by the [`MakeWriter`] implementation for [`Mutex`], because -/// [`MutexGuard`] itself will not implement [`io::Write`] — instead, it -/// _dereferences_ to a type implementing [`io::Write`]. Because [`MakeWriter`] -/// requires the `Writer` type to implement [`io::Write`], it's necessary to add -/// a newtype that forwards the trait implementation. -/// -/// [`io::Write`]: std::io::Write -/// [`MutexGuard`]: std::sync::MutexGuard -/// [`Mutex`]: std::sync::Mutex -#[derive(Debug)] -pub struct MutexGuardWriter<'a, W>(MutexGuard<'a, W>); - -/// Implements [`std::io::Write`] for an [`Arc`]<W> where `&W: Write`. -/// -/// This is an implementation detail of the [`MakeWriter`] impl for [`Arc`]. -#[derive(Clone, Debug)] -pub struct ArcWriter<W>(Arc<W>); - -/// A bridge between `fmt::Write` and `io::Write`. -/// -/// This is used by the timestamp formatting implementation for the `time` -/// crate and by the JSON formatter. In both cases, this is needed because -/// `tracing-subscriber`'s `FormatEvent`/`FormatTime` traits expect a -/// `fmt::Write` implementation, while `serde_json::Serializer` and `time`'s -/// `format_into` methods expect an `io::Write`. -#[cfg(any(feature = "json", feature = "time"))] -pub(in crate::fmt) struct WriteAdaptor<'a> { - fmt_write: &'a mut dyn fmt::Write, -} - -impl<'a, F, W> MakeWriter<'a> for F -where - F: Fn() -> W, - W: io::Write, -{ - type Writer = W; - - fn make_writer(&'a self) -> Self::Writer { - (self)() - } -} - -impl<'a, W> MakeWriter<'a> for Arc<W> -where - &'a W: io::Write + 'a, -{ - type Writer = &'a W; - fn make_writer(&'a self) -> Self::Writer { - &*self - } -} - -impl<'a> MakeWriter<'a> for std::fs::File { - type Writer = &'a std::fs::File; - fn make_writer(&'a self) -> Self::Writer { - self - } -} - -// === impl TestWriter === - -impl TestWriter { - /// Returns a new `TestWriter` with the default configuration. - pub fn new() -> Self { - Self::default() - } -} - -impl io::Write for TestWriter { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - let out_str = String::from_utf8_lossy(buf); - print!("{}", out_str); - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl<'a> MakeWriter<'a> for TestWriter { - type Writer = Self; - - fn make_writer(&'a self) -> Self::Writer { - Self::default() - } -} - -// === impl BoxMakeWriter === - -impl BoxMakeWriter { - /// Constructs a `BoxMakeWriter` wrapping a type implementing [`MakeWriter`]. - /// - pub fn new<M>(make_writer: M) -> Self - where - M: for<'a> MakeWriter<'a> + Send + Sync + 'static, - { - Self { - inner: Box::new(Boxed(make_writer)), - name: std::any::type_name::<M>(), - } - } -} - -impl fmt::Debug for BoxMakeWriter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("BoxMakeWriter") - .field(&format_args!("<{}>", self.name)) - .finish() - } -} - -impl<'a> MakeWriter<'a> for BoxMakeWriter { - type Writer = Box<dyn Write + 'a>; - - #[inline] - fn make_writer(&'a self) -> Self::Writer { - self.inner.make_writer() - } - - #[inline] - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - self.inner.make_writer_for(meta) - } -} - -struct Boxed<M>(M); - -impl<'a, M> MakeWriter<'a> for Boxed<M> -where - M: MakeWriter<'a>, -{ - type Writer = Box<dyn Write + 'a>; - - fn make_writer(&'a self) -> Self::Writer { - let w = self.0.make_writer(); - Box::new(w) - } - - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - let w = self.0.make_writer_for(meta); - Box::new(w) - } -} - -// === impl Mutex/MutexGuardWriter === - -impl<'a, W> MakeWriter<'a> for Mutex<W> -where - W: io::Write + 'a, -{ - type Writer = MutexGuardWriter<'a, W>; - - fn make_writer(&'a self) -> Self::Writer { - MutexGuardWriter(self.lock().expect("lock poisoned")) - } -} - -impl<'a, W> io::Write for MutexGuardWriter<'a, W> -where - W: io::Write, -{ - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.0.write(buf) - } - - #[inline] - fn flush(&mut self) -> io::Result<()> { - self.0.flush() - } - - #[inline] - fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { - self.0.write_vectored(bufs) - } - - #[inline] - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - self.0.write_all(buf) - } - - #[inline] - fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> { - self.0.write_fmt(fmt) - } -} - -// === impl EitherWriter === - -impl<A, B> io::Write for EitherWriter<A, B> -where - A: io::Write, - B: io::Write, -{ - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - match self { - EitherWriter::A(a) => a.write(buf), - EitherWriter::B(b) => b.write(buf), - } - } - - #[inline] - fn flush(&mut self) -> io::Result<()> { - match self { - EitherWriter::A(a) => a.flush(), - EitherWriter::B(b) => b.flush(), - } - } - - #[inline] - fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { - match self { - EitherWriter::A(a) => a.write_vectored(bufs), - EitherWriter::B(b) => b.write_vectored(bufs), - } - } - - #[inline] - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - match self { - EitherWriter::A(a) => a.write_all(buf), - EitherWriter::B(b) => b.write_all(buf), - } - } - - #[inline] - fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> { - match self { - EitherWriter::A(a) => a.write_fmt(fmt), - EitherWriter::B(b) => b.write_fmt(fmt), - } - } -} - -impl<T> OptionalWriter<T> { - /// Returns a [disabled writer]. - /// - /// Any bytes written to the returned writer are discarded. - /// - /// This is equivalent to returning [`Option::None`]. - /// - /// [disabled writer]: std::io::sink - #[inline] - pub fn none() -> Self { - EitherWriter::B(std::io::sink()) - } - - /// Returns an enabled writer of type `T`. - /// - /// This is equivalent to returning [`Option::Some`]. - #[inline] - pub fn some(t: T) -> Self { - EitherWriter::A(t) - } -} - -impl<T> From<Option<T>> for OptionalWriter<T> { - #[inline] - fn from(opt: Option<T>) -> Self { - match opt { - Some(writer) => Self::some(writer), - None => Self::none(), - } - } -} - -// === impl WithMaxLevel === - -impl<M> WithMaxLevel<M> { - /// Wraps the provided [`MakeWriter`] with a maximum [`Level`], so that it - /// returns [`OptionalWriter::none`] for spans and events whose level is - /// more verbose than the maximum level. - /// - /// See [`MakeWriterExt::with_max_level`] for details. - /// - /// [`Level`]: tracing_core::Level - pub fn new(make: M, level: tracing_core::Level) -> Self { - Self { make, level } - } -} - -impl<'a, M: MakeWriter<'a>> MakeWriter<'a> for WithMaxLevel<M> { - type Writer = OptionalWriter<M::Writer>; - - #[inline] - fn make_writer(&'a self) -> Self::Writer { - // If we don't know the level, assume it's disabled. - OptionalWriter::none() - } - - #[inline] - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - if meta.level() <= &self.level { - return OptionalWriter::some(self.make.make_writer_for(meta)); - } - OptionalWriter::none() - } -} - -// === impl WithMinLevel === - -impl<M> WithMinLevel<M> { - /// Wraps the provided [`MakeWriter`] with a minimum [`Level`], so that it - /// returns [`OptionalWriter::none`] for spans and events whose level is - /// less verbose than the maximum level. - /// - /// See [`MakeWriterExt::with_min_level`] for details. - /// - /// [`Level`]: tracing_core::Level - pub fn new(make: M, level: tracing_core::Level) -> Self { - Self { make, level } - } -} - -impl<'a, M: MakeWriter<'a>> MakeWriter<'a> for WithMinLevel<M> { - type Writer = OptionalWriter<M::Writer>; - - #[inline] - fn make_writer(&'a self) -> Self::Writer { - // If we don't know the level, assume it's disabled. - OptionalWriter::none() - } - - #[inline] - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - if meta.level() >= &self.level { - return OptionalWriter::some(self.make.make_writer_for(meta)); - } - OptionalWriter::none() - } -} - -// ==== impl WithFilter === - -impl<M, F> WithFilter<M, F> { - /// Wraps `make` with the provided `filter`, returning a [`MakeWriter`] that - /// will call `make.make_writer_for()` when `filter` returns `true` for a - /// span or event's [`Metadata`], and returns a [`sink`] otherwise. - /// - /// See [`MakeWriterExt::with_filter`] for details. - /// - /// [`Metadata`]: tracing_core::Metadata - /// [`sink`]: std::io::sink - pub fn new(make: M, filter: F) -> Self - where - F: Fn(&Metadata<'_>) -> bool, - { - Self { make, filter } - } -} - -impl<'a, M, F> MakeWriter<'a> for WithFilter<M, F> -where - M: MakeWriter<'a>, - F: Fn(&Metadata<'_>) -> bool, -{ - type Writer = OptionalWriter<M::Writer>; - - #[inline] - fn make_writer(&'a self) -> Self::Writer { - OptionalWriter::some(self.make.make_writer()) - } - - #[inline] - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - if (self.filter)(meta) { - OptionalWriter::some(self.make.make_writer_for(meta)) - } else { - OptionalWriter::none() - } - } -} - -// === impl Tee === - -impl<A, B> Tee<A, B> { - /// Combines two types implementing [`MakeWriter`], returning - /// a new [`MakeWriter`] that produces [writers] that write to *both* - /// outputs. - /// - /// See the documentation for [`MakeWriterExt::and`] for details. - /// - /// [writers]: std::io::Write - pub fn new(a: A, b: B) -> Self { - Self { a, b } - } -} - -impl<'a, A, B> MakeWriter<'a> for Tee<A, B> -where - A: MakeWriter<'a>, - B: MakeWriter<'a>, -{ - type Writer = Tee<A::Writer, B::Writer>; - - #[inline] - fn make_writer(&'a self) -> Self::Writer { - Tee::new(self.a.make_writer(), self.b.make_writer()) - } - - #[inline] - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - Tee::new(self.a.make_writer_for(meta), self.b.make_writer_for(meta)) - } -} - -macro_rules! impl_tee { - ($self_:ident.$f:ident($($arg:ident),*)) => { - { - let res_a = $self_.a.$f($($arg),*); - let res_b = $self_.b.$f($($arg),*); - (res_a?, res_b?) - } - } -} - -impl<A, B> io::Write for Tee<A, B> -where - A: io::Write, - B: io::Write, -{ - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - let (a, b) = impl_tee!(self.write(buf)); - Ok(std::cmp::max(a, b)) - } - - #[inline] - fn flush(&mut self) -> io::Result<()> { - impl_tee!(self.flush()); - Ok(()) - } - - #[inline] - fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { - let (a, b) = impl_tee!(self.write_vectored(bufs)); - Ok(std::cmp::max(a, b)) - } - - #[inline] - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - impl_tee!(self.write_all(buf)); - Ok(()) - } - - #[inline] - fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> { - impl_tee!(self.write_fmt(fmt)); - Ok(()) - } -} - -// === impl OrElse === - -impl<A, B> OrElse<A, B> { - /// Combines - pub fn new<'a, W>(inner: A, or_else: B) -> Self - where - A: MakeWriter<'a, Writer = OptionalWriter<W>>, - B: MakeWriter<'a>, - W: Write, - { - Self { inner, or_else } - } -} - -impl<'a, A, B, W> MakeWriter<'a> for OrElse<A, B> -where - A: MakeWriter<'a, Writer = OptionalWriter<W>>, - B: MakeWriter<'a>, - W: io::Write, -{ - type Writer = EitherWriter<W, B::Writer>; - - #[inline] - fn make_writer(&'a self) -> Self::Writer { - match self.inner.make_writer() { - EitherWriter::A(writer) => EitherWriter::A(writer), - EitherWriter::B(_) => EitherWriter::B(self.or_else.make_writer()), - } - } - - #[inline] - fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { - match self.inner.make_writer_for(meta) { - EitherWriter::A(writer) => EitherWriter::A(writer), - EitherWriter::B(_) => EitherWriter::B(self.or_else.make_writer_for(meta)), - } - } -} - -// === impl ArcWriter === - -impl<W> io::Write for ArcWriter<W> -where - for<'a> &'a W: io::Write, -{ - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - (&*self.0).write(buf) - } - - #[inline] - fn flush(&mut self) -> io::Result<()> { - (&*self.0).flush() - } - - #[inline] - fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { - (&*self.0).write_vectored(bufs) - } - - #[inline] - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - (&*self.0).write_all(buf) - } - - #[inline] - fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> { - (&*self.0).write_fmt(fmt) - } -} - -// === impl WriteAdaptor === - -#[cfg(any(feature = "json", feature = "time"))] -impl<'a> WriteAdaptor<'a> { - pub(in crate::fmt) fn new(fmt_write: &'a mut dyn fmt::Write) -> Self { - Self { fmt_write } - } -} -#[cfg(any(feature = "json", feature = "time"))] -impl<'a> io::Write for WriteAdaptor<'a> { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - let s = - std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; - - self.fmt_write - .write_str(s) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - - Ok(s.as_bytes().len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[cfg(any(feature = "json", feature = "time"))] -impl<'a> fmt::Debug for WriteAdaptor<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("WriteAdaptor { .. }") - } -} -// === blanket impls === - -impl<'a, M> MakeWriterExt<'a> for M where M: MakeWriter<'a> {} -#[cfg(test)] -mod test { - use super::*; - use crate::fmt::format::Format; - use crate::fmt::test::{MockMakeWriter, MockWriter}; - use crate::fmt::Subscriber; - use std::sync::atomic::{AtomicBool, Ordering}; - use std::sync::{Arc, Mutex}; - use tracing::{debug, error, info, trace, warn, Level}; - use tracing_core::dispatcher::{self, Dispatch}; - - fn test_writer<T>(make_writer: T, msg: &str, buf: &Mutex<Vec<u8>>) - where - T: for<'writer> MakeWriter<'writer> + Send + Sync + 'static, - { - let subscriber = { - #[cfg(feature = "ansi")] - let f = Format::default().without_time().with_ansi(false); - #[cfg(not(feature = "ansi"))] - let f = Format::default().without_time(); - Subscriber::builder() - .event_format(f) - .with_writer(make_writer) - .finish() - }; - let dispatch = Dispatch::from(subscriber); - - dispatcher::with_default(&dispatch, || { - error!("{}", msg); - }); - - let expected = format!("ERROR {}: {}\n", module_path!(), msg); - let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap(); - assert!(actual.contains(expected.as_str())); - } - - fn has_lines(buf: &Mutex<Vec<u8>>, msgs: &[(tracing::Level, &str)]) { - let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap(); - let mut expected_lines = msgs.iter(); - for line in actual.lines() { - let line = dbg!(line).trim(); - let (level, msg) = expected_lines - .next() - .unwrap_or_else(|| panic!("expected no more lines, but got: {:?}", line)); - let expected = format!("{} {}: {}", level, module_path!(), msg); - assert_eq!(line, expected.as_str()); - } - } - - #[test] - fn custom_writer_closure() { - let buf = Arc::new(Mutex::new(Vec::new())); - let buf2 = buf.clone(); - let make_writer = move || MockWriter::new(buf2.clone()); - let msg = "my custom writer closure error"; - test_writer(make_writer, msg, &buf); - } - - #[test] - fn custom_writer_struct() { - let buf = Arc::new(Mutex::new(Vec::new())); - let make_writer = MockMakeWriter::new(buf.clone()); - let msg = "my custom writer struct error"; - test_writer(make_writer, msg, &buf); - } - - #[test] - fn custom_writer_mutex() { - let buf = Arc::new(Mutex::new(Vec::new())); - let writer = MockWriter::new(buf.clone()); - let make_writer = Mutex::new(writer); - let msg = "my mutex writer error"; - test_writer(make_writer, msg, &buf); - } - - #[test] - fn combinators_level_filters() { - let info_buf = Arc::new(Mutex::new(Vec::new())); - let info = MockMakeWriter::new(info_buf.clone()); - - let debug_buf = Arc::new(Mutex::new(Vec::new())); - let debug = MockMakeWriter::new(debug_buf.clone()); - - let warn_buf = Arc::new(Mutex::new(Vec::new())); - let warn = MockMakeWriter::new(warn_buf.clone()); - - let err_buf = Arc::new(Mutex::new(Vec::new())); - let err = MockMakeWriter::new(err_buf.clone()); - - let make_writer = info - .with_max_level(Level::INFO) - .and(debug.with_max_level(Level::DEBUG)) - .and(warn.with_max_level(Level::WARN)) - .and(err.with_max_level(Level::ERROR)); - - let c = { - #[cfg(feature = "ansi")] - let f = Format::default().without_time().with_ansi(false); - #[cfg(not(feature = "ansi"))] - let f = Format::default().without_time(); - Subscriber::builder() - .event_format(f) - .with_writer(make_writer) - .with_max_level(Level::TRACE) - .finish() - }; - - let _s = tracing::subscriber::set_default(c); - - trace!("trace"); - debug!("debug"); - info!("info"); - warn!("warn"); - error!("error"); - - let all_lines = [ - (Level::TRACE, "trace"), - (Level::DEBUG, "debug"), - (Level::INFO, "info"), - (Level::WARN, "warn"), - (Level::ERROR, "error"), - ]; - - println!("max level debug"); - has_lines(&debug_buf, &all_lines[1..]); - - println!("max level info"); - has_lines(&info_buf, &all_lines[2..]); - - println!("max level warn"); - has_lines(&warn_buf, &all_lines[3..]); - - println!("max level error"); - has_lines(&err_buf, &all_lines[4..]); - } - - #[test] - fn combinators_or_else() { - let some_buf = Arc::new(Mutex::new(Vec::new())); - let some = MockMakeWriter::new(some_buf.clone()); - - let or_else_buf = Arc::new(Mutex::new(Vec::new())); - let or_else = MockMakeWriter::new(or_else_buf.clone()); - - let return_some = AtomicBool::new(true); - let make_writer = move || { - if return_some.swap(false, Ordering::Relaxed) { - OptionalWriter::some(some.make_writer()) - } else { - OptionalWriter::none() - } - }; - let make_writer = make_writer.or_else(or_else); - let c = { - #[cfg(feature = "ansi")] - let f = Format::default().without_time().with_ansi(false); - #[cfg(not(feature = "ansi"))] - let f = Format::default().without_time(); - Subscriber::builder() - .event_format(f) - .with_writer(make_writer) - .with_max_level(Level::TRACE) - .finish() - }; - - let _s = tracing::subscriber::set_default(c); - info!("hello"); - info!("world"); - info!("goodbye"); - - has_lines(&some_buf, &[(Level::INFO, "hello")]); - has_lines( - &or_else_buf, - &[(Level::INFO, "world"), (Level::INFO, "goodbye")], - ); - } - - #[test] - fn combinators_or_else_chain() { - let info_buf = Arc::new(Mutex::new(Vec::new())); - let info = MockMakeWriter::new(info_buf.clone()); - - let debug_buf = Arc::new(Mutex::new(Vec::new())); - let debug = MockMakeWriter::new(debug_buf.clone()); - - let warn_buf = Arc::new(Mutex::new(Vec::new())); - let warn = MockMakeWriter::new(warn_buf.clone()); - - let err_buf = Arc::new(Mutex::new(Vec::new())); - let err = MockMakeWriter::new(err_buf.clone()); - - let make_writer = err.with_max_level(Level::ERROR).or_else( - warn.with_max_level(Level::WARN).or_else( - info.with_max_level(Level::INFO) - .or_else(debug.with_max_level(Level::DEBUG)), - ), - ); - - let c = { - #[cfg(feature = "ansi")] - let f = Format::default().without_time().with_ansi(false); - #[cfg(not(feature = "ansi"))] - let f = Format::default().without_time(); - Subscriber::builder() - .event_format(f) - .with_writer(make_writer) - .with_max_level(Level::TRACE) - .finish() - }; - - let _s = tracing::subscriber::set_default(c); - - trace!("trace"); - debug!("debug"); - info!("info"); - warn!("warn"); - error!("error"); - - println!("max level debug"); - has_lines(&debug_buf, &[(Level::DEBUG, "debug")]); - - println!("max level info"); - has_lines(&info_buf, &[(Level::INFO, "info")]); - - println!("max level warn"); - has_lines(&warn_buf, &[(Level::WARN, "warn")]); - - println!("max level error"); - has_lines(&err_buf, &[(Level::ERROR, "error")]); - } - - #[test] - fn combinators_and() { - let a_buf = Arc::new(Mutex::new(Vec::new())); - let a = MockMakeWriter::new(a_buf.clone()); - - let b_buf = Arc::new(Mutex::new(Vec::new())); - let b = MockMakeWriter::new(b_buf.clone()); - - let lines = &[(Level::INFO, "hello"), (Level::INFO, "world")]; - - let make_writer = a.and(b); - let c = { - #[cfg(feature = "ansi")] - let f = Format::default().without_time().with_ansi(false); - #[cfg(not(feature = "ansi"))] - let f = Format::default().without_time(); - Subscriber::builder() - .event_format(f) - .with_writer(make_writer) - .with_max_level(Level::TRACE) - .finish() - }; - - let _s = tracing::subscriber::set_default(c); - info!("hello"); - info!("world"); - - has_lines(&a_buf, &lines[..]); - has_lines(&b_buf, &lines[..]); - } -} diff --git a/vendor/tracing-subscriber/src/layer/context.rs b/vendor/tracing-subscriber/src/layer/context.rs deleted file mode 100644 index 46254994f..000000000 --- a/vendor/tracing-subscriber/src/layer/context.rs +++ /dev/null @@ -1,434 +0,0 @@ -use tracing_core::{metadata::Metadata, span, subscriber::Subscriber, Event}; - -use crate::registry::{self, LookupSpan, SpanRef}; - -#[cfg(all(feature = "registry", feature = "std"))] -use crate::{filter::FilterId, registry::Registry}; -/// Represents information about the current context provided to [`Layer`]s by the -/// wrapped [`Subscriber`]. -/// -/// To access [stored data] keyed by a span ID, implementors of the `Layer` -/// trait should ensure that the `Subscriber` type parameter is *also* bound by the -/// [`LookupSpan`]: -/// -/// ```rust -/// use tracing::Subscriber; -/// use tracing_subscriber::{Layer, registry::LookupSpan}; -/// -/// pub struct MyLayer; -/// -/// impl<S> Layer<S> for MyLayer -/// where -/// S: Subscriber + for<'a> LookupSpan<'a>, -/// { -/// // ... -/// } -/// ``` -/// -/// [`Layer`]: super::Layer -/// [`Subscriber`]: tracing_core::Subscriber -/// [stored data]: crate::registry::SpanRef -/// [`LookupSpan`]: crate::registry::LookupSpan -#[derive(Debug)] -pub struct Context<'a, S> { - subscriber: Option<&'a S>, - /// The bitmask of all [`Filtered`] layers that currently apply in this - /// context. If there is only a single [`Filtered`] wrapping the layer that - /// produced this context, then this is that filter's ID. Otherwise, if we - /// are in a nested tree with multiple filters, this is produced by - /// [`and`]-ing together the [`FilterId`]s of each of the filters that wrap - /// the current layer. - /// - /// [`Filtered`]: crate::filter::Filtered - /// [`FilterId`]: crate::filter::FilterId - /// [`and`]: crate::filter::FilterId::and - #[cfg(all(feature = "registry", feature = "std"))] - filter: FilterId, -} - -// === impl Context === - -impl<'a, S> Context<'a, S> -where - S: Subscriber, -{ - pub(super) fn new(subscriber: &'a S) -> Self { - Self { - subscriber: Some(subscriber), - - #[cfg(feature = "registry")] - filter: FilterId::none(), - } - } - - /// Returns the wrapped subscriber's view of the current span. - #[inline] - pub fn current_span(&self) -> span::Current { - self.subscriber - .map(Subscriber::current_span) - // TODO: this would be more correct as "unknown", so perhaps - // `tracing-core` should make `Current::unknown()` public? - .unwrap_or_else(span::Current::none) - } - - /// Returns whether the wrapped subscriber would enable the current span. - #[inline] - pub fn enabled(&self, metadata: &Metadata<'_>) -> bool { - self.subscriber - .map(|subscriber| subscriber.enabled(metadata)) - // If this context is `None`, we are registering a callsite, so - // return `true` so that the layer does not incorrectly assume that - // the inner subscriber has disabled this metadata. - // TODO(eliza): would it be more correct for this to return an `Option`? - .unwrap_or(true) - } - - /// Records the provided `event` with the wrapped subscriber. - /// - /// # Notes - /// - /// - The subscriber is free to expect that the event's callsite has been - /// [registered][register], and may panic or fail to observe the event if this is - /// not the case. The `tracing` crate's macros ensure that all events are - /// registered, but if the event is constructed through other means, the - /// user is responsible for ensuring that [`register_callsite`][register] - /// has been called prior to calling this method. - /// - This does _not_ call [`enabled`] on the inner subscriber. If the - /// caller wishes to apply the wrapped subscriber's filter before choosing - /// whether to record the event, it may first call [`Context::enabled`] to - /// check whether the event would be enabled. This allows `Layer`s to - /// elide constructing the event if it would not be recorded. - /// - /// [register]: tracing_core::subscriber::Subscriber::register_callsite() - /// [`enabled`]: tracing_core::subscriber::Subscriber::enabled() - /// [`Context::enabled`]: Context::enabled() - #[inline] - pub fn event(&self, event: &Event<'_>) { - if let Some(subscriber) = self.subscriber { - subscriber.event(event); - } - } - - /// Returns a [`SpanRef`] for the parent span of the given [`Event`], if - /// it has a parent. - /// - /// If the event has an explicitly overridden parent, this method returns - /// a reference to that span. If the event's parent is the current span, - /// this returns a reference to the current span, if there is one. If this - /// returns `None`, then either the event's parent was explicitly set to - /// `None`, or the event's parent was defined contextually, but no span - /// is currently entered. - /// - /// Compared to [`Context::current_span`] and [`Context::lookup_current`], - /// this respects overrides provided by the [`Event`]. - /// - /// Compared to [`Event::parent`], this automatically falls back to the contextual - /// span, if required. - /// - /// ```rust - /// use tracing::{Event, Subscriber}; - /// use tracing_subscriber::{ - /// layer::{Context, Layer}, - /// prelude::*, - /// registry::LookupSpan, - /// }; - /// - /// struct PrintingLayer; - /// impl<S> Layer<S> for PrintingLayer - /// where - /// S: Subscriber + for<'lookup> LookupSpan<'lookup>, - /// { - /// fn on_event(&self, event: &Event, ctx: Context<S>) { - /// let span = ctx.event_span(event); - /// println!("Event in span: {:?}", span.map(|s| s.name())); - /// } - /// } - /// - /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || { - /// tracing::info!("no span"); - /// // Prints: Event in span: None - /// - /// let span = tracing::info_span!("span"); - /// tracing::info!(parent: &span, "explicitly specified"); - /// // Prints: Event in span: Some("span") - /// - /// let _guard = span.enter(); - /// tracing::info!("contextual span"); - /// // Prints: Event in span: Some("span") - /// }); - /// ``` - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This requires the wrapped subscriber to - /// implement the <a href="../registry/trait.LookupSpan.html"><code> - /// LookupSpan</code></a> trait. See the documentation on - /// <a href="./struct.Context.html"><code>Context</code>'s - /// declaration</a> for details. - /// </pre> - #[inline] - pub fn event_span(&self, event: &Event<'_>) -> Option<SpanRef<'_, S>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - if event.is_root() { - None - } else if event.is_contextual() { - self.lookup_current() - } else { - // TODO(eliza): this should handle parent IDs - event.parent().and_then(|id| self.span(id)) - } - } - - /// Returns metadata for the span with the given `id`, if it exists. - /// - /// If this returns `None`, then no span exists for that ID (either it has - /// closed or the ID is invalid). - #[inline] - pub fn metadata(&self, id: &span::Id) -> Option<&'static Metadata<'static>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - let span = self.span(id)?; - Some(span.metadata()) - } - - /// Returns [stored data] for the span with the given `id`, if it exists. - /// - /// If this returns `None`, then no span exists for that ID (either it has - /// closed or the ID is invalid). - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This requires the wrapped subscriber to - /// implement the <a href="../registry/trait.LookupSpan.html"><code> - /// LookupSpan</code></a> trait. See the documentation on - /// <a href="./struct.Context.html"><code>Context</code>'s - /// declaration</a> for details. - /// </pre> - /// - /// [stored data]: crate::registry::SpanRef - #[inline] - pub fn span(&self, id: &span::Id) -> Option<registry::SpanRef<'_, S>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - let span = self.subscriber.as_ref()?.span(id)?; - - #[cfg(all(feature = "registry", feature = "std"))] - return span.try_with_filter(self.filter); - - #[cfg(not(feature = "registry"))] - Some(span) - } - - /// Returns `true` if an active span exists for the given `Id`. - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This requires the wrapped subscriber to - /// implement the <a href="../registry/trait.LookupSpan.html"><code> - /// LookupSpan</code></a> trait. See the documentation on - /// <a href="./struct.Context.html"><code>Context</code>'s - /// declaration</a> for details. - /// </pre> - #[inline] - pub fn exists(&self, id: &span::Id) -> bool - where - S: for<'lookup> LookupSpan<'lookup>, - { - self.subscriber.as_ref().and_then(|s| s.span(id)).is_some() - } - - /// Returns [stored data] for the span that the wrapped subscriber considers - /// to be the current. - /// - /// If this returns `None`, then we are not currently within a span. - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This requires the wrapped subscriber to - /// implement the <a href="../registry/trait.LookupSpan.html"><code> - /// LookupSpan</code></a> trait. See the documentation on - /// <a href="./struct.Context.html"><code>Context</code>'s - /// declaration</a> for details. - /// </pre> - /// - /// [stored data]: crate::registry::SpanRef - #[inline] - pub fn lookup_current(&self) -> Option<registry::SpanRef<'_, S>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - let subscriber = *self.subscriber.as_ref()?; - let current = subscriber.current_span(); - let id = current.id()?; - let span = subscriber.span(id); - debug_assert!( - span.is_some(), - "the subscriber should have data for the current span ({:?})!", - id, - ); - - // If we found a span, and our per-layer filter enables it, return that - // span! - #[cfg(all(feature = "registry", feature = "std"))] - { - if let Some(span) = span?.try_with_filter(self.filter) { - Some(span) - } else { - // Otherwise, the span at the *top* of the stack is disabled by - // per-layer filtering, but there may be additional spans in the stack. - // - // Currently, `LookupSpan` doesn't have a nice way of exposing access to - // the whole span stack. However, if we can downcast the innermost - // subscriber to a a `Registry`, we can iterate over its current span - // stack. - // - // TODO(eliza): when https://github.com/tokio-rs/tracing/issues/1459 is - // implemented, change this to use that instead... - self.lookup_current_filtered(subscriber) - } - } - - #[cfg(not(feature = "registry"))] - span - } - - /// Slow path for when the current span is disabled by PLF and we have a - /// registry. - // This is called by `lookup_current` in the case that per-layer filtering - // is in use. `lookup_current` is allowed to be inlined, but this method is - // factored out to prevent the loop and (potentially-recursive) subscriber - // downcasting from being inlined if `lookup_current` is inlined. - #[inline(never)] - #[cfg(all(feature = "registry", feature = "std"))] - fn lookup_current_filtered<'lookup>( - &self, - subscriber: &'lookup S, - ) -> Option<registry::SpanRef<'lookup, S>> - where - S: LookupSpan<'lookup>, - { - let registry = (subscriber as &dyn Subscriber).downcast_ref::<Registry>()?; - registry - .span_stack() - .iter() - .find_map(|id| subscriber.span(id)?.try_with_filter(self.filter)) - } - - /// Returns an iterator over the [stored data] for all the spans in the - /// current context, starting with the specified span and ending with the - /// root of the trace tree and ending with the current span. - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this - /// returns the spans in reverse order (from leaf to root). Use - /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a> - /// in case root-to-leaf ordering is desired. - /// </pre> - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This requires the wrapped subscriber to - /// implement the <a href="../registry/trait.LookupSpan.html"><code> - /// LookupSpan</code></a> trait. See the documentation on - /// <a href="./struct.Context.html"><code>Context</code>'s - /// declaration</a> for details. - /// </pre> - /// - /// [stored data]: crate::registry::SpanRef - pub fn span_scope(&self, id: &span::Id) -> Option<registry::Scope<'_, S>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - Some(self.span(id)?.scope()) - } - - /// Returns an iterator over the [stored data] for all the spans in the - /// current context, starting with the parent span of the specified event, - /// and ending with the root of the trace tree and ending with the current span. - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this - /// returns the spans in reverse order (from leaf to root). Use - /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a> - /// in case root-to-leaf ordering is desired. - /// </pre> - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This requires the wrapped subscriber to - /// implement the <a href="../registry/trait.LookupSpan.html"><code> - /// LookupSpan</code></a> trait. See the documentation on - /// <a href="./struct.Context.html"><code>Context</code>'s - /// declaration</a> for details. - /// </pre> - /// - /// [stored data]: crate::registry::SpanRef - pub fn event_scope(&self, event: &Event<'_>) -> Option<registry::Scope<'_, S>> - where - S: for<'lookup> LookupSpan<'lookup>, - { - Some(self.event_span(event)?.scope()) - } - - #[cfg(all(feature = "registry", feature = "std"))] - pub(crate) fn with_filter(self, filter: FilterId) -> Self { - // If we already have our own `FilterId`, combine it with the provided - // one. That way, the new `FilterId` will consider a span to be disabled - // if it was disabled by the given `FilterId` *or* any `FilterId`s for - // layers "above" us in the stack. - // - // See the doc comment for `FilterId::and` for details. - let filter = self.filter.and(filter); - Self { filter, ..self } - } - - #[cfg(all(feature = "registry", feature = "std"))] - pub(crate) fn is_enabled_for(&self, span: &span::Id, filter: FilterId) -> bool - where - S: for<'lookup> LookupSpan<'lookup>, - { - self.is_enabled_inner(span, filter).unwrap_or(false) - } - - #[cfg(all(feature = "registry", feature = "std"))] - pub(crate) fn if_enabled_for(self, span: &span::Id, filter: FilterId) -> Option<Self> - where - S: for<'lookup> LookupSpan<'lookup>, - { - if self.is_enabled_inner(span, filter)? { - Some(self.with_filter(filter)) - } else { - None - } - } - - #[cfg(all(feature = "registry", feature = "std"))] - fn is_enabled_inner(&self, span: &span::Id, filter: FilterId) -> Option<bool> - where - S: for<'lookup> LookupSpan<'lookup>, - { - Some(self.span(span)?.is_enabled_for(filter)) - } -} - -impl<'a, S> Context<'a, S> { - pub(crate) fn none() -> Self { - Self { - subscriber: None, - - #[cfg(feature = "registry")] - filter: FilterId::none(), - } - } -} - -impl<'a, S> Clone for Context<'a, S> { - #[inline] - fn clone(&self) -> Self { - let subscriber = self.subscriber.as_ref().copied(); - Context { - subscriber, - - #[cfg(all(feature = "registry", feature = "std"))] - filter: self.filter, - } - } -} diff --git a/vendor/tracing-subscriber/src/layer/layered.rs b/vendor/tracing-subscriber/src/layer/layered.rs deleted file mode 100644 index 805ec13dc..000000000 --- a/vendor/tracing-subscriber/src/layer/layered.rs +++ /dev/null @@ -1,520 +0,0 @@ -use tracing_core::{ - metadata::Metadata, - span, - subscriber::{Interest, Subscriber}, - Event, LevelFilter, -}; - -use crate::{ - filter, - layer::{Context, Layer}, - registry::LookupSpan, -}; -#[cfg(all(feature = "registry", feature = "std"))] -use crate::{filter::FilterId, registry::Registry}; -use core::{ - any::{Any, TypeId}, - cmp, fmt, - marker::PhantomData, -}; - -/// A [`Subscriber`] composed of a `Subscriber` wrapped by one or more -/// [`Layer`]s. -/// -/// [`Layer`]: crate::Layer -/// [`Subscriber`]: tracing_core::Subscriber -#[derive(Clone)] -pub struct Layered<L, I, S = I> { - /// The layer. - layer: L, - - /// The inner value that `self.layer` was layered onto. - /// - /// If this is also a `Layer`, then this `Layered` will implement `Layer`. - /// If this is a `Subscriber`, then this `Layered` will implement - /// `Subscriber` instead. - inner: I, - - // These booleans are used to determine how to combine `Interest`s and max - // level hints when per-layer filters are in use. - /// Is `self.inner` a `Registry`? - /// - /// If so, when combining `Interest`s, we want to "bubble up" its - /// `Interest`. - inner_is_registry: bool, - - /// Does `self.layer` have per-layer filters? - /// - /// This will be true if: - /// - `self.inner` is a `Filtered`. - /// - `self.inner` is a tree of `Layered`s where _all_ arms of those - /// `Layered`s have per-layer filters. - /// - /// Otherwise, if it's a `Layered` with one per-layer filter in one branch, - /// but a non-per-layer-filtered layer in the other branch, this will be - /// _false_, because the `Layered` is already handling the combining of - /// per-layer filter `Interest`s and max level hints with its non-filtered - /// `Layer`. - has_layer_filter: bool, - - /// Does `self.inner` have per-layer filters? - /// - /// This is determined according to the same rules as - /// `has_layer_filter` above. - inner_has_layer_filter: bool, - _s: PhantomData<fn(S)>, -} - -// === impl Layered === - -impl<L, S> Layered<L, S> -where - L: Layer<S>, - S: Subscriber, -{ - /// Returns `true` if this [`Subscriber`] is the same type as `T`. - pub fn is<T: Any>(&self) -> bool { - self.downcast_ref::<T>().is_some() - } - - /// Returns some reference to this [`Subscriber`] value if it is of type `T`, - /// or `None` if it isn't. - pub fn downcast_ref<T: Any>(&self) -> Option<&T> { - unsafe { - let raw = self.downcast_raw(TypeId::of::<T>())?; - if raw.is_null() { - None - } else { - Some(&*(raw as *const T)) - } - } - } -} - -impl<L, S> Subscriber for Layered<L, S> -where - L: Layer<S>, - S: Subscriber, -{ - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.pick_interest(self.layer.register_callsite(metadata), || { - self.inner.register_callsite(metadata) - }) - } - - fn enabled(&self, metadata: &Metadata<'_>) -> bool { - if self.layer.enabled(metadata, self.ctx()) { - // if the outer layer enables the callsite metadata, ask the subscriber. - self.inner.enabled(metadata) - } else { - // otherwise, the callsite is disabled by the layer - - // If per-layer filters are in use, and we are short-circuiting - // (rather than calling into the inner type), clear the current - // per-layer filter `enabled` state. - #[cfg(feature = "registry")] - filter::FilterState::clear_enabled(); - - false - } - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - self.pick_level_hint(self.layer.max_level_hint(), self.inner.max_level_hint()) - } - - fn new_span(&self, span: &span::Attributes<'_>) -> span::Id { - let id = self.inner.new_span(span); - self.layer.on_new_span(span, &id, self.ctx()); - id - } - - fn record(&self, span: &span::Id, values: &span::Record<'_>) { - self.inner.record(span, values); - self.layer.on_record(span, values, self.ctx()); - } - - fn record_follows_from(&self, span: &span::Id, follows: &span::Id) { - self.inner.record_follows_from(span, follows); - self.layer.on_follows_from(span, follows, self.ctx()); - } - - fn event_enabled(&self, event: &Event<'_>) -> bool { - if self.layer.event_enabled(event, self.ctx()) { - // if the outer layer enables the event, ask the inner subscriber. - self.inner.event_enabled(event) - } else { - // otherwise, the event is disabled by this layer - false - } - } - - fn event(&self, event: &Event<'_>) { - self.inner.event(event); - self.layer.on_event(event, self.ctx()); - } - - fn enter(&self, span: &span::Id) { - self.inner.enter(span); - self.layer.on_enter(span, self.ctx()); - } - - fn exit(&self, span: &span::Id) { - self.inner.exit(span); - self.layer.on_exit(span, self.ctx()); - } - - fn clone_span(&self, old: &span::Id) -> span::Id { - let new = self.inner.clone_span(old); - if &new != old { - self.layer.on_id_change(old, &new, self.ctx()) - }; - new - } - - #[inline] - fn drop_span(&self, id: span::Id) { - self.try_close(id); - } - - fn try_close(&self, id: span::Id) -> bool { - #[cfg(all(feature = "registry", feature = "std"))] - let subscriber = &self.inner as &dyn Subscriber; - #[cfg(all(feature = "registry", feature = "std"))] - let mut guard = subscriber - .downcast_ref::<Registry>() - .map(|registry| registry.start_close(id.clone())); - if self.inner.try_close(id.clone()) { - // If we have a registry's close guard, indicate that the span is - // closing. - #[cfg(all(feature = "registry", feature = "std"))] - { - if let Some(g) = guard.as_mut() { - g.set_closing() - }; - } - - self.layer.on_close(id, self.ctx()); - true - } else { - false - } - } - - #[inline] - fn current_span(&self) -> span::Current { - self.inner.current_span() - } - - #[doc(hidden)] - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - // Unlike the implementation of `Layer` for `Layered`, we don't have to - // handle the "magic PLF downcast marker" here. If a `Layered` - // implements `Subscriber`, we already know that the `inner` branch is - // going to contain something that doesn't have per-layer filters (the - // actual root `Subscriber`). Thus, a `Layered` that implements - // `Subscriber` will always be propagating the root subscriber's - // `Interest`/level hint, even if it includes a `Layer` that has - // per-layer filters, because it will only ever contain layers where - // _one_ child has per-layer filters. - // - // The complex per-layer filter detection logic is only relevant to - // *trees* of layers, which involve the `Layer` implementation for - // `Layered`, not *lists* of layers, where every `Layered` implements - // `Subscriber`. Of course, a linked list can be thought of as a - // degenerate tree...but luckily, we are able to make a type-level - // distinction between individual `Layered`s that are definitely - // list-shaped (their inner child implements `Subscriber`), and - // `Layered`s that might be tree-shaped (the inner child is also a - // `Layer`). - - // If downcasting to `Self`, return a pointer to `self`. - if id == TypeId::of::<Self>() { - return Some(self as *const _ as *const ()); - } - - self.layer - .downcast_raw(id) - .or_else(|| self.inner.downcast_raw(id)) - } -} - -impl<S, A, B> Layer<S> for Layered<A, B, S> -where - A: Layer<S>, - B: Layer<S>, - S: Subscriber, -{ - fn on_layer(&mut self, subscriber: &mut S) { - self.layer.on_layer(subscriber); - self.inner.on_layer(subscriber); - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.pick_interest(self.layer.register_callsite(metadata), || { - self.inner.register_callsite(metadata) - }) - } - - fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { - if self.layer.enabled(metadata, ctx.clone()) { - // if the outer subscriber enables the callsite metadata, ask the inner layer. - self.inner.enabled(metadata, ctx) - } else { - // otherwise, the callsite is disabled by this layer - false - } - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - self.pick_level_hint(self.layer.max_level_hint(), self.inner.max_level_hint()) - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - self.inner.on_new_span(attrs, id, ctx.clone()); - self.layer.on_new_span(attrs, id, ctx); - } - - #[inline] - fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - self.inner.on_record(span, values, ctx.clone()); - self.layer.on_record(span, values, ctx); - } - - #[inline] - fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, S>) { - self.inner.on_follows_from(span, follows, ctx.clone()); - self.layer.on_follows_from(span, follows, ctx); - } - - #[inline] - fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool { - if self.layer.event_enabled(event, ctx.clone()) { - // if the outer layer enables the event, ask the inner subscriber. - self.inner.event_enabled(event, ctx) - } else { - // otherwise, the event is disabled by this layer - false - } - } - - #[inline] - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { - self.inner.on_event(event, ctx.clone()); - self.layer.on_event(event, ctx); - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - self.inner.on_enter(id, ctx.clone()); - self.layer.on_enter(id, ctx); - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - self.inner.on_exit(id, ctx.clone()); - self.layer.on_exit(id, ctx); - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - self.inner.on_close(id.clone(), ctx.clone()); - self.layer.on_close(id, ctx); - } - - #[inline] - fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: Context<'_, S>) { - self.inner.on_id_change(old, new, ctx.clone()); - self.layer.on_id_change(old, new, ctx); - } - - #[doc(hidden)] - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - match id { - // If downcasting to `Self`, return a pointer to `self`. - id if id == TypeId::of::<Self>() => Some(self as *const _ as *const ()), - - // Oh, we're looking for per-layer filters! - // - // This should only happen if we are inside of another `Layered`, - // and it's trying to determine how it should combine `Interest`s - // and max level hints. - // - // In that case, this `Layered` should be considered to be - // "per-layer filtered" if *both* the outer layer and the inner - // layer/subscriber have per-layer filters. Otherwise, this `Layered - // should *not* be considered per-layer filtered (even if one or the - // other has per layer filters). If only one `Layer` is per-layer - // filtered, *this* `Layered` will handle aggregating the `Interest` - // and level hints on behalf of its children, returning the - // aggregate (which is the value from the &non-per-layer-filtered* - // child). - // - // Yes, this rule *is* slightly counter-intuitive, but it's - // necessary due to a weird edge case that can occur when two - // `Layered`s where one side is per-layer filtered and the other - // isn't are `Layered` together to form a tree. If we didn't have - // this rule, we would actually end up *ignoring* `Interest`s from - // the non-per-layer-filtered layers, since both branches would - // claim to have PLF. - // - // If you don't understand this...that's fine, just don't mess with - // it. :) - id if filter::is_plf_downcast_marker(id) => { - self.layer.downcast_raw(id).and(self.inner.downcast_raw(id)) - } - - // Otherwise, try to downcast both branches normally... - _ => self - .layer - .downcast_raw(id) - .or_else(|| self.inner.downcast_raw(id)), - } - } -} - -impl<'a, L, S> LookupSpan<'a> for Layered<L, S> -where - S: Subscriber + LookupSpan<'a>, -{ - type Data = S::Data; - - fn span_data(&'a self, id: &span::Id) -> Option<Self::Data> { - self.inner.span_data(id) - } - - #[cfg(all(feature = "registry", feature = "std"))] - fn register_filter(&mut self) -> FilterId { - self.inner.register_filter() - } -} - -impl<L, S> Layered<L, S> -where - S: Subscriber, -{ - fn ctx(&self) -> Context<'_, S> { - Context::new(&self.inner) - } -} - -impl<A, B, S> Layered<A, B, S> -where - A: Layer<S>, - S: Subscriber, -{ - pub(super) fn new(layer: A, inner: B, inner_has_layer_filter: bool) -> Self { - #[cfg(all(feature = "registry", feature = "std"))] - let inner_is_registry = TypeId::of::<S>() == TypeId::of::<crate::registry::Registry>(); - - #[cfg(not(all(feature = "registry", feature = "std")))] - let inner_is_registry = false; - - let inner_has_layer_filter = inner_has_layer_filter || inner_is_registry; - let has_layer_filter = filter::layer_has_plf(&layer); - Self { - layer, - inner, - has_layer_filter, - inner_has_layer_filter, - inner_is_registry, - _s: PhantomData, - } - } - - fn pick_interest(&self, outer: Interest, inner: impl FnOnce() -> Interest) -> Interest { - if self.has_layer_filter { - return inner(); - } - - // If the outer layer has disabled the callsite, return now so that - // the inner layer/subscriber doesn't get its hopes up. - if outer.is_never() { - // If per-layer filters are in use, and we are short-circuiting - // (rather than calling into the inner type), clear the current - // per-layer filter interest state. - #[cfg(feature = "registry")] - filter::FilterState::take_interest(); - - return outer; - } - - // The `inner` closure will call `inner.register_callsite()`. We do this - // before the `if` statement to ensure that the inner subscriber is - // informed that the callsite exists regardless of the outer layer's - // filtering decision. - let inner = inner(); - if outer.is_sometimes() { - // if this interest is "sometimes", return "sometimes" to ensure that - // filters are reevaluated. - return outer; - } - - // If there is a per-layer filter in the `inner` stack, and it returns - // `never`, change the interest to `sometimes`, because the `outer` - // layer didn't return `never`. This means that _some_ layer still wants - // to see that callsite, even though the inner stack's per-layer filter - // didn't want it. Therefore, returning `sometimes` will ensure - // `enabled` is called so that the per-layer filter can skip that - // span/event, while the `outer` layer still gets to see it. - if inner.is_never() && self.inner_has_layer_filter { - return Interest::sometimes(); - } - - // otherwise, allow the inner subscriber or collector to weigh in. - inner - } - - fn pick_level_hint( - &self, - outer_hint: Option<LevelFilter>, - inner_hint: Option<LevelFilter>, - ) -> Option<LevelFilter> { - if self.inner_is_registry { - return outer_hint; - } - - if self.has_layer_filter && self.inner_has_layer_filter { - return Some(cmp::max(outer_hint?, inner_hint?)); - } - - if self.has_layer_filter && inner_hint.is_none() { - return None; - } - - if self.inner_has_layer_filter && outer_hint.is_none() { - return None; - } - - cmp::max(outer_hint, inner_hint) - } -} - -impl<A, B, S> fmt::Debug for Layered<A, B, S> -where - A: fmt::Debug, - B: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[cfg(all(feature = "registry", feature = "std"))] - let alt = f.alternate(); - let mut s = f.debug_struct("Layered"); - // These additional fields are more verbose and usually only necessary - // for internal debugging purposes, so only print them if alternate mode - // is enabled. - - #[cfg(all(feature = "registry", feature = "std"))] - { - if alt { - s.field("inner_is_registry", &self.inner_is_registry) - .field("has_layer_filter", &self.has_layer_filter) - .field("inner_has_layer_filter", &self.inner_has_layer_filter); - } - } - - s.field("layer", &self.layer) - .field("inner", &self.inner) - .finish() - } -} diff --git a/vendor/tracing-subscriber/src/layer/mod.rs b/vendor/tracing-subscriber/src/layer/mod.rs deleted file mode 100644 index 24b853323..000000000 --- a/vendor/tracing-subscriber/src/layer/mod.rs +++ /dev/null @@ -1,1798 +0,0 @@ -//! The [`Layer`] trait, a composable abstraction for building [`Subscriber`]s. -//! -//! The [`Subscriber`] trait in `tracing-core` represents the _complete_ set of -//! functionality required to consume `tracing` instrumentation. This means that -//! a single `Subscriber` instance is a self-contained implementation of a -//! complete strategy for collecting traces; but it _also_ means that the -//! `Subscriber` trait cannot easily be composed with other `Subscriber`s. -//! -//! In particular, [`Subscriber`]s are responsible for generating [span IDs] and -//! assigning them to spans. Since these IDs must uniquely identify a span -//! within the context of the current trace, this means that there may only be -//! a single `Subscriber` for a given thread at any point in time — -//! otherwise, there would be no authoritative source of span IDs. -//! -//! On the other hand, the majority of the [`Subscriber`] trait's functionality -//! is composable: any number of subscribers may _observe_ events, span entry -//! and exit, and so on, provided that there is a single authoritative source of -//! span IDs. The [`Layer`] trait represents this composable subset of the -//! [`Subscriber`] behavior; it can _observe_ events and spans, but does not -//! assign IDs. -//! -//! # Composing Layers -//! -//! Since a [`Layer`] does not implement a complete strategy for collecting -//! traces, it must be composed with a `Subscriber` in order to be used. The -//! [`Layer`] trait is generic over a type parameter (called `S` in the trait -//! definition), representing the types of `Subscriber` they can be composed -//! with. Thus, a [`Layer`] may be implemented that will only compose with a -//! particular `Subscriber` implementation, or additional trait bounds may be -//! added to constrain what types implementing `Subscriber` a `Layer` can wrap. -//! -//! `Layer`s may be added to a `Subscriber` by using the [`SubscriberExt::with`] -//! method, which is provided by `tracing-subscriber`'s [prelude]. This method -//! returns a [`Layered`] struct that implements `Subscriber` by composing the -//! `Layer` with the `Subscriber`. -//! -//! For example: -//! ```rust -//! use tracing_subscriber::Layer; -//! use tracing_subscriber::prelude::*; -//! use tracing::Subscriber; -//! -//! pub struct MyLayer { -//! // ... -//! } -//! -//! impl<S: Subscriber> Layer<S> for MyLayer { -//! // ... -//! } -//! -//! pub struct MySubscriber { -//! // ... -//! } -//! -//! # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event}; -//! impl Subscriber for MySubscriber { -//! // ... -//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) } -//! # fn record(&self, _: &Id, _: &Record) {} -//! # fn event(&self, _: &Event) {} -//! # fn record_follows_from(&self, _: &Id, _: &Id) {} -//! # fn enabled(&self, _: &Metadata) -> bool { false } -//! # fn enter(&self, _: &Id) {} -//! # fn exit(&self, _: &Id) {} -//! } -//! # impl MyLayer { -//! # fn new() -> Self { Self {} } -//! # } -//! # impl MySubscriber { -//! # fn new() -> Self { Self { }} -//! # } -//! -//! let subscriber = MySubscriber::new() -//! .with(MyLayer::new()); -//! -//! tracing::subscriber::set_global_default(subscriber); -//! ``` -//! -//! Multiple `Layer`s may be composed in the same manner: -//! ```rust -//! # use tracing_subscriber::{Layer, layer::SubscriberExt}; -//! # use tracing::Subscriber; -//! pub struct MyOtherLayer { -//! // ... -//! } -//! -//! impl<S: Subscriber> Layer<S> for MyOtherLayer { -//! // ... -//! } -//! -//! pub struct MyThirdLayer { -//! // ... -//! } -//! -//! impl<S: Subscriber> Layer<S> for MyThirdLayer { -//! // ... -//! } -//! # pub struct MyLayer {} -//! # impl<S: Subscriber> Layer<S> for MyLayer {} -//! # pub struct MySubscriber { } -//! # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event}; -//! # impl Subscriber for MySubscriber { -//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) } -//! # fn record(&self, _: &Id, _: &Record) {} -//! # fn event(&self, _: &Event) {} -//! # fn record_follows_from(&self, _: &Id, _: &Id) {} -//! # fn enabled(&self, _: &Metadata) -> bool { false } -//! # fn enter(&self, _: &Id) {} -//! # fn exit(&self, _: &Id) {} -//! } -//! # impl MyLayer { -//! # fn new() -> Self { Self {} } -//! # } -//! # impl MyOtherLayer { -//! # fn new() -> Self { Self {} } -//! # } -//! # impl MyThirdLayer { -//! # fn new() -> Self { Self {} } -//! # } -//! # impl MySubscriber { -//! # fn new() -> Self { Self { }} -//! # } -//! -//! let subscriber = MySubscriber::new() -//! .with(MyLayer::new()) -//! .with(MyOtherLayer::new()) -//! .with(MyThirdLayer::new()); -//! -//! tracing::subscriber::set_global_default(subscriber); -//! ``` -//! -//! The [`Layer::with_subscriber`] constructs the [`Layered`] type from a -//! [`Layer`] and [`Subscriber`], and is called by [`SubscriberExt::with`]. In -//! general, it is more idiomatic to use [`SubscriberExt::with`], and treat -//! [`Layer::with_subscriber`] as an implementation detail, as `with_subscriber` -//! calls must be nested, leading to less clear code for the reader. -//! -//! ## Runtime Configuration With `Layer`s -//! -//! In some cases, a particular [`Layer`] may be enabled or disabled based on -//! runtime configuration. This can introduce challenges, because the type of a -//! layered [`Subscriber`] depends on which layers are added to it: if an `if` -//! or `match` expression adds some [`Layer`] implementation in one branch, -//! and other layers in another, the [`Subscriber`] values returned by those -//! branches will have different types. For example, the following _will not_ -//! work: -//! -//! ```compile_fail -//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> { -//! # struct Config { -//! # is_prod: bool, -//! # path: &'static str, -//! # } -//! # let cfg = Config { is_prod: false, path: "debug.log" }; -//! use std::fs::File; -//! use tracing_subscriber::{Registry, prelude::*}; -//! -//! let stdout_log = tracing_subscriber::fmt::layer().pretty(); -//! let subscriber = Registry::default().with(stdout_log); -//! -//! // The compile error will occur here because the if and else -//! // branches have different (and therefore incompatible) types. -//! let subscriber = if cfg.is_prod { -//! let file = File::create(cfg.path)?; -//! let layer = tracing_subscriber::fmt::layer() -//! .json() -//! .with_writer(Arc::new(file)); -//! layer.with(subscriber) -//! } else { -//! layer -//! }; -//! -//! tracing::subscriber::set_global_default(subscriber) -//! .expect("Unable to set global subscriber"); -//! # Ok(()) } -//! ``` -//! -//! However, a [`Layer`] wrapped in an [`Option`] [also implements the `Layer` -//! trait][option-impl]. This allows individual layers to be enabled or disabled at -//! runtime while always producing a [`Subscriber`] of the same type. For -//! example: -//! -//! ``` -//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> { -//! # struct Config { -//! # is_prod: bool, -//! # path: &'static str, -//! # } -//! # let cfg = Config { is_prod: false, path: "debug.log" }; -//! use std::fs::File; -//! use tracing_subscriber::{Registry, prelude::*}; -//! -//! let stdout_log = tracing_subscriber::fmt::layer().pretty(); -//! let subscriber = Registry::default().with(stdout_log); -//! -//! // if `cfg.is_prod` is true, also log JSON-formatted logs to a file. -//! let json_log = if cfg.is_prod { -//! let file = File::create(cfg.path)?; -//! let json_log = tracing_subscriber::fmt::layer() -//! .json() -//! .with_writer(file); -//! Some(json_log) -//! } else { -//! None -//! }; -//! -//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer -//! // will do nothing. However, the subscriber will still have the same type -//! // regardless of whether the `Option`'s value is `None` or `Some`. -//! let subscriber = subscriber.with(json_log); -//! -//! tracing::subscriber::set_global_default(subscriber) -//! .expect("Unable to set global subscriber"); -//! # Ok(()) } -//! ``` -//! -//! If a [`Layer`] may be one of several different types, note that [`Box<dyn -//! Layer<S> + Send + Sync>` implements `Layer`][box-impl]. -//! This may be used to erase the type of a [`Layer`]. -//! -//! For example, a function that configures a [`Layer`] to log to one of -//! several outputs might return a `Box<dyn Layer<S> + Send + Sync + 'static>`: -//! ``` -//! use tracing_subscriber::{ -//! Layer, -//! registry::LookupSpan, -//! prelude::*, -//! }; -//! use std::{path::PathBuf, fs::File, io}; -//! -//! /// Configures whether logs are emitted to a file, to stdout, or to stderr. -//! pub enum LogConfig { -//! File(PathBuf), -//! Stdout, -//! Stderr, -//! } -//! -//! impl LogConfig { -//! pub fn layer<S>(self) -> Box<dyn Layer<S> + Send + Sync + 'static> -//! where -//! S: tracing_core::Subscriber, -//! for<'a> S: LookupSpan<'a>, -//! { -//! // Shared configuration regardless of where logs are output to. -//! let fmt = tracing_subscriber::fmt::layer() -//! .with_target(true) -//! .with_thread_names(true); -//! -//! // Configure the writer based on the desired log target: -//! match self { -//! LogConfig::File(path) => { -//! let file = File::create(path).expect("failed to create log file"); -//! Box::new(fmt.with_writer(file)) -//! }, -//! LogConfig::Stdout => Box::new(fmt.with_writer(io::stdout)), -//! LogConfig::Stderr => Box::new(fmt.with_writer(io::stderr)), -//! } -//! } -//! } -//! -//! let config = LogConfig::Stdout; -//! tracing_subscriber::registry() -//! .with(config.layer()) -//! .init(); -//! ``` -//! -//! The [`Layer::boxed`] method is provided to make boxing a `Layer` -//! more convenient, but [`Box::new`] may be used as well. -//! -//! When the number of `Layer`s varies at runtime, note that a -//! [`Vec<L> where L: Layer` also implements `Layer`][vec-impl]. This -//! can be used to add a variable number of `Layer`s to a `Subscriber`: -//! -//! ``` -//! use tracing_subscriber::{Layer, prelude::*}; -//! struct MyLayer { -//! // ... -//! } -//! # impl MyLayer { fn new() -> Self { Self {} }} -//! -//! impl<S: tracing_core::Subscriber> Layer<S> for MyLayer { -//! // ... -//! } -//! -//! /// Returns how many layers we need -//! fn how_many_layers() -> usize { -//! // ... -//! # 3 -//! } -//! -//! // Create a variable-length `Vec` of layers -//! let mut layers = Vec::new(); -//! for _ in 0..how_many_layers() { -//! layers.push(MyLayer::new()); -//! } -//! -//! tracing_subscriber::registry() -//! .with(layers) -//! .init(); -//! ``` -//! -//! If a variable number of `Layer` is needed and those `Layer`s have -//! different types, a `Vec` of [boxed `Layer` trait objects][box-impl] may -//! be used. For example: -//! -//! ``` -//! use tracing_subscriber::{filter::LevelFilter, Layer, prelude::*}; -//! use std::fs::File; -//! # fn main() -> Result<(), Box<dyn std::error::Error>> { -//! struct Config { -//! enable_log_file: bool, -//! enable_stdout: bool, -//! enable_stderr: bool, -//! // ... -//! } -//! # impl Config { -//! # fn from_config_file()-> Result<Self, Box<dyn std::error::Error>> { -//! # // don't enable the log file so that the example doesn't actually create it -//! # Ok(Self { enable_log_file: false, enable_stdout: true, enable_stderr: true }) -//! # } -//! # } -//! -//! let cfg = Config::from_config_file()?; -//! -//! // Based on our dynamically loaded config file, create any number of layers: -//! let mut layers = Vec::new(); -//! -//! if cfg.enable_log_file { -//! let file = File::create("myapp.log")?; -//! let layer = tracing_subscriber::fmt::layer() -//! .with_thread_names(true) -//! .with_target(true) -//! .json() -//! .with_writer(file) -//! // Box the layer as a type-erased trait object, so that it can -//! // be pushed to the `Vec`. -//! .boxed(); -//! layers.push(layer); -//! } -//! -//! if cfg.enable_stdout { -//! let layer = tracing_subscriber::fmt::layer() -//! .pretty() -//! .with_filter(LevelFilter::INFO) -//! // Box the layer as a type-erased trait object, so that it can -//! // be pushed to the `Vec`. -//! .boxed(); -//! layers.push(layer); -//! } -//! -//! if cfg.enable_stdout { -//! let layer = tracing_subscriber::fmt::layer() -//! .with_target(false) -//! .with_filter(LevelFilter::WARN) -//! // Box the layer as a type-erased trait object, so that it can -//! // be pushed to the `Vec`. -//! .boxed(); -//! layers.push(layer); -//! } -//! -//! tracing_subscriber::registry() -//! .with(layers) -//! .init(); -//!# Ok(()) } -//! ``` -//! -//! Finally, if the number of layers _changes_ at runtime, a `Vec` of -//! subscribers can be used alongside the [`reload`](crate::reload) module to -//! add or remove subscribers dynamically at runtime. -//! -//! [option-impl]: Layer#impl-Layer<S>-for-Option<L> -//! [box-impl]: Layer#impl-Layer%3CS%3E-for-Box%3Cdyn%20Layer%3CS%3E%20+%20Send%20+%20Sync%3E -//! [vec-impl]: Layer#impl-Layer<S>-for-Vec<L> -//! [prelude]: crate::prelude -//! -//! # Recording Traces -//! -//! The [`Layer`] trait defines a set of methods for consuming notifications from -//! tracing instrumentation, which are generally equivalent to the similarly -//! named methods on [`Subscriber`]. Unlike [`Subscriber`], the methods on -//! `Layer` are additionally passed a [`Context`] type, which exposes additional -//! information provided by the wrapped subscriber (such as [the current span]) -//! to the layer. -//! -//! # Filtering with `Layer`s -//! -//! As well as strategies for handling trace events, the `Layer` trait may also -//! be used to represent composable _filters_. This allows the determination of -//! what spans and events should be recorded to be decoupled from _how_ they are -//! recorded: a filtering layer can be applied to other layers or -//! subscribers. `Layer`s can be used to implement _global filtering_, where a -//! `Layer` provides a filtering strategy for the entire subscriber. -//! Additionally, individual recording `Layer`s or sets of `Layer`s may be -//! combined with _per-layer filters_ that control what spans and events are -//! recorded by those layers. -//! -//! ## Global Filtering -//! -//! A `Layer` that implements a filtering strategy should override the -//! [`register_callsite`] and/or [`enabled`] methods. It may also choose to implement -//! methods such as [`on_enter`], if it wishes to filter trace events based on -//! the current span context. -//! -//! Note that the [`Layer::register_callsite`] and [`Layer::enabled`] methods -//! determine whether a span or event is enabled *globally*. Thus, they should -//! **not** be used to indicate whether an individual layer wishes to record a -//! particular span or event. Instead, if a layer is only interested in a subset -//! of trace data, but does *not* wish to disable other spans and events for the -//! rest of the layer stack should ignore those spans and events in its -//! notification methods. -//! -//! The filtering methods on a stack of `Layer`s are evaluated in a top-down -//! order, starting with the outermost `Layer` and ending with the wrapped -//! [`Subscriber`]. If any layer returns `false` from its [`enabled`] method, or -//! [`Interest::never()`] from its [`register_callsite`] method, filter -//! evaluation will short-circuit and the span or event will be disabled. -//! -//! ### Enabling Interest -//! -//! Whenever an tracing event (or span) is emitted, it goes through a number of -//! steps to determine how and how much it should be processed. The earlier an -//! event is disabled, the less work has to be done to process the event, so -//! `Layer`s that implement filtering should attempt to disable unwanted -//! events as early as possible. In order, each event checks: -//! -//! - [`register_callsite`], once per callsite (roughly: once per time that -//! `event!` or `span!` is written in the source code; this is cached at the -//! callsite). See [`Subscriber::register_callsite`] and -//! [`tracing_core::callsite`] for a summary of how this behaves. -//! - [`enabled`], once per emitted event (roughly: once per time that `event!` -//! or `span!` is *executed*), and only if `register_callsite` regesters an -//! [`Interest::sometimes`]. This is the main customization point to globally -//! filter events based on their [`Metadata`]. If an event can be disabled -//! based only on [`Metadata`], it should be, as this allows the construction -//! of the actual `Event`/`Span` to be skipped. -//! - For events only (and not spans), [`event_enabled`] is called just before -//! processing the event. This gives layers one last chance to say that -//! an event should be filtered out, now that the event's fields are known. -//! -//! ## Per-Layer Filtering -//! -//! **Note**: per-layer filtering APIs currently require the [`"registry"` crate -//! feature flag][feat] to be enabled. -//! -//! Sometimes, it may be desirable for one `Layer` to record a particular subset -//! of spans and events, while a different subset of spans and events are -//! recorded by other `Layer`s. For example: -//! -//! - A layer that records metrics may wish to observe only events including -//! particular tracked values, while a logging layer ignores those events. -//! - If recording a distributed trace is expensive, it might be desirable to -//! only send spans with `INFO` and lower verbosity to the distributed tracing -//! system, while logging more verbose spans to a file. -//! - Spans and events with a particular target might be recorded differently -//! from others, such as by generating an HTTP access log from a span that -//! tracks the lifetime of an HTTP request. -//! -//! The [`Filter`] trait is used to control what spans and events are -//! observed by an individual `Layer`, while still allowing other `Layer`s to -//! potentially record them. The [`Layer::with_filter`] method combines a -//! `Layer` with a [`Filter`], returning a [`Filtered`] layer. -//! -//! This crate's [`filter`] module provides a number of types which implement -//! the [`Filter`] trait, such as [`LevelFilter`], [`Targets`], and -//! [`FilterFn`]. These [`Filter`]s provide ready-made implementations of -//! common forms of filtering. For custom filtering policies, the [`FilterFn`] -//! and [`DynFilterFn`] types allow implementing a [`Filter`] with a closure or -//! function pointer. In addition, when more control is required, the [`Filter`] -//! trait may also be implemented for user-defined types. -//! -//! <pre class="compile_fail" style="white-space:normal;font:inherit;"> -//! <strong>Warning</strong>: Currently, the <a href="../struct.Registry.html"> -//! <code>Registry</code></a> type defined in this crate is the only root -//! <code>Subscriber</code> capable of supporting <code>Layer</code>s with -//! per-layer filters. In the future, new APIs will be added to allow other -//! root <code>Subscriber</code>s to support per-layer filters. -//! </pre> -//! -//! For example, to generate an HTTP access log based on spans with -//! the `http_access` target, while logging other spans and events to -//! standard out, a [`Filter`] can be added to the access log layer: -//! -//! ``` -//! use tracing_subscriber::{filter, prelude::*}; -//! -//! // Generates an HTTP access log. -//! let access_log = // ... -//! # filter::LevelFilter::INFO; -//! -//! // Add a filter to the access log layer so that it only observes -//! // spans and events with the `http_access` target. -//! let access_log = access_log.with_filter(filter::filter_fn(|metadata| { -//! // Returns `true` if and only if the span or event's target is -//! // "http_access". -//! metadata.target() == "http_access" -//! })); -//! -//! // A general-purpose logging layer. -//! let fmt_layer = tracing_subscriber::fmt::layer(); -//! -//! // Build a subscriber that combines the access log and stdout log -//! // layers. -//! tracing_subscriber::registry() -//! .with(fmt_layer) -//! .with(access_log) -//! .init(); -//! ``` -//! -//! Multiple layers can have their own, separate per-layer filters. A span or -//! event will be recorded if it is enabled by _any_ per-layer filter, but it -//! will be skipped by the layers whose filters did not enable it. Building on -//! the previous example: -//! -//! ``` -//! use tracing_subscriber::{filter::{filter_fn, LevelFilter}, prelude::*}; -//! -//! let access_log = // ... -//! # LevelFilter::INFO; -//! let fmt_layer = tracing_subscriber::fmt::layer(); -//! -//! tracing_subscriber::registry() -//! // Add the filter for the "http_access" target to the access -//! // log layer, like before. -//! .with(access_log.with_filter(filter_fn(|metadata| { -//! metadata.target() == "http_access" -//! }))) -//! // Add a filter for spans and events with the INFO level -//! // and below to the logging layer. -//! .with(fmt_layer.with_filter(LevelFilter::INFO)) -//! .init(); -//! -//! // Neither layer will observe this event -//! tracing::debug!(does_anyone_care = false, "a tree fell in the forest"); -//! -//! // This event will be observed by the logging layer, but not -//! // by the access log layer. -//! tracing::warn!(dose_roentgen = %3.8, "not great, but not terrible"); -//! -//! // This event will be observed only by the access log layer. -//! tracing::trace!(target: "http_access", "HTTP request started"); -//! -//! // Both layers will observe this event. -//! tracing::error!(target: "http_access", "HTTP request failed with a very bad error!"); -//! ``` -//! -//! A per-layer filter can be applied to multiple [`Layer`]s at a time, by -//! combining them into a [`Layered`] layer using [`Layer::and_then`], and then -//! calling [`Layer::with_filter`] on the resulting [`Layered`] layer. -//! -//! Consider the following: -//! - `layer_a` and `layer_b`, which should only receive spans and events at -//! the [`INFO`] [level] and above. -//! - A third layer, `layer_c`, which should receive spans and events at -//! the [`DEBUG`] [level] as well. -//! The layers and filters would be composed thusly: -//! -//! ``` -//! use tracing_subscriber::{filter::LevelFilter, prelude::*}; -//! -//! let layer_a = // ... -//! # LevelFilter::INFO; -//! let layer_b = // ... -//! # LevelFilter::INFO; -//! let layer_c = // ... -//! # LevelFilter::INFO; -//! -//! let info_layers = layer_a -//! // Combine `layer_a` and `layer_b` into a `Layered` layer: -//! .and_then(layer_b) -//! // ...and then add an `INFO` `LevelFilter` to that layer: -//! .with_filter(LevelFilter::INFO); -//! -//! tracing_subscriber::registry() -//! // Add `layer_c` with a `DEBUG` filter. -//! .with(layer_c.with_filter(LevelFilter::DEBUG)) -//! .with(info_layers) -//! .init(); -//!``` -//! -//! If a [`Filtered`] [`Layer`] is combined with another [`Layer`] -//! [`Layer::and_then`], and a filter is added to the [`Layered`] layer, that -//! layer will be filtered by *both* the inner filter and the outer filter. -//! Only spans and events that are enabled by *both* filters will be -//! observed by that layer. This can be used to implement complex filtering -//! trees. -//! -//! As an example, consider the following constraints: -//! - Suppose that a particular [target] is used to indicate events that -//! should be counted as part of a metrics system, which should be only -//! observed by a layer that collects metrics. -//! - A log of high-priority events ([`INFO`] and above) should be logged -//! to stdout, while more verbose events should be logged to a debugging log file. -//! - Metrics-focused events should *not* be included in either log output. -//! -//! In that case, it is possible to apply a filter to both logging layers to -//! exclude the metrics events, while additionally adding a [`LevelFilter`] -//! to the stdout log: -//! -//! ``` -//! # // wrap this in a function so we don't actually create `debug.log` when -//! # // running the doctests.. -//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> { -//! use tracing_subscriber::{filter, prelude::*}; -//! use std::{fs::File, sync::Arc}; -//! -//! // A layer that logs events to stdout using the human-readable "pretty" -//! // format. -//! let stdout_log = tracing_subscriber::fmt::layer() -//! .pretty(); -//! -//! // A layer that logs events to a file. -//! let file = File::create("debug.log")?; -//! let debug_log = tracing_subscriber::fmt::layer() -//! .with_writer(Arc::new(file)); -//! -//! // A layer that collects metrics using specific events. -//! let metrics_layer = /* ... */ filter::LevelFilter::INFO; -//! -//! tracing_subscriber::registry() -//! .with( -//! stdout_log -//! // Add an `INFO` filter to the stdout logging layer -//! .with_filter(filter::LevelFilter::INFO) -//! // Combine the filtered `stdout_log` layer with the -//! // `debug_log` layer, producing a new `Layered` layer. -//! .and_then(debug_log) -//! // Add a filter to *both* layers that rejects spans and -//! // events whose targets start with `metrics`. -//! .with_filter(filter::filter_fn(|metadata| { -//! !metadata.target().starts_with("metrics") -//! })) -//! ) -//! .with( -//! // Add a filter to the metrics label that *only* enables -//! // events whose targets start with `metrics`. -//! metrics_layer.with_filter(filter::filter_fn(|metadata| { -//! metadata.target().starts_with("metrics") -//! })) -//! ) -//! .init(); -//! -//! // This event will *only* be recorded by the metrics layer. -//! tracing::info!(target: "metrics::cool_stuff_count", value = 42); -//! -//! // This event will only be seen by the debug log file layer: -//! tracing::debug!("this is a message, and part of a system of messages"); -//! -//! // This event will be seen by both the stdout log layer *and* -//! // the debug log file layer, but not by the metrics layer. -//! tracing::warn!("the message is a warning about danger!"); -//! # Ok(()) } -//! ``` -//! -//! [`Subscriber`]: tracing_core::subscriber::Subscriber -//! [span IDs]: tracing_core::span::Id -//! [the current span]: Context::current_span -//! [`register_callsite`]: Layer::register_callsite -//! [`enabled`]: Layer::enabled -//! [`event_enabled`]: Layer::event_enabled -//! [`on_enter`]: Layer::on_enter -//! [`Layer::register_callsite`]: Layer::register_callsite -//! [`Layer::enabled`]: Layer::enabled -//! [`Interest::never()`]: tracing_core::subscriber::Interest::never() -//! [`Filtered`]: crate::filter::Filtered -//! [`filter`]: crate::filter -//! [`Targets`]: crate::filter::Targets -//! [`FilterFn`]: crate::filter::FilterFn -//! [`DynFilterFn`]: crate::filter::DynFilterFn -//! [level]: tracing_core::Level -//! [`INFO`]: tracing_core::Level::INFO -//! [`DEBUG`]: tracing_core::Level::DEBUG -//! [target]: tracing_core::Metadata::target -//! [`LevelFilter`]: crate::filter::LevelFilter -//! [feat]: crate#feature-flags -use crate::filter; - -use tracing_core::{ - metadata::Metadata, - span, - subscriber::{Interest, Subscriber}, - Event, LevelFilter, -}; - -use core::any::TypeId; - -feature! { - #![feature = "alloc"] - use alloc::boxed::Box; - use core::ops::{Deref, DerefMut}; -} - -mod context; -mod layered; -pub use self::{context::*, layered::*}; - -// The `tests` module is `pub(crate)` because it contains test utilities used by -// other modules. -#[cfg(test)] -pub(crate) mod tests; - -/// A composable handler for `tracing` events. -/// -/// A `Layer` implements a behavior for recording or collecting traces that can -/// be composed together with other `Layer`s to build a [`Subscriber`]. See the -/// [module-level documentation](crate::layer) for details. -/// -/// [`Subscriber`]: tracing_core::Subscriber -#[cfg_attr(docsrs, doc(notable_trait))] -pub trait Layer<S> -where - S: Subscriber, - Self: 'static, -{ - /// Performs late initialization when attaching a `Layer` to a - /// [`Subscriber`]. - /// - /// This is a callback that is called when the `Layer` is added to a - /// [`Subscriber`] (e.g. in [`Layer::with_subscriber`] and - /// [`SubscriberExt::with`]). Since this can only occur before the - /// [`Subscriber`] has been set as the default, both the `Layer` and - /// [`Subscriber`] are passed to this method _mutably_. This gives the - /// `Layer` the opportunity to set any of its own fields with values - /// recieved by method calls on the [`Subscriber`]. - /// - /// For example, [`Filtered`] layers implement `on_layer` to call the - /// [`Subscriber`]'s [`register_filter`] method, and store the returned - /// [`FilterId`] as a field. - /// - /// **Note** In most cases, `Layer` implementations will not need to - /// implement this method. However, in cases where a type implementing - /// `Layer` wraps one or more other types that implement `Layer`, like the - /// [`Layered`] and [`Filtered`] types in this crate, that type MUST ensure - /// that the inner `Layer`s' `on_layer` methods are called. Otherwise, - /// functionality that relies on `on_layer`, such as [per-layer filtering], - /// may not work correctly. - /// - /// [`Filtered`]: crate::filter::Filtered - /// [`register_filter`]: crate::registry::LookupSpan::register_filter - /// [per-layer filtering]: #per-layer-filtering - /// [`FilterId`]: crate::filter::FilterId - fn on_layer(&mut self, subscriber: &mut S) { - let _ = subscriber; - } - - /// Registers a new callsite with this layer, returning whether or not - /// the layer is interested in being notified about the callsite, similarly - /// to [`Subscriber::register_callsite`]. - /// - /// By default, this returns [`Interest::always()`] if [`self.enabled`] returns - /// true, or [`Interest::never()`] if it returns false. - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This method (and <a href="#method.enabled"> - /// <code>Layer::enabled</code></a>) determine whether a span or event is - /// globally enabled, <em>not</em> whether the individual layer will be - /// notified about that span or event. This is intended to be used - /// by layers that implement filtering for the entire stack. Layers which do - /// not wish to be notified about certain spans or events but do not wish to - /// globally disable them should ignore those spans or events in their - /// <a href="#method.on_event"><code>on_event</code></a>, - /// <a href="#method.on_enter"><code>on_enter</code></a>, - /// <a href="#method.on_exit"><code>on_exit</code></a>, and other notification - /// methods. - /// </pre> - /// - /// See [the trait-level documentation] for more information on filtering - /// with `Layer`s. - /// - /// Layers may also implement this method to perform any behaviour that - /// should be run once per callsite. If the layer wishes to use - /// `register_callsite` for per-callsite behaviour, but does not want to - /// globally enable or disable those callsites, it should always return - /// [`Interest::always()`]. - /// - /// [`Interest`]: tracing_core::Interest - /// [`Subscriber::register_callsite`]: tracing_core::Subscriber::register_callsite() - /// [`Interest::never()`]: tracing_core::subscriber::Interest::never() - /// [`Interest::always()`]: tracing_core::subscriber::Interest::always() - /// [`self.enabled`]: Layer::enabled() - /// [`Layer::enabled`]: Layer::enabled() - /// [`on_event`]: Layer::on_event() - /// [`on_enter`]: Layer::on_enter() - /// [`on_exit`]: Layer::on_exit() - /// [the trait-level documentation]: #filtering-with-layers - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - if self.enabled(metadata, Context::none()) { - Interest::always() - } else { - Interest::never() - } - } - - /// Returns `true` if this layer is interested in a span or event with the - /// given `metadata` in the current [`Context`], similarly to - /// [`Subscriber::enabled`]. - /// - /// By default, this always returns `true`, allowing the wrapped subscriber - /// to choose to disable the span. - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: This method (and <a href="#method.register_callsite"> - /// <code>Layer::register_callsite</code></a>) determine whether a span or event is - /// globally enabled, <em>not</em> whether the individual layer will be - /// notified about that span or event. This is intended to be used - /// by layers that implement filtering for the entire stack. Layers which do - /// not wish to be notified about certain spans or events but do not wish to - /// globally disable them should ignore those spans or events in their - /// <a href="#method.on_event"><code>on_event</code></a>, - /// <a href="#method.on_enter"><code>on_enter</code></a>, - /// <a href="#method.on_exit"><code>on_exit</code></a>, and other notification - /// methods. - /// </pre> - /// - /// - /// See [the trait-level documentation] for more information on filtering - /// with `Layer`s. - /// - /// [`Interest`]: tracing_core::Interest - /// [`Subscriber::enabled`]: tracing_core::Subscriber::enabled() - /// [`Layer::register_callsite`]: Layer::register_callsite() - /// [`on_event`]: Layer::on_event() - /// [`on_enter`]: Layer::on_enter() - /// [`on_exit`]: Layer::on_exit() - /// [the trait-level documentation]: #filtering-with-layers - fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { - let _ = (metadata, ctx); - true - } - - /// Notifies this layer that a new span was constructed with the given - /// `Attributes` and `Id`. - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - let _ = (attrs, id, ctx); - } - - // TODO(eliza): do we want this to be a public API? If we end up moving - // filtering layers to a separate trait, we may no longer want `Layer`s to - // be able to participate in max level hinting... - #[doc(hidden)] - fn max_level_hint(&self) -> Option<LevelFilter> { - None - } - - /// Notifies this layer that a span with the given `Id` recorded the given - /// `values`. - // Note: it's unclear to me why we'd need the current span in `record` (the - // only thing the `Context` type currently provides), but passing it in anyway - // seems like a good future-proofing measure as it may grow other methods later... - fn on_record(&self, _span: &span::Id, _values: &span::Record<'_>, _ctx: Context<'_, S>) {} - - /// Notifies this layer that a span with the ID `span` recorded that it - /// follows from the span with the ID `follows`. - // Note: it's unclear to me why we'd need the current span in `record` (the - // only thing the `Context` type currently provides), but passing it in anyway - // seems like a good future-proofing measure as it may grow other methods later... - fn on_follows_from(&self, _span: &span::Id, _follows: &span::Id, _ctx: Context<'_, S>) {} - - /// Called before [`on_event`], to determine if `on_event` should be called. - /// - /// <div class="example-wrap" style="display:inline-block"> - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// - /// **Note**: This method determines whether an event is globally enabled, - /// *not* whether the individual `Layer` will be notified about the - /// event. This is intended to be used by `Layer`s that implement - /// filtering for the entire stack. `Layer`s which do not wish to be - /// notified about certain events but do not wish to globally disable them - /// should ignore those events in their [on_event][Self::on_event]. - /// - /// </pre></div> - /// - /// See [the trait-level documentation] for more information on filtering - /// with `Layer`s. - /// - /// [`on_event`]: Self::on_event - /// [`Interest`]: tracing_core::Interest - /// [the trait-level documentation]: #filtering-with-layers - #[inline] // collapse this to a constant please mrs optimizer - fn event_enabled(&self, _event: &Event<'_>, _ctx: Context<'_, S>) -> bool { - true - } - - /// Notifies this layer that an event has occurred. - fn on_event(&self, _event: &Event<'_>, _ctx: Context<'_, S>) {} - - /// Notifies this layer that a span with the given ID was entered. - fn on_enter(&self, _id: &span::Id, _ctx: Context<'_, S>) {} - - /// Notifies this layer that the span with the given ID was exited. - fn on_exit(&self, _id: &span::Id, _ctx: Context<'_, S>) {} - - /// Notifies this layer that the span with the given ID has been closed. - fn on_close(&self, _id: span::Id, _ctx: Context<'_, S>) {} - - /// Notifies this layer that a span ID has been cloned, and that the - /// subscriber returned a different ID. - fn on_id_change(&self, _old: &span::Id, _new: &span::Id, _ctx: Context<'_, S>) {} - - /// Composes this layer around the given `Layer`, returning a `Layered` - /// struct implementing `Layer`. - /// - /// The returned `Layer` will call the methods on this `Layer` and then - /// those of the new `Layer`, before calling the methods on the subscriber - /// it wraps. For example: - /// - /// ```rust - /// # use tracing_subscriber::layer::Layer; - /// # use tracing_core::Subscriber; - /// pub struct FooLayer { - /// // ... - /// } - /// - /// pub struct BarLayer { - /// // ... - /// } - /// - /// pub struct MySubscriber { - /// // ... - /// } - /// - /// impl<S: Subscriber> Layer<S> for FooLayer { - /// // ... - /// } - /// - /// impl<S: Subscriber> Layer<S> for BarLayer { - /// // ... - /// } - /// - /// # impl FooLayer { - /// # fn new() -> Self { Self {} } - /// # } - /// # impl BarLayer { - /// # fn new() -> Self { Self { }} - /// # } - /// # impl MySubscriber { - /// # fn new() -> Self { Self { }} - /// # } - /// # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event}; - /// # impl tracing_core::Subscriber for MySubscriber { - /// # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) } - /// # fn record(&self, _: &Id, _: &Record) {} - /// # fn event(&self, _: &Event) {} - /// # fn record_follows_from(&self, _: &Id, _: &Id) {} - /// # fn enabled(&self, _: &Metadata) -> bool { false } - /// # fn enter(&self, _: &Id) {} - /// # fn exit(&self, _: &Id) {} - /// # } - /// let subscriber = FooLayer::new() - /// .and_then(BarLayer::new()) - /// .with_subscriber(MySubscriber::new()); - /// ``` - /// - /// Multiple layers may be composed in this manner: - /// - /// ```rust - /// # use tracing_subscriber::layer::Layer; - /// # use tracing_core::Subscriber; - /// # pub struct FooLayer {} - /// # pub struct BarLayer {} - /// # pub struct MySubscriber {} - /// # impl<S: Subscriber> Layer<S> for FooLayer {} - /// # impl<S: Subscriber> Layer<S> for BarLayer {} - /// # impl FooLayer { - /// # fn new() -> Self { Self {} } - /// # } - /// # impl BarLayer { - /// # fn new() -> Self { Self { }} - /// # } - /// # impl MySubscriber { - /// # fn new() -> Self { Self { }} - /// # } - /// # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event}; - /// # impl tracing_core::Subscriber for MySubscriber { - /// # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) } - /// # fn record(&self, _: &Id, _: &Record) {} - /// # fn event(&self, _: &Event) {} - /// # fn record_follows_from(&self, _: &Id, _: &Id) {} - /// # fn enabled(&self, _: &Metadata) -> bool { false } - /// # fn enter(&self, _: &Id) {} - /// # fn exit(&self, _: &Id) {} - /// # } - /// pub struct BazLayer { - /// // ... - /// } - /// - /// impl<S: Subscriber> Layer<S> for BazLayer { - /// // ... - /// } - /// # impl BazLayer { fn new() -> Self { BazLayer {} } } - /// - /// let subscriber = FooLayer::new() - /// .and_then(BarLayer::new()) - /// .and_then(BazLayer::new()) - /// .with_subscriber(MySubscriber::new()); - /// ``` - fn and_then<L>(self, layer: L) -> Layered<L, Self, S> - where - L: Layer<S>, - Self: Sized, - { - let inner_has_layer_filter = filter::layer_has_plf(&self); - Layered::new(layer, self, inner_has_layer_filter) - } - - /// Composes this `Layer` with the given [`Subscriber`], returning a - /// `Layered` struct that implements [`Subscriber`]. - /// - /// The returned `Layered` subscriber will call the methods on this `Layer` - /// and then those of the wrapped subscriber. - /// - /// For example: - /// ```rust - /// # use tracing_subscriber::layer::Layer; - /// # use tracing_core::Subscriber; - /// pub struct FooLayer { - /// // ... - /// } - /// - /// pub struct MySubscriber { - /// // ... - /// } - /// - /// impl<S: Subscriber> Layer<S> for FooLayer { - /// // ... - /// } - /// - /// # impl FooLayer { - /// # fn new() -> Self { Self {} } - /// # } - /// # impl MySubscriber { - /// # fn new() -> Self { Self { }} - /// # } - /// # use tracing_core::{span::{Id, Attributes, Record}, Metadata}; - /// # impl tracing_core::Subscriber for MySubscriber { - /// # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) } - /// # fn record(&self, _: &Id, _: &Record) {} - /// # fn event(&self, _: &tracing_core::Event) {} - /// # fn record_follows_from(&self, _: &Id, _: &Id) {} - /// # fn enabled(&self, _: &Metadata) -> bool { false } - /// # fn enter(&self, _: &Id) {} - /// # fn exit(&self, _: &Id) {} - /// # } - /// let subscriber = FooLayer::new() - /// .with_subscriber(MySubscriber::new()); - ///``` - /// - /// [`Subscriber`]: tracing_core::Subscriber - fn with_subscriber(mut self, mut inner: S) -> Layered<Self, S> - where - Self: Sized, - { - let inner_has_layer_filter = filter::subscriber_has_plf(&inner); - self.on_layer(&mut inner); - Layered::new(self, inner, inner_has_layer_filter) - } - - /// Combines `self` with a [`Filter`], returning a [`Filtered`] layer. - /// - /// The [`Filter`] will control which spans and events are enabled for - /// this layer. See [the trait-level documentation][plf] for details on - /// per-layer filtering. - /// - /// [`Filtered`]: crate::filter::Filtered - /// [plf]: crate::layer#per-layer-filtering - #[cfg(all(feature = "registry", feature = "std"))] - #[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))] - fn with_filter<F>(self, filter: F) -> filter::Filtered<Self, F, S> - where - Self: Sized, - F: Filter<S>, - { - filter::Filtered::new(self, filter) - } - - /// Erases the type of this [`Layer`], returning a [`Box`]ed `dyn - /// Layer` trait object. - /// - /// This can be used when a function returns a `Layer` which may be of - /// one of several types, or when a `Layer` subscriber has a very long type - /// signature. - /// - /// # Examples - /// - /// The following example will *not* compile, because the value assigned to - /// `log_layer` may have one of several different types: - /// - /// ```compile_fail - /// # fn main() -> Result<(), Box<dyn std::error::Error>> { - /// use tracing_subscriber::{Layer, filter::LevelFilter, prelude::*}; - /// use std::{path::PathBuf, fs::File, io}; - /// - /// /// Configures whether logs are emitted to a file, to stdout, or to stderr. - /// pub enum LogConfig { - /// File(PathBuf), - /// Stdout, - /// Stderr, - /// } - /// - /// let config = // ... - /// # LogConfig::Stdout; - /// - /// // Depending on the config, construct a layer of one of several types. - /// let log_layer = match config { - /// // If logging to a file, use a maximally-verbose configuration. - /// LogConfig::File(path) => { - /// let file = File::create(path)?; - /// tracing_subscriber::fmt::layer() - /// .with_thread_ids(true) - /// .with_thread_names(true) - /// // Selecting the JSON logging format changes the layer's - /// // type. - /// .json() - /// .with_span_list(true) - /// // Setting the writer to use our log file changes the - /// // layer's type again. - /// .with_writer(file) - /// }, - /// - /// // If logging to stdout, use a pretty, human-readable configuration. - /// LogConfig::Stdout => tracing_subscriber::fmt::layer() - /// // Selecting the "pretty" logging format changes the - /// // layer's type! - /// .pretty() - /// .with_writer(io::stdout) - /// // Add a filter based on the RUST_LOG environment variable; - /// // this changes the type too! - /// .and_then(tracing_subscriber::EnvFilter::from_default_env()), - /// - /// // If logging to stdout, only log errors and warnings. - /// LogConfig::Stderr => tracing_subscriber::fmt::layer() - /// // Changing the writer changes the layer's type - /// .with_writer(io::stderr) - /// // Only log the `WARN` and `ERROR` levels. Adding a filter - /// // changes the layer's type to `Filtered<LevelFilter, ...>`. - /// .with_filter(LevelFilter::WARN), - /// }; - /// - /// tracing_subscriber::registry() - /// .with(log_layer) - /// .init(); - /// # Ok(()) } - /// ``` - /// - /// However, adding a call to `.boxed()` after each match arm erases the - /// layer's type, so this code *does* compile: - /// - /// ``` - /// # fn main() -> Result<(), Box<dyn std::error::Error>> { - /// # use tracing_subscriber::{Layer, filter::LevelFilter, prelude::*}; - /// # use std::{path::PathBuf, fs::File, io}; - /// # pub enum LogConfig { - /// # File(PathBuf), - /// # Stdout, - /// # Stderr, - /// # } - /// # let config = LogConfig::Stdout; - /// let log_layer = match config { - /// LogConfig::File(path) => { - /// let file = File::create(path)?; - /// tracing_subscriber::fmt::layer() - /// .with_thread_ids(true) - /// .with_thread_names(true) - /// .json() - /// .with_span_list(true) - /// .with_writer(file) - /// // Erase the type by boxing the layer - /// .boxed() - /// }, - /// - /// LogConfig::Stdout => tracing_subscriber::fmt::layer() - /// .pretty() - /// .with_writer(io::stdout) - /// .and_then(tracing_subscriber::EnvFilter::from_default_env()) - /// // Erase the type by boxing the layer - /// .boxed(), - /// - /// LogConfig::Stderr => tracing_subscriber::fmt::layer() - /// .with_writer(io::stderr) - /// .with_filter(LevelFilter::WARN) - /// // Erase the type by boxing the layer - /// .boxed(), - /// }; - /// - /// tracing_subscriber::registry() - /// .with(log_layer) - /// .init(); - /// # Ok(()) } - /// ``` - #[cfg(any(feature = "alloc", feature = "std"))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] - fn boxed(self) -> Box<dyn Layer<S> + Send + Sync + 'static> - where - Self: Sized, - Self: Layer<S> + Send + Sync + 'static, - S: Subscriber, - { - Box::new(self) - } - - #[doc(hidden)] - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - if id == TypeId::of::<Self>() { - Some(self as *const _ as *const ()) - } else { - None - } - } -} - -feature! { - #![all(feature = "registry", feature = "std")] - - /// A per-[`Layer`] filter that determines whether a span or event is enabled - /// for an individual layer. - /// - /// See [the module-level documentation][plf] for details on using [`Filter`]s. - /// - /// [plf]: crate::layer#per-layer-filtering - #[cfg_attr(docsrs, doc(notable_trait))] - pub trait Filter<S> { - /// Returns `true` if this layer is interested in a span or event with the - /// given [`Metadata`] in the current [`Context`], similarly to - /// [`Subscriber::enabled`]. - /// - /// If this returns `false`, the span or event will be disabled _for the - /// wrapped [`Layer`]_. Unlike [`Layer::enabled`], the span or event will - /// still be recorded if any _other_ layers choose to enable it. However, - /// the layer [filtered] by this filter will skip recording that span or - /// event. - /// - /// If all layers indicate that they do not wish to see this span or event, - /// it will be disabled. - /// - /// [`metadata`]: tracing_core::Metadata - /// [`Subscriber::enabled`]: tracing_core::Subscriber::enabled - /// [filtered]: crate::filter::Filtered - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool; - - /// Returns an [`Interest`] indicating whether this layer will [always], - /// [sometimes], or [never] be interested in the given [`Metadata`]. - /// - /// When a given callsite will [always] or [never] be enabled, the results - /// of evaluating the filter may be cached for improved performance. - /// Therefore, if a filter is capable of determining that it will always or - /// never enable a particular callsite, providing an implementation of this - /// function is recommended. - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: If a <code>Filter</code> will perform - /// <em>dynamic filtering</em> that depends on the current context in which - /// a span or event was observered (e.g. only enabling an event when it - /// occurs within a particular span), it <strong>must</strong> return - /// <code>Interest::sometimes()</code> from this method. If it returns - /// <code>Interest::always()</code> or <code>Interest::never()</code>, the - /// <code>enabled</code> method may not be called when a particular instance - /// of that span or event is recorded. - /// </pre> - /// - /// This method is broadly similar to [`Subscriber::register_callsite`]; - /// however, since the returned value represents only the interest of - /// *this* layer, the resulting behavior is somewhat different. - /// - /// If a [`Subscriber`] returns [`Interest::always()`][always] or - /// [`Interest::never()`][never] for a given [`Metadata`], its [`enabled`] - /// method is then *guaranteed* to never be called for that callsite. On the - /// other hand, when a `Filter` returns [`Interest::always()`][always] or - /// [`Interest::never()`][never] for a callsite, _other_ [`Layer`]s may have - /// differing interests in that callsite. If this is the case, the callsite - /// will recieve [`Interest::sometimes()`][sometimes], and the [`enabled`] - /// method will still be called for that callsite when it records a span or - /// event. - /// - /// Returning [`Interest::always()`][always] or [`Interest::never()`][never] from - /// `Filter::callsite_enabled` will permanently enable or disable a - /// callsite (without requiring subsequent calls to [`enabled`]) if and only - /// if the following is true: - /// - /// - all [`Layer`]s that comprise the subscriber include `Filter`s - /// (this includes a tree of [`Layered`] layers that share the same - /// `Filter`) - /// - all those `Filter`s return the same [`Interest`]. - /// - /// For example, if a [`Subscriber`] consists of two [`Filtered`] layers, - /// and both of those layers return [`Interest::never()`][never], that - /// callsite *will* never be enabled, and the [`enabled`] methods of those - /// [`Filter`]s will not be called. - /// - /// ## Default Implementation - /// - /// The default implementation of this method assumes that the - /// `Filter`'s [`enabled`] method _may_ perform dynamic filtering, and - /// returns [`Interest::sometimes()`][sometimes], to ensure that [`enabled`] - /// is called to determine whether a particular _instance_ of the callsite - /// is enabled in the current context. If this is *not* the case, and the - /// `Filter`'s [`enabled`] method will always return the same result - /// for a particular [`Metadata`], this method can be overridden as - /// follows: - /// - /// ``` - /// use tracing_subscriber::layer; - /// use tracing_core::{Metadata, subscriber::Interest}; - /// - /// struct MyFilter { - /// // ... - /// } - /// - /// impl MyFilter { - /// // The actual logic for determining whether a `Metadata` is enabled - /// // must be factored out from the `enabled` method, so that it can be - /// // called without a `Context` (which is not provided to the - /// // `callsite_enabled` method). - /// fn is_enabled(&self, metadata: &Metadata<'_>) -> bool { - /// // ... - /// # drop(metadata); true - /// } - /// } - /// - /// impl<S> layer::Filter<S> for MyFilter { - /// fn enabled(&self, metadata: &Metadata<'_>, _: &layer::Context<'_, S>) -> bool { - /// // Even though we are implementing `callsite_enabled`, we must still provide a - /// // working implementation of `enabled`, as returning `Interest::always()` or - /// // `Interest::never()` will *allow* caching, but will not *guarantee* it. - /// // Other filters may still return `Interest::sometimes()`, so we may be - /// // asked again in `enabled`. - /// self.is_enabled(metadata) - /// } - /// - /// fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - /// // The result of `self.enabled(metadata, ...)` will always be - /// // the same for any given `Metadata`, so we can convert it into - /// // an `Interest`: - /// if self.is_enabled(metadata) { - /// Interest::always() - /// } else { - /// Interest::never() - /// } - /// } - /// } - /// ``` - /// - /// [`Metadata`]: tracing_core::Metadata - /// [`Interest`]: tracing_core::Interest - /// [always]: tracing_core::Interest::always - /// [sometimes]: tracing_core::Interest::sometimes - /// [never]: tracing_core::Interest::never - /// [`Subscriber::register_callsite`]: tracing_core::Subscriber::register_callsite - /// [`Subscriber`]: tracing_core::Subscriber - /// [`enabled`]: Filter::enabled - /// [`Filtered`]: crate::filter::Filtered - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - let _ = meta; - Interest::sometimes() - } - - /// Returns an optional hint of the highest [verbosity level][level] that - /// this `Filter` will enable. - /// - /// If this method returns a [`LevelFilter`], it will be used as a hint to - /// determine the most verbose level that will be enabled. This will allow - /// spans and events which are more verbose than that level to be skipped - /// more efficiently. An implementation of this method is optional, but - /// strongly encouraged. - /// - /// If the maximum level the `Filter` will enable can change over the - /// course of its lifetime, it is free to return a different value from - /// multiple invocations of this method. However, note that changes in the - /// maximum level will **only** be reflected after the callsite [`Interest`] - /// cache is rebuilt, by calling the - /// [`tracing_core::callsite::rebuild_interest_cache`][rebuild] function. - /// Therefore, if the `Filter will change the value returned by this - /// method, it is responsible for ensuring that - /// [`rebuild_interest_cache`][rebuild] is called after the value of the max - /// level changes. - /// - /// ## Default Implementation - /// - /// By default, this method returns `None`, indicating that the maximum - /// level is unknown. - /// - /// [level]: tracing_core::metadata::Level - /// [`LevelFilter`]: crate::filter::LevelFilter - /// [`Interest`]: tracing_core::subscriber::Interest - /// [rebuild]: tracing_core::callsite::rebuild_interest_cache - fn max_level_hint(&self) -> Option<LevelFilter> { - None - } - - /// Notifies this filter that a new span was constructed with the given - /// `Attributes` and `Id`. - /// - /// By default, this method does nothing. `Filter` implementations that - /// need to be notified when new spans are created can override this - /// method. - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - let _ = (attrs, id, ctx); - } - - - /// Notifies this filter that a span with the given `Id` recorded the given - /// `values`. - /// - /// By default, this method does nothing. `Filter` implementations that - /// need to be notified when new spans are created can override this - /// method. - fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - let _ = (id, values, ctx); - } - - /// Notifies this filter that a span with the given ID was entered. - /// - /// By default, this method does nothing. `Filter` implementations that - /// need to be notified when a span is entered can override this method. - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - let _ = (id, ctx); - } - - /// Notifies this filter that a span with the given ID was exited. - /// - /// By default, this method does nothing. `Filter` implementations that - /// need to be notified when a span is exited can override this method. - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - let _ = (id, ctx); - } - - /// Notifies this filter that a span with the given ID has been closed. - /// - /// By default, this method does nothing. `Filter` implementations that - /// need to be notified when a span is closed can override this method. - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - let _ = (id, ctx); - } - } -} - -/// Extension trait adding a `with(Layer)` combinator to `Subscriber`s. -pub trait SubscriberExt: Subscriber + crate::sealed::Sealed { - /// Wraps `self` with the provided `layer`. - fn with<L>(self, layer: L) -> Layered<L, Self> - where - L: Layer<Self>, - Self: Sized, - { - layer.with_subscriber(self) - } -} - -/// A layer that does nothing. -#[derive(Clone, Debug, Default)] -pub struct Identity { - _p: (), -} - -// === impl Layer === - -impl<L, S> Layer<S> for Option<L> -where - L: Layer<S>, - S: Subscriber, -{ - fn on_layer(&mut self, subscriber: &mut S) { - if let Some(ref mut layer) = self { - layer.on_layer(subscriber) - } - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - if let Some(ref inner) = self { - inner.on_new_span(attrs, id, ctx) - } - } - - #[inline] - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - match self { - Some(ref inner) => inner.register_callsite(metadata), - None => Interest::always(), - } - } - - #[inline] - fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { - match self { - Some(ref inner) => inner.enabled(metadata, ctx), - None => true, - } - } - - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - match self { - Some(ref inner) => inner.max_level_hint(), - None => { - // There is no inner layer, so this layer will - // never enable anything. - Some(LevelFilter::OFF) - } - } - } - - #[inline] - fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - if let Some(ref inner) = self { - inner.on_record(span, values, ctx); - } - } - - #[inline] - fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, S>) { - if let Some(ref inner) = self { - inner.on_follows_from(span, follows, ctx); - } - } - - #[inline] - fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool { - match self { - Some(ref inner) => inner.event_enabled(event, ctx), - None => true, - } - } - - #[inline] - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { - if let Some(ref inner) = self { - inner.on_event(event, ctx); - } - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - if let Some(ref inner) = self { - inner.on_enter(id, ctx); - } - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - if let Some(ref inner) = self { - inner.on_exit(id, ctx); - } - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - if let Some(ref inner) = self { - inner.on_close(id, ctx); - } - } - - #[inline] - fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: Context<'_, S>) { - if let Some(ref inner) = self { - inner.on_id_change(old, new, ctx) - } - } - - #[doc(hidden)] - #[inline] - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - if id == TypeId::of::<Self>() { - Some(self as *const _ as *const ()) - } else { - self.as_ref().and_then(|inner| inner.downcast_raw(id)) - } - } -} - -feature! { - #![any(feature = "std", feature = "alloc")] - #[cfg(not(feature = "std"))] - use alloc::vec::Vec; - - macro_rules! layer_impl_body { - () => { - #[inline] - fn on_layer(&mut self, subscriber: &mut S) { - self.deref_mut().on_layer(subscriber); - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - self.deref().on_new_span(attrs, id, ctx) - } - - #[inline] - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - self.deref().register_callsite(metadata) - } - - #[inline] - fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { - self.deref().enabled(metadata, ctx) - } - - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - self.deref().max_level_hint() - } - - #[inline] - fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - self.deref().on_record(span, values, ctx) - } - - #[inline] - fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, S>) { - self.deref().on_follows_from(span, follows, ctx) - } - - #[inline] - fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool { - self.deref().event_enabled(event, ctx) - } - - #[inline] - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { - self.deref().on_event(event, ctx) - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - self.deref().on_enter(id, ctx) - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - self.deref().on_exit(id, ctx) - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - self.deref().on_close(id, ctx) - } - - #[inline] - fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: Context<'_, S>) { - self.deref().on_id_change(old, new, ctx) - } - - #[doc(hidden)] - #[inline] - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - self.deref().downcast_raw(id) - } - }; - } - - impl<L, S> Layer<S> for Box<L> - where - L: Layer<S>, - S: Subscriber, - { - layer_impl_body! {} - } - - impl<S> Layer<S> for Box<dyn Layer<S> + Send + Sync> - where - S: Subscriber, - { - layer_impl_body! {} - } - - - - impl<S, L> Layer<S> for Vec<L> - where - L: Layer<S>, - S: Subscriber, - { - - fn on_layer(&mut self, subscriber: &mut S) { - for l in self { - l.on_layer(subscriber); - } - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - // Return highest level of interest. - let mut interest = Interest::never(); - for l in self { - let new_interest = l.register_callsite(metadata); - if (interest.is_sometimes() && new_interest.is_always()) - || (interest.is_never() && !new_interest.is_never()) - { - interest = new_interest; - } - } - - interest - } - - fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { - self.iter().all(|l| l.enabled(metadata, ctx.clone())) - } - - fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool { - self.iter().all(|l| l.event_enabled(event, ctx.clone())) - } - - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - for l in self { - l.on_new_span(attrs, id, ctx.clone()); - } - } - - fn max_level_hint(&self) -> Option<LevelFilter> { - // Default to `OFF` if there are no inner layers. - let mut max_level = LevelFilter::OFF; - for l in self { - // NOTE(eliza): this is slightly subtle: if *any* layer - // returns `None`, we have to return `None`, assuming there is - // no max level hint, since that particular layer cannot - // provide a hint. - let hint = l.max_level_hint()?; - max_level = core::cmp::max(hint, max_level); - } - Some(max_level) - } - - fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - for l in self { - l.on_record(span, values, ctx.clone()) - } - } - - fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, S>) { - for l in self { - l.on_follows_from(span, follows, ctx.clone()); - } - } - - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { - for l in self { - l.on_event(event, ctx.clone()); - } - } - - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - for l in self { - l.on_enter(id, ctx.clone()); - } - } - - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - for l in self { - l.on_exit(id, ctx.clone()); - } - } - - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - for l in self { - l.on_close(id.clone(), ctx.clone()); - } - } - - #[doc(hidden)] - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - // If downcasting to `Self`, return a pointer to `self`. - if id == TypeId::of::<Self>() { - return Some(self as *const _ as *const ()); - } - - // Someone is looking for per-layer filters. But, this `Vec` - // might contain layers with per-layer filters *and* - // layers without filters. It should only be treated as a - // per-layer-filtered layer if *all* its layers have - // per-layer filters. - // XXX(eliza): it's a bummer we have to do this linear search every - // time. It would be nice if this could be cached, but that would - // require replacing the `Vec` impl with an impl for a newtype... - if filter::is_plf_downcast_marker(id) && self.iter().any(|s| s.downcast_raw(id).is_none()) { - return None; - } - - // Otherwise, return the first child of `self` that downcaasts to - // the selected type, if any. - // XXX(eliza): hope this is reasonable lol - self.iter().find_map(|l| l.downcast_raw(id)) - } - } -} - -// === impl SubscriberExt === - -impl<S: Subscriber> crate::sealed::Sealed for S {} -impl<S: Subscriber> SubscriberExt for S {} - -// === impl Identity === - -impl<S: Subscriber> Layer<S> for Identity {} - -impl Identity { - /// Returns a new `Identity` layer. - pub fn new() -> Self { - Self { _p: () } - } -} diff --git a/vendor/tracing-subscriber/src/layer/tests.rs b/vendor/tracing-subscriber/src/layer/tests.rs deleted file mode 100644 index d7ad61769..000000000 --- a/vendor/tracing-subscriber/src/layer/tests.rs +++ /dev/null @@ -1,308 +0,0 @@ -use super::*; -use tracing_core::subscriber::NoSubscriber; - -#[derive(Debug)] -pub(crate) struct NopLayer; -impl<S: Subscriber> Layer<S> for NopLayer {} - -#[allow(dead_code)] -struct NopLayer2; -impl<S: Subscriber> Layer<S> for NopLayer2 {} - -/// A layer that holds a string. -/// -/// Used to test that pointers returned by downcasting are actually valid. -struct StringLayer(&'static str); -impl<S: Subscriber> Layer<S> for StringLayer {} -struct StringLayer2(&'static str); -impl<S: Subscriber> Layer<S> for StringLayer2 {} - -struct StringLayer3(&'static str); -impl<S: Subscriber> Layer<S> for StringLayer3 {} - -pub(crate) struct StringSubscriber(&'static str); - -impl Subscriber for StringSubscriber { - fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest { - Interest::never() - } - - fn enabled(&self, _: &Metadata<'_>) -> bool { - false - } - - fn new_span(&self, _: &span::Attributes<'_>) -> span::Id { - span::Id::from_u64(1) - } - - fn record(&self, _: &span::Id, _: &span::Record<'_>) {} - fn record_follows_from(&self, _: &span::Id, _: &span::Id) {} - fn event(&self, _: &Event<'_>) {} - fn enter(&self, _: &span::Id) {} - fn exit(&self, _: &span::Id) {} -} - -fn assert_subscriber(_s: impl Subscriber) {} -fn assert_layer<S: Subscriber>(_l: &impl Layer<S>) {} - -#[test] -fn layer_is_subscriber() { - let s = NopLayer.with_subscriber(NoSubscriber::default()); - assert_subscriber(s) -} - -#[test] -fn two_layers_are_subscriber() { - let s = NopLayer - .and_then(NopLayer) - .with_subscriber(NoSubscriber::default()); - assert_subscriber(s) -} - -#[test] -fn three_layers_are_subscriber() { - let s = NopLayer - .and_then(NopLayer) - .and_then(NopLayer) - .with_subscriber(NoSubscriber::default()); - assert_subscriber(s) -} - -#[test] -fn three_layers_are_layer() { - let layers = NopLayer.and_then(NopLayer).and_then(NopLayer); - assert_layer(&layers); - let _ = layers.with_subscriber(NoSubscriber::default()); -} - -#[test] -#[cfg(feature = "alloc")] -fn box_layer_is_layer() { - use alloc::boxed::Box; - let l: Box<dyn Layer<NoSubscriber> + Send + Sync> = Box::new(NopLayer); - assert_layer(&l); - l.with_subscriber(NoSubscriber::default()); -} - -#[test] -fn downcasts_to_subscriber() { - let s = NopLayer - .and_then(NopLayer) - .and_then(NopLayer) - .with_subscriber(StringSubscriber("subscriber")); - let subscriber = - <dyn Subscriber>::downcast_ref::<StringSubscriber>(&s).expect("subscriber should downcast"); - assert_eq!(subscriber.0, "subscriber"); -} - -#[test] -fn downcasts_to_layer() { - let s = StringLayer("layer_1") - .and_then(StringLayer2("layer_2")) - .and_then(StringLayer3("layer_3")) - .with_subscriber(NoSubscriber::default()); - let layer = <dyn Subscriber>::downcast_ref::<StringLayer>(&s).expect("layer 1 should downcast"); - assert_eq!(layer.0, "layer_1"); - let layer = - <dyn Subscriber>::downcast_ref::<StringLayer2>(&s).expect("layer 2 should downcast"); - assert_eq!(layer.0, "layer_2"); - let layer = - <dyn Subscriber>::downcast_ref::<StringLayer3>(&s).expect("layer 3 should downcast"); - assert_eq!(layer.0, "layer_3"); -} - -#[cfg(all(feature = "registry", feature = "std"))] -mod registry_tests { - use super::*; - use crate::registry::LookupSpan; - - #[test] - fn context_event_span() { - use std::sync::{Arc, Mutex}; - let last_event_span = Arc::new(Mutex::new(None)); - - struct RecordingLayer { - last_event_span: Arc<Mutex<Option<&'static str>>>, - } - - impl<S> Layer<S> for RecordingLayer - where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - { - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { - let span = ctx.event_span(event); - *self.last_event_span.lock().unwrap() = span.map(|s| s.name()); - } - } - - tracing::subscriber::with_default( - crate::registry().with(RecordingLayer { - last_event_span: last_event_span.clone(), - }), - || { - tracing::info!("no span"); - assert_eq!(*last_event_span.lock().unwrap(), None); - - let parent = tracing::info_span!("explicit"); - tracing::info!(parent: &parent, "explicit span"); - assert_eq!(*last_event_span.lock().unwrap(), Some("explicit")); - - let _guard = tracing::info_span!("contextual").entered(); - tracing::info!("contextual span"); - assert_eq!(*last_event_span.lock().unwrap(), Some("contextual")); - }, - ); - } - - /// Tests for how max-level hints are calculated when combining layers - /// with and without per-layer filtering. - mod max_level_hints { - - use super::*; - use crate::filter::*; - - #[test] - fn mixed_with_unfiltered() { - let subscriber = crate::registry() - .with(NopLayer) - .with(NopLayer.with_filter(LevelFilter::INFO)); - assert_eq!(subscriber.max_level_hint(), None); - } - - #[test] - fn mixed_with_unfiltered_layered() { - let subscriber = crate::registry().with(NopLayer).with( - NopLayer - .with_filter(LevelFilter::INFO) - .and_then(NopLayer.with_filter(LevelFilter::TRACE)), - ); - assert_eq!(dbg!(subscriber).max_level_hint(), None); - } - - #[test] - fn mixed_interleaved() { - let subscriber = crate::registry() - .with(NopLayer) - .with(NopLayer.with_filter(LevelFilter::INFO)) - .with(NopLayer) - .with(NopLayer.with_filter(LevelFilter::INFO)); - assert_eq!(dbg!(subscriber).max_level_hint(), None); - } - - #[test] - fn mixed_layered() { - let subscriber = crate::registry() - .with(NopLayer.with_filter(LevelFilter::INFO).and_then(NopLayer)) - .with(NopLayer.and_then(NopLayer.with_filter(LevelFilter::INFO))); - assert_eq!(dbg!(subscriber).max_level_hint(), None); - } - - #[test] - fn plf_only_unhinted() { - let subscriber = crate::registry() - .with(NopLayer.with_filter(LevelFilter::INFO)) - .with(NopLayer.with_filter(filter_fn(|_| true))); - assert_eq!(dbg!(subscriber).max_level_hint(), None); - } - - #[test] - fn plf_only_unhinted_nested_outer() { - // if a nested tree of per-layer filters has an _outer_ filter with - // no max level hint, it should return `None`. - let subscriber = crate::registry() - .with( - NopLayer - .with_filter(LevelFilter::INFO) - .and_then(NopLayer.with_filter(LevelFilter::WARN)), - ) - .with( - NopLayer - .with_filter(filter_fn(|_| true)) - .and_then(NopLayer.with_filter(LevelFilter::DEBUG)), - ); - assert_eq!(dbg!(subscriber).max_level_hint(), None); - } - - #[test] - fn plf_only_unhinted_nested_inner() { - // If a nested tree of per-layer filters has an _inner_ filter with - // no max-level hint, but the _outer_ filter has a max level hint, - // it should pick the outer hint. This is because the outer filter - // will disable the spans/events before they make it to the inner - // filter. - let subscriber = dbg!(crate::registry().with( - NopLayer - .with_filter(filter_fn(|_| true)) - .and_then(NopLayer.with_filter(filter_fn(|_| true))) - .with_filter(LevelFilter::INFO), - )); - assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO)); - } - - #[test] - fn unhinted_nested_inner() { - let subscriber = dbg!(crate::registry() - .with(NopLayer.and_then(NopLayer).with_filter(LevelFilter::INFO)) - .with( - NopLayer - .with_filter(filter_fn(|_| true)) - .and_then(NopLayer.with_filter(filter_fn(|_| true))) - .with_filter(LevelFilter::WARN), - )); - assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO)); - } - - #[test] - fn unhinted_nested_inner_mixed() { - let subscriber = dbg!(crate::registry() - .with( - NopLayer - .and_then(NopLayer.with_filter(filter_fn(|_| true))) - .with_filter(LevelFilter::INFO) - ) - .with( - NopLayer - .with_filter(filter_fn(|_| true)) - .and_then(NopLayer.with_filter(filter_fn(|_| true))) - .with_filter(LevelFilter::WARN), - )); - assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO)); - } - - #[test] - fn plf_only_picks_max() { - let subscriber = crate::registry() - .with(NopLayer.with_filter(LevelFilter::WARN)) - .with(NopLayer.with_filter(LevelFilter::DEBUG)); - assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG)); - } - - #[test] - fn many_plf_only_picks_max() { - let subscriber = crate::registry() - .with(NopLayer.with_filter(LevelFilter::WARN)) - .with(NopLayer.with_filter(LevelFilter::DEBUG)) - .with(NopLayer.with_filter(LevelFilter::INFO)) - .with(NopLayer.with_filter(LevelFilter::ERROR)); - assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG)); - } - - #[test] - fn nested_plf_only_picks_max() { - let subscriber = crate::registry() - .with( - NopLayer.with_filter(LevelFilter::INFO).and_then( - NopLayer - .with_filter(LevelFilter::WARN) - .and_then(NopLayer.with_filter(LevelFilter::DEBUG)), - ), - ) - .with( - NopLayer - .with_filter(LevelFilter::INFO) - .and_then(NopLayer.with_filter(LevelFilter::ERROR)), - ); - assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG)); - } - } -} diff --git a/vendor/tracing-subscriber/src/lib.rs b/vendor/tracing-subscriber/src/lib.rs deleted file mode 100644 index 4bd61000e..000000000 --- a/vendor/tracing-subscriber/src/lib.rs +++ /dev/null @@ -1,252 +0,0 @@ -//! Utilities for implementing and composing [`tracing`] subscribers. -//! -//! [`tracing`] is a framework for instrumenting Rust programs to collect -//! scoped, structured, and async-aware diagnostics. The [`Subscriber`] trait -//! represents the functionality necessary to collect this trace data. This -//! crate contains tools for composing subscribers out of smaller units of -//! behaviour, and batteries-included implementations of common subscriber -//! functionality. -//! -//! `tracing-subscriber` is intended for use by both `Subscriber` authors and -//! application authors using `tracing` to instrument their applications. -//! -//! *Compiler support: [requires `rustc` 1.49+][msrv]* -//! -//! [msrv]: #supported-rust-versions -//! -//! ## `Layer`s and `Filter`s -//! -//! The most important component of the `tracing-subscriber` API is the -//! [`Layer`] trait, which provides a composable abstraction for building -//! [`Subscriber`]s. Like the [`Subscriber`] trait, a [`Layer`] defines a -//! particular behavior for collecting trace data. Unlike [`Subscriber`]s, -//! which implement a *complete* strategy for how trace data is collected, -//! [`Layer`]s provide *modular* implementations of specific behaviors. -//! Therefore, they can be [composed together] to form a [`Subscriber`] which is -//! capable of recording traces in a variety of ways. See the [`layer` module's -//! documentation][layer] for details on using [`Layer`]s. -//! -//! In addition, the [`Filter`] trait defines an interface for filtering what -//! spans and events are recorded by a particular layer. This allows different -//! [`Layer`]s to handle separate subsets of the trace data emitted by a -//! program. See the [documentation on per-layer filtering][plf] for more -//! information on using [`Filter`]s. -//! -//! [`Layer`]: crate::layer::Layer -//! [composed together]: crate::layer#composing-layers -//! [layer]: crate::layer -//! [`Filter`]: crate::layer::Filter -//! [plf]: crate::layer#per-layer-filtering -//! -//! ## Included Subscribers -//! -//! The following `Subscriber`s are provided for application authors: -//! -//! - [`fmt`] - Formats and logs tracing data (requires the `fmt` feature flag) -//! -//! ## Feature Flags -//! -//! - `std`: Enables APIs that depend on the on the Rust standard library -//! (enabled by default). -//! - `alloc`: Depend on [`liballoc`] (enabled by "std"). -//! - `env-filter`: Enables the [`EnvFilter`] type, which implements filtering -//! similar to the [`env_logger` crate]. **Requires "std"**. -//! - `fmt`: Enables the [`fmt`] module, which provides a subscriber -//! implementation for printing formatted representations of trace events. -//! Enabled by default. **Requires "std"**. -//! - `ansi`: Enables `fmt` support for ANSI terminal colors. Enabled by -//! default. -//! - `registry`: enables the [`registry`] module. Enabled by default. -//! **Requires "std"**. -//! - `json`: Enables `fmt` support for JSON output. In JSON output, the ANSI -//! feature does nothing. **Requires "fmt" and "std"**. -//! - `local-time`: Enables local time formatting when using the [`time` -//! crate]'s timestamp formatters with the `fmt` subscriber. -//! -//! [`registry`]: mod@registry -//! -//! ### Optional Dependencies -//! -//! - [`tracing-log`]: Enables better formatting for events emitted by `log` -//! macros in the `fmt` subscriber. Enabled by default. -//! - [`time`][`time` crate]: Enables support for using the [`time` crate] for timestamp -//! formatting in the `fmt` subscriber. -//! - [`smallvec`]: Causes the `EnvFilter` type to use the `smallvec` crate (rather -//! than `Vec`) as a performance optimization. Enabled by default. -//! - [`parking_lot`]: Use the `parking_lot` crate's `RwLock` implementation -//! rather than the Rust standard library's implementation. -//! -//! ### `no_std` Support -//! -//! In embedded systems and other bare-metal applications, `tracing` can be -//! used without requiring the Rust standard library, although some features are -//! disabled. Although most of the APIs provided by `tracing-subscriber`, such -//! as [`fmt`] and [`EnvFilter`], require the standard library, some -//! functionality, such as the [`Layer`] trait, can still be used in -//! `no_std` environments. -//! -//! The dependency on the standard library is controlled by two crate feature -//! flags, "std", which enables the dependency on [`libstd`], and "alloc", which -//! enables the dependency on [`liballoc`] (and is enabled by the "std" -//! feature). These features are enabled by default, but `no_std` users can -//! disable them using: -//! -//! ```toml -//! # Cargo.toml -//! tracing-subscriber = { version = "0.3", default-features = false } -//! ``` -//! -//! Additional APIs are available when [`liballoc`] is available. To enable -//! `liballoc` but not `std`, use: -//! -//! ```toml -//! # Cargo.toml -//! tracing-subscriber = { version = "0.3", default-features = false, features = ["alloc"] } -//! ``` -//! -//! ### Unstable Features -//! -//! These feature flags enable **unstable** features. The public API may break in 0.1.x -//! releases. To enable these features, the `--cfg tracing_unstable` must be passed to -//! `rustc` when compiling. -//! -//! The following unstable feature flags are currently available: -//! -//! * `valuable`: Enables support for serializing values recorded using the -//! [`valuable`] crate as structured JSON in the [`format::Json`] formatter. -//! -//! #### Enabling Unstable Features -//! -//! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS` -//! env variable when running `cargo` commands: -//! -//! ```shell -//! RUSTFLAGS="--cfg tracing_unstable" cargo build -//! ``` -//! Alternatively, the following can be added to the `.cargo/config` file in a -//! project to automatically enable the cfg flag for that project: -//! -//! ```toml -//! [build] -//! rustflags = ["--cfg", "tracing_unstable"] -//! ``` -//! -//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section -//! [`valuable`]: https://crates.io/crates/valuable -//! [`format::Json`]: crate::fmt::format::Json -//! -//! ## Supported Rust Versions -//! -//! Tracing is built against the latest stable release. The minimum supported -//! version is 1.49. The current Tracing version is not guaranteed to build on -//! Rust versions earlier than the minimum supported version. -//! -//! Tracing follows the same compiler support policies as the rest of the Tokio -//! project. The current stable Rust compiler and the three most recent minor -//! versions before it will always be supported. For example, if the current -//! stable compiler version is 1.45, the minimum supported version will not be -//! increased past 1.42, three minor versions prior. Increasing the minimum -//! supported compiler version is not considered a semver breaking change as -//! long as doing so complies with this policy. -//! -//! [`Subscriber`]: tracing_core::subscriber::Subscriber -//! [`tracing`]: https://docs.rs/tracing/latest/tracing -//! [`EnvFilter`]: filter::EnvFilter -//! [`fmt`]: mod@fmt -//! [`tracing-log`]: https://crates.io/crates/tracing-log -//! [`smallvec`]: https://crates.io/crates/smallvec -//! [`env_logger` crate]: https://crates.io/crates/env_logger -//! [`parking_lot`]: https://crates.io/crates/parking_lot -//! [`time` crate]: https://crates.io/crates/time -//! [`libstd`]: std -//! [`liballoc`]: alloc -#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.3.14")] -#![doc( - html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", - issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" -)] -#![cfg_attr( - docsrs, - // Allows displaying cfgs/feature flags in the documentation. - feature(doc_cfg), - // Allows adding traits to RustDoc's list of "notable traits" - feature(doc_notable_trait), - // Fail the docs build if any intra-docs links are broken - deny(rustdoc::broken_intra_doc_links), -)] -#![warn( - missing_debug_implementations, - missing_docs, - rust_2018_idioms, - unreachable_pub, - bad_style, - const_err, - dead_code, - improper_ctypes, - non_shorthand_field_patterns, - no_mangle_generic_items, - overflowing_literals, - path_statements, - patterns_in_fns_without_body, - private_in_public, - unconditional_recursion, - unused, - unused_allocation, - unused_comparisons, - unused_parens, - while_true -)] -// Using struct update syntax when a struct has no additional fields avoids -// a potential source change if additional fields are added to the struct in the -// future, reducing diff noise. Allow this even though clippy considers it -// "needless". -#![allow(clippy::needless_update)] -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "alloc")] -extern crate alloc; - -#[macro_use] -mod macros; - -pub mod field; -pub mod filter; -pub mod prelude; -pub mod registry; - -pub mod layer; -pub mod util; - -feature! { - #![feature = "std"] - pub mod reload; - pub(crate) mod sync; -} - -feature! { - #![all(feature = "fmt", feature = "std")] - pub mod fmt; - pub use fmt::fmt; - pub use fmt::Subscriber as FmtSubscriber; -} - -feature! { - #![all(feature = "env-filter", feature = "std")] - pub use filter::EnvFilter; -} - -pub use layer::Layer; - -feature! { - #![all(feature = "registry", feature = "std")] - pub use registry::Registry; - - /// - pub fn registry() -> Registry { - Registry::default() - } -} - -mod sealed { - pub trait Sealed<A = ()> {} -} diff --git a/vendor/tracing-subscriber/src/macros.rs b/vendor/tracing-subscriber/src/macros.rs deleted file mode 100644 index 81351132f..000000000 --- a/vendor/tracing-subscriber/src/macros.rs +++ /dev/null @@ -1,28 +0,0 @@ -#[cfg(feature = "std")] -macro_rules! try_lock { - ($lock:expr) => { - try_lock!($lock, else return) - }; - ($lock:expr, else $els:expr) => { - if let Ok(l) = $lock { - l - } else if std::thread::panicking() { - $els - } else { - panic!("lock poisoned") - } - }; -} - -macro_rules! feature { - ( - #![$meta:meta] - $($item:item)* - ) => { - $( - #[cfg($meta)] - #[cfg_attr(docsrs, doc(cfg($meta)))] - $item - )* - } -} diff --git a/vendor/tracing-subscriber/src/prelude.rs b/vendor/tracing-subscriber/src/prelude.rs deleted file mode 100644 index c2230907b..000000000 --- a/vendor/tracing-subscriber/src/prelude.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! The `tracing-subscriber` prelude. -//! -//! This brings into scope a number of extension traits that define methods on -//! types defined here and in other crates. - -pub use crate::field::{ - MakeExt as __tracing_subscriber_field_MakeExt, - RecordFields as __tracing_subscriber_field_RecordFields, -}; -pub use crate::layer::{ - Layer as __tracing_subscriber_Layer, SubscriberExt as __tracing_subscriber_SubscriberExt, -}; - -pub use crate::util::SubscriberInitExt as _; - -feature! { - #![all(feature = "fmt", feature = "std")] - pub use crate::fmt::writer::MakeWriterExt as _; -} diff --git a/vendor/tracing-subscriber/src/registry/extensions.rs b/vendor/tracing-subscriber/src/registry/extensions.rs deleted file mode 100644 index ff76fb599..000000000 --- a/vendor/tracing-subscriber/src/registry/extensions.rs +++ /dev/null @@ -1,274 +0,0 @@ -// taken from https://github.com/hyperium/http/blob/master/src/extensions.rs. - -use crate::sync::{RwLockReadGuard, RwLockWriteGuard}; -use std::{ - any::{Any, TypeId}, - collections::HashMap, - fmt, - hash::{BuildHasherDefault, Hasher}, -}; - -#[allow(warnings)] -type AnyMap = HashMap<TypeId, Box<dyn Any + Send + Sync>, BuildHasherDefault<IdHasher>>; - -/// With TypeIds as keys, there's no need to hash them. They are already hashes -/// themselves, coming from the compiler. The IdHasher holds the u64 of -/// the TypeId, and then returns it, instead of doing any bit fiddling. -#[derive(Default, Debug)] -struct IdHasher(u64); - -impl Hasher for IdHasher { - fn write(&mut self, _: &[u8]) { - unreachable!("TypeId calls write_u64"); - } - - #[inline] - fn write_u64(&mut self, id: u64) { - self.0 = id; - } - - #[inline] - fn finish(&self) -> u64 { - self.0 - } -} - -/// An immutable, read-only reference to a Span's extensions. -#[derive(Debug)] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub struct Extensions<'a> { - inner: RwLockReadGuard<'a, ExtensionsInner>, -} - -impl<'a> Extensions<'a> { - #[cfg(feature = "registry")] - pub(crate) fn new(inner: RwLockReadGuard<'a, ExtensionsInner>) -> Self { - Self { inner } - } - - /// Immutably borrows a type previously inserted into this `Extensions`. - pub fn get<T: 'static>(&self) -> Option<&T> { - self.inner.get::<T>() - } -} - -/// An mutable reference to a Span's extensions. -#[derive(Debug)] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub struct ExtensionsMut<'a> { - inner: RwLockWriteGuard<'a, ExtensionsInner>, -} - -impl<'a> ExtensionsMut<'a> { - #[cfg(feature = "registry")] - pub(crate) fn new(inner: RwLockWriteGuard<'a, ExtensionsInner>) -> Self { - Self { inner } - } - - /// Insert a type into this `Extensions`. - /// - /// Note that extensions are _not_ - /// `Layer`-specific—they are _span_-specific. This means that - /// other layers can access and mutate extensions that - /// a different Layer recorded. For example, an application might - /// have a layer that records execution timings, alongside a layer - /// that reports spans and events to a distributed - /// tracing system that requires timestamps for spans. - /// Ideally, if one layer records a timestamp _x_, the other layer - /// should be able to reuse timestamp _x_. - /// - /// Therefore, extensions should generally be newtypes, rather than common - /// types like [`String`](std::string::String), to avoid accidental - /// cross-`Layer` clobbering. - /// - /// ## Panics - /// - /// If `T` is already present in `Extensions`, then this method will panic. - pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) { - assert!(self.replace(val).is_none()) - } - - /// Replaces an existing `T` into this extensions. - /// - /// If `T` is not present, `Option::None` will be returned. - pub fn replace<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> { - self.inner.insert(val) - } - - /// Get a mutable reference to a type previously inserted on this `ExtensionsMut`. - pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> { - self.inner.get_mut::<T>() - } - - /// Remove a type from this `Extensions`. - /// - /// If a extension of this type existed, it will be returned. - pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> { - self.inner.remove::<T>() - } -} - -/// A type map of span extensions. -/// -/// [ExtensionsInner] is used by `SpanData` to store and -/// span-specific data. A given `Layer` can read and write -/// data that it is interested in recording and emitting. -#[derive(Default)] -pub(crate) struct ExtensionsInner { - map: AnyMap, -} - -impl ExtensionsInner { - /// Create an empty `Extensions`. - #[cfg(any(test, feature = "registry"))] - #[inline] - #[cfg(any(test, feature = "registry"))] - pub(crate) fn new() -> ExtensionsInner { - ExtensionsInner { - map: AnyMap::default(), - } - } - - /// Insert a type into this `Extensions`. - /// - /// If a extension of this type already existed, it will - /// be returned. - pub(crate) fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> { - self.map - .insert(TypeId::of::<T>(), Box::new(val)) - .and_then(|boxed| { - #[allow(warnings)] - { - (boxed as Box<Any + 'static>) - .downcast() - .ok() - .map(|boxed| *boxed) - } - }) - } - - /// Get a reference to a type previously inserted on this `Extensions`. - pub(crate) fn get<T: 'static>(&self) -> Option<&T> { - self.map - .get(&TypeId::of::<T>()) - .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref()) - } - - /// Get a mutable reference to a type previously inserted on this `Extensions`. - pub(crate) fn get_mut<T: 'static>(&mut self) -> Option<&mut T> { - self.map - .get_mut(&TypeId::of::<T>()) - .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut()) - } - - /// Remove a type from this `Extensions`. - /// - /// If a extension of this type existed, it will be returned. - pub(crate) fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> { - self.map.remove(&TypeId::of::<T>()).and_then(|boxed| { - #[allow(warnings)] - { - (boxed as Box<Any + 'static>) - .downcast() - .ok() - .map(|boxed| *boxed) - } - }) - } - - /// Clear the `ExtensionsInner` in-place, dropping any elements in the map but - /// retaining allocated capacity. - /// - /// This permits the hash map allocation to be pooled by the registry so - /// that future spans will not need to allocate new hashmaps. - #[cfg(any(test, feature = "registry"))] - pub(crate) fn clear(&mut self) { - self.map.clear(); - } -} - -impl fmt::Debug for ExtensionsInner { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Extensions") - .field("len", &self.map.len()) - .field("capacity", &self.map.capacity()) - .finish() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[derive(Debug, PartialEq)] - struct MyType(i32); - - #[test] - fn test_extensions() { - let mut extensions = ExtensionsInner::new(); - - extensions.insert(5i32); - extensions.insert(MyType(10)); - - assert_eq!(extensions.get(), Some(&5i32)); - assert_eq!(extensions.get_mut(), Some(&mut 5i32)); - - assert_eq!(extensions.remove::<i32>(), Some(5i32)); - assert!(extensions.get::<i32>().is_none()); - - assert_eq!(extensions.get::<bool>(), None); - assert_eq!(extensions.get(), Some(&MyType(10))); - } - - #[test] - fn clear_retains_capacity() { - let mut extensions = ExtensionsInner::new(); - extensions.insert(5i32); - extensions.insert(MyType(10)); - extensions.insert(true); - - assert_eq!(extensions.map.len(), 3); - let prev_capacity = extensions.map.capacity(); - extensions.clear(); - - assert_eq!( - extensions.map.len(), - 0, - "after clear(), extensions map should have length 0" - ); - assert_eq!( - extensions.map.capacity(), - prev_capacity, - "after clear(), extensions map should retain prior capacity" - ); - } - - #[test] - fn clear_drops_elements() { - use std::sync::Arc; - struct DropMePlease(Arc<()>); - struct DropMeTooPlease(Arc<()>); - - let mut extensions = ExtensionsInner::new(); - let val1 = DropMePlease(Arc::new(())); - let val2 = DropMeTooPlease(Arc::new(())); - - let val1_dropped = Arc::downgrade(&val1.0); - let val2_dropped = Arc::downgrade(&val2.0); - extensions.insert(val1); - extensions.insert(val2); - - assert!(val1_dropped.upgrade().is_some()); - assert!(val2_dropped.upgrade().is_some()); - - extensions.clear(); - assert!( - val1_dropped.upgrade().is_none(), - "after clear(), val1 should be dropped" - ); - assert!( - val2_dropped.upgrade().is_none(), - "after clear(), val2 should be dropped" - ); - } -} diff --git a/vendor/tracing-subscriber/src/registry/mod.rs b/vendor/tracing-subscriber/src/registry/mod.rs deleted file mode 100644 index 38af53e8a..000000000 --- a/vendor/tracing-subscriber/src/registry/mod.rs +++ /dev/null @@ -1,600 +0,0 @@ -//! Storage for span data shared by multiple [`Layer`]s. -//! -//! ## Using the Span Registry -//! -//! This module provides the [`Registry`] type, a [`Subscriber`] implementation -//! which tracks per-span data and exposes it to [`Layer`]s. When a `Registry` -//! is used as the base `Subscriber` of a `Layer` stack, the -//! [`layer::Context`][ctx] type will provide methods allowing `Layer`s to -//! [look up span data][lookup] stored in the registry. While [`Registry`] is a -//! reasonable default for storing spans and events, other stores that implement -//! [`LookupSpan`] and [`Subscriber`] themselves (with [`SpanData`] implemented -//! by the per-span data they store) can be used as a drop-in replacement. -//! -//! For example, we might create a `Registry` and add multiple `Layer`s like so: -//! ```rust -//! use tracing_subscriber::{registry::Registry, Layer, prelude::*}; -//! # use tracing_core::Subscriber; -//! # pub struct FooLayer {} -//! # pub struct BarLayer {} -//! # impl<S: Subscriber> Layer<S> for FooLayer {} -//! # impl<S: Subscriber> Layer<S> for BarLayer {} -//! # impl FooLayer { -//! # fn new() -> Self { Self {} } -//! # } -//! # impl BarLayer { -//! # fn new() -> Self { Self {} } -//! # } -//! -//! let subscriber = Registry::default() -//! .with(FooLayer::new()) -//! .with(BarLayer::new()); -//! ``` -//! -//! If a type implementing `Layer` depends on the functionality of a `Registry` -//! implementation, it should bound its `Subscriber` type parameter with the -//! [`LookupSpan`] trait, like so: -//! -//! ```rust -//! use tracing_subscriber::{registry, Layer}; -//! use tracing_core::Subscriber; -//! -//! pub struct MyLayer { -//! // ... -//! } -//! -//! impl<S> Layer<S> for MyLayer -//! where -//! S: Subscriber + for<'a> registry::LookupSpan<'a>, -//! { -//! // ... -//! } -//! ``` -//! When this bound is added, the `Layer` implementation will be guaranteed -//! access to the [`Context`][ctx] methods, such as [`Context::span`][lookup], that -//! require the root subscriber to be a registry. -//! -//! [`Layer`]: crate::layer::Layer -//! [`Subscriber`]: tracing_core::Subscriber -//! [ctx]: crate::layer::Context -//! [lookup]: crate::layer::Context::span() -use tracing_core::{field::FieldSet, span::Id, Metadata}; - -feature! { - #![feature = "std"] - /// A module containing a type map of span extensions. - mod extensions; - pub use extensions::{Extensions, ExtensionsMut}; - -} - -feature! { - #![all(feature = "registry", feature = "std")] - - mod sharded; - mod stack; - - pub use sharded::Data; - pub use sharded::Registry; - - use crate::filter::FilterId; -} - -/// Provides access to stored span data. -/// -/// Subscribers which store span data and associate it with span IDs should -/// implement this trait; if they do, any [`Layer`]s wrapping them can look up -/// metadata via the [`Context`] type's [`span()`] method. -/// -/// [`Layer`]: super::layer::Layer -/// [`Context`]: super::layer::Context -/// [`span()`]: super::layer::Context::span -pub trait LookupSpan<'a> { - /// The type of span data stored in this registry. - type Data: SpanData<'a>; - - /// Returns the [`SpanData`] for a given `Id`, if it exists. - /// - /// <pre class="ignore" style="white-space:normal;font:inherit;"> - /// <strong>Note</strong>: users of the <code>LookupSpan</code> trait should - /// typically call the <a href="#method.span"><code>span</code></a> method rather - /// than this method. The <code>span</code> method is implemented by - /// <em>calling</em> <code>span_data</code>, but returns a reference which is - /// capable of performing more sophisiticated queries. - /// </pre> - /// - fn span_data(&'a self, id: &Id) -> Option<Self::Data>; - - /// Returns a [`SpanRef`] for the span with the given `Id`, if it exists. - /// - /// A `SpanRef` is similar to [`SpanData`], but it allows performing - /// additional lookups against the registryr that stores the wrapped data. - /// - /// In general, _users_ of the `LookupSpan` trait should use this method - /// rather than the [`span_data`] method; while _implementors_ of this trait - /// should only implement `span_data`. - /// - /// [`span_data`]: LookupSpan::span_data() - fn span(&'a self, id: &Id) -> Option<SpanRef<'_, Self>> - where - Self: Sized, - { - let data = self.span_data(id)?; - Some(SpanRef { - registry: self, - data, - #[cfg(feature = "registry")] - filter: FilterId::none(), - }) - } - - /// Registers a [`Filter`] for [per-layer filtering] with this - /// [`Subscriber`]. - /// - /// The [`Filter`] can then use the returned [`FilterId`] to - /// [check if it previously enabled a span][check]. - /// - /// # Panics - /// - /// If this `Subscriber` does not support [per-layer filtering]. - /// - /// [`Filter`]: crate::layer::Filter - /// [per-layer filtering]: crate::layer::Layer#per-layer-filtering - /// [`Subscriber`]: tracing_core::Subscriber - /// [`FilterId`]: crate::filter::FilterId - /// [check]: SpanData::is_enabled_for - #[cfg(feature = "registry")] - #[cfg_attr(docsrs, doc(cfg(feature = "registry")))] - fn register_filter(&mut self) -> FilterId { - panic!( - "{} does not currently support filters", - std::any::type_name::<Self>() - ) - } -} - -/// A stored representation of data associated with a span. -pub trait SpanData<'a> { - /// Returns this span's ID. - fn id(&self) -> Id; - - /// Returns a reference to the span's `Metadata`. - fn metadata(&self) -> &'static Metadata<'static>; - - /// Returns a reference to the ID - fn parent(&self) -> Option<&Id>; - - /// Returns a reference to this span's `Extensions`. - /// - /// The extensions may be used by `Layer`s to store additional data - /// describing the span. - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] - fn extensions(&self) -> Extensions<'_>; - - /// Returns a mutable reference to this span's `Extensions`. - /// - /// The extensions may be used by `Layer`s to store additional data - /// describing the span. - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] - fn extensions_mut(&self) -> ExtensionsMut<'_>; - - /// Returns `true` if this span is enabled for the [per-layer filter][plf] - /// corresponding to the provided [`FilterId`]. - /// - /// ## Default Implementation - /// - /// By default, this method assumes that the [`LookupSpan`] implementation - /// does not support [per-layer filtering][plf], and always returns `true`. - /// - /// [plf]: crate::layer::Layer#per-layer-filtering - /// [`FilterId`]: crate::filter::FilterId - #[cfg(feature = "registry")] - #[cfg_attr(docsrs, doc(cfg(feature = "registry")))] - fn is_enabled_for(&self, filter: FilterId) -> bool { - let _ = filter; - true - } -} - -/// A reference to [span data] and the associated [registry]. -/// -/// This type implements all the same methods as [`SpanData`][span data], and -/// provides additional methods for querying the registry based on values from -/// the span. -/// -/// [span data]: SpanData -/// [registry]: LookupSpan -#[derive(Debug)] -pub struct SpanRef<'a, R: LookupSpan<'a>> { - registry: &'a R, - data: R::Data, - - #[cfg(feature = "registry")] - filter: FilterId, -} - -/// An iterator over the parents of a span, ordered from leaf to root. -/// -/// This is returned by the [`SpanRef::scope`] method. -#[derive(Debug)] -pub struct Scope<'a, R> { - registry: &'a R, - next: Option<Id>, - - #[cfg(all(feature = "registry", feature = "std"))] - filter: FilterId, -} - -feature! { - #![any(feature = "alloc", feature = "std")] - - #[cfg(not(feature = "smallvec"))] - use alloc::vec::{self, Vec}; - - use core::{fmt,iter}; - - /// An iterator over the parents of a span, ordered from root to leaf. - /// - /// This is returned by the [`Scope::from_root`] method. - pub struct ScopeFromRoot<'a, R> - where - R: LookupSpan<'a>, - { - #[cfg(feature = "smallvec")] - spans: iter::Rev<smallvec::IntoIter<SpanRefVecArray<'a, R>>>, - #[cfg(not(feature = "smallvec"))] - spans: iter::Rev<vec::IntoIter<SpanRef<'a, R>>>, - } - - #[cfg(feature = "smallvec")] - type SpanRefVecArray<'span, L> = [SpanRef<'span, L>; 16]; - - impl<'a, R> Scope<'a, R> - where - R: LookupSpan<'a>, - { - /// Flips the order of the iterator, so that it is ordered from root to leaf. - /// - /// The iterator will first return the root span, then that span's immediate child, - /// and so on until it finally returns the span that [`SpanRef::scope`] was called on. - /// - /// If any items were consumed from the [`Scope`] before calling this method then they - /// will *not* be returned from the [`ScopeFromRoot`]. - /// - /// **Note**: this will allocate if there are many spans remaining, or if the - /// "smallvec" feature flag is not enabled. - #[allow(clippy::wrong_self_convention)] - pub fn from_root(self) -> ScopeFromRoot<'a, R> { - #[cfg(feature = "smallvec")] - type Buf<T> = smallvec::SmallVec<T>; - #[cfg(not(feature = "smallvec"))] - type Buf<T> = Vec<T>; - ScopeFromRoot { - spans: self.collect::<Buf<_>>().into_iter().rev(), - } - } - } - - impl<'a, R> Iterator for ScopeFromRoot<'a, R> - where - R: LookupSpan<'a>, - { - type Item = SpanRef<'a, R>; - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - self.spans.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.spans.size_hint() - } - } - - impl<'a, R> fmt::Debug for ScopeFromRoot<'a, R> - where - R: LookupSpan<'a>, - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("ScopeFromRoot { .. }") - } - } -} - -impl<'a, R> Iterator for Scope<'a, R> -where - R: LookupSpan<'a>, -{ - type Item = SpanRef<'a, R>; - - fn next(&mut self) -> Option<Self::Item> { - loop { - let curr = self.registry.span(self.next.as_ref()?)?; - - #[cfg(all(feature = "registry", feature = "std"))] - let curr = curr.with_filter(self.filter); - self.next = curr.data.parent().cloned(); - - // If the `Scope` is filtered, check if the current span is enabled - // by the selected filter ID. - - #[cfg(all(feature = "registry", feature = "std"))] - { - if !curr.is_enabled_for(self.filter) { - // The current span in the chain is disabled for this - // filter. Try its parent. - continue; - } - } - - return Some(curr); - } - } -} - -impl<'a, R> SpanRef<'a, R> -where - R: LookupSpan<'a>, -{ - /// Returns this span's ID. - pub fn id(&self) -> Id { - self.data.id() - } - - /// Returns a static reference to the span's metadata. - pub fn metadata(&self) -> &'static Metadata<'static> { - self.data.metadata() - } - - /// Returns the span's name, - pub fn name(&self) -> &'static str { - self.data.metadata().name() - } - - /// Returns a list of [fields] defined by the span. - /// - /// [fields]: tracing_core::field - pub fn fields(&self) -> &FieldSet { - self.data.metadata().fields() - } - - /// Returns a `SpanRef` describing this span's parent, or `None` if this - /// span is the root of its trace tree. - pub fn parent(&self) -> Option<Self> { - let id = self.data.parent()?; - let data = self.registry.span_data(id)?; - - #[cfg(all(feature = "registry", feature = "std"))] - { - // move these into mut bindings if the registry feature is enabled, - // since they may be mutated in the loop. - let mut data = data; - loop { - // Is this parent enabled by our filter? - if data.is_enabled_for(self.filter) { - return Some(Self { - registry: self.registry, - filter: self.filter, - data, - }); - } - - // It's not enabled. If the disabled span has a parent, try that! - let id = data.parent()?; - data = self.registry.span_data(id)?; - } - } - - #[cfg(not(all(feature = "registry", feature = "std")))] - Some(Self { - registry: self.registry, - data, - }) - } - - /// Returns an iterator over all parents of this span, starting with this span, - /// ordered from leaf to root. - /// - /// The iterator will first return the span, then the span's immediate parent, - /// followed by that span's parent, and so on, until it reaches a root span. - /// - /// ```rust - /// use tracing::{span, Subscriber}; - /// use tracing_subscriber::{ - /// layer::{Context, Layer}, - /// prelude::*, - /// registry::LookupSpan, - /// }; - /// - /// struct PrintingLayer; - /// impl<S> Layer<S> for PrintingLayer - /// where - /// S: Subscriber + for<'lookup> LookupSpan<'lookup>, - /// { - /// fn on_enter(&self, id: &span::Id, ctx: Context<S>) { - /// let span = ctx.span(id).unwrap(); - /// let scope = span.scope().map(|span| span.name()).collect::<Vec<_>>(); - /// println!("Entering span: {:?}", scope); - /// } - /// } - /// - /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || { - /// let _root = tracing::info_span!("root").entered(); - /// // Prints: Entering span: ["root"] - /// let _child = tracing::info_span!("child").entered(); - /// // Prints: Entering span: ["child", "root"] - /// let _leaf = tracing::info_span!("leaf").entered(); - /// // Prints: Entering span: ["leaf", "child", "root"] - /// }); - /// ``` - /// - /// If the opposite order (from the root to this span) is desired, calling [`Scope::from_root`] on - /// the returned iterator reverses the order. - /// - /// ```rust - /// # use tracing::{span, Subscriber}; - /// # use tracing_subscriber::{ - /// # layer::{Context, Layer}, - /// # prelude::*, - /// # registry::LookupSpan, - /// # }; - /// # struct PrintingLayer; - /// impl<S> Layer<S> for PrintingLayer - /// where - /// S: Subscriber + for<'lookup> LookupSpan<'lookup>, - /// { - /// fn on_enter(&self, id: &span::Id, ctx: Context<S>) { - /// let span = ctx.span(id).unwrap(); - /// let scope = span.scope().from_root().map(|span| span.name()).collect::<Vec<_>>(); - /// println!("Entering span: {:?}", scope); - /// } - /// } - /// - /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || { - /// let _root = tracing::info_span!("root").entered(); - /// // Prints: Entering span: ["root"] - /// let _child = tracing::info_span!("child").entered(); - /// // Prints: Entering span: ["root", "child"] - /// let _leaf = tracing::info_span!("leaf").entered(); - /// // Prints: Entering span: ["root", "child", "leaf"] - /// }); - /// ``` - pub fn scope(&self) -> Scope<'a, R> { - Scope { - registry: self.registry, - next: Some(self.id()), - - #[cfg(feature = "registry")] - filter: self.filter, - } - } - - /// Returns a reference to this span's `Extensions`. - /// - /// The extensions may be used by `Layer`s to store additional data - /// describing the span. - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] - pub fn extensions(&self) -> Extensions<'_> { - self.data.extensions() - } - - /// Returns a mutable reference to this span's `Extensions`. - /// - /// The extensions may be used by `Layer`s to store additional data - /// describing the span. - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] - pub fn extensions_mut(&self) -> ExtensionsMut<'_> { - self.data.extensions_mut() - } - - #[cfg(all(feature = "registry", feature = "std"))] - pub(crate) fn try_with_filter(self, filter: FilterId) -> Option<Self> { - if self.is_enabled_for(filter) { - return Some(self.with_filter(filter)); - } - - None - } - - #[inline] - #[cfg(all(feature = "registry", feature = "std"))] - pub(crate) fn is_enabled_for(&self, filter: FilterId) -> bool { - self.data.is_enabled_for(filter) - } - - #[inline] - #[cfg(all(feature = "registry", feature = "std"))] - fn with_filter(self, filter: FilterId) -> Self { - Self { filter, ..self } - } -} - -#[cfg(all(test, feature = "registry", feature = "std"))] -mod tests { - use crate::{ - layer::{Context, Layer}, - prelude::*, - registry::LookupSpan, - }; - use std::sync::{Arc, Mutex}; - use tracing::{span, Subscriber}; - - #[test] - fn spanref_scope_iteration_order() { - let last_entered_scope = Arc::new(Mutex::new(Vec::new())); - - #[derive(Default)] - struct PrintingLayer { - last_entered_scope: Arc<Mutex<Vec<&'static str>>>, - } - - impl<S> Layer<S> for PrintingLayer - where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - { - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - let span = ctx.span(id).unwrap(); - let scope = span.scope().map(|span| span.name()).collect::<Vec<_>>(); - *self.last_entered_scope.lock().unwrap() = scope; - } - } - - let _guard = tracing::subscriber::set_default(crate::registry().with(PrintingLayer { - last_entered_scope: last_entered_scope.clone(), - })); - - let _root = tracing::info_span!("root").entered(); - assert_eq!(&*last_entered_scope.lock().unwrap(), &["root"]); - let _child = tracing::info_span!("child").entered(); - assert_eq!(&*last_entered_scope.lock().unwrap(), &["child", "root"]); - let _leaf = tracing::info_span!("leaf").entered(); - assert_eq!( - &*last_entered_scope.lock().unwrap(), - &["leaf", "child", "root"] - ); - } - - #[test] - fn spanref_scope_fromroot_iteration_order() { - let last_entered_scope = Arc::new(Mutex::new(Vec::new())); - - #[derive(Default)] - struct PrintingLayer { - last_entered_scope: Arc<Mutex<Vec<&'static str>>>, - } - - impl<S> Layer<S> for PrintingLayer - where - S: Subscriber + for<'lookup> LookupSpan<'lookup>, - { - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - let span = ctx.span(id).unwrap(); - let scope = span - .scope() - .from_root() - .map(|span| span.name()) - .collect::<Vec<_>>(); - *self.last_entered_scope.lock().unwrap() = scope; - } - } - - let _guard = tracing::subscriber::set_default(crate::registry().with(PrintingLayer { - last_entered_scope: last_entered_scope.clone(), - })); - - let _root = tracing::info_span!("root").entered(); - assert_eq!(&*last_entered_scope.lock().unwrap(), &["root"]); - let _child = tracing::info_span!("child").entered(); - assert_eq!(&*last_entered_scope.lock().unwrap(), &["root", "child",]); - let _leaf = tracing::info_span!("leaf").entered(); - assert_eq!( - &*last_entered_scope.lock().unwrap(), - &["root", "child", "leaf"] - ); - } -} diff --git a/vendor/tracing-subscriber/src/registry/sharded.rs b/vendor/tracing-subscriber/src/registry/sharded.rs deleted file mode 100644 index b81d5fef8..000000000 --- a/vendor/tracing-subscriber/src/registry/sharded.rs +++ /dev/null @@ -1,901 +0,0 @@ -use sharded_slab::{pool::Ref, Clear, Pool}; -use thread_local::ThreadLocal; - -use super::stack::SpanStack; -use crate::{ - filter::{FilterId, FilterMap, FilterState}, - registry::{ - extensions::{Extensions, ExtensionsInner, ExtensionsMut}, - LookupSpan, SpanData, - }, - sync::RwLock, -}; -use std::{ - cell::{self, Cell, RefCell}, - sync::atomic::{fence, AtomicUsize, Ordering}, -}; -use tracing_core::{ - dispatcher::{self, Dispatch}, - span::{self, Current, Id}, - Event, Interest, Metadata, Subscriber, -}; - -/// A shared, reusable store for spans. -/// -/// A `Registry` is a [`Subscriber`] around which multiple [`Layer`]s -/// implementing various behaviors may be [added]. Unlike other types -/// implementing `Subscriber`, `Registry` does not actually record traces itself: -/// instead, it collects and stores span data that is exposed to any [`Layer`]s -/// wrapping it through implementations of the [`LookupSpan`] trait. -/// The `Registry` is responsible for storing span metadata, recording -/// relationships between spans, and tracking which spans are active and which -/// are closed. In addition, it provides a mechanism for [`Layer`]s to store -/// user-defined per-span data, called [extensions], in the registry. This -/// allows [`Layer`]-specific data to benefit from the `Registry`'s -/// high-performance concurrent storage. -/// -/// This registry is implemented using a [lock-free sharded slab][slab], and is -/// highly optimized for concurrent access. -/// -/// # Span ID Generation -/// -/// Span IDs are not globally unique, but the registry ensures that -/// no two currently active spans have the same ID within a process. -/// -/// One of the primary responsibilities of the registry is to generate [span -/// IDs]. Therefore, it's important for other code that interacts with the -/// registry, such as [`Layer`]s, to understand the guarantees of the -/// span IDs that are generated. -/// -/// The registry's span IDs are guaranteed to be unique **at a given point -/// in time**. This means that an active span will never be assigned the -/// same ID as another **currently active** span. However, the registry -/// **will** eventually reuse the IDs of [closed] spans, although an ID -/// will never be reassigned immediately after a span has closed. -/// -/// Spans are not [considered closed] by the `Registry` until *every* -/// [`Span`] reference with that ID has been dropped. -/// -/// Thus: span IDs generated by the registry should be considered unique -/// only at a given point in time, and only relative to other spans -/// generated by the same process. Two spans with the same ID will not exist -/// in the same process concurrently. However, if historical span data is -/// being stored, the same ID may occur for multiple spans times in that -/// data. If spans must be uniquely identified in historical data, the user -/// code storing this data must assign its own unique identifiers to those -/// spans. A counter is generally sufficient for this. -/// -/// Similarly, span IDs generated by the registry are not unique outside of -/// a given process. Distributed tracing systems may require identifiers -/// that are unique across multiple processes on multiple machines (for -/// example, [OpenTelemetry's `SpanId`s and `TraceId`s][ot]). `tracing` span -/// IDs generated by the registry should **not** be used for this purpose. -/// Instead, code which integrates with a distributed tracing system should -/// generate and propagate its own IDs according to the rules specified by -/// the distributed tracing system. These IDs can be associated with -/// `tracing` spans using [fields] and/or [stored span data]. -/// -/// [span IDs]: tracing_core::span::Id -/// [slab]: sharded_slab -/// [`Layer`]: crate::Layer -/// [added]: crate::layer::Layer#composing-layers -/// [extensions]: super::Extensions -/// [closed]: https://docs.rs/tracing/latest/tracing/span/index.html#closing-spans -/// [considered closed]: tracing_core::subscriber::Subscriber::try_close() -/// [`Span`]: https://docs.rs/tracing/latest/tracing/span/struct.Span.html -/// [ot]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#spancontext -/// [fields]: tracing_core::field -/// [stored span data]: crate::registry::SpanData::extensions_mut -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))] -#[derive(Debug)] -pub struct Registry { - spans: Pool<DataInner>, - current_spans: ThreadLocal<RefCell<SpanStack>>, - next_filter_id: u8, -} - -/// Span data stored in a [`Registry`]. -/// -/// The registry stores well-known data defined by tracing: span relationships, -/// metadata and reference counts. Additional user-defined data provided by -/// [`Layer`s], such as formatted fields, metrics, or distributed traces should -/// be stored in the [extensions] typemap. -/// -/// [`Layer`s]: crate::layer::Layer -/// [extensions]: Extensions -#[cfg(feature = "registry")] -#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))] -#[derive(Debug)] -pub struct Data<'a> { - /// Immutable reference to the pooled `DataInner` entry. - inner: Ref<'a, DataInner>, -} - -/// Stored data associated with a span. -/// -/// This type is pooled using [`sharded_slab::Pool`]; when a span is -/// dropped, the `DataInner` entry at that span's slab index is cleared -/// in place and reused by a future span. Thus, the `Default` and -/// [`sharded_slab::Clear`] implementations for this type are -/// load-bearing. -#[derive(Debug)] -struct DataInner { - filter_map: FilterMap, - metadata: &'static Metadata<'static>, - parent: Option<Id>, - ref_count: AtomicUsize, - // The span's `Extensions` typemap. Allocations for the `HashMap` backing - // this are pooled and reused in place. - pub(crate) extensions: RwLock<ExtensionsInner>, -} - -// === impl Registry === - -impl Default for Registry { - fn default() -> Self { - Self { - spans: Pool::new(), - current_spans: ThreadLocal::new(), - next_filter_id: 0, - } - } -} - -#[inline] -fn idx_to_id(idx: usize) -> Id { - Id::from_u64(idx as u64 + 1) -} - -#[inline] -fn id_to_idx(id: &Id) -> usize { - id.into_u64() as usize - 1 -} - -/// A guard that tracks how many [`Registry`]-backed `Layer`s have -/// processed an `on_close` event. -/// -/// This is needed to enable a [`Registry`]-backed Layer to access span -/// data after the `Layer` has recieved the `on_close` callback. -/// -/// Once all `Layer`s have processed this event, the [`Registry`] knows -/// that is able to safely remove the span tracked by `id`. `CloseGuard` -/// accomplishes this through a two-step process: -/// 1. Whenever a [`Registry`]-backed `Layer::on_close` method is -/// called, `Registry::start_close` is closed. -/// `Registry::start_close` increments a thread-local `CLOSE_COUNT` -/// by 1 and returns a `CloseGuard`. -/// 2. The `CloseGuard` is dropped at the end of `Layer::on_close`. On -/// drop, `CloseGuard` checks thread-local `CLOSE_COUNT`. If -/// `CLOSE_COUNT` is 0, the `CloseGuard` removes the span with the -/// `id` from the registry, as all `Layers` that might have seen the -/// `on_close` notification have processed it. If `CLOSE_COUNT` is -/// greater than 0, `CloseGuard` decrements the counter by one and -/// _does not_ remove the span from the [`Registry`]. -/// -pub(crate) struct CloseGuard<'a> { - id: Id, - registry: &'a Registry, - is_closing: bool, -} - -impl Registry { - fn get(&self, id: &Id) -> Option<Ref<'_, DataInner>> { - self.spans.get(id_to_idx(id)) - } - - /// Returns a guard which tracks how many `Layer`s have - /// processed an `on_close` notification via the `CLOSE_COUNT` thread-local. - /// For additional details, see [`CloseGuard`]. - /// - pub(crate) fn start_close(&self, id: Id) -> CloseGuard<'_> { - CLOSE_COUNT.with(|count| { - let c = count.get(); - count.set(c + 1); - }); - CloseGuard { - id, - registry: self, - is_closing: false, - } - } - - pub(crate) fn has_per_layer_filters(&self) -> bool { - self.next_filter_id > 0 - } - - pub(crate) fn span_stack(&self) -> cell::Ref<'_, SpanStack> { - self.current_spans.get_or_default().borrow() - } -} - -thread_local! { - /// `CLOSE_COUNT` is the thread-local counter used by `CloseGuard` to - /// track how many layers have processed the close. - /// For additional details, see [`CloseGuard`]. - /// - static CLOSE_COUNT: Cell<usize> = Cell::new(0); -} - -impl Subscriber for Registry { - fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest { - if self.has_per_layer_filters() { - return FilterState::take_interest().unwrap_or_else(Interest::always); - } - - Interest::always() - } - - fn enabled(&self, _: &Metadata<'_>) -> bool { - if self.has_per_layer_filters() { - return FilterState::event_enabled(); - } - true - } - - #[inline] - fn new_span(&self, attrs: &span::Attributes<'_>) -> span::Id { - let parent = if attrs.is_root() { - None - } else if attrs.is_contextual() { - self.current_span().id().map(|id| self.clone_span(id)) - } else { - attrs.parent().map(|id| self.clone_span(id)) - }; - - let id = self - .spans - // Check out a `DataInner` entry from the pool for the new span. If - // there are free entries already allocated in the pool, this will - // preferentially reuse one; otherwise, a new `DataInner` is - // allocated and added to the pool. - .create_with(|data| { - data.metadata = attrs.metadata(); - data.parent = parent; - data.filter_map = crate::filter::FILTERING.with(|filtering| filtering.filter_map()); - #[cfg(debug_assertions)] - { - if data.filter_map != FilterMap::default() { - debug_assert!(self.has_per_layer_filters()); - } - } - - let refs = data.ref_count.get_mut(); - debug_assert_eq!(*refs, 0); - *refs = 1; - }) - .expect("Unable to allocate another span"); - idx_to_id(id) - } - - /// This is intentionally not implemented, as recording fields - /// on a span is the responsibility of layers atop of this registry. - #[inline] - fn record(&self, _: &span::Id, _: &span::Record<'_>) {} - - fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {} - - /// This is intentionally not implemented, as recording events - /// is the responsibility of layers atop of this registry. - fn event(&self, _: &Event<'_>) {} - - fn enter(&self, id: &span::Id) { - if self - .current_spans - .get_or_default() - .borrow_mut() - .push(id.clone()) - { - self.clone_span(id); - } - } - - fn exit(&self, id: &span::Id) { - if let Some(spans) = self.current_spans.get() { - if spans.borrow_mut().pop(id) { - dispatcher::get_default(|dispatch| dispatch.try_close(id.clone())); - } - } - } - - fn clone_span(&self, id: &span::Id) -> span::Id { - let span = self - .get(id) - .unwrap_or_else(|| panic!( - "tried to clone {:?}, but no span exists with that ID\n\ - This may be caused by consuming a parent span (`parent: span`) rather than borrowing it (`parent: &span`).", - id, - )); - // Like `std::sync::Arc`, adds to the ref count (on clone) don't require - // a strong ordering; if we call` clone_span`, the reference count must - // always at least 1. The only synchronization necessary is between - // calls to `try_close`: we have to ensure that all threads have - // dropped their refs to the span before the span is closed. - let refs = span.ref_count.fetch_add(1, Ordering::Relaxed); - assert_ne!( - refs, 0, - "tried to clone a span ({:?}) that already closed", - id - ); - id.clone() - } - - fn current_span(&self) -> Current { - self.current_spans - .get() - .and_then(|spans| { - let spans = spans.borrow(); - let id = spans.current()?; - let span = self.get(id)?; - Some(Current::new(id.clone(), span.metadata)) - }) - .unwrap_or_else(Current::none) - } - - /// Decrements the reference count of the span with the given `id`, and - /// removes the span if it is zero. - /// - /// The allocated span slot will be reused when a new span is created. - fn try_close(&self, id: span::Id) -> bool { - let span = match self.get(&id) { - Some(span) => span, - None if std::thread::panicking() => return false, - None => panic!("tried to drop a ref to {:?}, but no such span exists!", id), - }; - - let refs = span.ref_count.fetch_sub(1, Ordering::Release); - if !std::thread::panicking() { - assert!(refs < std::usize::MAX, "reference count overflow!"); - } - if refs > 1 { - return false; - } - - // Synchronize if we are actually removing the span (stolen - // from std::Arc); this ensures that all other `try_close` calls on - // other threads happen-before we actually remove the span. - fence(Ordering::Acquire); - true - } -} - -impl<'a> LookupSpan<'a> for Registry { - type Data = Data<'a>; - - fn span_data(&'a self, id: &Id) -> Option<Self::Data> { - let inner = self.get(id)?; - Some(Data { inner }) - } - - fn register_filter(&mut self) -> FilterId { - let id = FilterId::new(self.next_filter_id); - self.next_filter_id += 1; - id - } -} - -// === impl CloseGuard === - -impl<'a> CloseGuard<'a> { - pub(crate) fn set_closing(&mut self) { - self.is_closing = true; - } -} - -impl<'a> Drop for CloseGuard<'a> { - fn drop(&mut self) { - // If this returns with an error, we are already panicking. At - // this point, there's nothing we can really do to recover - // except by avoiding a double-panic. - let _ = CLOSE_COUNT.try_with(|count| { - let c = count.get(); - // Decrement the count to indicate that _this_ guard's - // `on_close` callback has completed. - // - // Note that we *must* do this before we actually remove the span - // from the registry, since dropping the `DataInner` may trigger a - // new close, if this span is the last reference to a parent span. - count.set(c - 1); - - // If the current close count is 1, this stack frame is the last - // `on_close` call. If the span is closing, it's okay to remove the - // span. - if c == 1 && self.is_closing { - self.registry.spans.clear(id_to_idx(&self.id)); - } - }); - } -} - -// === impl Data === - -impl<'a> SpanData<'a> for Data<'a> { - fn id(&self) -> Id { - idx_to_id(self.inner.key()) - } - - fn metadata(&self) -> &'static Metadata<'static> { - (*self).inner.metadata - } - - fn parent(&self) -> Option<&Id> { - self.inner.parent.as_ref() - } - - fn extensions(&self) -> Extensions<'_> { - Extensions::new(self.inner.extensions.read().expect("Mutex poisoned")) - } - - fn extensions_mut(&self) -> ExtensionsMut<'_> { - ExtensionsMut::new(self.inner.extensions.write().expect("Mutex poisoned")) - } - - #[inline] - fn is_enabled_for(&self, filter: FilterId) -> bool { - self.inner.filter_map.is_enabled(filter) - } -} - -// === impl DataInner === - -impl Default for DataInner { - fn default() -> Self { - // Since `DataInner` owns a `&'static Callsite` pointer, we need - // something to use as the initial default value for that callsite. - // Since we can't access a `DataInner` until it has had actual span data - // inserted into it, the null metadata will never actually be accessed. - struct NullCallsite; - impl tracing_core::callsite::Callsite for NullCallsite { - fn set_interest(&self, _: Interest) { - unreachable!( - "/!\\ Tried to register the null callsite /!\\\n \ - This should never have happened and is definitely a bug. \ - A `tracing` bug report would be appreciated." - ) - } - - fn metadata(&self) -> &Metadata<'_> { - unreachable!( - "/!\\ Tried to access the null callsite's metadata /!\\\n \ - This should never have happened and is definitely a bug. \ - A `tracing` bug report would be appreciated." - ) - } - } - - static NULL_CALLSITE: NullCallsite = NullCallsite; - static NULL_METADATA: Metadata<'static> = tracing_core::metadata! { - name: "", - target: "", - level: tracing_core::Level::TRACE, - fields: &[], - callsite: &NULL_CALLSITE, - kind: tracing_core::metadata::Kind::SPAN, - }; - - Self { - filter_map: FilterMap::default(), - metadata: &NULL_METADATA, - parent: None, - ref_count: AtomicUsize::new(0), - extensions: RwLock::new(ExtensionsInner::new()), - } - } -} - -impl Clear for DataInner { - /// Clears the span's data in place, dropping the parent's reference count. - fn clear(&mut self) { - // A span is not considered closed until all of its children have closed. - // Therefore, each span's `DataInner` holds a "reference" to the parent - // span, keeping the parent span open until all its children have closed. - // When we close a span, we must then decrement the parent's ref count - // (potentially, allowing it to close, if this child is the last reference - // to that span). - // We have to actually unpack the option inside the `get_default` - // closure, since it is a `FnMut`, but testing that there _is_ a value - // here lets us avoid the thread-local access if we don't need the - // dispatcher at all. - if self.parent.is_some() { - // Note that --- because `Layered::try_close` works by calling - // `try_close` on the inner subscriber and using the return value to - // determine whether to call the `Layer`'s `on_close` callback --- - // we must call `try_close` on the entire subscriber stack, rather - // than just on the registry. If the registry called `try_close` on - // itself directly, the layers wouldn't see the close notification. - let subscriber = dispatcher::get_default(Dispatch::clone); - if let Some(parent) = self.parent.take() { - let _ = subscriber.try_close(parent); - } - } - - // Clear (but do not deallocate!) the pooled `HashMap` for the span's extensions. - self.extensions - .get_mut() - .unwrap_or_else(|l| { - // This function can be called in a `Drop` impl, such as while - // panicking, so ignore lock poisoning. - l.into_inner() - }) - .clear(); - - self.filter_map = FilterMap::default(); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{layer::Context, registry::LookupSpan, Layer}; - use std::{ - collections::HashMap, - sync::{Arc, Mutex, Weak}, - }; - use tracing::{self, subscriber::with_default}; - use tracing_core::{ - dispatcher, - span::{Attributes, Id}, - Subscriber, - }; - - #[derive(Debug)] - struct DoesNothing; - impl<S: Subscriber> Layer<S> for DoesNothing {} - - struct AssertionLayer; - impl<S> Layer<S> for AssertionLayer - where - S: Subscriber + for<'a> LookupSpan<'a>, - { - fn on_close(&self, id: Id, ctx: Context<'_, S>) { - dbg!(format_args!("closing {:?}", id)); - assert!(&ctx.span(&id).is_some()); - } - } - - #[test] - fn single_layer_can_access_closed_span() { - let subscriber = AssertionLayer.with_subscriber(Registry::default()); - - with_default(subscriber, || { - let span = tracing::debug_span!("span"); - drop(span); - }); - } - - #[test] - fn multiple_layers_can_access_closed_span() { - let subscriber = AssertionLayer - .and_then(AssertionLayer) - .with_subscriber(Registry::default()); - - with_default(subscriber, || { - let span = tracing::debug_span!("span"); - drop(span); - }); - } - - struct CloseLayer { - inner: Arc<Mutex<CloseState>>, - } - - struct CloseHandle { - state: Arc<Mutex<CloseState>>, - } - - #[derive(Default)] - struct CloseState { - open: HashMap<&'static str, Weak<()>>, - closed: Vec<(&'static str, Weak<()>)>, - } - - struct SetRemoved(Arc<()>); - - impl<S> Layer<S> for CloseLayer - where - S: Subscriber + for<'a> LookupSpan<'a>, - { - fn on_new_span(&self, _: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { - let span = ctx.span(id).expect("Missing span; this is a bug"); - let mut lock = self.inner.lock().unwrap(); - let is_removed = Arc::new(()); - assert!( - lock.open - .insert(span.name(), Arc::downgrade(&is_removed)) - .is_none(), - "test layer saw multiple spans with the same name, the test is probably messed up" - ); - let mut extensions = span.extensions_mut(); - extensions.insert(SetRemoved(is_removed)); - } - - fn on_close(&self, id: Id, ctx: Context<'_, S>) { - let span = if let Some(span) = ctx.span(&id) { - span - } else { - println!( - "span {:?} did not exist in `on_close`, are we panicking?", - id - ); - return; - }; - let name = span.name(); - println!("close {} ({:?})", name, id); - if let Ok(mut lock) = self.inner.lock() { - if let Some(is_removed) = lock.open.remove(name) { - assert!(is_removed.upgrade().is_some()); - lock.closed.push((name, is_removed)); - } - } - } - } - - impl CloseLayer { - fn new() -> (Self, CloseHandle) { - let state = Arc::new(Mutex::new(CloseState::default())); - ( - Self { - inner: state.clone(), - }, - CloseHandle { state }, - ) - } - } - - impl CloseState { - fn is_open(&self, span: &str) -> bool { - self.open.contains_key(span) - } - - fn is_closed(&self, span: &str) -> bool { - self.closed.iter().any(|(name, _)| name == &span) - } - } - - impl CloseHandle { - fn assert_closed(&self, span: &str) { - let lock = self.state.lock().unwrap(); - assert!( - lock.is_closed(span), - "expected {} to be closed{}", - span, - if lock.is_open(span) { - " (it was still open)" - } else { - ", but it never existed (is there a problem with the test?)" - } - ) - } - - fn assert_open(&self, span: &str) { - let lock = self.state.lock().unwrap(); - assert!( - lock.is_open(span), - "expected {} to be open{}", - span, - if lock.is_closed(span) { - " (it was still open)" - } else { - ", but it never existed (is there a problem with the test?)" - } - ) - } - - fn assert_removed(&self, span: &str) { - let lock = self.state.lock().unwrap(); - let is_removed = match lock.closed.iter().find(|(name, _)| name == &span) { - Some((_, is_removed)) => is_removed, - None => panic!( - "expected {} to be removed from the registry, but it was not closed {}", - span, - if lock.is_closed(span) { - " (it was still open)" - } else { - ", but it never existed (is there a problem with the test?)" - } - ), - }; - assert!( - is_removed.upgrade().is_none(), - "expected {} to have been removed from the registry", - span - ) - } - - fn assert_not_removed(&self, span: &str) { - let lock = self.state.lock().unwrap(); - let is_removed = match lock.closed.iter().find(|(name, _)| name == &span) { - Some((_, is_removed)) => is_removed, - None if lock.is_open(span) => return, - None => unreachable!(), - }; - assert!( - is_removed.upgrade().is_some(), - "expected {} to have been removed from the registry", - span - ) - } - - #[allow(unused)] // may want this for future tests - fn assert_last_closed(&self, span: Option<&str>) { - let lock = self.state.lock().unwrap(); - let last = lock.closed.last().map(|(span, _)| span); - assert_eq!( - last, - span.as_ref(), - "expected {:?} to have closed last", - span - ); - } - - fn assert_closed_in_order(&self, order: impl AsRef<[&'static str]>) { - let lock = self.state.lock().unwrap(); - let order = order.as_ref(); - for (i, name) in order.iter().enumerate() { - assert_eq!( - lock.closed.get(i).map(|(span, _)| span), - Some(name), - "expected close order: {:?}, actual: {:?}", - order, - lock.closed.iter().map(|(name, _)| name).collect::<Vec<_>>() - ); - } - } - } - - #[test] - fn spans_are_removed_from_registry() { - let (close_layer, state) = CloseLayer::new(); - let subscriber = AssertionLayer - .and_then(close_layer) - .with_subscriber(Registry::default()); - - // Create a `Dispatch` (which is internally reference counted) so that - // the subscriber lives to the end of the test. Otherwise, if we just - // passed the subscriber itself to `with_default`, we could see the span - // be dropped when the subscriber itself is dropped, destroying the - // registry. - let dispatch = dispatcher::Dispatch::new(subscriber); - - dispatcher::with_default(&dispatch, || { - let span = tracing::debug_span!("span1"); - drop(span); - let span = tracing::info_span!("span2"); - drop(span); - }); - - state.assert_removed("span1"); - state.assert_removed("span2"); - - // Ensure the registry itself outlives the span. - drop(dispatch); - } - - #[test] - fn spans_are_only_closed_when_the_last_ref_drops() { - let (close_layer, state) = CloseLayer::new(); - let subscriber = AssertionLayer - .and_then(close_layer) - .with_subscriber(Registry::default()); - - // Create a `Dispatch` (which is internally reference counted) so that - // the subscriber lives to the end of the test. Otherwise, if we just - // passed the subscriber itself to `with_default`, we could see the span - // be dropped when the subscriber itself is dropped, destroying the - // registry. - let dispatch = dispatcher::Dispatch::new(subscriber); - - let span2 = dispatcher::with_default(&dispatch, || { - let span = tracing::debug_span!("span1"); - drop(span); - let span2 = tracing::info_span!("span2"); - let span2_clone = span2.clone(); - drop(span2); - span2_clone - }); - - state.assert_removed("span1"); - state.assert_not_removed("span2"); - - drop(span2); - state.assert_removed("span1"); - - // Ensure the registry itself outlives the span. - drop(dispatch); - } - - #[test] - fn span_enter_guards_are_dropped_out_of_order() { - let (close_layer, state) = CloseLayer::new(); - let subscriber = AssertionLayer - .and_then(close_layer) - .with_subscriber(Registry::default()); - - // Create a `Dispatch` (which is internally reference counted) so that - // the subscriber lives to the end of the test. Otherwise, if we just - // passed the subscriber itself to `with_default`, we could see the span - // be dropped when the subscriber itself is dropped, destroying the - // registry. - let dispatch = dispatcher::Dispatch::new(subscriber); - - dispatcher::with_default(&dispatch, || { - let span1 = tracing::debug_span!("span1"); - let span2 = tracing::info_span!("span2"); - - let enter1 = span1.enter(); - let enter2 = span2.enter(); - - drop(enter1); - drop(span1); - - state.assert_removed("span1"); - state.assert_not_removed("span2"); - - drop(enter2); - state.assert_not_removed("span2"); - - drop(span2); - state.assert_removed("span1"); - state.assert_removed("span2"); - }); - } - - #[test] - fn child_closes_parent() { - // This test asserts that if a parent span's handle is dropped before - // a child span's handle, the parent will remain open until child - // closes, and will then be closed. - - let (close_layer, state) = CloseLayer::new(); - let subscriber = close_layer.with_subscriber(Registry::default()); - - let dispatch = dispatcher::Dispatch::new(subscriber); - - dispatcher::with_default(&dispatch, || { - let span1 = tracing::info_span!("parent"); - let span2 = tracing::info_span!(parent: &span1, "child"); - - state.assert_open("parent"); - state.assert_open("child"); - - drop(span1); - state.assert_open("parent"); - state.assert_open("child"); - - drop(span2); - state.assert_closed("parent"); - state.assert_closed("child"); - }); - } - - #[test] - fn child_closes_grandparent() { - // This test asserts that, when a span is kept open by a child which - // is *itself* kept open by a child, closing the grandchild will close - // both the parent *and* the grandparent. - let (close_layer, state) = CloseLayer::new(); - let subscriber = close_layer.with_subscriber(Registry::default()); - - let dispatch = dispatcher::Dispatch::new(subscriber); - - dispatcher::with_default(&dispatch, || { - let span1 = tracing::info_span!("grandparent"); - let span2 = tracing::info_span!(parent: &span1, "parent"); - let span3 = tracing::info_span!(parent: &span2, "child"); - - state.assert_open("grandparent"); - state.assert_open("parent"); - state.assert_open("child"); - - drop(span1); - drop(span2); - state.assert_open("grandparent"); - state.assert_open("parent"); - state.assert_open("child"); - - drop(span3); - - state.assert_closed_in_order(&["child", "parent", "grandparent"]); - }); - } -} diff --git a/vendor/tracing-subscriber/src/registry/stack.rs b/vendor/tracing-subscriber/src/registry/stack.rs deleted file mode 100644 index 4a3f7e59d..000000000 --- a/vendor/tracing-subscriber/src/registry/stack.rs +++ /dev/null @@ -1,77 +0,0 @@ -pub(crate) use tracing_core::span::Id; - -#[derive(Debug)] -struct ContextId { - id: Id, - duplicate: bool, -} - -/// `SpanStack` tracks what spans are currently executing on a thread-local basis. -/// -/// A "separate current span" for each thread is a semantic choice, as each span -/// can be executing in a different thread. -#[derive(Debug, Default)] -pub(crate) struct SpanStack { - stack: Vec<ContextId>, -} - -impl SpanStack { - #[inline] - pub(super) fn push(&mut self, id: Id) -> bool { - let duplicate = self.stack.iter().any(|i| i.id == id); - self.stack.push(ContextId { id, duplicate }); - !duplicate - } - - #[inline] - pub(super) fn pop(&mut self, expected_id: &Id) -> bool { - if let Some((idx, _)) = self - .stack - .iter() - .enumerate() - .rev() - .find(|(_, ctx_id)| ctx_id.id == *expected_id) - { - let ContextId { id: _, duplicate } = self.stack.remove(idx); - return !duplicate; - } - false - } - - #[inline] - pub(crate) fn iter(&self) -> impl Iterator<Item = &Id> { - self.stack - .iter() - .rev() - .filter_map(|ContextId { id, duplicate }| if !*duplicate { Some(id) } else { None }) - } - - #[inline] - pub(crate) fn current(&self) -> Option<&Id> { - self.iter().next() - } -} - -#[cfg(test)] -mod tests { - use super::{Id, SpanStack}; - - #[test] - fn pop_last_span() { - let mut stack = SpanStack::default(); - let id = Id::from_u64(1); - stack.push(id.clone()); - - assert!(stack.pop(&id)); - } - - #[test] - fn pop_first_span() { - let mut stack = SpanStack::default(); - stack.push(Id::from_u64(1)); - stack.push(Id::from_u64(2)); - - let id = Id::from_u64(1); - assert!(stack.pop(&id)); - } -} diff --git a/vendor/tracing-subscriber/src/reload.rs b/vendor/tracing-subscriber/src/reload.rs deleted file mode 100644 index 3d1743440..000000000 --- a/vendor/tracing-subscriber/src/reload.rs +++ /dev/null @@ -1,350 +0,0 @@ -//! Wrapper for a `Layer` to allow it to be dynamically reloaded. -//! -//! This module provides a [`Layer` type] implementing the [`Layer` trait] or [`Filter` trait] -//! which wraps another type implementing the corresponding trait. This -//! allows the wrapped type to be replaced with another -//! instance of that type at runtime. -//! -//! This can be used in cases where a subset of `Layer` or `Filter` functionality -//! should be dynamically reconfigured, such as when filtering directives may -//! change at runtime. Note that this layer introduces a (relatively small) -//! amount of overhead, and should thus only be used as needed. -//! -//! # Examples -//! -//! Reloading a [global filtering](crate::layer#global-filtering) layer: -//! -//! ```rust -//! # use tracing::info; -//! use tracing_subscriber::{filter, fmt, reload, prelude::*}; -//! let filter = filter::LevelFilter::WARN; -//! let (filter, reload_handle) = reload::Layer::new(filter); -//! tracing_subscriber::registry() -//! .with(filter) -//! .with(fmt::Layer::default()) -//! .init(); -//! # -//! # // specifying the Registry type is required -//! # let _: &reload::Handle<filter::LevelFilter, tracing_subscriber::Registry> = &reload_handle; -//! # -//! info!("This will be ignored"); -//! reload_handle.modify(|filter| *filter = filter::LevelFilter::INFO); -//! info!("This will be logged"); -//! ``` -//! -//! Reloading a [`Filtered`](crate::filter::Filtered) layer: -//! -//! ```rust -//! # use tracing::info; -//! use tracing_subscriber::{filter, fmt, reload, prelude::*}; -//! let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN); -//! let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer); -//! # -//! # // specifying the Registry type is required -//! # let _: &reload::Handle<filter::Filtered<fmt::Layer<tracing_subscriber::Registry>, -//! # filter::LevelFilter, tracing_subscriber::Registry>,tracing_subscriber::Registry> -//! # = &reload_handle; -//! # -//! tracing_subscriber::registry() -//! .with(filtered_layer) -//! .init(); -//! info!("This will be ignored"); -//! reload_handle.modify(|layer| *layer.filter_mut() = filter::LevelFilter::INFO); -//! info!("This will be logged"); -//! ``` -//! -//! ## Note -//! -//! The [`Layer`] implementation is unable to implement downcasting functionality, -//! so certain [`Layer`] will fail to downcast if wrapped in a `reload::Layer`. -//! -//! If you only want to be able to dynamically change the -//! `Filter` on a layer, prefer wrapping that `Filter` in the `reload::Layer`. -//! -//! [`Filter` trait]: crate::layer::Filter -//! [`Layer` type]: Layer -//! [`Layer` trait]: super::layer::Layer -use crate::layer; -use crate::sync::RwLock; - -use std::{ - error, fmt, - marker::PhantomData, - sync::{Arc, Weak}, -}; -use tracing_core::{ - callsite, span, - subscriber::{Interest, Subscriber}, - Event, Metadata, -}; - -/// Wraps a `Layer` or `Filter`, allowing it to be reloaded dynamically at runtime. -#[derive(Debug)] -pub struct Layer<L, S> { - // TODO(eliza): this once used a `crossbeam_util::ShardedRwLock`. We may - // eventually wish to replace it with a sharded lock implementation on top - // of our internal `RwLock` wrapper type. If possible, we should profile - // this first to determine if it's necessary. - inner: Arc<RwLock<L>>, - _s: PhantomData<fn(S)>, -} - -/// Allows reloading the state of an associated [`Layer`](crate::layer::Layer). -#[derive(Debug)] -pub struct Handle<L, S> { - inner: Weak<RwLock<L>>, - _s: PhantomData<fn(S)>, -} - -/// Indicates that an error occurred when reloading a layer. -#[derive(Debug)] -pub struct Error { - kind: ErrorKind, -} - -#[derive(Debug)] -enum ErrorKind { - SubscriberGone, - Poisoned, -} - -// ===== impl Layer ===== - -impl<L, S> crate::Layer<S> for Layer<L, S> -where - L: crate::Layer<S> + 'static, - S: Subscriber, -{ - fn on_layer(&mut self, subscriber: &mut S) { - try_lock!(self.inner.write(), else return).on_layer(subscriber); - } - - #[inline] - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - try_lock!(self.inner.read(), else return Interest::sometimes()).register_callsite(metadata) - } - - #[inline] - fn enabled(&self, metadata: &Metadata<'_>, ctx: layer::Context<'_, S>) -> bool { - try_lock!(self.inner.read(), else return false).enabled(metadata, ctx) - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_new_span(attrs, id, ctx) - } - - #[inline] - fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_record(span, values, ctx) - } - - #[inline] - fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_follows_from(span, follows, ctx) - } - - #[inline] - fn event_enabled(&self, event: &Event<'_>, ctx: layer::Context<'_, S>) -> bool { - try_lock!(self.inner.read(), else return false).event_enabled(event, ctx) - } - - #[inline] - fn on_event(&self, event: &Event<'_>, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_event(event, ctx) - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_enter(id, ctx) - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_exit(id, ctx) - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_close(id, ctx) - } - - #[inline] - fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_id_change(old, new, ctx) - } -} - -// ===== impl Filter ===== - -#[cfg(all(feature = "registry", feature = "std"))] -#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))] -impl<S, L> crate::layer::Filter<S> for Layer<L, S> -where - L: crate::layer::Filter<S> + 'static, - S: Subscriber, -{ - #[inline] - fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { - try_lock!(self.inner.read(), else return Interest::sometimes()).callsite_enabled(metadata) - } - - #[inline] - fn enabled(&self, metadata: &Metadata<'_>, ctx: &layer::Context<'_, S>) -> bool { - try_lock!(self.inner.read(), else return false).enabled(metadata, ctx) - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_new_span(attrs, id, ctx) - } - - #[inline] - fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_record(span, values, ctx) - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_enter(id, ctx) - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_exit(id, ctx) - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: layer::Context<'_, S>) { - try_lock!(self.inner.read()).on_close(id, ctx) - } -} - -impl<L, S> Layer<L, S> { - /// Wraps the given [`Layer`] or [`Filter`], returning a `reload::Layer` - /// and a `Handle` that allows the inner value to be modified at runtime. - /// - /// [`Layer`]: crate::layer::Layer - /// [`Filter`]: crate::layer::Filter - pub fn new(inner: L) -> (Self, Handle<L, S>) { - let this = Self { - inner: Arc::new(RwLock::new(inner)), - _s: PhantomData, - }; - let handle = this.handle(); - (this, handle) - } - - /// Returns a `Handle` that can be used to reload the wrapped [`Layer`] or [`Filter`]. - /// - /// [`Layer`]: crate::layer::Layer - /// [`Filter`]: crate::filter::Filter - pub fn handle(&self) -> Handle<L, S> { - Handle { - inner: Arc::downgrade(&self.inner), - _s: PhantomData, - } - } -} - -// ===== impl Handle ===== - -impl<L, S> Handle<L, S> { - /// Replace the current [`Layer`] or [`Filter`] with the provided `new_value`. - /// - /// [`Handle::reload`] cannot be used with the [`Filtered`] layer; use - /// [`Handle::modify`] instead (see [this issue] for additional details). - /// - /// However, if the _only_ the [`Filter`] needs to be modified, use - /// `reload::Layer` to wrap the `Filter` directly. - /// - /// [`Layer`]: crate::layer::Layer - /// [`Filter`]: crate::layer::Filter - /// [`Filtered`]: crate::filter::Filtered - /// - /// [this issue]: https://github.com/tokio-rs/tracing/issues/1629 - pub fn reload(&self, new_value: impl Into<L>) -> Result<(), Error> { - self.modify(|layer| { - *layer = new_value.into(); - }) - } - - /// Invokes a closure with a mutable reference to the current layer or filter, - /// allowing it to be modified in place. - pub fn modify(&self, f: impl FnOnce(&mut L)) -> Result<(), Error> { - let inner = self.inner.upgrade().ok_or(Error { - kind: ErrorKind::SubscriberGone, - })?; - - let mut lock = try_lock!(inner.write(), else return Err(Error::poisoned())); - f(&mut *lock); - // Release the lock before rebuilding the interest cache, as that - // function will lock the new layer. - drop(lock); - - callsite::rebuild_interest_cache(); - Ok(()) - } - - /// Returns a clone of the layer or filter's current value if it still exists. - /// Otherwise, if the subscriber has been dropped, returns `None`. - pub fn clone_current(&self) -> Option<L> - where - L: Clone, - { - self.with_current(L::clone).ok() - } - - /// Invokes a closure with a borrowed reference to the current layer or filter, - /// returning the result (or an error if the subscriber no longer exists). - pub fn with_current<T>(&self, f: impl FnOnce(&L) -> T) -> Result<T, Error> { - let inner = self.inner.upgrade().ok_or(Error { - kind: ErrorKind::SubscriberGone, - })?; - let inner = try_lock!(inner.read(), else return Err(Error::poisoned())); - Ok(f(&*inner)) - } -} - -impl<L, S> Clone for Handle<L, S> { - fn clone(&self) -> Self { - Handle { - inner: self.inner.clone(), - _s: PhantomData, - } - } -} - -// ===== impl Error ===== - -impl Error { - fn poisoned() -> Self { - Self { - kind: ErrorKind::Poisoned, - } - } - - /// Returns `true` if this error occurred because the layer was poisoned by - /// a panic on another thread. - pub fn is_poisoned(&self) -> bool { - matches!(self.kind, ErrorKind::Poisoned) - } - - /// Returns `true` if this error occurred because the `Subscriber` - /// containing the reloadable layer was dropped. - pub fn is_dropped(&self) -> bool { - matches!(self.kind, ErrorKind::SubscriberGone) - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let msg = match self.kind { - ErrorKind::SubscriberGone => "subscriber no longer exists", - ErrorKind::Poisoned => "lock poisoned", - }; - f.pad(msg) - } -} - -impl error::Error for Error {} diff --git a/vendor/tracing-subscriber/src/sync.rs b/vendor/tracing-subscriber/src/sync.rs deleted file mode 100644 index ec42b834a..000000000 --- a/vendor/tracing-subscriber/src/sync.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! Abstracts over sync primitive implementations. -//! -//! Optionally, we allow the Rust standard library's `RwLock` to be replaced -//! with the `parking_lot` crate's implementation. This may provide improved -//! performance in some cases. However, the `parking_lot` dependency is an -//! opt-in feature flag. Because `parking_lot::RwLock` has a slightly different -//! API than `std::sync::RwLock` (it does not support poisoning on panics), we -//! wrap it with a type that provides the same method signatures. This allows us -//! to transparently swap `parking_lot` in without changing code at the callsite. -#[allow(unused_imports)] // may be used later; -pub(crate) use std::sync::{LockResult, PoisonError, TryLockResult}; - -#[cfg(not(feature = "parking_lot"))] -pub(crate) use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; - -#[cfg(feature = "parking_lot")] -pub(crate) use self::parking_lot_impl::*; - -#[cfg(feature = "parking_lot")] -mod parking_lot_impl { - pub(crate) use parking_lot::{RwLockReadGuard, RwLockWriteGuard}; - use std::sync::{LockResult, TryLockError, TryLockResult}; - - #[derive(Debug)] - pub(crate) struct RwLock<T> { - inner: parking_lot::RwLock<T>, - } - - impl<T> RwLock<T> { - pub(crate) fn new(val: T) -> Self { - Self { - inner: parking_lot::RwLock::new(val), - } - } - - #[inline] - pub(crate) fn get_mut(&mut self) -> LockResult<&mut T> { - Ok(self.inner.get_mut()) - } - - #[inline] - pub(crate) fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> { - Ok(self.inner.read()) - } - - #[inline] - #[allow(dead_code)] // may be used later; - pub(crate) fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> { - self.inner.try_read().ok_or(TryLockError::WouldBlock) - } - - #[inline] - pub(crate) fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> { - Ok(self.inner.write()) - } - } -} diff --git a/vendor/tracing-subscriber/src/util.rs b/vendor/tracing-subscriber/src/util.rs deleted file mode 100644 index 1c98aa4d2..000000000 --- a/vendor/tracing-subscriber/src/util.rs +++ /dev/null @@ -1,153 +0,0 @@ -//! Extension traits and other utilities to make working with subscribers more -//! ergonomic. -use core::fmt; -#[cfg(feature = "std")] -use std::error::Error; -use tracing_core::dispatcher::{self, Dispatch}; -#[cfg(feature = "tracing-log")] -use tracing_log::AsLog; - -/// Extension trait adding utility methods for subscriber initialization. -/// -/// This trait provides extension methods to make configuring and setting a -/// [default subscriber] more ergonomic. It is automatically implemented for all -/// types that can be converted into a [trace dispatcher]. Since `Dispatch` -/// implements `From<T>` for all `T: Subscriber`, all `Subscriber` -/// implementations will implement this extension trait as well. Types which -/// can be converted into `Subscriber`s, such as builders that construct a -/// `Subscriber`, may implement `Into<Dispatch>`, and will also receive an -/// implementation of this trait. -/// -/// [default subscriber]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html#setting-the-default-subscriber -/// [trace dispatcher]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html -pub trait SubscriberInitExt -where - Self: Into<Dispatch>, -{ - /// Sets `self` as the [default subscriber] in the current scope, returning a - /// guard that will unset it when dropped. - /// - /// If the "tracing-log" feature flag is enabled, this will also initialize - /// a [`log`] compatibility layer. This allows the subscriber to consume - /// `log::Record`s as though they were `tracing` `Event`s. - /// - /// [default subscriber]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html#setting-the-default-subscriber - /// [`log`]: https://crates.io/log - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] - fn set_default(self) -> dispatcher::DefaultGuard { - #[cfg(feature = "tracing-log")] - let _ = tracing_log::LogTracer::init(); - - dispatcher::set_default(&self.into()) - } - - /// Attempts to set `self` as the [global default subscriber] in the current - /// scope, returning an error if one is already set. - /// - /// If the "tracing-log" feature flag is enabled, this will also attempt to - /// initialize a [`log`] compatibility layer. This allows the subscriber to - /// consume `log::Record`s as though they were `tracing` `Event`s. - /// - /// This method returns an error if a global default subscriber has already - /// been set, or if a `log` logger has already been set (when the - /// "tracing-log" feature is enabled). - /// - /// [global default subscriber]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html#setting-the-default-subscriber - /// [`log`]: https://crates.io/log - fn try_init(self) -> Result<(), TryInitError> { - dispatcher::set_global_default(self.into()).map_err(TryInitError::new)?; - - // Since we are setting the global default subscriber, we can - // opportunistically go ahead and set its global max level hint as - // the max level for the `log` crate as well. This should make - // skipping `log` diagnostics much faster. - #[cfg(feature = "tracing-log")] - tracing_log::LogTracer::builder() - // Note that we must call this *after* setting the global default - // subscriber, so that we get its max level hint. - .with_max_level(tracing_core::LevelFilter::current().as_log()) - .init() - .map_err(TryInitError::new)?; - - Ok(()) - } - - /// Attempts to set `self` as the [global default subscriber] in the current - /// scope, panicking if this fails. - /// - /// If the "tracing-log" feature flag is enabled, this will also attempt to - /// initialize a [`log`] compatibility layer. This allows the subscriber to - /// consume `log::Record`s as though they were `tracing` `Event`s. - /// - /// This method panics if a global default subscriber has already been set, - /// or if a `log` logger has already been set (when the "tracing-log" - /// feature is enabled). - /// - /// [global default subscriber]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html#setting-the-default-subscriber - /// [`log`]: https://crates.io/log - fn init(self) { - self.try_init() - .expect("failed to set global default subscriber") - } -} - -impl<T> SubscriberInitExt for T where T: Into<Dispatch> {} - -/// Error returned by [`try_init`](SubscriberInitExt::try_init) if a global default subscriber could not be initialized. -pub struct TryInitError { - #[cfg(feature = "std")] - inner: Box<dyn Error + Send + Sync + 'static>, - - #[cfg(not(feature = "std"))] - _p: (), -} - -// ==== impl TryInitError ==== - -impl TryInitError { - #[cfg(feature = "std")] - fn new(e: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self { - Self { inner: e.into() } - } - - #[cfg(not(feature = "std"))] - fn new<T>(_: T) -> Self { - Self { _p: () } - } -} - -impl fmt::Debug for TryInitError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[cfg(feature = "std")] - { - fmt::Debug::fmt(&self.inner, f) - } - - #[cfg(not(feature = "std"))] - { - f.write_str("TryInitError(())") - } - } -} - -impl fmt::Display for TryInitError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[cfg(feature = "std")] - { - fmt::Display::fmt(&self.inner, f) - } - - #[cfg(not(feature = "std"))] - { - f.write_str("failed to set global default subscriber") - } - } -} - -#[cfg(feature = "std")] -impl Error for TryInitError { - fn source(&self) -> Option<&(dyn Error + 'static)> { - self.inner.source() - } -} diff --git a/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs deleted file mode 100644 index 00e98a994..000000000 --- a/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs +++ /dev/null @@ -1,123 +0,0 @@ -#![cfg(feature = "registry")] -mod support; -use self::support::*; -use tracing::Level; -use tracing_subscriber::{filter::LevelFilter, prelude::*}; - -#[test] -fn layer_filters() { - let (unfiltered, unfiltered_handle) = unfiltered("unfiltered"); - let (filtered, filtered_handle) = filtered("filtered"); - - let _subscriber = tracing_subscriber::registry() - .with(unfiltered) - .with(filtered.with_filter(filter())) - .set_default(); - - events(); - - unfiltered_handle.assert_finished(); - filtered_handle.assert_finished(); -} - -#[test] -fn layered_layer_filters() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - let unfiltered = unfiltered1.and_then(unfiltered2); - - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - let filtered = filtered1 - .with_filter(filter()) - .and_then(filtered2.with_filter(filter())); - - let _subscriber = tracing_subscriber::registry() - .with(unfiltered) - .with(filtered) - .set_default(); - - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -#[test] -fn out_of_order() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - - let _subscriber = tracing_subscriber::registry() - .with(unfiltered1) - .with(filtered1.with_filter(filter())) - .with(unfiltered2) - .with(filtered2.with_filter(filter())) - .set_default(); - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -#[test] -fn mixed_layered() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - - let layered1 = filtered1.with_filter(filter()).and_then(unfiltered1); - let layered2 = unfiltered2.and_then(filtered2.with_filter(filter())); - - let _subscriber = tracing_subscriber::registry() - .with(layered1) - .with(layered2) - .set_default(); - - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -fn events() { - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); -} - -fn filter() -> LevelFilter { - LevelFilter::INFO -} - -fn unfiltered(name: &str) -> (ExpectLayer, subscriber::MockHandle) { - layer::named(name) - .event(event::mock().at_level(Level::TRACE)) - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle() -} - -fn filtered(name: &str) -> (ExpectLayer, subscriber::MockHandle) { - layer::named(name) - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle() -} diff --git a/vendor/tracing-subscriber/tests/duplicate_spans.rs b/vendor/tracing-subscriber/tests/duplicate_spans.rs deleted file mode 100644 index 5d4dc6a85..000000000 --- a/vendor/tracing-subscriber/tests/duplicate_spans.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![cfg(all(feature = "env-filter", feature = "fmt"))] -use tracing::{self, subscriber::with_default, Span}; -use tracing_subscriber::{filter::EnvFilter, FmtSubscriber}; - -#[test] -fn duplicate_spans() { - let subscriber = FmtSubscriber::builder() - .with_env_filter(EnvFilter::new("[root]=debug")) - .finish(); - - with_default(subscriber, || { - let root = tracing::debug_span!("root"); - root.in_scope(|| { - // root: - assert_eq!(root, Span::current(), "Current span must be 'root'"); - let leaf = tracing::debug_span!("leaf"); - leaf.in_scope(|| { - // root:leaf: - assert_eq!(leaf, Span::current(), "Current span must be 'leaf'"); - root.in_scope(|| { - // root:leaf: - assert_eq!( - leaf, - Span::current(), - "Current span must be 'leaf' after entering twice the 'root' span" - ); - }) - }); - // root: - assert_eq!( - root, - Span::current(), - "Current span must be root ('leaf' exited, nested 'root' exited)" - ); - - root.in_scope(|| { - assert_eq!(root, Span::current(), "Current span must be root"); - }); - // root: - assert_eq!( - root, - Span::current(), - "Current span must still be root after exiting nested 'root'" - ); - }); - }); -} diff --git a/vendor/tracing-subscriber/tests/env_filter/main.rs b/vendor/tracing-subscriber/tests/env_filter/main.rs deleted file mode 100644 index 3c3d4868b..000000000 --- a/vendor/tracing-subscriber/tests/env_filter/main.rs +++ /dev/null @@ -1,547 +0,0 @@ -#![cfg(feature = "env-filter")] - -#[path = "../support.rs"] -mod support; -use self::support::*; - -mod per_layer; - -use tracing::{self, subscriber::with_default, Level}; -use tracing_subscriber::{ - filter::{EnvFilter, LevelFilter}, - prelude::*, -}; - -#[test] -fn level_filter_event() { - let filter: EnvFilter = "info".parse().expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "foo", "this should also be disabled"); - tracing::warn!(target: "foo", "this should be enabled"); - tracing::error!("this should be enabled too"); - }); - - finished.assert_finished(); -} - -#[test] -fn same_name_spans() { - let filter: EnvFilter = "[foo{bar}]=trace,[foo{baz}]=trace" - .parse() - .expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .new_span( - span::mock() - .named("foo") - .at_level(Level::TRACE) - .with_field(field::mock("bar")), - ) - .new_span( - span::mock() - .named("foo") - .at_level(Level::TRACE) - .with_field(field::mock("baz")), - ) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - with_default(subscriber, || { - tracing::trace_span!("foo", bar = 1); - tracing::trace_span!("foo", baz = 1); - }); - - finished.assert_finished(); -} - -#[test] -fn level_filter_event_with_target() { - let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::DEBUG).with_target("stuff")) - .event(event::mock().at_level(Level::WARN).with_target("stuff")) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::ERROR).with_target("stuff")) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "stuff", "this should be enabled"); - tracing::debug!("but this shouldn't"); - tracing::trace!(target: "stuff", "and neither should this"); - tracing::warn!(target: "stuff", "this should be enabled"); - tracing::error!("this should be enabled too"); - tracing::error!(target: "stuff", "this should be enabled also"); - }); - - finished.assert_finished(); -} - -#[test] -fn level_filter_event_with_target_and_span_global() { - let filter: EnvFilter = "info,stuff[cool_span]=debug" - .parse() - .expect("filter should parse"); - - let cool_span = span::named("cool_span"); - let uncool_span = span::named("uncool_span"); - let (subscriber, handle) = subscriber::mock() - .enter(cool_span.clone()) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![cool_span.clone()]), - ) - .exit(cool_span) - .enter(uncool_span.clone()) - .exit(uncool_span) - .done() - .run_with_handle(); - - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - { - let _span = tracing::info_span!(target: "stuff", "cool_span").entered(); - tracing::debug!("this should be enabled"); - } - - tracing::debug!("should also be disabled"); - - { - let _span = tracing::info_span!("uncool_span").entered(); - tracing::debug!("this should be disabled"); - } - }); - - handle.assert_finished(); -} - -#[test] -fn not_order_dependent() { - // this test reproduces tokio-rs/tracing#623 - - let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::DEBUG).with_target("stuff")) - .event(event::mock().at_level(Level::WARN).with_target("stuff")) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::ERROR).with_target("stuff")) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "stuff", "this should be enabled"); - tracing::debug!("but this shouldn't"); - tracing::trace!(target: "stuff", "and neither should this"); - tracing::warn!(target: "stuff", "this should be enabled"); - tracing::error!("this should be enabled too"); - tracing::error!(target: "stuff", "this should be enabled also"); - }); - - finished.assert_finished(); -} - -#[test] -fn add_directive_enables_event() { - // this test reproduces tokio-rs/tracing#591 - - // by default, use info level - let mut filter = EnvFilter::new(LevelFilter::INFO.to_string()); - - // overwrite with a more specific directive - filter = filter.add_directive("hello=trace".parse().expect("directive should parse")); - - let (subscriber, finished) = subscriber::mock() - .event(event::mock().at_level(Level::INFO).with_target("hello")) - .event(event::mock().at_level(Level::TRACE).with_target("hello")) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - tracing::info!(target: "hello", "hello info"); - tracing::trace!(target: "hello", "hello trace"); - }); - - finished.assert_finished(); -} - -#[test] -fn span_name_filter_is_dynamic() { - let filter: EnvFilter = "info,[cool_span]=debug" - .parse() - .expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .event(event::mock().at_level(Level::INFO)) - .enter(span::named("cool_span")) - .event(event::mock().at_level(Level::DEBUG)) - .enter(span::named("uncool_span")) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::DEBUG)) - .exit(span::named("uncool_span")) - .exit(span::named("cool_span")) - .enter(span::named("uncool_span")) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .exit(span::named("uncool_span")) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - let cool_span = tracing::info_span!("cool_span"); - let uncool_span = tracing::info_span!("uncool_span"); - - { - let _enter = cool_span.enter(); - tracing::debug!("i'm a cool event"); - tracing::trace!("i'm cool, but not cool enough"); - let _enter2 = uncool_span.enter(); - tracing::warn!("warning: extremely cool!"); - tracing::debug!("i'm still cool"); - } - - let _enter = uncool_span.enter(); - tracing::warn!("warning: not that cool"); - tracing::trace!("im not cool enough"); - tracing::error!("uncool error"); - }); - - finished.assert_finished(); -} - -#[test] -fn method_name_resolution() { - #[allow(unused_imports)] - use tracing_subscriber::layer::{Filter, Layer}; - - let filter = EnvFilter::new("hello_world=info"); - filter.max_level_hint(); -} - -// contains the same tests as the first half of this file -// but using EnvFilter as a `Filter`, not as a `Layer` -mod per_layer_filter { - use super::*; - - #[test] - fn level_filter_event() { - let filter: EnvFilter = "info".parse().expect("filter should parse"); - let (layer, handle) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "foo", "this should also be disabled"); - tracing::warn!(target: "foo", "this should be enabled"); - tracing::error!("this should be enabled too"); - - handle.assert_finished(); - } - - #[test] - fn same_name_spans() { - let filter: EnvFilter = "[foo{bar}]=trace,[foo{baz}]=trace" - .parse() - .expect("filter should parse"); - let (layer, handle) = layer::mock() - .new_span( - span::mock() - .named("foo") - .at_level(Level::TRACE) - .with_field(field::mock("bar")), - ) - .new_span( - span::mock() - .named("foo") - .at_level(Level::TRACE) - .with_field(field::mock("baz")), - ) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace_span!("foo", bar = 1); - tracing::trace_span!("foo", baz = 1); - - handle.assert_finished(); - } - - #[test] - fn level_filter_event_with_target() { - let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse"); - let (layer, handle) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::DEBUG).with_target("stuff")) - .event(event::mock().at_level(Level::WARN).with_target("stuff")) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::ERROR).with_target("stuff")) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "stuff", "this should be enabled"); - tracing::debug!("but this shouldn't"); - tracing::trace!(target: "stuff", "and neither should this"); - tracing::warn!(target: "stuff", "this should be enabled"); - tracing::error!("this should be enabled too"); - tracing::error!(target: "stuff", "this should be enabled also"); - - handle.assert_finished(); - } - - #[test] - fn level_filter_event_with_target_and_span() { - let filter: EnvFilter = "stuff[cool_span]=debug" - .parse() - .expect("filter should parse"); - - let cool_span = span::named("cool_span"); - let (layer, handle) = layer::mock() - .enter(cool_span.clone()) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![cool_span.clone()]), - ) - .exit(cool_span) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - { - let _span = tracing::info_span!(target: "stuff", "cool_span").entered(); - tracing::debug!("this should be enabled"); - } - - tracing::debug!("should also be disabled"); - - { - let _span = tracing::info_span!("uncool_span").entered(); - tracing::debug!("this should be disabled"); - } - - handle.assert_finished(); - } - - #[test] - fn not_order_dependent() { - // this test reproduces tokio-rs/tracing#623 - - let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse"); - let (layer, finished) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::DEBUG).with_target("stuff")) - .event(event::mock().at_level(Level::WARN).with_target("stuff")) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::ERROR).with_target("stuff")) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "stuff", "this should be enabled"); - tracing::debug!("but this shouldn't"); - tracing::trace!(target: "stuff", "and neither should this"); - tracing::warn!(target: "stuff", "this should be enabled"); - tracing::error!("this should be enabled too"); - tracing::error!(target: "stuff", "this should be enabled also"); - - finished.assert_finished(); - } - - #[test] - fn add_directive_enables_event() { - // this test reproduces tokio-rs/tracing#591 - - // by default, use info level - let mut filter = EnvFilter::new(LevelFilter::INFO.to_string()); - - // overwrite with a more specific directive - filter = filter.add_directive("hello=trace".parse().expect("directive should parse")); - - let (layer, finished) = layer::mock() - .event(event::mock().at_level(Level::INFO).with_target("hello")) - .event(event::mock().at_level(Level::TRACE).with_target("hello")) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::info!(target: "hello", "hello info"); - tracing::trace!(target: "hello", "hello trace"); - - finished.assert_finished(); - } - - #[test] - fn span_name_filter_is_dynamic() { - let filter: EnvFilter = "info,[cool_span]=debug" - .parse() - .expect("filter should parse"); - let cool_span = span::named("cool_span"); - let uncool_span = span::named("uncool_span"); - let (layer, finished) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .enter(cool_span.clone()) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![cool_span.clone()]), - ) - .enter(uncool_span.clone()) - .event( - event::mock() - .at_level(Level::WARN) - .in_scope(vec![uncool_span.clone()]), - ) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![uncool_span.clone()]), - ) - .exit(uncool_span.clone()) - .exit(cool_span) - .enter(uncool_span.clone()) - .event( - event::mock() - .at_level(Level::WARN) - .in_scope(vec![uncool_span.clone()]), - ) - .event( - event::mock() - .at_level(Level::ERROR) - .in_scope(vec![uncool_span.clone()]), - ) - .exit(uncool_span) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - let cool_span = tracing::info_span!("cool_span"); - let uncool_span = tracing::info_span!("uncool_span"); - - { - let _enter = cool_span.enter(); - tracing::debug!("i'm a cool event"); - tracing::trace!("i'm cool, but not cool enough"); - let _enter2 = uncool_span.enter(); - tracing::warn!("warning: extremely cool!"); - tracing::debug!("i'm still cool"); - } - - { - let _enter = uncool_span.enter(); - tracing::warn!("warning: not that cool"); - tracing::trace!("im not cool enough"); - tracing::error!("uncool error"); - } - - finished.assert_finished(); - } - - #[test] - fn multiple_dynamic_filters() { - // Test that multiple dynamic (span) filters only apply to the layers - // they're attached to. - let (layer1, handle1) = { - let span = span::named("span1"); - let filter: EnvFilter = "[span1]=debug".parse().expect("filter 1 should parse"); - let (layer, handle) = layer::named("layer1") - .enter(span.clone()) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![span.clone()]), - ) - .exit(span) - .done() - .run_with_handle(); - (layer.with_filter(filter), handle) - }; - - let (layer2, handle2) = { - let span = span::named("span2"); - let filter: EnvFilter = "[span2]=info".parse().expect("filter 2 should parse"); - let (layer, handle) = layer::named("layer2") - .enter(span.clone()) - .event( - event::mock() - .at_level(Level::INFO) - .in_scope(vec![span.clone()]), - ) - .exit(span) - .done() - .run_with_handle(); - (layer.with_filter(filter), handle) - }; - - let _subscriber = tracing_subscriber::registry() - .with(layer1) - .with(layer2) - .set_default(); - - tracing::info_span!("span1").in_scope(|| { - tracing::debug!("hello from span 1"); - tracing::trace!("not enabled"); - }); - - tracing::info_span!("span2").in_scope(|| { - tracing::info!("hello from span 2"); - tracing::debug!("not enabled"); - }); - - handle1.assert_finished(); - handle2.assert_finished(); - } -} diff --git a/vendor/tracing-subscriber/tests/env_filter/per_layer.rs b/vendor/tracing-subscriber/tests/env_filter/per_layer.rs deleted file mode 100644 index 8bf5698a4..000000000 --- a/vendor/tracing-subscriber/tests/env_filter/per_layer.rs +++ /dev/null @@ -1,305 +0,0 @@ -//! Tests for using `EnvFilter` as a per-layer filter (rather than a global -//! `Layer` filter). -#![cfg(feature = "registry")] -use super::*; - -#[test] -fn level_filter_event() { - let filter: EnvFilter = "info".parse().expect("filter should parse"); - let (layer, handle) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "foo", "this should also be disabled"); - tracing::warn!(target: "foo", "this should be enabled"); - tracing::error!("this should be enabled too"); - - handle.assert_finished(); -} - -#[test] -fn same_name_spans() { - let filter: EnvFilter = "[foo{bar}]=trace,[foo{baz}]=trace" - .parse() - .expect("filter should parse"); - let (layer, handle) = layer::mock() - .new_span( - span::mock() - .named("foo") - .at_level(Level::TRACE) - .with_field(field::mock("bar")), - ) - .new_span( - span::mock() - .named("foo") - .at_level(Level::TRACE) - .with_field(field::mock("baz")), - ) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace_span!("foo", bar = 1); - tracing::trace_span!("foo", baz = 1); - - handle.assert_finished(); -} - -#[test] -fn level_filter_event_with_target() { - let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse"); - let (layer, handle) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::DEBUG).with_target("stuff")) - .event(event::mock().at_level(Level::WARN).with_target("stuff")) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::ERROR).with_target("stuff")) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "stuff", "this should be enabled"); - tracing::debug!("but this shouldn't"); - tracing::trace!(target: "stuff", "and neither should this"); - tracing::warn!(target: "stuff", "this should be enabled"); - tracing::error!("this should be enabled too"); - tracing::error!(target: "stuff", "this should be enabled also"); - - handle.assert_finished(); -} - -#[test] -fn level_filter_event_with_target_and_span() { - let filter: EnvFilter = "stuff[cool_span]=debug" - .parse() - .expect("filter should parse"); - - let cool_span = span::named("cool_span"); - let (layer, handle) = layer::mock() - .enter(cool_span.clone()) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![cool_span.clone()]), - ) - .exit(cool_span) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - { - let _span = tracing::info_span!(target: "stuff", "cool_span").entered(); - tracing::debug!("this should be enabled"); - } - - tracing::debug!("should also be disabled"); - - { - let _span = tracing::info_span!("uncool_span").entered(); - tracing::debug!("this should be disabled"); - } - - handle.assert_finished(); -} - -#[test] -fn not_order_dependent() { - // this test reproduces tokio-rs/tracing#623 - - let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse"); - let (layer, finished) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::DEBUG).with_target("stuff")) - .event(event::mock().at_level(Level::WARN).with_target("stuff")) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::ERROR).with_target("stuff")) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - tracing::debug!(target: "stuff", "this should be enabled"); - tracing::debug!("but this shouldn't"); - tracing::trace!(target: "stuff", "and neither should this"); - tracing::warn!(target: "stuff", "this should be enabled"); - tracing::error!("this should be enabled too"); - tracing::error!(target: "stuff", "this should be enabled also"); - - finished.assert_finished(); -} - -#[test] -fn add_directive_enables_event() { - // this test reproduces tokio-rs/tracing#591 - - // by default, use info level - let mut filter = EnvFilter::new(LevelFilter::INFO.to_string()); - - // overwrite with a more specific directive - filter = filter.add_directive("hello=trace".parse().expect("directive should parse")); - - let (layer, finished) = layer::mock() - .event(event::mock().at_level(Level::INFO).with_target("hello")) - .event(event::mock().at_level(Level::TRACE).with_target("hello")) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::info!(target: "hello", "hello info"); - tracing::trace!(target: "hello", "hello trace"); - - finished.assert_finished(); -} - -#[test] -fn span_name_filter_is_dynamic() { - let filter: EnvFilter = "info,[cool_span]=debug" - .parse() - .expect("filter should parse"); - let cool_span = span::named("cool_span"); - let uncool_span = span::named("uncool_span"); - let (layer, finished) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .enter(cool_span.clone()) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![cool_span.clone()]), - ) - .enter(uncool_span.clone()) - .event( - event::mock() - .at_level(Level::WARN) - .in_scope(vec![uncool_span.clone()]), - ) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![uncool_span.clone()]), - ) - .exit(uncool_span.clone()) - .exit(cool_span) - .enter(uncool_span.clone()) - .event( - event::mock() - .at_level(Level::WARN) - .in_scope(vec![uncool_span.clone()]), - ) - .event( - event::mock() - .at_level(Level::ERROR) - .in_scope(vec![uncool_span.clone()]), - ) - .exit(uncool_span) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - tracing::trace!("this should be disabled"); - tracing::info!("this shouldn't be"); - let cool_span = tracing::info_span!("cool_span"); - let uncool_span = tracing::info_span!("uncool_span"); - - { - let _enter = cool_span.enter(); - tracing::debug!("i'm a cool event"); - tracing::trace!("i'm cool, but not cool enough"); - let _enter2 = uncool_span.enter(); - tracing::warn!("warning: extremely cool!"); - tracing::debug!("i'm still cool"); - } - - { - let _enter = uncool_span.enter(); - tracing::warn!("warning: not that cool"); - tracing::trace!("im not cool enough"); - tracing::error!("uncool error"); - } - - finished.assert_finished(); -} - -#[test] -fn multiple_dynamic_filters() { - // Test that multiple dynamic (span) filters only apply to the layers - // they're attached to. - let (layer1, handle1) = { - let span = span::named("span1"); - let filter: EnvFilter = "[span1]=debug".parse().expect("filter 1 should parse"); - let (layer, handle) = layer::named("layer1") - .enter(span.clone()) - .event( - event::mock() - .at_level(Level::DEBUG) - .in_scope(vec![span.clone()]), - ) - .exit(span) - .done() - .run_with_handle(); - (layer.with_filter(filter), handle) - }; - - let (layer2, handle2) = { - let span = span::named("span2"); - let filter: EnvFilter = "[span2]=info".parse().expect("filter 2 should parse"); - let (layer, handle) = layer::named("layer2") - .enter(span.clone()) - .event( - event::mock() - .at_level(Level::INFO) - .in_scope(vec![span.clone()]), - ) - .exit(span) - .done() - .run_with_handle(); - (layer.with_filter(filter), handle) - }; - - let _subscriber = tracing_subscriber::registry() - .with(layer1) - .with(layer2) - .set_default(); - - tracing::info_span!("span1").in_scope(|| { - tracing::debug!("hello from span 1"); - tracing::trace!("not enabled"); - }); - - tracing::info_span!("span2").in_scope(|| { - tracing::info!("hello from span 2"); - tracing::debug!("not enabled"); - }); - - handle1.assert_finished(); - handle2.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/event_enabling.rs b/vendor/tracing-subscriber/tests/event_enabling.rs deleted file mode 100644 index 8f67cfcba..000000000 --- a/vendor/tracing-subscriber/tests/event_enabling.rs +++ /dev/null @@ -1,81 +0,0 @@ -#![cfg(feature = "registry")] - -use std::sync::{Arc, Mutex}; -use tracing::{subscriber::with_default, Event, Metadata, Subscriber}; -use tracing_subscriber::{layer::Context, prelude::*, registry, Layer}; - -struct TrackingLayer { - enabled: bool, - event_enabled_count: Arc<Mutex<usize>>, - event_enabled: bool, - on_event_count: Arc<Mutex<usize>>, -} - -impl<C> Layer<C> for TrackingLayer -where - C: Subscriber + Send + Sync + 'static, -{ - fn enabled(&self, _metadata: &Metadata<'_>, _ctx: Context<'_, C>) -> bool { - self.enabled - } - - fn event_enabled(&self, _event: &Event<'_>, _ctx: Context<'_, C>) -> bool { - *self.event_enabled_count.lock().unwrap() += 1; - self.event_enabled - } - - fn on_event(&self, _event: &Event<'_>, _ctx: Context<'_, C>) { - *self.on_event_count.lock().unwrap() += 1; - } -} - -#[test] -fn event_enabled_is_only_called_once() { - let event_enabled_count = Arc::new(Mutex::default()); - let count = event_enabled_count.clone(); - let subscriber = registry().with(TrackingLayer { - enabled: true, - event_enabled_count, - event_enabled: true, - on_event_count: Arc::new(Mutex::default()), - }); - with_default(subscriber, || { - tracing::error!("hiya!"); - }); - - assert_eq!(1, *count.lock().unwrap()); -} - -#[test] -fn event_enabled_not_called_when_not_enabled() { - let event_enabled_count = Arc::new(Mutex::default()); - let count = event_enabled_count.clone(); - let subscriber = registry().with(TrackingLayer { - enabled: false, - event_enabled_count, - event_enabled: true, - on_event_count: Arc::new(Mutex::default()), - }); - with_default(subscriber, || { - tracing::error!("hiya!"); - }); - - assert_eq!(0, *count.lock().unwrap()); -} - -#[test] -fn event_disabled_does_disable_event() { - let on_event_count = Arc::new(Mutex::default()); - let count = on_event_count.clone(); - let subscriber = registry().with(TrackingLayer { - enabled: true, - event_enabled_count: Arc::new(Mutex::default()), - event_enabled: false, - on_event_count, - }); - with_default(subscriber, || { - tracing::error!("hiya!"); - }); - - assert_eq!(0, *count.lock().unwrap()); -} diff --git a/vendor/tracing-subscriber/tests/field_filter.rs b/vendor/tracing-subscriber/tests/field_filter.rs deleted file mode 100644 index f14a0626d..000000000 --- a/vendor/tracing-subscriber/tests/field_filter.rs +++ /dev/null @@ -1,115 +0,0 @@ -#![cfg(feature = "env-filter")] - -use tracing::{self, subscriber::with_default, Level}; -use tracing_mock::*; -use tracing_subscriber::{filter::EnvFilter, prelude::*}; - -#[test] -#[cfg_attr(not(flaky_tests), ignore)] -fn field_filter_events() { - let filter: EnvFilter = "[{thing}]=debug".parse().expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .event( - event::mock() - .at_level(Level::INFO) - .with_fields(field::mock("thing")), - ) - .event( - event::mock() - .at_level(Level::DEBUG) - .with_fields(field::mock("thing")), - ) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - tracing::trace!(disabled = true); - tracing::info!("also disabled"); - tracing::info!(thing = 1); - tracing::debug!(thing = 2); - tracing::trace!(thing = 3); - }); - - finished.assert_finished(); -} - -#[test] -#[cfg_attr(not(flaky_tests), ignore)] -fn field_filter_spans() { - let filter: EnvFilter = "[{enabled=true}]=debug" - .parse() - .expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .enter(span::mock().named("span1")) - .event( - event::mock() - .at_level(Level::INFO) - .with_fields(field::mock("something")), - ) - .exit(span::mock().named("span1")) - .enter(span::mock().named("span2")) - .exit(span::mock().named("span2")) - .enter(span::mock().named("span3")) - .event( - event::mock() - .at_level(Level::DEBUG) - .with_fields(field::mock("something")), - ) - .exit(span::mock().named("span3")) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - tracing::trace!("disabled"); - tracing::info!("also disabled"); - tracing::info_span!("span1", enabled = true).in_scope(|| { - tracing::info!(something = 1); - }); - tracing::debug_span!("span2", enabled = false, foo = "hi").in_scope(|| { - tracing::warn!(something = 2); - }); - tracing::trace_span!("span3", enabled = true, answer = 42).in_scope(|| { - tracing::debug!(something = 2); - }); - }); - - finished.assert_finished(); -} - -#[test] -fn record_after_created() { - let filter: EnvFilter = "[{enabled=true}]=debug" - .parse() - .expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .enter(span::mock().named("span")) - .exit(span::mock().named("span")) - .record( - span::mock().named("span"), - field::mock("enabled").with_value(&true), - ) - .enter(span::mock().named("span")) - .event(event::mock().at_level(Level::DEBUG)) - .exit(span::mock().named("span")) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - let span = tracing::info_span!("span", enabled = false); - span.in_scope(|| { - tracing::debug!("i'm disabled!"); - }); - - span.record("enabled", &true); - span.in_scope(|| { - tracing::debug!("i'm enabled!"); - }); - - tracing::debug!("i'm also disabled"); - }); - - finished.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/filter_log.rs b/vendor/tracing-subscriber/tests/filter_log.rs deleted file mode 100644 index 8d57ed600..000000000 --- a/vendor/tracing-subscriber/tests/filter_log.rs +++ /dev/null @@ -1,63 +0,0 @@ -#![cfg(all(feature = "env-filter", feature = "tracing-log"))] - -use tracing::{self, Level}; -use tracing_mock::*; -use tracing_subscriber::{filter::EnvFilter, prelude::*}; - -mod my_module { - pub(crate) fn test_records() { - log::trace!("this should be disabled"); - log::info!("this shouldn't be"); - log::debug!("this should be disabled"); - log::warn!("this should be enabled"); - log::warn!(target: "something else", "this shouldn't be enabled"); - log::error!("this should be enabled too"); - } - - pub(crate) fn test_log_enabled() { - assert!( - log::log_enabled!(log::Level::Info), - "info should be enabled inside `my_module`" - ); - assert!( - !log::log_enabled!(log::Level::Debug), - "debug should not be enabled inside `my_module`" - ); - assert!( - log::log_enabled!(log::Level::Warn), - "warn should be enabled inside `my_module`" - ); - } -} - -#[test] -fn log_is_enabled() { - let filter: EnvFilter = "filter_log::my_module=info" - .parse() - .expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - - // Note: we have to set the global default in order to set the `log` max - // level, which can only be set once. - subscriber.with(filter).init(); - - my_module::test_records(); - log::info!("this is disabled"); - - my_module::test_log_enabled(); - assert!( - !log::log_enabled!(log::Level::Info), - "info should not be enabled outside `my_module`" - ); - assert!( - !log::log_enabled!(log::Level::Warn), - "warn should not be enabled outside `my_module`" - ); - - finished.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/fmt_max_level_hint.rs b/vendor/tracing-subscriber/tests/fmt_max_level_hint.rs deleted file mode 100644 index 57a0f6e3f..000000000 --- a/vendor/tracing-subscriber/tests/fmt_max_level_hint.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![cfg(feature = "fmt")] -use tracing_subscriber::filter::LevelFilter; - -#[test] -fn fmt_sets_max_level_hint() { - tracing_subscriber::fmt() - .with_max_level(LevelFilter::DEBUG) - .init(); - assert_eq!(LevelFilter::current(), LevelFilter::DEBUG); -} diff --git a/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs deleted file mode 100644 index 897dae282..000000000 --- a/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs +++ /dev/null @@ -1,131 +0,0 @@ -#![cfg(feature = "registry")] -mod support; -use self::support::*; -use tracing::{Level, Metadata, Subscriber}; -use tracing_subscriber::{filter::DynFilterFn, layer::Context, prelude::*}; - -#[test] -fn layer_filters() { - let (unfiltered, unfiltered_handle) = unfiltered("unfiltered"); - let (filtered, filtered_handle) = filtered("filtered"); - - let subscriber = tracing_subscriber::registry() - .with(unfiltered) - .with(filtered.with_filter(filter())); - assert_eq!(subscriber.max_level_hint(), None); - let _subscriber = subscriber.set_default(); - - events(); - - unfiltered_handle.assert_finished(); - filtered_handle.assert_finished(); -} - -#[test] -fn layered_layer_filters() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - let unfiltered = unfiltered1.and_then(unfiltered2); - - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - let filtered = filtered1 - .with_filter(filter()) - .and_then(filtered2.with_filter(filter())); - - let subscriber = tracing_subscriber::registry() - .with(unfiltered) - .with(filtered); - assert_eq!(subscriber.max_level_hint(), None); - let _subscriber = subscriber.set_default(); - - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -#[test] -fn out_of_order() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - - let subscriber = tracing_subscriber::registry() - .with(unfiltered1) - .with(filtered1.with_filter(filter())) - .with(unfiltered2) - .with(filtered2.with_filter(filter())); - assert_eq!(subscriber.max_level_hint(), None); - let _subscriber = subscriber.set_default(); - - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -#[test] -fn mixed_layered() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - - let layered1 = filtered1.with_filter(filter()).and_then(unfiltered1); - let layered2 = unfiltered2.and_then(filtered2.with_filter(filter())); - - let subscriber = tracing_subscriber::registry().with(layered1).with(layered2); - assert_eq!(subscriber.max_level_hint(), None); - let _subscriber = subscriber.set_default(); - - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -fn events() { - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); -} - -fn filter<S>() -> DynFilterFn<S> { - DynFilterFn::new( - (|metadata: &Metadata<'_>, _: &tracing_subscriber::layer::Context<'_, S>| { - metadata.level() <= &Level::INFO - }) as fn(&Metadata<'_>, &Context<'_, S>) -> bool, - ) - .with_max_level_hint(Level::INFO) -} - -fn unfiltered(name: &str) -> (ExpectLayer, subscriber::MockHandle) { - layer::named(name) - .event(event::mock().at_level(Level::TRACE)) - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle() -} - -fn filtered(name: &str) -> (ExpectLayer, subscriber::MockHandle) { - layer::named(name) - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle() -} diff --git a/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs b/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs deleted file mode 100644 index d89d3bf17..000000000 --- a/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![cfg(feature = "registry")] -mod support; -use self::support::*; - -use std::{ - collections::HashMap, - sync::{Arc, Mutex}, -}; -use tracing::{Level, Subscriber}; -use tracing_subscriber::{filter, prelude::*}; - -#[test] -fn layer_filter_interests_are_cached() { - let seen = Arc::new(Mutex::new(HashMap::new())); - let seen2 = seen.clone(); - let filter = filter::filter_fn(move |meta| { - *seen - .lock() - .unwrap() - .entry(meta.callsite()) - .or_insert(0usize) += 1; - meta.level() == &Level::INFO - }); - - let (expect, handle) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - - let subscriber = tracing_subscriber::registry().with(expect.with_filter(filter)); - assert!(subscriber.max_level_hint().is_none()); - - let _subscriber = subscriber.set_default(); - - fn events() { - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); - } - - events(); - { - let lock = seen2.lock().unwrap(); - for (callsite, &count) in lock.iter() { - assert_eq!( - count, 1, - "callsite {:?} should have been seen 1 time (after first set of events)", - callsite - ); - } - } - - events(); - { - let lock = seen2.lock().unwrap(); - for (callsite, &count) in lock.iter() { - assert_eq!( - count, 1, - "callsite {:?} should have been seen 1 time (after second set of events)", - callsite - ); - } - } - - handle.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/layer_filters/boxed.rs b/vendor/tracing-subscriber/tests/layer_filters/boxed.rs deleted file mode 100644 index 0fe37188e..000000000 --- a/vendor/tracing-subscriber/tests/layer_filters/boxed.rs +++ /dev/null @@ -1,42 +0,0 @@ -use super::*; -use tracing_subscriber::{filter, prelude::*, Layer}; - -fn layer() -> (ExpectLayer, subscriber::MockHandle) { - layer::mock().done().run_with_handle() -} - -fn filter<S>() -> filter::DynFilterFn<S> { - // Use dynamic filter fn to disable interest caching and max-level hints, - // allowing us to put all of these tests in the same file. - filter::dynamic_filter_fn(|_, _| false) -} - -/// reproduces https://github.com/tokio-rs/tracing/issues/1563#issuecomment-921363629 -#[test] -fn box_works() { - let (layer, handle) = layer(); - let layer = Box::new(layer.with_filter(filter())); - - let _guard = tracing_subscriber::registry().with(layer).set_default(); - - for i in 0..2 { - tracing::info!(i); - } - - handle.assert_finished(); -} - -/// the same as `box_works` but with a type-erased `Box`. -#[test] -fn dyn_box_works() { - let (layer, handle) = layer(); - let layer: Box<dyn Layer<_> + Send + Sync + 'static> = Box::new(layer.with_filter(filter())); - - let _guard = tracing_subscriber::registry().with(layer).set_default(); - - for i in 0..2 { - tracing::info!(i); - } - - handle.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/layer_filters/combinators.rs b/vendor/tracing-subscriber/tests/layer_filters/combinators.rs deleted file mode 100644 index 6052a2d00..000000000 --- a/vendor/tracing-subscriber/tests/layer_filters/combinators.rs +++ /dev/null @@ -1,42 +0,0 @@ -use super::*; -use tracing_subscriber::{ - filter::{filter_fn, FilterExt, LevelFilter}, - prelude::*, -}; - -#[test] -fn and() { - let (layer, handle) = layer::mock() - .event( - event::msg("a very interesting event") - .at_level(tracing::Level::INFO) - .with_target("interesting_target"), - ) - .done() - .run_with_handle(); - - // Enables spans and events with targets starting with `interesting_target`: - let target_filter = filter::filter_fn(|meta| meta.target().starts_with("interesting_target")); - - // Enables spans and events with levels `INFO` and below: - let level_filter = LevelFilter::INFO; - - // Combine the two filters together, returning a filter that only enables - // spans and events that *both* filters will enable: - let filter = target_filter.and(level_filter); - - let _subscriber = tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .set_default(); - - // This event will *not* be enabled: - tracing::info!("an event with an uninteresting target"); - - // This event *will* be enabled: - tracing::info!(target: "interesting_target", "a very interesting event"); - - // This event will *not* be enabled: - tracing::debug!(target: "interesting_target", "interesting debug event..."); - - handle.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs b/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs deleted file mode 100644 index b5f7e35ce..000000000 --- a/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs +++ /dev/null @@ -1,68 +0,0 @@ -use tracing::Subscriber; -use tracing_subscriber::filter::Targets; -use tracing_subscriber::prelude::*; -use tracing_subscriber::Layer; - -#[test] -fn downcast_ref_to_inner_layer_and_filter() { - // Test that a filtered layer gives downcast_ref access to - // both the layer and the filter. - - struct WrappedLayer; - - impl<S> Layer<S> for WrappedLayer - where - S: Subscriber, - S: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>, - { - } - - let layer = WrappedLayer; - let filter = Targets::new().with_default(tracing::Level::INFO); - let registry = tracing_subscriber::registry().with(layer.with_filter(filter)); - let dispatch = tracing::dispatcher::Dispatch::new(registry); - - // The filter is available - assert!(dispatch.downcast_ref::<Targets>().is_some()); - // The wrapped layer is available - assert!(dispatch.downcast_ref::<WrappedLayer>().is_some()); -} - -#[test] -fn forward_downcast_raw_to_layer() { - // Test that a filtered layer still gives its wrapped layer a chance to - // return a custom struct from downcast_raw. - // https://github.com/tokio-rs/tracing/issues/1618 - - struct WrappedLayer { - with_context: WithContext, - } - - struct WithContext; - - impl<S> Layer<S> for WrappedLayer - where - S: Subscriber, - S: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>, - { - unsafe fn downcast_raw(&self, id: std::any::TypeId) -> Option<*const ()> { - match id { - id if id == std::any::TypeId::of::<Self>() => Some(self as *const _ as *const ()), - id if id == std::any::TypeId::of::<WithContext>() => { - Some(&self.with_context as *const _ as *const ()) - } - _ => None, - } - } - } - - let layer = WrappedLayer { - with_context: WithContext, - }; - let filter = Targets::new().with_default(tracing::Level::INFO); - let registry = tracing_subscriber::registry().with(layer.with_filter(filter)); - let dispatch = tracing::dispatcher::Dispatch::new(registry); - - // Types from a custom implementation of `downcast_raw` are available - assert!(dispatch.downcast_ref::<WithContext>().is_some()); -} diff --git a/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs b/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs deleted file mode 100644 index 7fd7d843b..000000000 --- a/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs +++ /dev/null @@ -1,131 +0,0 @@ -use super::*; - -#[test] -fn filters_span_scopes() { - let (debug_layer, debug_handle) = layer::named("debug") - .enter(span::mock().at_level(Level::DEBUG)) - .enter(span::mock().at_level(Level::INFO)) - .enter(span::mock().at_level(Level::WARN)) - .enter(span::mock().at_level(Level::ERROR)) - .event(event::msg("hello world").in_scope(vec![ - span::mock().at_level(Level::ERROR), - span::mock().at_level(Level::WARN), - span::mock().at_level(Level::INFO), - span::mock().at_level(Level::DEBUG), - ])) - .exit(span::mock().at_level(Level::ERROR)) - .exit(span::mock().at_level(Level::WARN)) - .exit(span::mock().at_level(Level::INFO)) - .exit(span::mock().at_level(Level::DEBUG)) - .done() - .run_with_handle(); - let (info_layer, info_handle) = layer::named("info") - .enter(span::mock().at_level(Level::INFO)) - .enter(span::mock().at_level(Level::WARN)) - .enter(span::mock().at_level(Level::ERROR)) - .event(event::msg("hello world").in_scope(vec![ - span::mock().at_level(Level::ERROR), - span::mock().at_level(Level::WARN), - span::mock().at_level(Level::INFO), - ])) - .exit(span::mock().at_level(Level::ERROR)) - .exit(span::mock().at_level(Level::WARN)) - .exit(span::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - let (warn_layer, warn_handle) = layer::named("warn") - .enter(span::mock().at_level(Level::WARN)) - .enter(span::mock().at_level(Level::ERROR)) - .event(event::msg("hello world").in_scope(vec![ - span::mock().at_level(Level::ERROR), - span::mock().at_level(Level::WARN), - ])) - .exit(span::mock().at_level(Level::ERROR)) - .exit(span::mock().at_level(Level::WARN)) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(debug_layer.with_filter(LevelFilter::DEBUG)) - .with(info_layer.with_filter(LevelFilter::INFO)) - .with(warn_layer.with_filter(LevelFilter::WARN)) - .set_default(); - - { - let _trace = tracing::trace_span!("my_span").entered(); - let _debug = tracing::debug_span!("my_span").entered(); - let _info = tracing::info_span!("my_span").entered(); - let _warn = tracing::warn_span!("my_span").entered(); - let _error = tracing::error_span!("my_span").entered(); - tracing::error!("hello world"); - } - - debug_handle.assert_finished(); - info_handle.assert_finished(); - warn_handle.assert_finished(); -} - -#[test] -fn filters_interleaved_span_scopes() { - fn target_layer(target: &'static str) -> (ExpectLayer, subscriber::MockHandle) { - layer::named(format!("target_{}", target)) - .enter(span::mock().with_target(target)) - .enter(span::mock().with_target(target)) - .event(event::msg("hello world").in_scope(vec![ - span::mock().with_target(target), - span::mock().with_target(target), - ])) - .event( - event::msg("hello to my target") - .in_scope(vec![ - span::mock().with_target(target), - span::mock().with_target(target), - ]) - .with_target(target), - ) - .exit(span::mock().with_target(target)) - .exit(span::mock().with_target(target)) - .done() - .run_with_handle() - } - - let (a_layer, a_handle) = target_layer("a"); - let (b_layer, b_handle) = target_layer("b"); - let (all_layer, all_handle) = layer::named("all") - .enter(span::mock().with_target("b")) - .enter(span::mock().with_target("a")) - .event(event::msg("hello world").in_scope(vec![ - span::mock().with_target("a"), - span::mock().with_target("b"), - ])) - .exit(span::mock().with_target("a")) - .exit(span::mock().with_target("b")) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(all_layer.with_filter(LevelFilter::INFO)) - .with(a_layer.with_filter(filter::filter_fn(|meta| { - let target = meta.target(); - target == "a" || target == module_path!() - }))) - .with(b_layer.with_filter(filter::filter_fn(|meta| { - let target = meta.target(); - target == "b" || target == module_path!() - }))) - .set_default(); - - { - let _a1 = tracing::trace_span!(target: "a", "a/trace").entered(); - let _b1 = tracing::info_span!(target: "b", "b/info").entered(); - let _a2 = tracing::info_span!(target: "a", "a/info").entered(); - let _b2 = tracing::trace_span!(target: "b", "b/trace").entered(); - tracing::info!("hello world"); - tracing::debug!(target: "a", "hello to my target"); - tracing::debug!(target: "b", "hello to my target"); - } - - a_handle.assert_finished(); - b_handle.assert_finished(); - all_handle.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/layer_filters/main.rs b/vendor/tracing-subscriber/tests/layer_filters/main.rs deleted file mode 100644 index 0233f063b..000000000 --- a/vendor/tracing-subscriber/tests/layer_filters/main.rs +++ /dev/null @@ -1,189 +0,0 @@ -#![cfg(feature = "registry")] -#[path = "../support.rs"] -mod support; -use self::support::*; -mod boxed; -mod downcast_raw; -mod filter_scopes; -mod targets; -mod trees; -mod vec; - -use tracing::{level_filters::LevelFilter, Level}; -use tracing_subscriber::{filter, prelude::*, Layer}; - -#[test] -fn basic_layer_filters() { - let (trace_layer, trace_handle) = layer::named("trace") - .event(event::mock().at_level(Level::TRACE)) - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - - let (debug_layer, debug_handle) = layer::named("debug") - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - - let (info_layer, info_handle) = layer::named("info") - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(trace_layer.with_filter(LevelFilter::TRACE)) - .with(debug_layer.with_filter(LevelFilter::DEBUG)) - .with(info_layer.with_filter(LevelFilter::INFO)) - .set_default(); - - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - - trace_handle.assert_finished(); - debug_handle.assert_finished(); - info_handle.assert_finished(); -} - -#[test] -fn basic_layer_filters_spans() { - let (trace_layer, trace_handle) = layer::named("trace") - .new_span(span::mock().at_level(Level::TRACE)) - .new_span(span::mock().at_level(Level::DEBUG)) - .new_span(span::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - - let (debug_layer, debug_handle) = layer::named("debug") - .new_span(span::mock().at_level(Level::DEBUG)) - .new_span(span::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - - let (info_layer, info_handle) = layer::named("info") - .new_span(span::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(trace_layer.with_filter(LevelFilter::TRACE)) - .with(debug_layer.with_filter(LevelFilter::DEBUG)) - .with(info_layer.with_filter(LevelFilter::INFO)) - .set_default(); - - tracing::trace_span!("hello trace"); - tracing::debug_span!("hello debug"); - tracing::info_span!("hello info"); - - trace_handle.assert_finished(); - debug_handle.assert_finished(); - info_handle.assert_finished(); -} - -#[test] -fn global_filters_layers_still_work() { - let (expect, handle) = layer::mock() - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(expect) - .with(LevelFilter::INFO) - .set_default(); - - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); - - handle.assert_finished(); -} - -#[test] -fn global_filter_interests_are_cached() { - let (expect, handle) = layer::mock() - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(expect.with_filter(filter::filter_fn(|meta| { - assert!( - meta.level() <= &Level::INFO, - "enabled should not be called for callsites disabled by the global filter" - ); - meta.level() <= &Level::WARN - }))) - .with(LevelFilter::INFO) - .set_default(); - - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); - - handle.assert_finished(); -} - -#[test] -fn global_filters_affect_layer_filters() { - let (expect, handle) = layer::named("debug") - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(expect.with_filter(LevelFilter::DEBUG)) - .with(LevelFilter::INFO) - .set_default(); - - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); - - handle.assert_finished(); -} - -#[test] -fn filter_fn() { - let (all, all_handle) = layer::named("all_targets") - .event(event::msg("hello foo")) - .event(event::msg("hello bar")) - .done() - .run_with_handle(); - - let (foo, foo_handle) = layer::named("foo_target") - .event(event::msg("hello foo")) - .done() - .run_with_handle(); - - let (bar, bar_handle) = layer::named("bar_target") - .event(event::msg("hello bar")) - .done() - .run_with_handle(); - - let _subscriber = tracing_subscriber::registry() - .with(all) - .with(foo.with_filter(filter::filter_fn(|meta| meta.target().starts_with("foo")))) - .with(bar.with_filter(filter::filter_fn(|meta| meta.target().starts_with("bar")))) - .set_default(); - - tracing::trace!(target: "foo", "hello foo"); - tracing::trace!(target: "bar", "hello bar"); - - foo_handle.assert_finished(); - bar_handle.assert_finished(); - all_handle.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/layer_filters/targets.rs b/vendor/tracing-subscriber/tests/layer_filters/targets.rs deleted file mode 100644 index c8133044b..000000000 --- a/vendor/tracing-subscriber/tests/layer_filters/targets.rs +++ /dev/null @@ -1,59 +0,0 @@ -use super::*; -use tracing_subscriber::{ - filter::{filter_fn, Targets}, - prelude::*, -}; - -#[test] -#[cfg_attr(not(feature = "tracing-log"), ignore)] -fn log_events() { - // Reproduces https://github.com/tokio-rs/tracing/issues/1563 - mod inner { - pub(super) const MODULE_PATH: &str = module_path!(); - - #[tracing::instrument] - pub(super) fn logs() { - log::debug!("inner"); - } - } - - let filter = Targets::new() - .with_default(LevelFilter::DEBUG) - .with_target(inner::MODULE_PATH, LevelFilter::WARN); - - let layer = - tracing_subscriber::layer::Identity::new().with_filter(filter_fn(move |_meta| true)); - - let _guard = tracing_subscriber::registry() - .with(filter) - .with(layer) - .set_default(); - - inner::logs(); -} - -#[test] -fn inner_layer_short_circuits() { - // This test ensures that when a global filter short-circuits `Interest` - // evaluation, we aren't left with a "dirty" per-layer filter state. - - let (layer, handle) = layer::mock() - .event(event::msg("hello world")) - .done() - .run_with_handle(); - - let filter = Targets::new().with_target("magic_target", LevelFilter::DEBUG); - - let _guard = tracing_subscriber::registry() - // Note: we don't just use a `LevelFilter` for the global filter here, - // because it will just return a max level filter, and the chain of - // `register_callsite` calls that would trigger the bug never happens... - .with(filter::filter_fn(|meta| meta.level() <= &Level::INFO)) - .with(layer.with_filter(filter)) - .set_default(); - - tracing::debug!("skip me please!"); - tracing::info!(target: "magic_target", "hello world"); - - handle.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/layer_filters/trees.rs b/vendor/tracing-subscriber/tests/layer_filters/trees.rs deleted file mode 100644 index 18cdd8ccc..000000000 --- a/vendor/tracing-subscriber/tests/layer_filters/trees.rs +++ /dev/null @@ -1,146 +0,0 @@ -use super::*; - -#[test] -fn basic_trees() { - let (with_target, with_target_handle) = layer::named("info_with_target") - .event(event::mock().at_level(Level::INFO).with_target("my_target")) - .done() - .run_with_handle(); - - let (info, info_handle) = layer::named("info") - .event( - event::mock() - .at_level(Level::INFO) - .with_target(module_path!()), - ) - .event(event::mock().at_level(Level::INFO).with_target("my_target")) - .done() - .run_with_handle(); - - let (all, all_handle) = layer::named("all") - .event( - event::mock() - .at_level(Level::INFO) - .with_target(module_path!()), - ) - .event(event::mock().at_level(Level::TRACE)) - .event(event::mock().at_level(Level::INFO).with_target("my_target")) - .event( - event::mock() - .at_level(Level::TRACE) - .with_target("my_target"), - ) - .done() - .run_with_handle(); - - let info_tree = info - .and_then( - with_target.with_filter(filter::filter_fn(|meta| dbg!(meta.target()) == "my_target")), - ) - .with_filter(LevelFilter::INFO); - - let subscriber = tracing_subscriber::registry().with(info_tree).with(all); - let _guard = dbg!(subscriber).set_default(); - - tracing::info!("hello world"); - tracing::trace!("hello trace"); - tracing::info!(target: "my_target", "hi to my target"); - tracing::trace!(target: "my_target", "hi to my target at trace"); - - all_handle.assert_finished(); - info_handle.assert_finished(); - with_target_handle.assert_finished(); -} - -#[test] -fn filter_span_scopes() { - fn target_layer(target: &'static str) -> (ExpectLayer, subscriber::MockHandle) { - layer::named(format!("target_{}", target)) - .enter(span::mock().with_target(target).at_level(Level::INFO)) - .event( - event::msg("hello world") - .in_scope(vec![span::mock().with_target(target).at_level(Level::INFO)]), - ) - .exit(span::mock().with_target(target).at_level(Level::INFO)) - .done() - .run_with_handle() - } - - let (a_layer, a_handle) = target_layer("a"); - let (b_layer, b_handle) = target_layer("b"); - let (info_layer, info_handle) = layer::named("info") - .enter(span::mock().with_target("b").at_level(Level::INFO)) - .enter(span::mock().with_target("a").at_level(Level::INFO)) - .event(event::msg("hello world").in_scope(vec![ - span::mock().with_target("a").at_level(Level::INFO), - span::mock().with_target("b").at_level(Level::INFO), - ])) - .exit(span::mock().with_target("a").at_level(Level::INFO)) - .exit(span::mock().with_target("b").at_level(Level::INFO)) - .done() - .run_with_handle(); - - let full_scope = vec![ - span::mock().with_target("b").at_level(Level::TRACE), - span::mock().with_target("a").at_level(Level::INFO), - span::mock().with_target("b").at_level(Level::INFO), - span::mock().with_target("a").at_level(Level::TRACE), - ]; - let (all_layer, all_handle) = layer::named("all") - .enter(span::mock().with_target("a").at_level(Level::TRACE)) - .enter(span::mock().with_target("b").at_level(Level::INFO)) - .enter(span::mock().with_target("a").at_level(Level::INFO)) - .enter(span::mock().with_target("b").at_level(Level::TRACE)) - .event(event::msg("hello world").in_scope(full_scope.clone())) - .event( - event::msg("hello to my target") - .with_target("a") - .in_scope(full_scope.clone()), - ) - .event( - event::msg("hello to my target") - .with_target("b") - .in_scope(full_scope), - ) - .exit(span::mock().with_target("b").at_level(Level::TRACE)) - .exit(span::mock().with_target("a").at_level(Level::INFO)) - .exit(span::mock().with_target("b").at_level(Level::INFO)) - .exit(span::mock().with_target("a").at_level(Level::TRACE)) - .done() - .run_with_handle(); - - let a_layer = a_layer.with_filter(filter::filter_fn(|meta| { - let target = meta.target(); - target == "a" || target == module_path!() - })); - - let b_layer = b_layer.with_filter(filter::filter_fn(|meta| { - let target = meta.target(); - target == "b" || target == module_path!() - })); - - let info_tree = info_layer - .and_then(a_layer) - .and_then(b_layer) - .with_filter(LevelFilter::INFO); - - let subscriber = tracing_subscriber::registry() - .with(info_tree) - .with(all_layer); - let _guard = dbg!(subscriber).set_default(); - - { - let _a1 = tracing::trace_span!(target: "a", "a/trace").entered(); - let _b1 = tracing::info_span!(target: "b", "b/info").entered(); - let _a2 = tracing::info_span!(target: "a", "a/info").entered(); - let _b2 = tracing::trace_span!(target: "b", "b/trace").entered(); - tracing::info!("hello world"); - tracing::debug!(target: "a", "hello to my target"); - tracing::debug!(target: "b", "hello to my target"); - } - - all_handle.assert_finished(); - info_handle.assert_finished(); - a_handle.assert_finished(); - b_handle.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/layer_filters/vec.rs b/vendor/tracing-subscriber/tests/layer_filters/vec.rs deleted file mode 100644 index 87244e4ab..000000000 --- a/vendor/tracing-subscriber/tests/layer_filters/vec.rs +++ /dev/null @@ -1,120 +0,0 @@ -use super::*; -use tracing::Subscriber; - -#[test] -fn with_filters_unboxed() { - let (trace_layer, trace_handle) = layer::named("trace") - .event(event::mock().at_level(Level::TRACE)) - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - let trace_layer = trace_layer.with_filter(LevelFilter::TRACE); - - let (debug_layer, debug_handle) = layer::named("debug") - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - let debug_layer = debug_layer.with_filter(LevelFilter::DEBUG); - - let (info_layer, info_handle) = layer::named("info") - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - let info_layer = info_layer.with_filter(LevelFilter::INFO); - - let _subscriber = tracing_subscriber::registry() - .with(vec![trace_layer, debug_layer, info_layer]) - .set_default(); - - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - - trace_handle.assert_finished(); - debug_handle.assert_finished(); - info_handle.assert_finished(); -} - -#[test] -fn with_filters_boxed() { - let (unfiltered_layer, unfiltered_handle) = layer::named("unfiltered") - .event(event::mock().at_level(Level::TRACE)) - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - let unfiltered_layer = unfiltered_layer.boxed(); - - let (debug_layer, debug_handle) = layer::named("debug") - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - let debug_layer = debug_layer.with_filter(LevelFilter::DEBUG).boxed(); - - let (target_layer, target_handle) = layer::named("target") - .event(event::mock().at_level(Level::INFO)) - .done() - .run_with_handle(); - let target_layer = target_layer - .with_filter(filter::filter_fn(|meta| meta.target() == "my_target")) - .boxed(); - - let _subscriber = tracing_subscriber::registry() - .with(vec![unfiltered_layer, debug_layer, target_layer]) - .set_default(); - - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!(target: "my_target", "hello my target"); - - unfiltered_handle.assert_finished(); - debug_handle.assert_finished(); - target_handle.assert_finished(); -} - -#[test] -fn mixed_max_level_hint() { - let unfiltered = layer::named("unfiltered").run().boxed(); - let info = layer::named("info") - .run() - .with_filter(LevelFilter::INFO) - .boxed(); - let debug = layer::named("debug") - .run() - .with_filter(LevelFilter::DEBUG) - .boxed(); - - let subscriber = tracing_subscriber::registry().with(vec![unfiltered, info, debug]); - - assert_eq!(subscriber.max_level_hint(), None); -} - -#[test] -fn all_filtered_max_level_hint() { - let warn = layer::named("warn") - .run() - .with_filter(LevelFilter::WARN) - .boxed(); - let info = layer::named("info") - .run() - .with_filter(LevelFilter::INFO) - .boxed(); - let debug = layer::named("debug") - .run() - .with_filter(LevelFilter::DEBUG) - .boxed(); - - let subscriber = tracing_subscriber::registry().with(vec![warn, info, debug]); - - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG)); -} - -#[test] -fn empty_vec() { - // Just a None means everything is off - let subscriber = tracing_subscriber::registry().with(Vec::<ExpectLayer>::new()); - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF)); -} diff --git a/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs b/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs deleted file mode 100644 index 5c25e7f03..000000000 --- a/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs +++ /dev/null @@ -1,131 +0,0 @@ -#![cfg(feature = "registry")] -mod support; -use self::support::*; - -use std::{ - collections::HashMap, - sync::{Arc, Mutex}, -}; -use tracing::{Level, Subscriber}; -use tracing_subscriber::{filter, prelude::*}; - -#[test] -fn multiple_layer_filter_interests_are_cached() { - // This layer will return Interest::always for INFO and lower. - let seen_info = Arc::new(Mutex::new(HashMap::new())); - let seen_info2 = seen_info.clone(); - let filter = filter::filter_fn(move |meta| { - *seen_info - .lock() - .unwrap() - .entry(*meta.level()) - .or_insert(0usize) += 1; - meta.level() <= &Level::INFO - }); - let seen_info = seen_info2; - - let (info_layer, info_handle) = layer::named("info") - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - let info_layer = info_layer.with_filter(filter); - - // This layer will return Interest::always for WARN and lower. - let seen_warn = Arc::new(Mutex::new(HashMap::new())); - let seen_warn2 = seen_warn.clone(); - let filter = filter::filter_fn(move |meta| { - *seen_warn - .lock() - .unwrap() - .entry(*meta.level()) - .or_insert(0usize) += 1; - meta.level() <= &Level::WARN - }); - let seen_warn = seen_warn2; - - let (warn_layer, warn_handle) = layer::named("warn") - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - let warn_layer = warn_layer.with_filter(filter); - - let subscriber = tracing_subscriber::registry() - .with(warn_layer) - .with(info_layer); - assert!(subscriber.max_level_hint().is_none()); - - let _subscriber = subscriber.set_default(); - - fn events() { - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); - } - - events(); - { - let lock = seen_info.lock().unwrap(); - for (&level, &count) in lock.iter() { - if level == Level::INFO { - continue; - } - assert_eq!( - count, 1, - "level {:?} should have been seen 1 time by the INFO layer (after first set of events)", - level - ); - } - - let lock = seen_warn.lock().unwrap(); - for (&level, &count) in lock.iter() { - if level == Level::INFO { - continue; - } - assert_eq!( - count, 1, - "level {:?} should have been seen 1 time by the WARN layer (after first set of events)", - level - ); - } - } - - events(); - { - let lock = seen_info.lock().unwrap(); - for (&level, &count) in lock.iter() { - if level == Level::INFO { - continue; - } - assert_eq!( - count, 1, - "level {:?} should have been seen 1 time by the INFO layer (after second set of events)", - level - ); - } - - let lock = seen_warn.lock().unwrap(); - for (&level, &count) in lock.iter() { - if level == Level::INFO { - continue; - } - assert_eq!( - count, 1, - "level {:?} should have been seen 1 time by the WARN layer (after second set of events)", - level - ); - } - } - - info_handle.assert_finished(); - warn_handle.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/option.rs b/vendor/tracing-subscriber/tests/option.rs deleted file mode 100644 index 738cc0a6c..000000000 --- a/vendor/tracing-subscriber/tests/option.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![cfg(feature = "registry")] -use tracing::level_filters::LevelFilter; -use tracing::Subscriber; -use tracing_subscriber::prelude::*; - -// This test is just used to compare to the tests below -#[test] -fn just_layer() { - let subscriber = tracing_subscriber::registry().with(LevelFilter::INFO); - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO)); -} - -#[test] -fn subscriber_and_option_some_layer() { - let subscriber = tracing_subscriber::registry() - .with(LevelFilter::INFO) - .with(Some(LevelFilter::DEBUG)); - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG)); -} - -#[test] -fn subscriber_and_option_none_layer() { - // None means the other layer takes control - let subscriber = tracing_subscriber::registry() - .with(LevelFilter::ERROR) - .with(None::<LevelFilter>); - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR)); -} - -#[test] -fn just_option_some_layer() { - // Just a None means everything is off - let subscriber = tracing_subscriber::registry().with(None::<LevelFilter>); - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF)); -} - -#[test] -fn just_option_none_layer() { - let subscriber = tracing_subscriber::registry().with(Some(LevelFilter::ERROR)); - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR)); -} diff --git a/vendor/tracing-subscriber/tests/registry_max_level_hint.rs b/vendor/tracing-subscriber/tests/registry_max_level_hint.rs deleted file mode 100644 index f94c8a1fb..000000000 --- a/vendor/tracing-subscriber/tests/registry_max_level_hint.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![cfg(all(feature = "registry", feature = "fmt"))] -use tracing_subscriber::{filter::LevelFilter, prelude::*}; - -#[test] -fn registry_sets_max_level_hint() { - tracing_subscriber::registry() - .with(tracing_subscriber::fmt::layer()) - .with(LevelFilter::DEBUG) - .init(); - assert_eq!(LevelFilter::current(), LevelFilter::DEBUG); -} diff --git a/vendor/tracing-subscriber/tests/registry_with_subscriber.rs b/vendor/tracing-subscriber/tests/registry_with_subscriber.rs deleted file mode 100644 index 50d2f551d..000000000 --- a/vendor/tracing-subscriber/tests/registry_with_subscriber.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![cfg(feature = "registry")] -use tracing_futures::{Instrument, WithSubscriber}; -use tracing_subscriber::prelude::*; - -#[tokio::test] -async fn future_with_subscriber() { - tracing_subscriber::registry().init(); - let span = tracing::info_span!("foo"); - let _e = span.enter(); - let span = tracing::info_span!("bar"); - let _e = span.enter(); - tokio::spawn( - async { - async { - let span = tracing::Span::current(); - println!("{:?}", span); - } - .instrument(tracing::info_span!("hi")) - .await - } - .with_subscriber(tracing_subscriber::registry()), - ) - .await - .unwrap(); -} diff --git a/vendor/tracing-subscriber/tests/reload.rs b/vendor/tracing-subscriber/tests/reload.rs deleted file mode 100644 index b8b6c2b46..000000000 --- a/vendor/tracing-subscriber/tests/reload.rs +++ /dev/null @@ -1,141 +0,0 @@ -#![cfg(feature = "std")] -use std::sync::atomic::{AtomicUsize, Ordering}; -use tracing_core::{ - span::{Attributes, Id, Record}, - subscriber::Interest, - Event, Metadata, Subscriber, -}; -use tracing_subscriber::{layer, prelude::*, reload::*}; - -pub struct NopSubscriber; - -impl Subscriber for NopSubscriber { - fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest { - Interest::never() - } - - fn enabled(&self, _: &Metadata<'_>) -> bool { - false - } - - fn new_span(&self, _: &Attributes<'_>) -> Id { - Id::from_u64(1) - } - - fn record(&self, _: &Id, _: &Record<'_>) {} - fn record_follows_from(&self, _: &Id, _: &Id) {} - fn event(&self, _: &Event<'_>) {} - fn enter(&self, _: &Id) {} - fn exit(&self, _: &Id) {} -} - -#[test] -fn reload_handle() { - static FILTER1_CALLS: AtomicUsize = AtomicUsize::new(0); - static FILTER2_CALLS: AtomicUsize = AtomicUsize::new(0); - - enum Filter { - One, - Two, - } - - impl<S: Subscriber> tracing_subscriber::Layer<S> for Filter { - fn register_callsite(&self, m: &Metadata<'_>) -> Interest { - println!("REGISTER: {:?}", m); - Interest::sometimes() - } - - fn enabled(&self, m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool { - println!("ENABLED: {:?}", m); - match self { - Filter::One => FILTER1_CALLS.fetch_add(1, Ordering::SeqCst), - Filter::Two => FILTER2_CALLS.fetch_add(1, Ordering::SeqCst), - }; - true - } - } - fn event() { - tracing::trace!("my event"); - } - - let (layer, handle) = Layer::new(Filter::One); - - let subscriber = tracing_core::dispatcher::Dispatch::new(layer.with_subscriber(NopSubscriber)); - - tracing_core::dispatcher::with_default(&subscriber, || { - assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 0); - assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0); - - event(); - - assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); - assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0); - - handle.reload(Filter::Two).expect("should reload"); - - event(); - - assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); - assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1); - }) -} - -#[test] -#[cfg(feature = "registry")] -fn reload_filter() { - struct NopLayer; - impl<S: Subscriber> tracing_subscriber::Layer<S> for NopLayer { - fn register_callsite(&self, _m: &Metadata<'_>) -> Interest { - Interest::sometimes() - } - - fn enabled(&self, _m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool { - true - } - } - - static FILTER1_CALLS: AtomicUsize = AtomicUsize::new(0); - static FILTER2_CALLS: AtomicUsize = AtomicUsize::new(0); - - enum Filter { - One, - Two, - } - - impl<S: Subscriber> tracing_subscriber::layer::Filter<S> for Filter { - fn enabled(&self, m: &Metadata<'_>, _: &layer::Context<'_, S>) -> bool { - println!("ENABLED: {:?}", m); - match self { - Filter::One => FILTER1_CALLS.fetch_add(1, Ordering::SeqCst), - Filter::Two => FILTER2_CALLS.fetch_add(1, Ordering::SeqCst), - }; - true - } - } - fn event() { - tracing::trace!("my event"); - } - - let (filter, handle) = Layer::new(Filter::One); - - let dispatcher = tracing_core::Dispatch::new( - tracing_subscriber::registry().with(NopLayer.with_filter(filter)), - ); - - tracing_core::dispatcher::with_default(&dispatcher, || { - assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 0); - assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0); - - event(); - - assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); - assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0); - - handle.reload(Filter::Two).expect("should reload"); - - event(); - - assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); - assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1); - }) -} diff --git a/vendor/tracing-subscriber/tests/same_len_filters.rs b/vendor/tracing-subscriber/tests/same_len_filters.rs deleted file mode 100644 index 879e578d7..000000000 --- a/vendor/tracing-subscriber/tests/same_len_filters.rs +++ /dev/null @@ -1,81 +0,0 @@ -// These tests include field filters with no targets, so they have to go in a -// separate file. -#![cfg(feature = "env-filter")] - -use tracing::{self, subscriber::with_default, Level}; -use tracing_mock::*; -use tracing_subscriber::{filter::EnvFilter, prelude::*}; - -#[test] -fn same_length_targets() { - let filter: EnvFilter = "foo=trace,bar=trace".parse().expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .event(event::mock().at_level(Level::TRACE)) - .event(event::mock().at_level(Level::TRACE)) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - - with_default(subscriber, || { - tracing::trace!(target: "foo", "foo"); - tracing::trace!(target: "bar", "bar"); - }); - - finished.assert_finished(); -} - -#[test] -fn same_num_fields_event() { - let filter: EnvFilter = "[{foo}]=trace,[{bar}]=trace" - .parse() - .expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .event( - event::mock() - .at_level(Level::TRACE) - .with_fields(field::mock("foo")), - ) - .event( - event::mock() - .at_level(Level::TRACE) - .with_fields(field::mock("bar")), - ) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - with_default(subscriber, || { - tracing::trace!(foo = 1); - tracing::trace!(bar = 3); - }); - - finished.assert_finished(); -} - -#[test] -fn same_num_fields_and_name_len() { - let filter: EnvFilter = "[foo{bar=1}]=trace,[baz{boz=1}]=trace" - .parse() - .expect("filter should parse"); - let (subscriber, finished) = subscriber::mock() - .new_span( - span::mock() - .named("foo") - .at_level(Level::TRACE) - .with_field(field::mock("bar")), - ) - .new_span( - span::mock() - .named("baz") - .at_level(Level::TRACE) - .with_field(field::mock("boz")), - ) - .done() - .run_with_handle(); - let subscriber = subscriber.with(filter); - with_default(subscriber, || { - tracing::trace_span!("foo", bar = 1); - tracing::trace_span!("baz", boz = 1); - }); - - finished.assert_finished(); -} diff --git a/vendor/tracing-subscriber/tests/support.rs b/vendor/tracing-subscriber/tests/support.rs deleted file mode 100644 index 50e0e6669..000000000 --- a/vendor/tracing-subscriber/tests/support.rs +++ /dev/null @@ -1,407 +0,0 @@ -#![allow(missing_docs, dead_code)] -pub use tracing_mock::{event, field, span, subscriber}; - -use tracing_core::{ - span::{Attributes, Id, Record}, - Event, Subscriber, -}; -use tracing_mock::{ - event::MockEvent, - span::{MockSpan, NewSpan}, - subscriber::{Expect, MockHandle}, -}; -use tracing_subscriber::{ - layer::{Context, Layer}, - registry::{LookupSpan, SpanRef}, -}; - -use std::{ - collections::VecDeque, - fmt, - sync::{Arc, Mutex}, -}; - -pub mod layer { - use super::ExpectLayerBuilder; - - pub fn mock() -> ExpectLayerBuilder { - ExpectLayerBuilder { - expected: Default::default(), - name: std::thread::current() - .name() - .map(String::from) - .unwrap_or_default(), - } - } - - pub fn named(name: impl std::fmt::Display) -> ExpectLayerBuilder { - mock().named(name) - } -} - -pub struct ExpectLayerBuilder { - expected: VecDeque<Expect>, - name: String, -} - -pub struct ExpectLayer { - expected: Arc<Mutex<VecDeque<Expect>>>, - current: Mutex<Vec<Id>>, - name: String, -} - -impl ExpectLayerBuilder { - /// Overrides the name printed by the mock subscriber's debugging output. - /// - /// The debugging output is displayed if the test panics, or if the test is - /// run with `--nocapture`. - /// - /// By default, the mock subscriber's name is the name of the test - /// (*technically*, the name of the thread where it was created, which is - /// the name of the test unless tests are run with `--test-threads=1`). - /// When a test has only one mock subscriber, this is sufficient. However, - /// some tests may include multiple subscribers, in order to test - /// interactions between multiple subscribers. In that case, it can be - /// helpful to give each subscriber a separate name to distinguish where the - /// debugging output comes from. - pub fn named(mut self, name: impl fmt::Display) -> Self { - use std::fmt::Write; - if !self.name.is_empty() { - write!(&mut self.name, "::{}", name).unwrap(); - } else { - self.name = name.to_string(); - } - self - } - - pub fn enter(mut self, span: MockSpan) -> Self { - self.expected.push_back(Expect::Enter(span)); - self - } - - pub fn event(mut self, event: MockEvent) -> Self { - self.expected.push_back(Expect::Event(event)); - self - } - - pub fn exit(mut self, span: MockSpan) -> Self { - self.expected.push_back(Expect::Exit(span)); - self - } - - pub fn done(mut self) -> Self { - self.expected.push_back(Expect::Nothing); - self - } - - pub fn record<I>(mut self, span: MockSpan, fields: I) -> Self - where - I: Into<field::Expect>, - { - self.expected.push_back(Expect::Visit(span, fields.into())); - self - } - - pub fn new_span<I>(mut self, new_span: I) -> Self - where - I: Into<NewSpan>, - { - self.expected.push_back(Expect::NewSpan(new_span.into())); - self - } - - pub fn run(self) -> ExpectLayer { - ExpectLayer { - expected: Arc::new(Mutex::new(self.expected)), - name: self.name, - current: Mutex::new(Vec::new()), - } - } - - pub fn run_with_handle(self) -> (ExpectLayer, MockHandle) { - let expected = Arc::new(Mutex::new(self.expected)); - let handle = MockHandle::new(expected.clone(), self.name.clone()); - let layer = ExpectLayer { - expected, - name: self.name, - current: Mutex::new(Vec::new()), - }; - (layer, handle) - } -} - -impl ExpectLayer { - fn check_span_ref<'spans, S>( - &self, - expected: &MockSpan, - actual: &SpanRef<'spans, S>, - what_happened: impl fmt::Display, - ) where - S: LookupSpan<'spans>, - { - if let Some(exp_name) = expected.name() { - assert_eq!( - actual.name(), - exp_name, - "\n[{}] expected {} a span named {:?}\n\ - [{}] but it was named {:?} instead (span {} {:?})", - self.name, - what_happened, - exp_name, - self.name, - actual.name(), - actual.name(), - actual.id() - ); - } - - if let Some(exp_level) = expected.level() { - let actual_level = actual.metadata().level(); - assert_eq!( - actual_level, - &exp_level, - "\n[{}] expected {} a span at {:?}\n\ - [{}] but it was at {:?} instead (span {} {:?})", - self.name, - what_happened, - exp_level, - self.name, - actual_level, - actual.name(), - actual.id(), - ); - } - - if let Some(exp_target) = expected.target() { - let actual_target = actual.metadata().target(); - assert_eq!( - actual_target, - exp_target, - "\n[{}] expected {} a span with target {:?}\n\ - [{}] but it had the target {:?} instead (span {} {:?})", - self.name, - what_happened, - exp_target, - self.name, - actual_target, - actual.name(), - actual.id(), - ); - } - } -} - -impl<S> Layer<S> for ExpectLayer -where - S: Subscriber + for<'a> LookupSpan<'a>, -{ - fn register_callsite( - &self, - metadata: &'static tracing::Metadata<'static>, - ) -> tracing_core::Interest { - println!("[{}] register_callsite {:#?}", self.name, metadata); - tracing_core::Interest::always() - } - - fn on_record(&self, _: &Id, _: &Record<'_>, _: Context<'_, S>) { - unimplemented!( - "so far, we don't have any tests that need an `on_record` \ - implementation.\nif you just wrote one that does, feel free to \ - implement it!" - ); - } - - fn on_event(&self, event: &Event<'_>, cx: Context<'_, S>) { - let name = event.metadata().name(); - println!( - "[{}] event: {}; level: {}; target: {}", - self.name, - name, - event.metadata().level(), - event.metadata().target(), - ); - match self.expected.lock().unwrap().pop_front() { - None => {} - Some(Expect::Event(mut expected)) => { - let get_parent_name = || cx.event_span(event).map(|span| span.name().to_string()); - expected.check(event, get_parent_name, &self.name); - let mut current_scope = cx.event_scope(event).into_iter().flatten(); - let expected_scope = expected.scope_mut(); - let mut i = 0; - for (expected, actual) in expected_scope.iter_mut().zip(&mut current_scope) { - println!( - "[{}] event_scope[{}] actual={} ({:?}); expected={}", - self.name, - i, - actual.name(), - actual.id(), - expected - ); - self.check_span_ref( - expected, - &actual, - format_args!("the {}th span in the event's scope to be", i), - ); - i += 1; - } - let remaining_expected = &expected_scope[i..]; - assert!( - remaining_expected.is_empty(), - "\n[{}] did not observe all expected spans in event scope!\n[{}] missing: {:#?}", - self.name, - self.name, - remaining_expected, - ); - assert!( - current_scope.next().is_none(), - "\n[{}] did not expect all spans in the actual event scope!", - self.name, - ); - } - Some(ex) => ex.bad(&self.name, format_args!("observed event {:#?}", event)), - } - } - - fn on_follows_from(&self, _span: &Id, _follows: &Id, _: Context<'_, S>) { - // TODO: it should be possible to expect spans to follow from other spans - } - - fn on_new_span(&self, span: &Attributes<'_>, id: &Id, cx: Context<'_, S>) { - let meta = span.metadata(); - println!( - "[{}] new_span: name={:?}; target={:?}; id={:?};", - self.name, - meta.name(), - meta.target(), - id - ); - let mut expected = self.expected.lock().unwrap(); - let was_expected = matches!(expected.front(), Some(Expect::NewSpan(_))); - if was_expected { - if let Expect::NewSpan(mut expected) = expected.pop_front().unwrap() { - let get_parent_name = || { - span.parent() - .and_then(|id| cx.span(id)) - .or_else(|| cx.lookup_current()) - .map(|span| span.name().to_string()) - }; - expected.check(span, get_parent_name, &self.name); - } - } - } - - fn on_enter(&self, id: &Id, cx: Context<'_, S>) { - let span = cx - .span(id) - .unwrap_or_else(|| panic!("[{}] no span for ID {:?}", self.name, id)); - println!("[{}] enter: {}; id={:?};", self.name, span.name(), id); - match self.expected.lock().unwrap().pop_front() { - None => {} - Some(Expect::Enter(ref expected_span)) => { - self.check_span_ref(expected_span, &span, "to enter"); - } - Some(ex) => ex.bad(&self.name, format_args!("entered span {:?}", span.name())), - } - self.current.lock().unwrap().push(id.clone()); - } - - fn on_exit(&self, id: &Id, cx: Context<'_, S>) { - if std::thread::panicking() { - // `exit()` can be called in `drop` impls, so we must guard against - // double panics. - println!("[{}] exit {:?} while panicking", self.name, id); - return; - } - let span = cx - .span(id) - .unwrap_or_else(|| panic!("[{}] no span for ID {:?}", self.name, id)); - println!("[{}] exit: {}; id={:?};", self.name, span.name(), id); - match self.expected.lock().unwrap().pop_front() { - None => {} - Some(Expect::Exit(ref expected_span)) => { - self.check_span_ref(expected_span, &span, "to exit"); - let curr = self.current.lock().unwrap().pop(); - assert_eq!( - Some(id), - curr.as_ref(), - "[{}] exited span {:?}, but the current span was {:?}", - self.name, - span.name(), - curr.as_ref().and_then(|id| cx.span(id)).map(|s| s.name()) - ); - } - Some(ex) => ex.bad(&self.name, format_args!("exited span {:?}", span.name())), - }; - } - - fn on_close(&self, id: Id, cx: Context<'_, S>) { - if std::thread::panicking() { - // `try_close` can be called in `drop` impls, so we must guard against - // double panics. - println!("[{}] close {:?} while panicking", self.name, id); - return; - } - let span = cx.span(&id); - let name = span.as_ref().map(|span| { - println!("[{}] close_span: {}; id={:?};", self.name, span.name(), id,); - span.name() - }); - if name.is_none() { - println!("[{}] drop_span: id={:?}", self.name, id); - } - if let Ok(mut expected) = self.expected.try_lock() { - let was_expected = match expected.front() { - Some(Expect::DropSpan(ref expected_span)) => { - // Don't assert if this function was called while panicking, - // as failing the assertion can cause a double panic. - if !::std::thread::panicking() { - if let Some(ref span) = span { - self.check_span_ref(expected_span, span, "to close"); - } - } - true - } - Some(Expect::Event(_)) => { - if !::std::thread::panicking() { - panic!( - "[{}] expected an event, but dropped span {} (id={:?}) instead", - self.name, - name.unwrap_or("<unknown name>"), - id - ); - } - true - } - _ => false, - }; - if was_expected { - expected.pop_front(); - } - } - } - - fn on_id_change(&self, _old: &Id, _new: &Id, _ctx: Context<'_, S>) { - panic!("well-behaved subscribers should never do this to us, lol"); - } -} - -impl fmt::Debug for ExpectLayer { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut s = f.debug_struct("ExpectLayer"); - s.field("name", &self.name); - - if let Ok(expected) = self.expected.try_lock() { - s.field("expected", &expected); - } else { - s.field("expected", &format_args!("<locked>")); - } - - if let Ok(current) = self.current.try_lock() { - s.field("current", &format_args!("{:?}", ¤t)); - } else { - s.field("current", &format_args!("<locked>")); - } - - s.finish() - } -} diff --git a/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs deleted file mode 100644 index 9fa5c6bd4..000000000 --- a/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs +++ /dev/null @@ -1,123 +0,0 @@ -#![cfg(feature = "registry")] -mod support; -use self::support::*; -use tracing::Level; -use tracing_subscriber::{filter::DynFilterFn, prelude::*}; - -#[test] -fn layer_filters() { - let (unfiltered, unfiltered_handle) = unfiltered("unfiltered"); - let (filtered, filtered_handle) = filtered("filtered"); - - let _subscriber = tracing_subscriber::registry() - .with(unfiltered) - .with(filtered.with_filter(filter())) - .set_default(); - - events(); - - unfiltered_handle.assert_finished(); - filtered_handle.assert_finished(); -} - -#[test] -fn layered_layer_filters() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - let unfiltered = unfiltered1.and_then(unfiltered2); - - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - let filtered = filtered1 - .with_filter(filter()) - .and_then(filtered2.with_filter(filter())); - - let _subscriber = tracing_subscriber::registry() - .with(unfiltered) - .with(filtered) - .set_default(); - - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -#[test] -fn out_of_order() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - - let _subscriber = tracing_subscriber::registry() - .with(unfiltered1) - .with(filtered1.with_filter(filter())) - .with(unfiltered2) - .with(filtered2.with_filter(filter())) - .set_default(); - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -#[test] -fn mixed_layered() { - let (unfiltered1, unfiltered1_handle) = unfiltered("unfiltered_1"); - let (unfiltered2, unfiltered2_handle) = unfiltered("unfiltered_2"); - let (filtered1, filtered1_handle) = filtered("filtered_1"); - let (filtered2, filtered2_handle) = filtered("filtered_2"); - - let layered1 = filtered1.with_filter(filter()).and_then(unfiltered1); - let layered2 = unfiltered2.and_then(filtered2.with_filter(filter())); - - let _subscriber = tracing_subscriber::registry() - .with(layered1) - .with(layered2) - .set_default(); - - events(); - - unfiltered1_handle.assert_finished(); - unfiltered2_handle.assert_finished(); - filtered1_handle.assert_finished(); - filtered2_handle.assert_finished(); -} - -fn events() { - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); -} - -fn filter<S>() -> DynFilterFn<S> { - DynFilterFn::new(|metadata, _| metadata.level() <= &Level::INFO) -} - -fn unfiltered(name: &str) -> (ExpectLayer, subscriber::MockHandle) { - layer::named(name) - .event(event::mock().at_level(Level::TRACE)) - .event(event::mock().at_level(Level::DEBUG)) - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle() -} - -fn filtered(name: &str) -> (ExpectLayer, subscriber::MockHandle) { - layer::named(name) - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle() -} diff --git a/vendor/tracing-subscriber/tests/utils.rs b/vendor/tracing-subscriber/tests/utils.rs deleted file mode 100644 index e95868d5e..000000000 --- a/vendor/tracing-subscriber/tests/utils.rs +++ /dev/null @@ -1,39 +0,0 @@ -#![cfg(feature = "std")] - -use tracing_mock::*; -use tracing_subscriber::prelude::*; - -#[test] -fn init_ext_works() { - let (subscriber, finished) = subscriber::mock() - .event( - event::mock() - .at_level(tracing::Level::INFO) - .with_target("init_works"), - ) - .done() - .run_with_handle(); - - let _guard = subscriber.set_default(); - tracing::info!(target: "init_works", "it worked!"); - finished.assert_finished(); -} - -#[test] -#[cfg(feature = "fmt")] -fn builders_are_init_ext() { - tracing_subscriber::fmt().set_default(); - let _ = tracing_subscriber::fmt() - .with_target(false) - .compact() - .try_init(); -} - -#[test] -#[cfg(all(feature = "fmt", feature = "env-filter"))] -fn layered_is_init_ext() { - tracing_subscriber::registry() - .with(tracing_subscriber::fmt::layer()) - .with(tracing_subscriber::EnvFilter::new("foo=info")) - .set_default(); -} diff --git a/vendor/tracing-subscriber/tests/vec.rs b/vendor/tracing-subscriber/tests/vec.rs deleted file mode 100644 index 92abf0bff..000000000 --- a/vendor/tracing-subscriber/tests/vec.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![cfg(feature = "registry")] -use tracing::level_filters::LevelFilter; -use tracing::Subscriber; -use tracing_subscriber::prelude::*; - -#[test] -fn just_empty_vec() { - // Just a None means everything is off - let subscriber = tracing_subscriber::registry().with(Vec::<LevelFilter>::new()); - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF)); -} - -#[test] -fn layer_and_empty_vec() { - let subscriber = tracing_subscriber::registry() - .with(LevelFilter::INFO) - .with(Vec::<LevelFilter>::new()); - assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO)); -} diff --git a/vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs b/vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs deleted file mode 100644 index 10467cb7d..000000000 --- a/vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs +++ /dev/null @@ -1,117 +0,0 @@ -#![cfg(feature = "registry")] -mod support; -use self::support::*; - -use std::{ - collections::HashMap, - sync::{Arc, Mutex}, -}; -use tracing::{Level, Subscriber}; -use tracing_subscriber::{filter, prelude::*}; - -#[test] -fn vec_layer_filter_interests_are_cached() { - let mk_filtered = |level: Level, subscriber: ExpectLayer| { - let seen = Arc::new(Mutex::new(HashMap::new())); - let filter = filter::filter_fn({ - let seen = seen.clone(); - move |meta| { - *seen.lock().unwrap().entry(*meta.level()).or_insert(0usize) += 1; - meta.level() <= &level - } - }); - (subscriber.with_filter(filter).boxed(), seen) - }; - - // This layer will return Interest::always for INFO and lower. - let (info_layer, info_handle) = layer::named("info") - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::INFO)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - let (info_layer, seen_info) = mk_filtered(Level::INFO, info_layer); - - // This layer will return Interest::always for WARN and lower. - let (warn_layer, warn_handle) = layer::named("warn") - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .done() - .run_with_handle(); - let (warn_layer, seen_warn) = mk_filtered(Level::WARN, warn_layer); - - let subscriber = tracing_subscriber::registry().with(vec![warn_layer, info_layer]); - assert!(subscriber.max_level_hint().is_none()); - - let _subscriber = subscriber.set_default(); - - fn events() { - tracing::trace!("hello trace"); - tracing::debug!("hello debug"); - tracing::info!("hello info"); - tracing::warn!("hello warn"); - tracing::error!("hello error"); - } - - events(); - { - let lock = seen_info.lock().unwrap(); - for (&level, &count) in lock.iter() { - if level == Level::INFO { - continue; - } - assert_eq!( - count, 1, - "level {:?} should have been seen 1 time by the INFO subscriber (after first set of events)", - level - ); - } - - let lock = seen_warn.lock().unwrap(); - for (&level, &count) in lock.iter() { - if level == Level::INFO { - continue; - } - assert_eq!( - count, 1, - "level {:?} should have been seen 1 time by the WARN subscriber (after first set of events)", - level - ); - } - } - - events(); - { - let lock = seen_info.lock().unwrap(); - for (&level, &count) in lock.iter() { - if level == Level::INFO { - continue; - } - assert_eq!( - count, 1, - "level {:?} should have been seen 1 time by the INFO subscriber (after second set of events)", - level - ); - } - - let lock = seen_warn.lock().unwrap(); - for (&level, &count) in lock.iter() { - if level == Level::INFO { - continue; - } - assert_eq!( - count, 1, - "level {:?} should have been seen 1 time by the WARN subscriber (after second set of events)", - level - ); - } - } - - info_handle.assert_finished(); - warn_handle.assert_finished(); -} |