diff options
Diffstat (limited to '')
-rw-r--r-- | vendor/tracing-subscriber-0.3.3/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs | 415 | ||||
-rw-r--r-- | vendor/tracing-subscriber-0.3.3/src/fmt/time/time_crate.rs | 276 | ||||
-rw-r--r-- | vendor/tracing-subscriber-0.3.3/src/reload.rs | 237 | ||||
-rw-r--r-- | vendor/tracing-subscriber-0.3.3/tests/filter.rs | 187 | ||||
-rw-r--r-- | vendor/tracing-subscriber-0.3.3/tests/reload.rs | 81 | ||||
-rw-r--r-- | vendor/tracing-subscriber/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/tracing-subscriber/CHANGELOG.md (renamed from vendor/tracing-subscriber-0.3.3/CHANGELOG.md) | 392 | ||||
-rw-r--r-- | vendor/tracing-subscriber/Cargo.toml (renamed from vendor/tracing-subscriber-0.3.3/Cargo.toml) | 168 | ||||
-rw-r--r-- | vendor/tracing-subscriber/LICENSE (renamed from vendor/tracing-subscriber-0.3.3/LICENSE) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/README.md (renamed from vendor/tracing-subscriber-0.3.3/README.md) | 6 | ||||
-rw-r--r-- | vendor/tracing-subscriber/benches/enter.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/enter.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/benches/filter.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/filter.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/benches/filter_log.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/filter_log.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/benches/fmt.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/fmt.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/benches/support/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/support/mod.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/field/debug.rs (renamed from vendor/tracing-subscriber-0.3.3/src/field/debug.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/field/delimited.rs (renamed from vendor/tracing-subscriber-0.3.3/src/field/delimited.rs) | 4 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/field/display.rs (renamed from vendor/tracing-subscriber-0.3.3/src/field/display.rs) | 2 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/field/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/field/mod.rs) | 14 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/directive.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/directive.rs) | 34 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/env/builder.rs | 325 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/env/directive.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs) | 160 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/env/field.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs) | 250 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/env/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs) | 677 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/filter_fn.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs | 542 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/layer_filters/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs) | 454 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/level.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/level.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/mod.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/filter/targets.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/targets.rs) | 104 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/fmt_layer.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs) | 321 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/format/json.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs) | 175 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/format/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/format/mod.rs) | 459 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/format/pretty.rs | 511 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/mod.rs) | 392 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/time/datetime.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/time/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs) | 8 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/time/time_crate.rs | 470 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/writer.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/writer.rs) | 30 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/layer/context.rs (renamed from vendor/tracing-subscriber-0.3.3/src/layer/context.rs) | 22 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/layer/layered.rs (renamed from vendor/tracing-subscriber-0.3.3/src/layer/layered.rs) | 107 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/layer/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/layer/mod.rs) | 820 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/layer/tests.rs (renamed from vendor/tracing-subscriber-0.3.3/src/layer/tests.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/lib.rs (renamed from vendor/tracing-subscriber-0.3.3/src/lib.rs) | 54 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/macros.rs (renamed from vendor/tracing-subscriber-0.3.3/src/macros.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/prelude.rs (renamed from vendor/tracing-subscriber-0.3.3/src/prelude.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/registry/extensions.rs (renamed from vendor/tracing-subscriber-0.3.3/src/registry/extensions.rs) | 2 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/registry/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/registry/mod.rs) | 20 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/registry/sharded.rs (renamed from vendor/tracing-subscriber-0.3.3/src/registry/sharded.rs) | 34 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/registry/stack.rs (renamed from vendor/tracing-subscriber-0.3.3/src/registry/stack.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/reload.rs | 384 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/sync.rs (renamed from vendor/tracing-subscriber-0.3.3/src/sync.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/src/util.rs (renamed from vendor/tracing-subscriber-0.3.3/src/util.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/duplicate_spans.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs) | 1 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/env_filter/main.rs | 547 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/env_filter/per_layer.rs | 305 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/event_enabling.rs | 81 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/field_filter.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/field_filter.rs) | 4 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/filter_log.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/filter_log.rs) | 4 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/fmt_max_level_hint.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/boxed.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/combinators.rs | 42 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/downcast_raw.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/main.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs) | 4 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/per_event.rs | 61 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/targets.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/trees.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/layer_filters/vec.rs | 120 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/multiple_layer_filter_interests_cached.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/option.rs | 262 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/registry_max_level_hint.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/registry_with_subscriber.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs) | 2 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/reload.rs | 155 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/same_len_filters.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/same_len_filters.rs) | 4 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/support.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/support.rs) | 19 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs) | 0 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/utils.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/utils.rs) | 4 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/vec.rs | 19 | ||||
-rw-r--r-- | vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs | 117 |
84 files changed, 7837 insertions, 2053 deletions
diff --git a/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json b/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json deleted file mode 100644 index 3fd14355e..000000000 --- a/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"fd7a732ca8d5997cf09a6ffbde0dda0667873031884aa3549d6044971dc00a66","Cargo.toml":"4908f04be83f94bc75fbcf4244fa57b8a52c984928a3320550b692c1038d5448","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"803714740b5ad75ac31a0f9dafd10e0d4d62f7c27c2c0e182d2076a313b0649b","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":"e6b2dcbf9cb1e9b5e862b462f91190adaf8e14f9c2c5d2048ad651f49cfa2007","src/field/display.rs":"9c06a52919dbe9bfd4cf7eec39293240c9facebe052a2fecc2f21184beb5195f","src/field/mod.rs":"35e3dd4ad7b49c99a24e80c6a40a00b3189a114488793657d6d733a90d2e10f6","src/filter/directive.rs":"7ecf87b17afbddadbc385764c2d9c1fda4b020a08d75f741f8e34c7dc475bd74","src/filter/env/directive.rs":"628f9f566ccee924d43d79b287c569abfc32c2fb74e078958aed6cb8285cfb4f","src/filter/env/field.rs":"9f2ceaedf2e2ecefaff863347ef8dfa85cd5f64a0fd09a0f77f64f412c9bb548","src/filter/env/mod.rs":"7f864a5ef0c008c7fe9a21d0a94bb87dd72746e628ff3e68c18b0fd173763918","src/filter/filter_fn.rs":"0debbc4a4b4d2a57b2a06905017ac908bf34b0a64aaf961535fbf6f4d5a700a9","src/filter/layer_filters.rs":"16ff19fed003b913de4f85a03b31864d71ee73c7ce86b07c80da07fe633f682e","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"8ebfd0dc92415ff27ec552f20919e598842a87186f13f120449053a96e1e3307","src/filter/targets.rs":"5cec882366d7f12de0a88f7daaac8499785ce9e3832619f251876a02ae19a6bf","src/fmt/fmt_layer.rs":"486264d810ab6b28428bd48e00774fc822762fc9f991332a2d94a42b3168f2e6","src/fmt/format/json.rs":"1a38c049e1bf99efaf7db1f1fd26d3a5bb1e768fc1524c95816708e5d39fca35","src/fmt/format/mod.rs":"ff92f7910bed4f3c0c2ce798333d273d6b5b5fc09cc78031f52d13e043986227","src/fmt/format/pretty.rs":"eecf278b15cc60b35c3f6aa5d05452401c7a4a29195357e92318d684fcfe3072","src/fmt/mod.rs":"270ffa0a9e6543a602247fccef276a3012daa558181f24cd9032292edbc8dc2c","src/fmt/time/datetime.rs":"778d4604d800e46b940087394e7b72750738b554e02aea523fa9820ab0768c08","src/fmt/time/mod.rs":"304c9383e5cfc0c42d79f47a10323ed5a98585e018b127924b0925ec067f0739","src/fmt/time/time_crate.rs":"bacec2c8bb31175b85f2fb3ae40155a08b2aab7a04adaf4c88679147dc651c58","src/fmt/writer.rs":"1d7a4e2dddddff1bfd1344f2cecdb6b2b69b015c9869d95987d26e177dffa793","src/layer/context.rs":"2478693e2faffdf2e519b6d37e1c3aa3dd75088185accc2b68ffa8612bf73195","src/layer/layered.rs":"ba918a9b944f2c083cbb75d6d7f99f90083aa0a29cf3f4f1dd78aa034e09ade6","src/layer/mod.rs":"e1804cfe91051020cac63fb1067d196552ebb844b6c6d1d2279b97dbec1c64df","src/layer/tests.rs":"3e974d627c4bc4269cfa10c82c890e596c9d46af8e6bc03c6c117bde1237e948","src/lib.rs":"cb362279b3c6d23645cda6d768707576f460e275d332d5350a036437cd5404e0","src/macros.rs":"e184bffc6b5999c48e365ad08343dca764a5fb711b789beb26bd1d5f1d767726","src/prelude.rs":"088635def33be9a4c4b6ed934dc22540c555e27d62f7625a43aa9c0e525ca467","src/registry/extensions.rs":"7333aefd69c767212a7924c57283442430edccb17092c91e02a7d13b2d312b11","src/registry/mod.rs":"4f0108e75e0f6e239b8eb69fcad052f25e3b887e412e951e0cbec02cf13f05d5","src/registry/sharded.rs":"972bdd94f43a33ef1f2ebf96ea69ebe4c1d4b0215e69315a3b525783c2025696","src/registry/stack.rs":"9ef333d6a8a28a064e80ff1e376dbb07bc597009010ec332b2dc3ab435d737c2","src/reload.rs":"41fa9a1a28fef626e302a80a68d665492e73ef6d1a2a3c2a7aac5d6c9a0bb496","src/sync.rs":"7f78f3de5b618a999be0e61f936a233975e7769f1ebb55a0e48c3d199e9c45e3","src/util.rs":"55b4e9d63112f9d5a12a287273a9b1212741058384332d3edc024168cacfd627","tests/cached_layer_filters_dont_break_other_layers.rs":"b2084542a014abeff821b30b2b8c21e32bfdcffae53ce5335fb588f557fa4244","tests/duplicate_spans.rs":"48f596bbfabcc6618244afddcf3c3f2e915b9d79284f17bdd0e0616ad29929be","tests/field_filter.rs":"c44d88ab711164a2b1b3a09377284b469f79ddf4651416515a035782c7c64b79","tests/filter.rs":"a43d23e867af779031b6245047092aca57ee26980a8f3faa19036542bcd37f06","tests/filter_log.rs":"e0cd9d394dbfeeb80570a7686bc7f588c5489657980436810711ed8852f86169","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/downcast_raw.rs":"9b90ead571543cbe14e89b4fe637360d9baf3069f6f656ed3bdf65e7318648f1","tests/layer_filters/filter_scopes.rs":"02611bc58d0d8a67a127eca8cab1b2d9a9901bd2c8a8daad41adf6089b28aee0","tests/layer_filters/main.rs":"0316d611c740e234b78ed9a9dae392fe80472c1e8b004a007ad2dd87d068c67b","tests/layer_filters/targets.rs":"138e3f9ddd68571d94c5aff9d54ee2fbc5f44724c6ee42477a411740ccb79ee6","tests/layer_filters/trees.rs":"4df7b5cf12da44a9255c56e5b80e2b0cf84820230ba916f324c67bc3ee4e4605","tests/multiple_layer_filter_interests_cached.rs":"1ea195f03e58d715228ec1b604f85bda2fc82812d05b2f6370d5edd34a035f32","tests/registry_max_level_hint.rs":"ba386d32b8d13832d7009163241c3d0723488c0393d85647eb9368776251e4fc","tests/registry_with_subscriber.rs":"13b92ed68d9013aefefbc4c73e695c690630e4460634206d214db4c19abb7c0f","tests/reload.rs":"4566386b1b26e6609f5a4bf0e6bef1c2245a591d12417cee189b26dfa14f7f95","tests/same_len_filters.rs":"50c8f5fa1494773410a9f52a56b303534a01a023b186cf2f3131e5e7706eb156","tests/support.rs":"75559505af8018012739d24b3c8743dd079b4d3a8ae28f08b4586a961720aa7b","tests/unhinted_layer_filters_dont_break_other_layers.rs":"519cfef4977e511af938546d4208c645a28248c8ed8666daf180f0ad32f0a261","tests/utils.rs":"2b04ce2d8b56a9062a025900104853e081eae8e3f113f990a915d5f9dea6577b"},"package":"245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"}
\ No newline at end of file diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs deleted file mode 100644 index 3e47e2d93..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs +++ /dev/null @@ -1,415 +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. -#[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`. - pub fn with_source_location(self, display_location: bool) -> Self { - Self { - display_location, - ..self - } - } -} - -impl<T> Format<Pretty, T> { - /// Sets whether or not the source code location from which an event - /// originated is displayed. - /// - /// This defaults to `true`. - pub fn with_source_location(mut self, display_location: bool) -> Self { - self.format = self.format.with_source_location(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 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 (true, Some(file), Some(line)) = - (self.format.display_location, meta.file(), meta.line()) - { - write!( - writer, - " {} {}:{}{}", - dimmed.paint("at"), - file, - line, - dimmed.paint(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 { - write!(writer, " ({:?})", thread.id())?; - } - } else if !self.display_thread_id { - write!(writer, " {:?}", thread.id())?; - } - } else 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, false); - 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-0.3.3/src/fmt/time/time_crate.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/time/time_crate.rs deleted file mode 100644 index 64d274365..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/time/time_crate.rs +++ /dev/null @@ -1,276 +0,0 @@ -use crate::fmt::{format::Writer, time::FormatTime, writer::WriteAdaptor}; -use std::fmt; -use time::{format_description::well_known, formatting::Formattable, OffsetDateTime}; - -/// Formats the current [local time] using a [formatter] from the [`time` crate]. -/// -/// To format the current [UTC time] instead, use the [`UtcTime`] type. -/// -/// [local time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_local -/// [UTC time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_utc -/// [formatter]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html -/// [`time` crate]: https://docs.rs/time/0.3/time/ -#[derive(Clone, Debug)] -#[cfg_attr(docsrs, doc(cfg(all(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]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_local -/// [UTC time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_utc -/// [formatter]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html -/// [`time` crate]: https://docs.rs/time/0.3/time/ -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] -#[derive(Clone, Debug)] -pub struct UtcTime<F> { - 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]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.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. - /// - /// 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]: https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.now_local - /// [`time` crate]: https://docs.rs/time/0.3/time/ - /// [`Formattable`]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html - /// [well-known formats]: https://docs.rs/time/0.3/time/format_description/well_known/index.html - /// [`format_description!`]: https://docs.rs/time/0.3/time/macros/macro.format_description.html - /// [`time::format_description::parse`]: https://docs.rs/time/0.3/time/format_description/fn.parse.html - /// [`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]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.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]: https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.now_utc - /// [`time` crate]: https://docs.rs/time/0.3/time/ - /// [`Formattable`]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html - /// [well-known formats]: https://docs.rs/time/0.3/time/format_description/well_known/index.html - /// [`format_description!`]: https://docs.rs/time/0.3/time/macros/macro.format_description.html - /// [`time::format_description::parse`]: https://docs.rs/time/0.3/time/format_description/fn.parse.html - /// [`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()) - } -} - -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-0.3.3/src/reload.rs b/vendor/tracing-subscriber-0.3.3/src/reload.rs deleted file mode 100644 index b8ec67dfa..000000000 --- a/vendor/tracing-subscriber-0.3.3/src/reload.rs +++ /dev/null @@ -1,237 +0,0 @@ -//! Wrapper for a `Layer` to allow it to be dynamically reloaded. -//! -//! This module provides a [`Layer` type] which wraps another type implementing -//! the [`Layer` trait], allowing the wrapped type to be replaced with another -//! instance of that type at runtime. -//! -//! This can be used in cases where a subset of `Subscriber` 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. -//! -//! [`Layer` type]: struct.Layer.html -//! [`Layer` trait]: ../layer/trait.Layer.html -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`, 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`. -#[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 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<L, S> Layer<L, S> -where - L: crate::Layer<S> + 'static, - S: Subscriber, -{ - /// Wraps the given `Layer`, returning a `Layer` and a `Handle` that allows - /// the inner type to be modified at runtime. - 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`. - pub fn handle(&self) -> Handle<L, S> { - Handle { - inner: Arc::downgrade(&self.inner), - _s: PhantomData, - } - } -} - -// ===== impl Handle ===== - -impl<L, S> Handle<L, S> -where - L: crate::Layer<S> + 'static, - S: Subscriber, -{ - /// Replace the current layer with the provided `new_layer`. - pub fn reload(&self, new_layer: impl Into<L>) -> Result<(), Error> { - self.modify(|layer| { - *layer = new_layer.into(); - }) - } - - /// Invokes a closure with a mutable reference to the current layer, - /// 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'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, - /// 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-0.3.3/tests/filter.rs b/vendor/tracing-subscriber-0.3.3/tests/filter.rs deleted file mode 100644 index 8386d34d2..000000000 --- a/vendor/tracing-subscriber-0.3.3/tests/filter.rs +++ /dev/null @@ -1,187 +0,0 @@ -#![cfg(feature = "env-filter")] - -mod support; -use self::support::*; -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 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::mock().named("cool_span")) - .event(event::mock().at_level(Level::DEBUG)) - .enter(span::mock().named("uncool_span")) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::DEBUG)) - .exit(span::mock().named("uncool_span")) - .exit(span::mock().named("cool_span")) - .enter(span::mock().named("uncool_span")) - .event(event::mock().at_level(Level::WARN)) - .event(event::mock().at_level(Level::ERROR)) - .exit(span::mock().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(); -} diff --git a/vendor/tracing-subscriber-0.3.3/tests/reload.rs b/vendor/tracing-subscriber-0.3.3/tests/reload.rs deleted file mode 100644 index 5fe422e08..000000000 --- a/vendor/tracing-subscriber-0.3.3/tests/reload.rs +++ /dev/null @@ -1,81 +0,0 @@ -#![cfg(feature = "reload")] -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); - }) -} diff --git a/vendor/tracing-subscriber/.cargo-checksum.json b/vendor/tracing-subscriber/.cargo-checksum.json new file mode 100644 index 000000000..c4ac8776d --- /dev/null +++ b/vendor/tracing-subscriber/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"b7eafabf247da01abf02b9b4aab602fd4f66c0da2ce0c8bcf9aa5fb030002180","Cargo.toml":"cb66c58bf1b31f81c8a6e6e394ba5c125a432c280e6559c052bbafc243694005","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"3a06b39f4d699fbc8d8edccea3afdc29b702f79a208abef04411b5c139c607cc","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":"57c3706a21e87d2ce73aac305cd55def268c5acb9bfc08f68423c150fd058e76","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":"695de9d8b0a04df09bea08cc40403e09ff66613c07f72c403f7bc65b89e1fd36","src/filter/layer_filters/mod.rs":"2f23fa79561248255a60d1948423a21bfac5bb8651e6c2ab29d311f4e387a8dc","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"8ebfd0dc92415ff27ec552f20919e598842a87186f13f120449053a96e1e3307","src/filter/targets.rs":"8fafbbaeb4023f498e64a2831be02fefb825345fbd58065fc7f6129dd70eae4b","src/fmt/fmt_layer.rs":"a596e32e196895866cbd867d52ca13edcdd7651aec971b39f10f9285322823b0","src/fmt/format/json.rs":"554985ed40f7c59787aae87626144241ca973929e33979c54f821b673b71fec9","src/fmt/format/mod.rs":"4e920ab448b1dd4b8c2679261dd337273620fd4f20b6439a4aab341c4d2b08e0","src/fmt/format/pretty.rs":"d4b61d70d1e5b9e01b856acc9db7b23dd27697c587e424f699fb586dd29f73a4","src/fmt/mod.rs":"94239bfefe2bd80722eb4c30f7d10cabe7b9319172a73a7ab5943092e84660fa","src/fmt/time/datetime.rs":"778d4604d800e46b940087394e7b72750738b554e02aea523fa9820ab0768c08","src/fmt/time/mod.rs":"30c97a9d3abd099f52c4c91c7b5f0d29ed9d54d80d1718c6fb74bfd664589de1","src/fmt/time/time_crate.rs":"1bfd59516a583e396afc1770250aa8c06b52f6162a6e7b2cadb860b7eebd9d76","src/fmt/writer.rs":"fa796f0afa3653bf9f666099c65df85d4f74ad1aa412ffc9058b0614632cf12b","src/layer/context.rs":"77137d8b2810c9059ce7838c3b665748bcb9765487d6103b92596e08b0e9e84b","src/layer/layered.rs":"6f08c9662a041652578054ba67b79c457029cc8c29301e8961b0d0e737a3e873","src/layer/mod.rs":"9c84a8260914c8ce7097c101c5be676b64952cf85bc1618d185729443aaabb03","src/layer/tests.rs":"3e974d627c4bc4269cfa10c82c890e596c9d46af8e6bc03c6c117bde1237e948","src/lib.rs":"81ecd4288bdbae864b1627de207779bd674081085d33ee1ff0c23b7df4e7f136","src/macros.rs":"e184bffc6b5999c48e365ad08343dca764a5fb711b789beb26bd1d5f1d767726","src/prelude.rs":"088635def33be9a4c4b6ed934dc22540c555e27d62f7625a43aa9c0e525ca467","src/registry/extensions.rs":"0418b39287bbc06cc95b8cecd6a25aa808b8e04714d842340ff75db458cafe5b","src/registry/mod.rs":"76627b056ce39d006708a6273b6418d001b688f016f58aa546e7821d1ef7f3bb","src/registry/sharded.rs":"1b18f7eaf05bfb9ce6bcd1572dcf9bac352cc69d8ba4633f9679163546bc1d01","src/registry/stack.rs":"9ef333d6a8a28a064e80ff1e376dbb07bc597009010ec332b2dc3ab435d737c2","src/reload.rs":"c9522d15d5cd2b840d37e2bbf366e55c1372df5c75781fde12c8bd092e9e21d1","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":"e9c3f5af7c65b41cde882d5a11a89bf8221e611f1ad881849546c4caf9a494c0","tests/layer_filters/per_event.rs":"424a027e5332e21e734a1833444352b7fbdeeecdc7a82b57f4efd6429bcfb14f","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":"0268ca64fb3068bfa95126a477009611253130f902fc558a4605649945bdae29","tests/registry_max_level_hint.rs":"ba386d32b8d13832d7009163241c3d0723488c0393d85647eb9368776251e4fc","tests/registry_with_subscriber.rs":"61a545e1bf3f75efd0dd18c20bb93e8a1f2e0158b342179a94228c4cbd5bb9cc","tests/reload.rs":"8f169b60ab67bbc171dd7e576236b901293b5baa08ea469765a042375855e0f4","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":"a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"}
\ No newline at end of file diff --git a/vendor/tracing-subscriber-0.3.3/CHANGELOG.md b/vendor/tracing-subscriber/CHANGELOG.md index c380ff3b1..f283dc61e 100644 --- a/vendor/tracing-subscriber-0.3.3/CHANGELOG.md +++ b/vendor/tracing-subscriber/CHANGELOG.md @@ -1,3 +1,395 @@ +# 0.3.16 (October 6, 2022) + +This release of `tracing-subscriber` fixes a regression introduced in +[v0.3.15][subscriber-0.3.15] where `Option::None`'s `Layer` implementation would +set the max level hint to `OFF`. In addition, it adds several new APIs, +including the `Filter::event_enabled` method for filtering events based on +fields values, and the ability to log internal errors that occur when writing a +log line. + +This release also replaces the dependency on the unmaintained [`ansi-term`] +crate with the [`nu-ansi-term`] crate, resolving an *informational* security +advisory ([RUSTSEC-2021-0139]) for [`ansi-term`]'s maintainance status. This +increases the minimum supported Rust version (MSRV) to Rust 1.50+, although the +crate should still compile for the previous MSRV of Rust 1.49+ when the `ansi` +feature is not enabled. + +### Fixed + +- **layer**: `Option::None`'s `Layer` impl always setting the `max_level_hint` + to `LevelFilter::OFF` ([#2321]) +- Compilation with `-Z minimal versions` ([#2246]) +- **env-filter**: Clarify that disabled level warnings are emitted by + `tracing-subscriber` ([#2285]) + +### Added + +- **fmt**: Log internal errors to `stderr` if writing a log line fails ([#2102]) +- **fmt**: `FmtLayer::log_internal_errors` and + `FmtSubscriber::log_internal_errors` methods for configuring whether internal + writer errors are printed to `stderr` ([#2102]) +- **fmt**: `#[must_use]` attributes on builders to warn if a `Subscriber` is + configured but not set as the default subscriber ([#2239]) +- **filter**: `Filter::event_enabled` method for filtering an event based on its + fields ([#2245], [#2251]) +- **filter**: `Targets::default_level` accessor ([#2242]) + +### Changed + +- **ansi**: Replaced dependency on unmaintained `ansi-term` crate with + `nu-ansi-term` (([#2287], fixes informational advisory [RUSTSEC-2021-0139]) +- `tracing-core`: updated to [0.1.30][core-0.1.30] +- Minimum Supported Rust Version (MSRV) increased to Rust 1.50+ (when the + `ansi`) feature flag is enabled ([#2287]) + +### Documented + +- **fmt**: Correct inaccuracies in `fmt::init` documentation ([#2224]) +- **filter**: Fix incorrect doc link in `filter::Not` combinator ([#2249]) + +Thanks to new contributors @cgbur, @DesmondWillowbrook, @RalfJung, and +@poliorcetics, as well as returning contributors @CAD97, @connec, @jswrenn, +@guswynn, and @bryangarza, for contributing to this release! + +[nu-ansi-term]: https://github.com/nushell/nu-ansi-term +[ansi_term]: https://github.com/ogham/rust-ansi-term +[RUSTSEC-2021-0139]: https://rustsec.org/advisories/RUSTSEC-2021-0139.html +[core-0.1.30]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.30 +[subscriber-0.3.15]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.15 +[#2321]: https://github.com/tokio-rs/tracing/pull/2321 +[#2246]: https://github.com/tokio-rs/tracing/pull/2246 +[#2285]: https://github.com/tokio-rs/tracing/pull/2285 +[#2102]: https://github.com/tokio-rs/tracing/pull/2102 +[#2239]: https://github.com/tokio-rs/tracing/pull/2239 +[#2245]: https://github.com/tokio-rs/tracing/pull/2245 +[#2251]: https://github.com/tokio-rs/tracing/pull/2251 +[#2287]: https://github.com/tokio-rs/tracing/pull/2287 +[#2224]: https://github.com/tokio-rs/tracing/pull/2224 +[#2249]: https://github.com/tokio-rs/tracing/pull/2249 + +# 0.3.15 (Jul 20, 2022) + +This release fixes a bug where the `reload` layer would fail to pass through +`max_level_hint` to the underlying layer, potentially breaking filtering. + +### Fixed + +- **reload**: pass through `max_level_hint` to the inner `Layer` ([#2204]) + +Thanks to @guswynn for contributing to this release! + +[#2204]: https://github.com/tokio-rs/tracing/pull/2204 + +# 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. diff --git a/vendor/tracing-subscriber-0.3.3/Cargo.toml b/vendor/tracing-subscriber/Cargo.toml index b5e7ba7db..c65075964 100644 --- a/vendor/tracing-subscriber-0.3.3/Cargo.toml +++ b/vendor/tracing-subscriber/Cargo.toml @@ -11,20 +11,39 @@ [package] edition = "2018" -rust-version = "1.42.0" +rust-version = "1.50.0" name = "tracing-subscriber" -version = "0.3.3" -authors = ["Eliza Weisman <eliza@buoyant.io>", "David Barsky <me@davidbarsky.com>", "Tokio Contributors <team@tokio.rs>"] -description = "Utilities for implementing and composing `tracing` subscribers.\n" +version = "0.3.16" +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"] +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"] +rustdoc-args = [ + "--cfg", + "docsrs", +] [[bench]] name = "filter" @@ -41,20 +60,21 @@ harness = false [[bench]] name = "enter" harness = false -[dependencies.ansi_term] -version = "0.12" + +[dependencies.matchers] +version = "0.1.0" optional = true -[dependencies.lazy_static] -version = "1" +[dependencies.nu-ansi-term] +version = "0.46.0" optional = true -[dependencies.matchers] -version = "0.1.0" +[dependencies.once_cell] +version = "1.13.0" optional = true [dependencies.parking_lot] -version = ">= 0.7, <= 0.11" +version = "0.12.1" optional = true [dependencies.regex] @@ -64,53 +84,58 @@ optional = true default-features = false [dependencies.serde] -version = "1.0" +version = "1.0.140" optional = true [dependencies.serde_json] -version = "1.0" +version = "1.0.82" optional = true [dependencies.sharded-slab] -version = "0.1.0" +version = "0.1.4" optional = true [dependencies.smallvec] -version = "1" +version = "1.9.0" optional = true [dependencies.thread_local] -version = "1.0.1" +version = "1.1.4" optional = true [dependencies.time] -version = "0.3" +version = "0.3.2" features = ["formatting"] optional = true [dependencies.tracing] -version = "0.1" +version = "0.1.35" optional = true default-features = false [dependencies.tracing-core] -version = "0.1.20" +version = "0.1.30" +default-features = false [dependencies.tracing-log] -version = "0.1.2" -features = ["log-tracer", "std"] +version = "0.1.3" +features = [ + "log-tracer", + "std", +] optional = true default-features = false [dependencies.tracing-serde] -version = "0.1.2" +version = "0.1.3" optional = true + [dev-dependencies.criterion] -version = "0.3" -default_features = false +version = "0.3.6" +default-features = false [dev-dependencies.log] -version = "0.4" +version = "0.4.17" [dev-dependencies.regex] version = "1" @@ -118,33 +143,90 @@ features = ["std"] default-features = false [dev-dependencies.time] -version = "0.3" -features = ["formatting", "macros"] +version = "0.3.2" +features = [ + "formatting", + "macros", +] [dev-dependencies.tokio] -version = "0.2" -features = ["rt-core", "macros"] +version = "1" +features = [ + "rt", + "macros", +] [dev-dependencies.tracing] -version = "0.1" +version = "0.1.35" [dev-dependencies.tracing-futures] -version = "0.2" -features = ["std-future", "std"] +version = "0.2.0" +features = [ + "std-future", + "std", +] default-features = false [dev-dependencies.tracing-log] -version = "0.1.2" +version = "0.1.3" [features] alloc = [] -ansi = ["fmt", "ansi_term"] -default = ["smallvec", "fmt", "ansi", "tracing-log", "std"] -env-filter = ["matchers", "regex", "lazy_static", "tracing", "std"] -fmt = ["registry", "std"] -json = ["tracing-serde", "serde", "serde_json"] +ansi = [ + "fmt", + "nu-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"] +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-0.3.3/LICENSE b/vendor/tracing-subscriber/LICENSE index cdb28b4b5..cdb28b4b5 100644 --- a/vendor/tracing-subscriber-0.3.3/LICENSE +++ b/vendor/tracing-subscriber/LICENSE diff --git a/vendor/tracing-subscriber-0.3.3/README.md b/vendor/tracing-subscriber/README.md index 75c62e8ca..124fb956d 100644 --- a/vendor/tracing-subscriber-0.3.3/README.md +++ b/vendor/tracing-subscriber/README.md @@ -21,7 +21,7 @@ Utilities for implementing and composing [`tracing`][tracing] subscribers. [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.1 +[docs-url]: https://docs.rs/tracing-subscriber/0.3.15 [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 @@ -32,14 +32,14 @@ Utilities for implementing and composing [`tracing`][tracing] subscribers. [discord-url]: https://discord.gg/EeF3cQw [maint-badge]: https://img.shields.io/badge/maintenance-experimental-blue.svg -*Compiler support: [requires `rustc` 1.42+][msrv]* +*Compiler support: [requires `rustc` 1.50+][msrv]* [msrv]: #supported-rust-versions ## Supported Rust Versions Tracing is built against the latest stable release. The minimum supported -version is 1.42. The current Tracing version is not guaranteed to build on Rust +version is 1.50. 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 diff --git a/vendor/tracing-subscriber-0.3.3/benches/enter.rs b/vendor/tracing-subscriber/benches/enter.rs index 49c6e730a..49c6e730a 100644 --- a/vendor/tracing-subscriber-0.3.3/benches/enter.rs +++ b/vendor/tracing-subscriber/benches/enter.rs diff --git a/vendor/tracing-subscriber-0.3.3/benches/filter.rs b/vendor/tracing-subscriber/benches/filter.rs index 91ab9c91d..91ab9c91d 100644 --- a/vendor/tracing-subscriber-0.3.3/benches/filter.rs +++ b/vendor/tracing-subscriber/benches/filter.rs diff --git a/vendor/tracing-subscriber-0.3.3/benches/filter_log.rs b/vendor/tracing-subscriber/benches/filter_log.rs index 4dcf3b4ec..4dcf3b4ec 100644 --- a/vendor/tracing-subscriber-0.3.3/benches/filter_log.rs +++ b/vendor/tracing-subscriber/benches/filter_log.rs diff --git a/vendor/tracing-subscriber-0.3.3/benches/fmt.rs b/vendor/tracing-subscriber/benches/fmt.rs index a039e66d4..a039e66d4 100644 --- a/vendor/tracing-subscriber-0.3.3/benches/fmt.rs +++ b/vendor/tracing-subscriber/benches/fmt.rs diff --git a/vendor/tracing-subscriber-0.3.3/benches/support/mod.rs b/vendor/tracing-subscriber/benches/support/mod.rs index 25e9e7e22..25e9e7e22 100644 --- a/vendor/tracing-subscriber-0.3.3/benches/support/mod.rs +++ b/vendor/tracing-subscriber/benches/support/mod.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/field/debug.rs b/vendor/tracing-subscriber/src/field/debug.rs index cc67d29fe..cc67d29fe 100644 --- a/vendor/tracing-subscriber-0.3.3/src/field/debug.rs +++ b/vendor/tracing-subscriber/src/field/debug.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/field/delimited.rs b/vendor/tracing-subscriber/src/field/delimited.rs index 8c78c4b20..98634cea9 100644 --- a/vendor/tracing-subscriber-0.3.3/src/field/delimited.rs +++ b/vendor/tracing-subscriber/src/field/delimited.rs @@ -41,7 +41,7 @@ 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`]: ../trait.MakeVisitor.html + /// [`MakeVisitor`]: super::MakeVisitor pub fn new(delimiter: D, inner: V) -> Self { Self { delimiter, inner } } @@ -53,7 +53,7 @@ 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`]: https://docs.rs/tracing-core/0.1.6/tracing_core/field/trait.Visit.html + /// [`Visit`]: tracing_core::field::Visit pub fn new(delimiter: D, inner: V) -> Self { Self { delimiter, diff --git a/vendor/tracing-subscriber-0.3.3/src/field/display.rs b/vendor/tracing-subscriber/src/field/display.rs index e0bbc55ed..78a039ce1 100644 --- a/vendor/tracing-subscriber-0.3.3/src/field/display.rs +++ b/vendor/tracing-subscriber/src/field/display.rs @@ -18,7 +18,7 @@ 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`]: ../trait.MakeVisitor.html + /// [`MakeVisitor`]: super::MakeVisitor pub fn new(inner: V) -> Self { Messages(inner) } diff --git a/vendor/tracing-subscriber-0.3.3/src/field/mod.rs b/vendor/tracing-subscriber/src/field/mod.rs index f7d03f2cc..5dfddb362 100644 --- a/vendor/tracing-subscriber-0.3.3/src/field/mod.rs +++ b/vendor/tracing-subscriber/src/field/mod.rs @@ -22,7 +22,7 @@ pub mod display; /// data to, configuration variables that determine the visitor's behavior, or /// `()` when no input is required to produce a visitor. /// -/// [visitors]: https://docs.rs/tracing-core/latest/tracing_core/field/trait.Visit.html +/// [visitors]: tracing_core::field::Visit pub trait MakeVisitor<T> { /// The visitor type produced by this `MakeVisitor`. type Visitor: Visit; @@ -33,7 +33,7 @@ pub trait MakeVisitor<T> { /// A [visitor] that produces output once it has visited a set of fields. /// -/// [visitor]: https://docs.rs/tracing-core/latest/tracing_core/field/trait.Visit.html +/// [visitor]: tracing_core::field::Visit pub trait VisitOutput<Out>: Visit { /// Completes the visitor, returning any output. /// @@ -82,10 +82,10 @@ pub trait VisitOutput<Out>: Visit { /// r.record(&mut visitor); /// } /// ``` -/// [visitor]: https://docs.rs/tracing-core/latest/tracing_core/field/trait.Visit.html -/// [attr]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Attributes.html -/// [rec]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Record.html -/// [event]: https://docs.rs/tracing-core/latest/tracing_core/event/struct.Event.html +/// [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); @@ -341,7 +341,7 @@ pub(in crate::field) mod test_util { impl<'a> Visit for DebugVisitor<'a> { fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - write!(&mut self.writer, "{}={:?}", field, value).unwrap(); + write!(self.writer, "{}={:?}", field, value).unwrap(); } } diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs b/vendor/tracing-subscriber/src/filter/directive.rs index dd6b063c4..2ae3f0f24 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs +++ b/vendor/tracing-subscriber/src/filter/directive.rs @@ -5,7 +5,7 @@ use alloc::vec; use alloc::{string::String, vec::Vec}; use core::{cmp::Ordering, fmt, iter::FromIterator, slice, str::FromStr}; -use tracing_core::Metadata; +use tracing_core::{Level, Metadata}; /// Indicates that a string could not be parsed as a filtering directive. #[derive(Debug)] pub struct ParseError { @@ -142,6 +142,22 @@ impl DirectiveSet<StaticDirective> { 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 === @@ -158,6 +174,22 @@ impl StaticDirective { 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 { diff --git a/vendor/tracing-subscriber/src/filter/env/builder.rs b/vendor/tracing-subscriber/src/filter/env/builder.rs new file mode 100644 index 000000000..c814707e6 --- /dev/null +++ b/vendor/tracing-subscriber/src/filter/env/builder.rs @@ -0,0 +1,325 @@ +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)] +#[must_use] +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 = "nu_ansi_term")] + use nu_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 = "nu_ansi_term"))] + let msg = format!("warning: {}", msg); + #[cfg(feature = "nu_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 = "nu_ansi_term"))] + let msg = format!("{} {}", prefix, msg); + #[cfg(feature = "nu_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 = "nu_ansi_term"))] + let msg = format!("note: {}", msg); + #[cfg(feature = "nu_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 from the `tracing` crate", + 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-0.3.3/src/filter/env/directive.rs b/vendor/tracing-subscriber/src/filter/env/directive.rs index 66ca23dc4..f062e6ef9 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs +++ b/vendor/tracing-subscriber/src/filter/env/directive.rs @@ -4,14 +4,14 @@ use crate::filter::{ env::{field, FieldMap}, level::LevelFilter, }; -use lazy_static::lazy_static; +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(Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))] pub struct Directive { in_span: Option<String>, @@ -107,80 +107,52 @@ impl Directive { .collect(); (Dynamics::from_iter(dyns), statics) } -} - -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 fields = meta.fields(); - for field in &self.fields { - if fields.field(&field.name).is_none() { - return false; + 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, } } - - true - } - - fn level(&self) -> &LevelFilter { - &self.level } -} -impl FromStr for Directive { - type Err = ParseError; - fn from_str(from: &str) -> Result<Self, Self::Err> { - lazy_static! { - static ref DIRECTIVE_RE: Regex = 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 ref SPAN_PART_RE: Regex = - Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap(); - static ref FIELD_FILTER_RE: Regex = - // TODO(eliza): this doesn't _currently_ handle value matchers that include comma - // characters. We should fix that. - Regex::new(r#"(?x) - ( - # field name - [[:word:]][[[:word:]]\.]* - # value part (optional) - (?:=[^,]+)? - ) - # trailing comma or EOS - (?:,\s?|$) - "#).unwrap(); - } + 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)?; @@ -214,7 +186,7 @@ impl FromStr for Directive { .map(|c| { FIELD_FILTER_RE .find_iter(c.as_str()) - .map(|c| c.as_str().parse()) + .map(|c| field::Match::parse(c.as_str(), regex)) .collect::<Result<Vec<_>, _>>() }) .unwrap_or_else(|| Ok(Vec::new())); @@ -228,7 +200,7 @@ impl FromStr for Directive { // Setting the target without the level enables every level for that target .unwrap_or(LevelFilter::TRACE); - Ok(Directive { + Ok(Self { level, target, in_span, @@ -237,6 +209,48 @@ impl FromStr for Directive { } } +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 { diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs b/vendor/tracing-subscriber/src/filter/env/field.rs index 970850f92..1394fd04a 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs +++ b/vendor/tracing-subscriber/src/filter/env/field.rs @@ -2,7 +2,7 @@ use matchers::Pattern; use std::{ cmp::Ordering, error::Error, - fmt, + fmt::{self, Write}, str::FromStr, sync::{ atomic::{AtomicBool, Ordering::*}, @@ -13,7 +13,7 @@ use std::{ use super::{FieldMap, LevelFilter}; use tracing_core::field::{Field, Visit}; -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct Match { pub(crate) name: String, // TODO: allow match patterns for names? pub(crate) value: Option<ValueMatch>, @@ -38,11 +38,20 @@ pub(crate) struct MatchVisitor<'a> { #[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>), } @@ -97,6 +106,9 @@ impl Ord for ValueMatch { (Pat(this), Pat(that)) => this.cmp(that), (Pat(_), _) => Ordering::Greater, + + (Debug(this), Debug(that)) => this.cmp(that), + (Debug(_), _) => Ordering::Greater, } } } @@ -107,12 +119,25 @@ impl PartialOrd for ValueMatch { } } +/// 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")))] @@ -122,9 +147,17 @@ pub struct BadName { // === impl Match === -impl FromStr for Match { - type Err = Box<dyn Error + Send + Sync>; - fn from_str(s: &str) -> Result<Self, Self::Err> { +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() @@ -133,22 +166,17 @@ impl FromStr for Match { })? // TODO: validate field name .to_string(); - let value = parts.next().map(ValueMatch::from_str).transpose()?; + 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 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() - } -} - impl fmt::Display for Match { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.name, f)?; @@ -199,9 +227,14 @@ fn value_match_f64(v: f64) -> ValueMatch { } } -impl FromStr for ValueMatch { - type Err = matchers::Error; - fn from_str(s: &str) -> Result<Self, Self::Err> { +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)) @@ -212,6 +245,21 @@ impl FromStr for ValueMatch { .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 { @@ -222,6 +270,7 @@ impl fmt::Display for ValueMatch { 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), } } @@ -264,6 +313,12 @@ impl MatchPattern { 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 { @@ -289,6 +344,102 @@ impl Ord for MatchPattern { } } +// === 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 {} @@ -401,6 +552,9 @@ impl<'a> Visit for MatchVisitor<'a> { 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) + } _ => {} } } @@ -410,7 +564,63 @@ impl<'a> Visit for MatchVisitor<'a> { 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-0.3.3/src/filter/env/mod.rs b/vendor/tracing-subscriber/src/filter/env/mod.rs index 81fe0e62d..81a9ae2bd 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs +++ b/vendor/tracing-subscriber/src/filter/env/mod.rs @@ -4,7 +4,8 @@ // these are publicly re-exported, but the compiler doesn't realize // that for some reason. #[allow(unreachable_pub)] -pub use self::{directive::Directive, field::BadName as BadFieldName}; +pub use self::{builder::Builder, directive::Directive, field::BadName as BadFieldName}; +mod builder; mod directive; mod field; @@ -15,6 +16,7 @@ use crate::{ }; 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, @@ -26,6 +28,16 @@ use tracing_core::{ /// 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. @@ -52,10 +64,27 @@ use tracing_core::{ /// 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 acts as a regex on -/// the `std::fmt::Debug` output from the value. +/// 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. @@ -72,7 +101,7 @@ use tracing_core::{ /// - A dash in a target will only appear when being specified explicitly: /// `tracing::info!(target: "target-name", ...);` /// -/// ## Examples +/// ## Example Syntax /// /// - `tokio::net=info` will enable all spans or events that: /// - have the `tokio::net` target, @@ -89,10 +118,68 @@ use tracing_core::{ /// - which has a field named `name` with value `bob`, /// - at _any_ level. /// -/// 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`]. +/// # 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 @@ -100,6 +187,11 @@ use tracing_core::{ /// [`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 { @@ -108,10 +200,8 @@ pub struct EnvFilter { has_dynamics: bool, by_id: RwLock<HashMap<span::Id, directive::SpanMatcher>>, by_cs: RwLock<HashMap<callsite::Identifier, directive::CallsiteMatcher>>, -} - -thread_local! { - static SCOPE: RefCell<Vec<LevelFilter>> = RefCell::new(Vec::new()); + scope: ThreadLocal<RefCell<Vec<LevelFilter>>>, + regex: bool, } type FieldMap<T> = HashMap<Field, T>; @@ -134,58 +224,181 @@ 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`]: #method.from_default_env - /// [`EnvFilter::try_from_default_env`]: #method.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::from_env(Self::DEFAULT_ENV) + 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 { - env::var(env.as_ref()).map(Self::new).unwrap_or_default() + 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. - pub fn new<S: AsRef<str>>(dirs: S) -> Self { - let directives = dirs.as_ref().split(',').filter_map(|s| match s.parse() { - Ok(d) => Some(d), - Err(err) => { - eprintln!("ignoring `{}`: {}", s, err); - None - } - }); - Self::from_directives(directives) + /// + /// 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> { - let directives = dirs - .as_ref() - .split(',') - .map(|s| s.parse()) - .collect::<Result<Vec<_>, _>>()?; - Ok(Self::from_directives(directives)) + Self::builder().parse(dirs) } /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment - /// variable, or an error if the environment variable contains any invalid - /// filter directives. + /// 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::try_from_env(Self::DEFAULT_ENV) + 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> { - env::var(env.as_ref())?.parse().map_err(Into::into) + Self::builder().with_env_var(env.as_ref()).try_from_env() } /// Add a filtering directive to this `EnvFilter`. @@ -202,13 +415,13 @@ impl EnvFilter { /// and events as a previous filter, but sets a different level for those /// spans and events, the previous directive is overwritten. /// - /// [`LevelFilter`]: ../filter/struct.LevelFilter.html - /// [`Level`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Level.html + /// [`LevelFilter`]: super::LevelFilter + /// [`Level`]: tracing_core::Level /// /// # Examples /// /// From [`LevelFilter`]: - //// + /// /// ```rust /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; /// let mut filter = EnvFilter::from_default_env() @@ -223,9 +436,9 @@ impl EnvFilter { /// let mut filter = EnvFilter::from_default_env() /// .add_directive(Level::INFO.into()); /// ``` - //// + /// /// Parsed from a string: - //// + /// /// ```rust /// use tracing_subscriber::filter::{EnvFilter, Directive}; /// @@ -236,7 +449,15 @@ impl EnvFilter { /// # Ok(()) /// # } /// ``` - pub fn add_directive(mut self, directive: Directive) -> Self { + /// 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 { @@ -246,165 +467,19 @@ impl EnvFilter { self } - fn from_directives(directives: impl IntoIterator<Item = Directive>) -> Self { - use tracing::level_filters::STATIC_MAX_LEVEL; - use tracing::Level; - - let directives: Vec<_> = directives.into_iter().collect(); - - let disabled: Vec<_> = directives - .iter() - .filter(|directive| directive.level > STATIC_MAX_LEVEL) - .collect(); - - 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 subscriber, 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!("note: {}", 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, mut statics) = Directive::make_tables(directives); - let has_dynamics = !dynamics.is_empty(); - - if statics.is_empty() && !has_dynamics { - statics.add(directive::StaticDirective::default()); - } - - Self { - statics, - dynamics, - has_dynamics, - by_id: RwLock::new(HashMap::new()), - by_cs: RwLock::new(HashMap::new()), - } - } - - 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() - } - } -} - -impl<S: Subscriber> Layer<S> for EnvFilter { - 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() - } - } - - 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(), - ) - } + // === filtering methods === - fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { + /// 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 local access + iterating over the + // 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() { @@ -420,14 +495,15 @@ impl<S: Subscriber> Layer<S> for EnvFilter { } } - let enabled_by_scope = SCOPE.with(|scope| { - for filter in scope.borrow().iter() { + 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; } @@ -443,7 +519,33 @@ impl<S: Subscriber> Layer<S> for EnvFilter { false } - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) { + /// 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); @@ -451,28 +553,37 @@ impl<S: Subscriber> Layer<S> for EnvFilter { } } - fn on_record(&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 on_enter(&self, id: &span::Id, _: Context<'_, S>) { + /// 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) { - SCOPE.with(|scope| scope.borrow_mut().push(span.level())); + self.scope.get_or_default().borrow_mut().push(span.level()); } } - fn on_exit(&self, id: &span::Id, _: Context<'_, S>) { + /// 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) { - SCOPE.with(|scope| scope.borrow_mut().pop()); + self.scope.get_or_default().borrow_mut().pop(); } } - fn on_close(&self, id: span::Id, _: Context<'_, S>) { + /// 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; @@ -481,6 +592,140 @@ impl<S: Subscriber> Layer<S> for EnvFilter { 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 { @@ -502,7 +747,7 @@ where impl Default for EnvFilter { fn default() -> Self { - Self::from_directives(std::iter::empty()) + Builder::default().from_directives(std::iter::empty()) } } @@ -735,4 +980,12 @@ mod tests { [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-0.3.3/src/filter/filter_fn.rs b/vendor/tracing-subscriber/src/filter/filter_fn.rs index 332bf860a..332bf860a 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs +++ b/vendor/tracing-subscriber/src/filter/filter_fn.rs diff --git a/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs b/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs new file mode 100644 index 000000000..3934a1326 --- /dev/null +++ b/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs @@ -0,0 +1,542 @@ +//! 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::not`] method. See that +/// method's documentation for details. +/// +/// [`Filter`]: crate::layer::Filter +/// [`FilterExt::not`]: crate::filter::FilterExt::not +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 event_enabled(&self, event: &tracing_core::Event<'_>, cx: &Context<'_, S>) -> bool { + self.a.event_enabled(event, cx) && self.b.event_enabled(event, cx) + } + + #[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 event_enabled(&self, event: &tracing_core::Event<'_>, cx: &Context<'_, S>) -> bool { + self.a.event_enabled(event, cx) || self.b.event_enabled(event, cx) + } + + #[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. + /// + /// This inverts the values returned by the [`enabled`] and [`callsite_enabled`] + /// methods on the wrapped filter; it does *not* invert [`event_enabled`], as + /// filters which do not implement filtering on event field values will return + /// the default `true` even for events that their [`enabled`] method disables. + /// + /// Consider a normal filter defined as: + /// + /// ```ignore (pseudo-code) + /// // for spans + /// match callsite_enabled() { + /// ALWAYS => on_span(), + /// SOMETIMES => if enabled() { on_span() }, + /// NEVER => (), + /// } + /// // for events + /// match callsite_enabled() { + /// ALWAYS => on_event(), + /// SOMETIMES => if enabled() && event_enabled() { on_event() }, + /// NEVER => (), + /// } + /// ``` + /// + /// and an inverted filter defined as: + /// + /// ```ignore (pseudo-code) + /// // for spans + /// match callsite_enabled() { + /// ALWAYS => (), + /// SOMETIMES => if !enabled() { on_span() }, + /// NEVER => on_span(), + /// } + /// // for events + /// match callsite_enabled() { + /// ALWAYS => (), + /// SOMETIMES => if !enabled() { on_event() }, + /// NEVER => on_event(), + /// } + /// ``` + /// + /// A proper inversion would do `!(enabled() && event_enabled())` (or + /// `!enabled() || !event_enabled()`), but because of the implicit `&&` + /// relation between `enabled` and `event_enabled`, it is difficult to + /// short circuit and not call the wrapped `event_enabled`. + /// + /// A combinator which remembers the result of `enabled` in order to call + /// `event_enabled` only when `enabled() == true` is possible, but requires + /// additional thread-local mutable state to support a very niche use case. + // + // Also, it'd mean the wrapped layer's `enabled()` always gets called and + // globally applied to events where it doesn't today, since we can't know + // what `event_enabled` will say until we have the event to call it with. + /// + /// [`Filter`]: crate::layer::Filter + /// [`enabled`]: crate::layer::Filter::enabled + /// [`event_enabled`]: crate::layer::Filter::event_enabled + /// [`callsite_enabled`]: crate::layer::Filter::callsite_enabled + 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 event_enabled(&self, event: &tracing_core::Event<'_>, cx: &Context<'_, S>) -> bool { + // Never disable based on event_enabled; we "disabled" it in `enabled`, + // so the `not` has already been applied and filtered this not out. + let _ = (event, cx); + true + } + + #[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-0.3.3/src/filter/layer_filters.rs b/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs index e77fd3751..e50ee6f00 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs +++ b/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs @@ -37,14 +37,16 @@ use std::{ cell::{Cell, RefCell}, fmt, marker::PhantomData, + ops::Deref, sync::Arc, thread_local, }; use tracing_core::{ span, subscriber::{Interest, Subscriber}, - Event, Metadata, + Dispatch, 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. @@ -158,7 +160,288 @@ 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. + /// + /// This inverts the values returned by the [`enabled`] and [`callsite_enabled`] + /// methods on the wrapped filter; it does *not* invert [`event_enabled`], as + /// filters which do not implement filtering on event field values will return + /// the default `true` even for events that their [`enabled`] method disables. + /// + /// Consider a normal filter defined as: + /// + /// ```ignore (pseudo-code) + /// // for spans + /// match callsite_enabled() { + /// ALWAYS => on_span(), + /// SOMETIMES => if enabled() { on_span() }, + /// NEVER => (), + /// } + /// // for events + /// match callsite_enabled() { + /// ALWAYS => on_event(), + /// SOMETIMES => if enabled() && event_enabled() { on_event() }, + /// NEVER => (), + /// } + /// ``` + /// + /// and an inverted filter defined as: + /// + /// ```ignore (pseudo-code) + /// // for spans + /// match callsite_enabled() { + /// ALWAYS => (), + /// SOMETIMES => if !enabled() { on_span() }, + /// NEVER => on_span(), + /// } + /// // for events + /// match callsite_enabled() { + /// ALWAYS => (), + /// SOMETIMES => if !enabled() { on_event() }, + /// NEVER => on_event(), + /// } + /// ``` + /// + /// A proper inversion would do `!(enabled() && event_enabled())` (or + /// `!enabled() || !event_enabled()`), but because of the implicit `&&` + /// relation between `enabled` and `event_enabled`, it is difficult to + /// short circuit and not call the wrapped `event_enabled`. + /// + /// A combinator which remembers the result of `enabled` in order to call + /// `event_enabled` only when `enabled() == true` is possible, but requires + /// additional thread-local mutable state to support a very niche use case. + // + // Also, it'd mean the wrapped layer's `enabled()` always gets called and + // globally applied to events where it doesn't today, since we can't know + // what `event_enabled` will say until we have the event to call it with. + /// + /// [`Filter`]: crate::subscribe::Filter + /// [`enabled`]: crate::subscribe::Filter::enabled + /// [`event_enabled`]: crate::subscribe::Filter::event_enabled + /// [`callsite_enabled`]: crate::subscribe::Filter::callsite_enabled + 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 { @@ -179,38 +462,35 @@ impl<S> layer::Filter<S> for LevelFilter { } } -impl<S> layer::Filter<S> for Arc<dyn layer::Filter<S> + Send + Sync + 'static> { - #[inline] - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - (**self).enabled(meta, cx) - } +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).callsite_enabled(meta) - } + #[inline] + fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { + self.deref().callsite_enabled(meta) + } - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - (**self).max_level_hint() - } + #[inline] + fn max_level_hint(&self) -> Option<LevelFilter> { + self.deref().max_level_hint() + } + }; } -impl<S> layer::Filter<S> for Box<dyn layer::Filter<S> + Send + Sync + 'static> { - #[inline] - fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool { - (**self).enabled(meta, cx) - } - - #[inline] - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - (**self).callsite_enabled(meta) - } +#[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!(); +} - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - (**self).max_level_hint() - } +#[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 === @@ -247,6 +527,78 @@ impl<L, F, S> Filtered<L, F, S> { 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> @@ -255,6 +607,10 @@ where F: layer::Filter<S> + 'static, L: Layer<S>, { + fn on_register_dispatch(&self, collector: &Dispatch) { + self.layer.on_register_dispatch(collector); + } + fn on_layer(&mut self, subscriber: &mut S) { self.id = MagicPlfDowncastMarker(subscriber.register_filter()); self.layer.on_layer(subscriber); @@ -322,7 +678,9 @@ where fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, cx: Context<'_, S>) { self.did_enable(|| { - self.layer.on_new_span(attrs, id, cx.with_filter(self.id())); + let cx = cx.with_filter(self.id()); + self.filter.on_new_span(attrs, id, cx.clone()); + self.layer.on_new_span(attrs, id, cx); }) } @@ -333,6 +691,7 @@ where 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) } } @@ -345,6 +704,22 @@ where } } + fn event_enabled(&self, event: &Event<'_>, cx: Context<'_, S>) -> bool { + let cx = cx.with_filter(self.id()); + let enabled = FILTERING + .with(|filtering| filtering.and(self.id(), || self.filter.event_enabled(event, &cx))); + + if enabled { + // If the filter enabled this event, ask the wrapped subscriber if + // _it_ wants it --- it might have a global filter. + self.layer.event_enabled(event, cx) + } else { + // Otherwise, return `true`. See the comment in `enabled` for why this + // is necessary. + true + } + } + fn on_event(&self, event: &Event<'_>, cx: Context<'_, S>) { self.did_enable(|| { self.layer.on_event(event, cx.with_filter(self.id())); @@ -353,19 +728,22 @@ where fn on_enter(&self, id: &span::Id, cx: Context<'_, S>) { if let Some(cx) = cx.if_enabled_for(id, self.id()) { - self.layer.on_enter(id, cx) + 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.layer.on_exit(id, cx) + 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.layer.on_close(id, cx) + self.filter.on_close(id.clone(), cx.clone()); + self.layer.on_close(id, cx); } } @@ -544,6 +922,10 @@ impl fmt::Binary for FilterId { } } +// === impl FilterExt === + +impl<F, S> FilterExt<S> for F where F: layer::Filter<S> {} + // === impl FilterMap === impl FilterMap { @@ -709,6 +1091,14 @@ impl FilterState { } } + /// Run a second filtering pass, e.g. for Subscribe::event_enabled. + fn and(&self, filter: FilterId, f: impl FnOnce() -> bool) -> bool { + let map = self.enabled.get(); + let enabled = map.is_enabled(filter) && f(); + self.enabled.set(map.set(filter, enabled)); + enabled + } + /// Clears the current in-progress filter state. /// /// This resets the [`FilterMap`] and current [`Interest`] as well as diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/level.rs b/vendor/tracing-subscriber/src/filter/level.rs index 0fa601260..0fa601260 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/level.rs +++ b/vendor/tracing-subscriber/src/filter/level.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs b/vendor/tracing-subscriber/src/filter/mod.rs index 000a27195..000a27195 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs +++ b/vendor/tracing-subscriber/src/filter/mod.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs b/vendor/tracing-subscriber/src/filter/targets.rs index e0c7fcf82..e1407114b 100644 --- a/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs +++ b/vendor/tracing-subscriber/src/filter/targets.rs @@ -20,7 +20,7 @@ use core::{ slice, str::FromStr, }; -use tracing_core::{Interest, Metadata, Subscriber}; +use tracing_core::{Interest, Level, Metadata, Subscriber}; /// A filter that enables or disables spans and events based on their [target] /// and [level]. @@ -111,7 +111,7 @@ use tracing_core::{Interest, Metadata, Subscriber}; /// by the user at runtime. /// /// The `Targets` filter can be used as a [per-layer filter][plf] *and* as a -/// [global filter]: +/// [global filter][global]: /// /// ```rust /// use tracing_subscriber::{ @@ -277,6 +277,62 @@ impl Targets { self } + /// Returns the default level for this filter, if one is set. + /// + /// The default level is used to filter any spans or events with targets + /// that do not match any of the configured set of prefixes. + /// + /// The default level can be set for a filter either by using + /// [`with_default`](Self::with_default) or when parsing from a filter string that includes a + /// level without a target (e.g. `"trace"`). + /// + /// # Examples + /// + /// ``` + /// use tracing_subscriber::filter::{LevelFilter, Targets}; + /// + /// let filter = Targets::new().with_default(LevelFilter::INFO); + /// assert_eq!(filter.default_level(), Some(LevelFilter::INFO)); + /// + /// let filter: Targets = "info".parse().unwrap(); + /// assert_eq!(filter.default_level(), Some(LevelFilter::INFO)); + /// ``` + /// + /// The default level is `None` if no default is set: + /// + /// ``` + /// use tracing_subscriber::filter::Targets; + /// + /// let filter = Targets::new(); + /// assert_eq!(filter.default_level(), None); + /// + /// let filter: Targets = "my_crate=info".parse().unwrap(); + /// assert_eq!(filter.default_level(), None); + /// ``` + /// + /// Note that an unset default level (`None`) behaves like [`LevelFilter::OFF`] when the filter is + /// used, but it could also be set explicitly which may be useful to distinguish (such as when + /// merging multiple `Targets`). + /// + /// ``` + /// use tracing_subscriber::filter::{LevelFilter, Targets}; + /// + /// let filter = Targets::new().with_default(LevelFilter::OFF); + /// assert_eq!(filter.default_level(), Some(LevelFilter::OFF)); + /// + /// let filter: Targets = "off".parse().unwrap(); + /// assert_eq!(filter.default_level(), Some(LevelFilter::OFF)); + /// ``` + pub fn default_level(&self) -> Option<LevelFilter> { + self.0.directives().into_iter().find_map(|d| { + if d.target.is_none() { + Some(d.level) + } else { + None + } + }) + } + /// Returns an iterator over the [target]-[`LevelFilter`] pairs in this filter. /// /// The order of iteration is undefined. @@ -313,6 +369,35 @@ impl Targets { 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 @@ -657,6 +742,21 @@ mod tests { } #[test] + fn targets_default_level() { + let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off"); + assert_eq!(filter.default_level(), None); + + let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off") + .with_default(LevelFilter::OFF); + assert_eq!(filter.default_level(), Some(LevelFilter::OFF)); + + let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off") + .with_default(LevelFilter::OFF) + .with_default(LevelFilter::INFO); + assert_eq!(filter.default_level(), Some(LevelFilter::INFO)); + } + + #[test] // `println!` is only available with `libstd`. #[cfg(feature = "std")] fn size_of_filters() { diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs b/vendor/tracing-subscriber/src/fmt/fmt_layer.rs index 0e0d5e0eb..6e4e2ac0b 100644 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs +++ b/vendor/tracing-subscriber/src/fmt/fmt_layer.rs @@ -56,7 +56,7 @@ use tracing_core::{ /// # tracing::subscriber::set_global_default(subscriber).unwrap(); /// ``` /// -/// [`Layer`]: ../layer/trait.Layer.html +/// [`Layer`]: super::layer::Layer #[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] #[derive(Debug)] pub struct Layer< @@ -70,11 +70,12 @@ pub struct Layer< fmt_event: E, fmt_span: format::FmtSpanConfig, is_ansi: bool, - _inner: PhantomData<S>, + log_internal_errors: bool, + _inner: PhantomData<fn(S)>, } impl<S> Layer<S> { - /// Returns a new [`Layer`](struct.Layer.html) with the default configuration. + /// Returns a new [`Layer`][self::Layer] with the default configuration. pub fn new() -> Self { Self::default() } @@ -87,8 +88,8 @@ where N: for<'writer> FormatFields<'writer> + 'static, W: for<'writer> MakeWriter<'writer> + 'static, { - /// Sets the [event formatter][`FormatEvent`] that the layer will use to - /// format events. + /// 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 @@ -108,7 +109,7 @@ where /// ``` /// [`FormatEvent`]: format::FormatEvent /// [`Event`]: tracing::Event - /// [`Writer`]: crate::format::Writer + /// [`Writer`]: format::Writer pub fn event_format<E2>(self, e: E2) -> Layer<S, N, E2, W> where E2: FormatEvent<S, N> + 'static, @@ -119,6 +120,37 @@ where fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, + _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, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -126,7 +158,7 @@ where // 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. + /// Sets the [`MakeWriter`] that the layer being built will use to write events. /// /// # Examples /// @@ -142,9 +174,6 @@ impl<S, N, E, W> Layer<S, N, E, W> { /// # use tracing_subscriber::Layer as _; /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); /// ``` - /// - /// [`MakeWriter`]: ../fmt/trait.MakeWriter.html - /// [`Layer`]: ../layer/trait.Layer.html pub fn with_writer<W2>(self, make_writer: W2) -> Layer<S, N, E, W2> where W2: for<'writer> MakeWriter<'writer> + 'static, @@ -154,12 +183,63 @@ impl<S, N, E, W> Layer<S, N, E, W> { fmt_event: self.fmt_event, fmt_span: self.fmt_span, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, make_writer, _inner: self._inner, } } - /// Configures the subscriber to support [`libtest`'s output capturing][capturing] when used in + /// 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. @@ -180,13 +260,14 @@ impl<S, N, E, W> Layer<S, N, E, W> { /// ``` /// [capturing]: /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output - /// [`TestWriter`]: writer/struct.TestWriter.html + /// [`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, + log_internal_errors: self.log_internal_errors, make_writer: TestWriter::default(), _inner: self._inner, } @@ -201,6 +282,58 @@ impl<S, N, E, W> Layer<S, N, E, W> { ..self } } + + /// Sets whether to write errors from [`FormatEvent`] to the writer. + /// Defaults to true. + /// + /// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to + /// the writer. These errors are unlikely and will only occur if there is a + /// bug in the `FormatEvent` implementation or its dependencies. + /// + /// If writing to the writer fails, the error message is printed to stderr + /// as a fallback. + /// + /// [`FormatEvent`]: crate::fmt::FormatEvent + pub fn log_internal_errors(self, log_internal_errors: bool) -> Self { + Self { + log_internal_errors, + ..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, + log_internal_errors: self.log_internal_errors, + make_writer: f(self.make_writer), + _inner: self._inner, + } + } } impl<S, N, L, T, W> Layer<S, N, format::Format<L, T>, W> @@ -228,6 +361,7 @@ where fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -240,6 +374,7 @@ where fmt_span: self.fmt_span.without_time(), make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -284,7 +419,7 @@ where /// `Layer`s added to this subscriber. /// /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle - /// [time]: #method.without_time + /// [time]: Layer::without_time() pub fn with_span_events(self, kind: FmtSpan) -> Self { Layer { fmt_span: self.fmt_span.with_kind(kind), @@ -299,6 +434,30 @@ where ..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> { @@ -309,9 +468,9 @@ where } /// Sets whether or not the [thread ID] of the current thread is displayed - /// when formatting events + /// when formatting events. /// - /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html + /// [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), @@ -320,9 +479,9 @@ where } /// Sets whether or not the [name] of the current thread is displayed - /// when formatting events + /// when formatting events. /// - /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads + /// [name]: std::thread#naming-threads pub fn with_thread_names( self, display_thread_names: bool, @@ -333,7 +492,7 @@ where } } - /// Sets the layer being built to use a [less verbose formatter](../fmt/format/struct.Compact.html). + /// 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, @@ -344,6 +503,7 @@ where fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -358,11 +518,12 @@ where fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } - /// Sets the layer being built to use a [JSON formatter](../fmt/format/struct.Json.html). + /// Sets the layer being built to use a [JSON formatter][super::format::Json]. /// /// The full format includes fields from all entered spans. /// @@ -377,7 +538,7 @@ where /// - [`Layer::flatten_event`] can be used to enable flattening event fields into the root /// object. /// - /// [`Layer::flatten_event`]: #method.flatten_event + /// [`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> { @@ -388,6 +549,7 @@ where make_writer: self.make_writer, // always disable ANSI escapes in JSON mode! is_ansi: false, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -398,7 +560,7 @@ where 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`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::format::Json] pub fn flatten_event( self, flatten_event: bool, @@ -413,7 +575,7 @@ impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { /// Sets whether or not the formatter will include the current span in /// formatted events. /// - /// See [`format::Json`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::format::Json] pub fn with_current_span( self, display_current_span: bool, @@ -428,7 +590,7 @@ impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { /// 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`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::format::Json] pub fn with_span_list( self, display_span_list: bool, @@ -454,6 +616,38 @@ impl<S, N, E, W> Layer<S, N, E, W> { fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, + _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, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -467,6 +661,7 @@ impl<S> Default for Layer<S> { fmt_span: format::FmtSpanConfig::default(), make_writer: io::stdout, is_ansi: cfg!(feature = "ansi"), + log_internal_errors: false, _inner: PhantomData, } } @@ -497,7 +692,7 @@ where /// formatters are in use, each can store its own formatted representation /// without conflicting. /// -/// [extensions]: ../registry/struct.Extensions.html +/// [extensions]: crate::registry::Extensions #[derive(Default)] pub struct FormattedFields<E: ?Sized> { _format_fields: PhantomData<fn(E)>, @@ -586,6 +781,11 @@ where { fields.was_ansi = self.is_ansi; extensions.insert(fields); + } else { + eprintln!( + "[tracing-subscriber] Unable to format the following event, ignoring: {:?}", + attrs + ); } } @@ -732,7 +932,20 @@ where .is_ok() { let mut writer = self.make_writer.make_writer_for(event.metadata()); - let _ = io::Write::write_all(&mut writer, buf.as_bytes()); + let res = io::Write::write_all(&mut writer, buf.as_bytes()); + if self.log_internal_errors { + if let Err(e) = res { + eprintln!("[tracing-subscriber] Unable to write an event to the Writer for this Subscriber! Error: {}\n", e); + } + } + } else if self.log_internal_errors { + let err_msg = format!("Unable to format the following event. Name: {}; Fields: {:?}\n", + event.metadata().name(), event.fields()); + let mut writer = self.make_writer.make_writer_for(event.metadata()); + let res = io::Write::write_all(&mut writer, err_msg.as_bytes()); + if let Err(e) = res { + eprintln!("[tracing-subscriber] Unable to write an \"event formatting error\" to the Writer for this Subscriber! Error: {}\n", e); + } } buf.clear(); @@ -821,7 +1034,7 @@ where /// If this returns `None`, then no span exists for that ID (either it has /// closed or the ID is invalid). /// - /// [stored data]: ../registry/struct.SpanRef.html + /// [stored data]: crate::registry::SpanRef #[inline] pub fn span(&self, id: &Id) -> Option<SpanRef<'_, S>> where @@ -844,7 +1057,7 @@ where /// /// If this returns `None`, then we are not currently within a span. /// - /// [stored data]: ../registry/struct.SpanRef.html + /// [stored data]: crate::registry::SpanRef #[inline] pub fn lookup_current(&self) -> Option<SpanRef<'_, S>> where @@ -1030,6 +1243,60 @@ mod test { } #[test] + fn format_error_print_to_stderr() { + struct AlwaysError; + + impl std::fmt::Debug for AlwaysError { + fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + Err(std::fmt::Error) + } + } + + 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) + .finish(); + + with_default(subscriber, || { + tracing::info!(?AlwaysError); + }); + let actual = sanitize_timings(make_writer.get_string()); + + // Only assert the start because the line number and callsite may change. + let expected = concat!("Unable to format the following event. Name: event ", file!(), ":"); + assert!(actual.as_str().starts_with(expected), "\nactual = {}\nshould start with expected = {}\n", actual, expected); + } + + #[test] + fn format_error_ignore_if_log_internal_errors_is_false() { + struct AlwaysError; + + impl std::fmt::Debug for AlwaysError { + fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + Err(std::fmt::Error) + } + } + + 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) + .log_internal_errors(false) + .finish(); + + with_default(subscriber, || { + tracing::info!(?AlwaysError); + }); + let actual = sanitize_timings(make_writer.get_string()); + assert_eq!("", actual.as_str()); + } + + #[test] fn synthesize_span_none() { let make_writer = MockMakeWriter::default(); let subscriber = crate::fmt::Subscriber::builder() diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs b/vendor/tracing-subscriber/src/fmt/format/json.rs index cc86f03c7..c2f4d3755 100644 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs +++ b/vendor/tracing-subscriber/src/fmt/format/json.rs @@ -23,25 +23,42 @@ use tracing_serde::AsSerde; #[cfg(feature = "tracing-log")] use tracing_log::NormalizeEvent; -/// Marker for `Format` that indicates that the verbose JSON log format should be used. +/// Marker for [`Format`] that indicates that the newline-delimited JSON log +/// format should be used. /// -/// The full format includes fields from all entered spans. +/// 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 /// -/// ```json -/// { -/// "timestamp":"Feb 20 11:28:15.096", -/// "level":"INFO", -/// "fields":{"message":"some message","key":"value"} -/// "target":"mycrate", -/// "span":{name":"leaf"}, -/// "spans":[{"name":"root"},{"name":"leaf"}], -/// } -/// ``` +/// <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 @@ -52,9 +69,23 @@ use tracing_log::NormalizeEvent; /// By default, event fields are not flattened, and both current span and span /// list are logged. /// -/// [`Json::flatten_event`]: #method.flatten_event -/// [`Json::with_current_span`]: #method.with_current_span -/// [`Json::with_span_list`]: #method.with_span_list +/// # 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, @@ -243,6 +274,18 @@ where 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 @@ -298,7 +341,6 @@ impl Default for Json { /// The JSON [`FormatFields`] implementation. /// -/// [`FormatFields`]: trait.FormatFields.html #[derive(Debug)] pub struct JsonFields { // reserve the ability to add fields to this without causing a breaking @@ -309,7 +351,6 @@ pub struct JsonFields { impl JsonFields { /// Returns a new JSON [`FormatFields`] implementation. /// - /// [`FormatFields`]: trait.FormatFields.html pub fn new() -> Self { Self { _private: () } } @@ -378,9 +419,8 @@ impl<'a> FormatFields<'a> for JsonFields { /// The [visitor] produced by [`JsonFields`]'s [`MakeVisitor`] implementation. /// -/// [visitor]: ../../field/trait.Visit.html -/// [`JsonFields`]: struct.JsonFields.html -/// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html +/// [visitor]: crate::field::Visit +/// [`MakeVisitor`]: crate::field::MakeVisitor pub struct JsonVisitor<'a> { values: BTreeMap<&'a str, serde_json::Value>, writer: &'a mut dyn Write, @@ -435,6 +475,26 @@ impl<'a> crate::field::VisitOutput<fmt::Result> for JsonVisitor<'a> { } 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 @@ -488,6 +548,7 @@ mod test { use tracing::{self, subscriber::with_default}; use std::fmt; + use std::path::Path; struct MockTime; impl FormatTime for MockTime { @@ -516,6 +577,50 @@ mod 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"; @@ -747,4 +852,34 @@ mod test { 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-0.3.3/src/fmt/format/mod.rs b/vendor/tracing-subscriber/src/fmt/format/mod.rs index 9001e102e..b8a482e55 100644 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/format/mod.rs +++ b/vendor/tracing-subscriber/src/fmt/format/mod.rs @@ -1,4 +1,33 @@ //! 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}, @@ -17,7 +46,7 @@ use tracing_core::{ use tracing_log::NormalizeEvent; #[cfg(feature = "ansi")] -use ansi_term::{Colour, Style}; +use nu_ansi_term::{Color, Style}; #[cfg(feature = "json")] mod json; @@ -72,7 +101,7 @@ pub use pretty::*; /// 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 +/// Crates like [`nu_ansi_term`] and [`owo-colors`] can be used to add ANSI /// escape codes to formatted output. /// /// * The actual [`Event`] to be formatted. @@ -153,13 +182,14 @@ pub use pretty::*; /// 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 +/// [`nu_ansi_term`]: https://crates.io/crates/nu_ansi_term /// [`owo-colors`]: https://crates.io/crates/owo-colors /// [default formatter]: Full pub trait FormatEvent<S, N> @@ -197,8 +227,8 @@ where /// time a span or event with fields is recorded, the subscriber will format /// those fields with its associated `FormatFields` implementation. /// -/// [set of fields]: ../field/trait.RecordFields.html -/// [`FmtSubscriber`]: ../fmt/struct.Subscriber.html +/// [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; @@ -251,7 +281,6 @@ pub fn json() -> Format<Json> { /// Returns a [`FormatFields`] implementation that formats fields using the /// provided function or closure. /// -/// [`FormatFields`]: trait.FormatFields.html pub fn debug_fn<F>(f: F) -> FieldFn<F> where F: Fn(&mut Writer<'_>, &Field, &dyn fmt::Debug) -> fmt::Result + Clone, @@ -272,6 +301,8 @@ where /// /// 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 @@ -281,28 +312,76 @@ pub struct Writer<'writer> { /// A [`FormatFields`] implementation that formats fields by calling a function /// or closure. /// -/// [`FormatFields`]: trait.FormatFields.html #[derive(Debug, Clone)] pub struct FieldFn<F>(F); /// The [visitor] produced by [`FieldFn`]'s [`MakeVisitor`] implementation. /// -/// [visitor]: ../../field/trait.Visit.html -/// [`FieldFn`]: struct.FieldFn.html -/// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html +/// [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. +/// 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 /// -/// The compact format only includes the fields from the most recently entered span. +/// <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 verbose log format should be used. +/// 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. /// -/// The full format includes fields from all entered spans. +/// # 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; @@ -311,8 +390,11 @@ pub struct Full; /// 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 includes only the fields from the most-recently-entered -/// span. +/// 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, @@ -323,6 +405,8 @@ pub struct Format<F = Full, T = SystemTime> { 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 === @@ -499,6 +583,8 @@ impl Default for Format<Full, SystemTime> { display_level: true, display_thread_id: false, display_thread_name: false, + display_filename: false, + display_line_number: false, } } } @@ -517,6 +603,8 @@ impl<F, T> Format<F, T> { 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, } } @@ -554,6 +642,8 @@ impl<F, T> Format<F, T> { 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, } } @@ -571,8 +661,6 @@ impl<F, T> Format<F, T> { /// /// - [`Format::flatten_event`] can be used to enable flattening event fields into the root /// object. - /// - /// [`Format::flatten_event`]: #method.flatten_event #[cfg(feature = "json")] #[cfg_attr(docsrs, doc(cfg(feature = "json")))] pub fn json(self) -> Format<Json, T> { @@ -585,6 +673,8 @@ impl<F, T> Format<F, T> { 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, } } @@ -612,6 +702,8 @@ impl<F, T> Format<F, T> { 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, } } @@ -626,6 +718,8 @@ impl<F, T> Format<F, T> { 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, } } @@ -654,9 +748,9 @@ impl<F, T> Format<F, T> { } /// Sets whether or not the [thread ID] of the current thread is displayed - /// when formatting events + /// when formatting events. /// - /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html + /// [thread ID]: std::thread::ThreadId pub fn with_thread_ids(self, display_thread_id: bool) -> Format<F, T> { Format { display_thread_id, @@ -665,9 +759,9 @@ impl<F, T> Format<F, T> { } /// Sets whether or not the [name] of the current thread is displayed - /// when formatting events + /// when formatting events. /// - /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads + /// [name]: std::thread#naming-threads pub fn with_thread_names(self, display_thread_name: bool) -> Format<F, T> { Format { display_thread_name, @@ -675,6 +769,38 @@ impl<F, T> Format<F, T> { } } + /// 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 @@ -692,14 +818,24 @@ impl<F, T> Format<F, T> { if writer.has_ansi_escapes() { let style = Style::new().dimmed(); write!(writer, "{}", style.prefix())?; - self.timer.format_time(writer)?; + + // 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. - self.timer.format_time(writer)?; + // 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(' ') } } @@ -714,7 +850,7 @@ impl<T> Format<Json, T> { /// ```ignore,json /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate", "message":"some message", "key": "value"} /// ``` - /// See [`Json`](../format/struct.Json.html). + /// 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> { @@ -725,7 +861,7 @@ impl<T> Format<Json, T> { /// Sets whether or not the formatter will include the current span in /// formatted events. /// - /// See [`format::Json`](../fmt/format/struct.Json.html) + /// 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> { @@ -736,7 +872,7 @@ impl<T> Format<Json, T> { /// 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`](../fmt/format/struct.Json.html) + /// 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> { @@ -840,6 +976,34 @@ where )?; } + 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) } @@ -918,23 +1082,49 @@ where }; write!(writer, "{}", fmt_ctx)?; + let bold = writer.bold(); + let dimmed = writer.dimmed(); + + let mut needs_space = false; if self.display_target { - write!( - writer, - "{}{} ", - writer.bold().paint(meta.target()), - writer.dimmed().paint(":") - )?; + 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)?; - let dimmed = writer.dimmed(); for span in ctx .event_scope() .into_iter() - .map(crate::registry::Scope::from_root) - .flatten() + .flat_map(crate::registry::Scope::from_root) { let exts = span.extensions(); if let Some(fields) = exts.get::<FormattedFields<N>>() { @@ -962,7 +1152,6 @@ where /// The default [`FormatFields`] implementation. /// -/// [`FormatFields`]: trait.FormatFields.html #[derive(Debug)] pub struct DefaultFields { // reserve the ability to add fields to this without causing a breaking @@ -984,7 +1173,6 @@ pub struct DefaultVisitor<'a> { impl DefaultFields { /// Returns a new default [`FormatFields`] implementation. /// - /// [`FormatFields`]: trait.FormatFields.html pub fn new() -> Self { Self { _private: () } } @@ -1201,6 +1389,14 @@ impl Style { 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> { @@ -1288,11 +1484,11 @@ 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)), + Level::TRACE => write!(f, "{}", Color::Purple.paint(TRACE_STR)), + Level::DEBUG => write!(f, "{}", Color::Blue.paint(DEBUG_STR)), + Level::INFO => write!(f, "{}", Color::Green.paint(INFO_STR)), + Level::WARN => write!(f, "{}", Color::Yellow.paint(WARN_STR)), + Level::ERROR => write!(f, "{}", Color::Red.paint(ERROR_STR)), } } else { match *self.level { @@ -1366,7 +1562,7 @@ impl<'a, F> fmt::Debug for FieldFnVisitor<'a, F> { /// Configures what points in the span lifecycle are logged as events. /// -/// See also [`with_span_events`](../struct.SubscriberBuilder.html#method.with_span_events). +/// See also [`with_span_events`](super::SubscriberBuilder.html::with_span_events). #[derive(Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct FmtSpan(u8); @@ -1528,7 +1724,9 @@ pub(super) mod test { }; use super::*; - use std::fmt; + + use regex::Regex; + use std::{fmt, path::Path}; pub(crate) struct MockTime; impl FormatTime for MockTime { @@ -1550,7 +1748,7 @@ pub(super) mod test { .with_thread_names(false); #[cfg(feature = "ansi")] let subscriber = subscriber.with_ansi(false); - run_test(subscriber, make_writer, "hello\n") + assert_info_hello(subscriber, make_writer, "hello\n") } fn test_ansi<T>( @@ -1598,6 +1796,124 @@ pub(super) mod test { 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>>, @@ -1606,14 +1922,14 @@ pub(super) mod test { T: Send + Sync + 'static, { let make_writer = MockMakeWriter::default(); - let collector = builder + let subscriber = builder .with_writer(make_writer.clone()) .with_level(false) .with_ansi(false) .with_timer(MockTime) .finish(); - with_default(collector, || { + 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"); @@ -1659,6 +1975,21 @@ pub(super) mod test { 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() { @@ -1748,6 +2079,26 @@ pub(super) mod test { } } + 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 { @@ -1795,4 +2146,16 @@ pub(super) mod test { 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 new file mode 100644 index 000000000..12071de92 --- /dev/null +++ b/vendor/tracing-subscriber/src/fmt/format/pretty.rs @@ -0,0 +1,511 @@ +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 nu_ansi_term::{Color, 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(Color::Purple), + Level::DEBUG => Style::new().fg(Color::Blue), + Level::INFO => Style::new().fg(Color::Green), + Level::WARN => Style::new().fg(Color::Yellow), + Level::ERROR => Style::new().fg(Color::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-0.3.3/src/fmt/mod.rs b/vendor/tracing-subscriber/src/fmt/mod.rs index d5deb8f0c..025e17504 100644 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/mod.rs +++ b/vendor/tracing-subscriber/src/fmt/mod.rs @@ -13,10 +13,12 @@ //! //! ```toml //! [dependencies] -//! tracing-subscriber = "0.2" +//! tracing-subscriber = "0.3" //! ``` //! -//! *Compiler support: requires rustc 1.39+* +//! *Compiler support: [requires `rustc` 1.49+][msrv]* +//! +//! [msrv]: super#supported-rust-versions //! //! Add the following to your executable to initialize the default subscriber: //! ```rust @@ -68,132 +70,25 @@ //! //! * [`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. +//! displayed before the formatted representation of the event. See +//! [here](format::Full#example-output) for sample output. //! -//! For example: -//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.59s -//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt` -//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#4E9A06"> INFO</font> fmt: preparing to shave yaks number_of_yaks=3 -//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#4E9A06"> INFO</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: shaving yaks -//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=1<b>}</b>: fmt::yak_shave: hello! I'm gonna shave a yak excitement="yay!" -//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=1<b>}</b>: fmt::yak_shave: yak shaved successfully -//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=1 shaved=true -//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=1 -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=2<b>}</b>: fmt::yak_shave: hello! I'm gonna shave a yak excitement="yay!" -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=2<b>}</b>: fmt::yak_shave: yak shaved successfully -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=2 shaved=true -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=2 -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=3<b>}</b>: fmt::yak_shave: hello! I'm gonna shave a yak excitement="yay!" -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#C4A000"> WARN</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=3<b>}</b>: fmt::yak_shave: could not locate yak -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=3 shaved=false -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#CC0000">ERROR</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: failed to shave yak yak=3 error=missing yak -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=2 -//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#4E9A06"> INFO</font> fmt: yak shaving completed all_yaks_shaved=false -//! </pre> +//! * [`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. -//! -//! For example: -//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.61s -//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-pretty` -//! Oct 24 12:57:29.386 <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 -//! -//! Oct 24 12:57:29.386 <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:38<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 -//! -//! Oct 24 12:57:29.387 <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:14<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 -//! -//! Oct 24 12:57:29.387 <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:22<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 -//! -//! Oct 24 12:57:29.387 <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:43<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 -//! -//! Oct 24 12:57:29.387 <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:52<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 -//! -//! Oct 24 12:57:29.387 <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:14<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 -//! -//! Oct 24 12:57:29.387 <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:22<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 -//! -//! Oct 24 12:57:29.387 <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:43<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 -//! -//! Oct 24 12:57:29.387 <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:52<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 -//! -//! Oct 24 12:57:29.387 <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:14<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 -//! -//! Oct 24 12:57:29.387 <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: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 -//! -//! Oct 24 12:57:29.387 <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:43<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 -//! -//! Oct 24 12:57:29.387 <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="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:48<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 -//! -//! Oct 24 12:57:29.387 <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:52<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 -//! -//! Oct 24 12:57:29.387 <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> +//! 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, as seen below, is *not* -//! optimized for human readability. -//! -//! For example: -//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.58s -//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-json` -//! {"timestamp":"Oct 24 13:00:00.873","level":"INFO","fields":{"message":"preparing to shave yaks","number_of_yaks":3},"target":"fmt_json"} -//! {"timestamp":"Oct 24 13:00:00.874","level":"INFO","fields":{"message":"shaving yaks"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -//! {"timestamp":"Oct 24 13:00:00.874","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":"Oct 24 13:00:00.874","level":"TRACE","fields":{"message":"yak shaved successfully"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"1","name":"shave"}]} -//! {"timestamp":"Oct 24 13:00:00.874","level":"DEBUG","fields":{"yak":1,"shaved":true},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]} -//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"yaks_shaved":1},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -//! {"timestamp":"Oct 24 13:00:00.874","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":"Oct 24 13:00:00.874","level":"TRACE","fields":{"message":"yak shaved successfully"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"2","name":"shave"}]} -//! {"timestamp":"Oct 24 13:00:00.874","level":"DEBUG","fields":{"yak":2,"shaved":true},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]} -//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"yaks_shaved":2},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -//! {"timestamp":"Oct 24 13:00:00.874","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":"Oct 24 13:00:00.875","level":"WARN","fields":{"message":"could not locate yak"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"3","name":"shave"}]} -//! {"timestamp":"Oct 24 13:00:00.875","level":"DEBUG","fields":{"yak":3,"shaved":false},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]} -//! {"timestamp":"Oct 24 13:00:00.875","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":"Oct 24 13:00:00.875","level":"TRACE","fields":{"yaks_shaved":2},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]} -//! {"timestamp":"Oct 24 13:00:00.875","level":"INFO","fields":{"message":"yak shaving completed","all_yaks_shaved":false},"target":"fmt_json"} -//! </pre> +//! 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 //! @@ -221,7 +116,7 @@ //! .with_thread_names(true) // include the name of the current thread //! .compact(); // use the `Compact` formatting style. //! -//! // Create a `fmt` collector that uses our custom event format, and set it +//! // Create a `fmt` subscriber that uses our custom event format, and set it //! // as the default. //! tracing_subscriber::fmt() //! .event_format(format) @@ -268,7 +163,7 @@ //! //! ### Composing Layers //! -//! Composing an [`EnvFilter`] `Layer` and a [format `Layer`](../fmt/struct.Layer.html): +//! Composing an [`EnvFilter`] `Layer` and a [format `Layer`][super::fmt::Layer]: //! //! ```rust //! use tracing_subscriber::{fmt, EnvFilter}; @@ -286,11 +181,10 @@ //! .init(); //! ``` //! -//! [`EnvFilter`]: ../filter/struct.EnvFilter.html +//! [`EnvFilter`]: super::filter::EnvFilter //! [`env_logger`]: https://docs.rs/env_logger/ -//! [`filter`]: ../filter/index.html -//! [`SubscriberBuilder`]: ./struct.SubscriberBuilder.html -//! [`FmtSubscriber`]: ./struct.Subscriber.html +//! [`filter`]: super::filter +//! [`FmtSubscriber`]: Subscriber //! [`Subscriber`]: //! https://docs.rs/tracing/latest/tracing/trait.Subscriber.html //! [`tracing`]: https://crates.io/crates/tracing @@ -309,6 +203,7 @@ pub mod writer; pub use fmt_layer::{FmtContext, FormattedFields, Layer}; use crate::layer::Layer as _; +use crate::util::SubscriberInitExt; use crate::{ filter::LevelFilter, layer, @@ -348,6 +243,7 @@ pub type Formatter< /// Configures and constructs `Subscriber`s. #[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] #[derive(Debug)] +#[must_use] pub struct SubscriberBuilder< N = format::DefaultFields, E = format::Format<format::Full>, @@ -417,7 +313,7 @@ pub struct SubscriberBuilder< /// ``` /// /// [formatting subscriber]: Subscriber -/// [`SubscriberBuilder::default()`]: SubscriberBuilder::default() +/// [`SubscriberBuilder::default()`]: SubscriberBuilder::default /// [`init`]: SubscriberBuilder::init() /// [`try_init`]: SubscriberBuilder::try_init() /// [`finish`]: SubscriberBuilder::finish() @@ -429,10 +325,11 @@ pub fn fmt() -> SubscriberBuilder { /// 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. +/// 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() @@ -444,8 +341,8 @@ impl Subscriber { /// /// This can be overridden with the [`SubscriberBuilder::with_max_level`] method. /// - /// [verbosity level]: https://docs.rs/tracing-core/0.1.5/tracing_core/struct.Level.html - /// [`SubscriberBuilder::with_max_level`]: struct.SubscriberBuilder.html#method.with_max_level + /// [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. @@ -502,6 +399,11 @@ where } #[inline] + fn event_enabled(&self, event: &Event<'_>) -> bool { + self.inner.event_enabled(event) + } + + #[inline] fn event(&self, event: &Event<'_>) { self.inner.event(event); } @@ -565,6 +467,7 @@ impl Default for SubscriberBuilder { filter: Subscriber::DEFAULT_MAX_LEVEL, inner: Default::default(), } + .log_internal_errors(true) } } @@ -701,7 +604,7 @@ where /// `Layer`s added to this subscriber. /// /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle - /// [time]: #method.without_time + /// [time]: SubscriberBuilder::without_time() pub fn with_span_events(self, kind: format::FmtSpan) -> Self { SubscriberBuilder { inner: self.inner.with_span_events(kind), @@ -719,6 +622,27 @@ where } } + /// Sets whether to write errors from [`FormatEvent`] to the writer. + /// Defaults to true. + /// + /// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to + /// the writer. These errors are unlikely and will only occur if there is a + /// bug in the `FormatEvent` implementation or its dependencies. + /// + /// If writing to the writer fails, the error message is printed to stderr + /// as a fallback. + /// + /// [`FormatEvent`]: crate::fmt::FormatEvent + pub fn log_internal_errors( + self, + log_internal_errors: bool, + ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> { + SubscriberBuilder { + inner: self.inner.log_internal_errors(log_internal_errors), + ..self + } + } + /// Sets whether or not an event's target is displayed. pub fn with_target( self, @@ -730,6 +654,34 @@ where } } + /// 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, @@ -742,9 +694,9 @@ where } /// Sets whether or not the [name] of the current thread is displayed - /// when formatting events + /// when formatting events. /// - /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads + /// [name]: std::thread#naming-threads pub fn with_thread_names( self, display_thread_names: bool, @@ -756,9 +708,9 @@ where } /// Sets whether or not the [thread ID] of the current thread is displayed - /// when formatting events + /// when formatting events. /// - /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html + /// [thread ID]: std::thread::ThreadId pub fn with_thread_ids( self, display_thread_ids: bool, @@ -796,7 +748,7 @@ where /// Sets the subscriber being built to use a JSON formatter. /// - /// See [`format::Json`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::fmt::format::Json] #[cfg(feature = "json")] #[cfg_attr(docsrs, doc(cfg(feature = "json")))] pub fn json( @@ -817,7 +769,7 @@ where 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`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::fmt::format::Json] pub fn flatten_event( self, flatten_event: bool, @@ -831,7 +783,7 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json, /// Sets whether or not the JSON subscriber being built will include the current span /// in formatted events. /// - /// See [`format::Json`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::fmt::format::Json] pub fn with_current_span( self, display_current_span: bool, @@ -845,7 +797,7 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json, /// 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`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::fmt::format::Json] pub fn with_span_list( self, display_span_list: bool, @@ -891,7 +843,7 @@ where } impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { - /// Sets the Visitor that the subscriber being built will use to record + /// Sets the field formatter that the subscriber being built will use to record /// fields. /// /// For example: @@ -967,8 +919,8 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// .try_init()?; /// # Ok(())} /// ``` - /// [`EnvFilter`]: ../filter/struct.EnvFilter.html - /// [`with_max_level`]: #method.with_max_level + /// [`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( @@ -989,7 +941,7 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// subscriber. /// /// If the max level has already been set, or a [`EnvFilter`] was added by - /// [`with_filter`], this replaces that configuration with the new + /// [`with_env_filter`], this replaces that configuration with the new /// maximum level. /// /// # Examples @@ -1011,9 +963,9 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// .with_max_level(LevelFilter::OFF) /// .finish(); /// ``` - /// [verbosity level]: https://docs.rs/tracing-core/0.1.5/tracing_core/struct.Level.html - /// [`EnvFilter`]: ../filter/struct.EnvFilter.html - /// [`with_filter`]: #method.with_filter + /// [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>, @@ -1025,8 +977,26 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { } } - /// Sets the function that the subscriber being built should use to format - /// events that occur. + /// 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, @@ -1053,8 +1023,6 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// .with_writer(io::stderr) /// .init(); /// ``` - /// - /// [`MakeWriter`]: trait.MakeWriter.html pub fn with_writer<W2>(self, make_writer: W2) -> SubscriberBuilder<N, E, F, W2> where W2: for<'writer> MakeWriter<'writer> + 'static, @@ -1088,13 +1056,89 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// /// [capturing]: /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output - /// [`TestWriter`]: writer/struct.TestWriter.html + /// [`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 @@ -1121,35 +1165,69 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// /// [`LogTracer`]: /// https://docs.rs/tracing-log/0.1.0/tracing_log/struct.LogTracer.html -/// [`RUST_LOG` environment variable]: -/// ../filter/struct.EnvFilter.html#associatedconstant.DEFAULT_ENV +/// [`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()); - builder.try_init() + // 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]. /// +/// The configuration of the subscriber initialized by this function +/// depends on what [feature flags](crate#feature-flags) are enabled. +/// /// 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 +/// If the `env-filter` feature is enabled, this is shorthand for /// /// ```rust -/// tracing_subscriber::fmt().init() +/// # use tracing_subscriber::EnvFilter; +/// tracing_subscriber::fmt() +/// .with_env_filter(EnvFilter::from_default_env()) +/// .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]: -/// ../filter/struct.EnvFilter.html#associatedconstant.DEFAULT_ENV +/// [`RUST_LOG` environment variable]: crate::filter::EnvFilter::DEFAULT_ENV pub fn init() { try_init().expect("Unable to install global subscriber") } diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs b/vendor/tracing-subscriber/src/fmt/time/datetime.rs index 531331687..531331687 100644 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs +++ b/vendor/tracing-subscriber/src/fmt/time/datetime.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs b/vendor/tracing-subscriber/src/fmt/time/mod.rs index 621df16e4..e5b7c83b0 100644 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs +++ b/vendor/tracing-subscriber/src/fmt/time/mod.rs @@ -12,9 +12,13 @@ mod time_crate; pub use time_crate::UtcTime; #[cfg(feature = "local-time")] -#[cfg_attr(docsrs, doc(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. @@ -26,7 +30,7 @@ pub use time_crate::LocalTime; /// /// The full list of provided implementations can be found in [`time`]. /// -/// [`time`]: ./index.html +/// [`time`]: self pub trait FormatTime { /// Measure and write out the current time. /// diff --git a/vendor/tracing-subscriber/src/fmt/time/time_crate.rs b/vendor/tracing-subscriber/src/fmt/time/time_crate.rs new file mode 100644 index 000000000..60d57fd0b --- /dev/null +++ b/vendor/tracing-subscriber/src/fmt/time/time_crate.rs @@ -0,0 +1,470 @@ +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-0.3.3/src/fmt/writer.rs b/vendor/tracing-subscriber/src/fmt/writer.rs index 0974891f7..3fe945566 100644 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/writer.rs +++ b/vendor/tracing-subscriber/src/fmt/writer.rs @@ -1,6 +1,6 @@ //! Abstractions for creating [`io::Write`] instances. //! -//! [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +//! [`io::Write`]: std::io::Write use std::{ fmt, io::{self, Write}, @@ -96,8 +96,8 @@ use tracing_core::Metadata; pub trait MakeWriter<'a> { /// The concrete [`io::Write`] implementation returned by [`make_writer`]. /// - /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html - /// [`make_writer`]: #tymethod.make_writer + /// [`io::Write`]: std::io::Write + /// [`make_writer`]: MakeWriter::make_writer type Writer: io::Write; /// Returns an instance of [`Writer`]. @@ -109,7 +109,7 @@ pub trait MakeWriter<'a> { /// creating a [`io::Write`] instance is expensive, be sure to cache it when implementing /// [`MakeWriter`] to improve performance. /// - /// [`Writer`]: #associatedtype.Writer + /// [`Writer`]: MakeWriter::Writer /// [`fmt::Layer`]: crate::fmt::Layer /// [`fmt::Subscriber`]: crate::fmt::Subscriber /// [`io::Write`]: std::io::Write @@ -501,13 +501,13 @@ pub trait MakeWriterExt<'a>: MakeWriter<'a> { /// 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`]: ../struct.Subscriber.html -/// [`fmt::Layer`]: ../struct.Layer.html +/// [`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`]: https://doc.rust-lang.org/std/io/fn.stdout.html -/// [`io::stderr`]: https://doc.rust-lang.org/std/io/fn.stderr.html -/// [`print!`]: https://doc.rust-lang.org/std/macro.print.html +/// [`io::stdout`]: std::io::stdout +/// [`io::stderr`]: std::io::stderr +/// [`print!`]: std::print! #[derive(Default, Debug)] pub struct TestWriter { _p: (), @@ -646,10 +646,9 @@ pub struct Tee<A, B> { /// requires the `Writer` type to implement [`io::Write`], it's necessary to add /// a newtype that forwards the trait implementation. /// -/// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html -/// [`MutexGuard`]: https://doc.rust-lang.org/std/sync/struct.MutexGuard.html -/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html -/// [`MakeWriter`]: trait.MakeWriter.html +/// [`io::Write`]: std::io::Write +/// [`MutexGuard`]: std::sync::MutexGuard +/// [`Mutex`]: std::sync::Mutex #[derive(Debug)] pub struct MutexGuardWriter<'a, W>(MutexGuard<'a, W>); @@ -689,7 +688,7 @@ where { type Writer = &'a W; fn make_writer(&'a self) -> Self::Writer { - &*self + self } } @@ -734,7 +733,6 @@ impl<'a> MakeWriter<'a> for TestWriter { impl BoxMakeWriter { /// Constructs a `BoxMakeWriter` wrapping a type implementing [`MakeWriter`]. /// - /// [`MakeWriter`]: trait.MakeWriter.html pub fn new<M>(make_writer: M) -> Self where M: for<'a> MakeWriter<'a> + Send + Sync + 'static, @@ -1025,6 +1023,8 @@ impl<A, B> Tee<A, B> { /// outputs. /// /// See the documentation for [`MakeWriterExt::and`] for details. + /// + /// [writers]: std::io::Write pub fn new(a: A, b: B) -> Self { Self { a, b } } diff --git a/vendor/tracing-subscriber-0.3.3/src/layer/context.rs b/vendor/tracing-subscriber/src/layer/context.rs index e11959526..46254994f 100644 --- a/vendor/tracing-subscriber-0.3.3/src/layer/context.rs +++ b/vendor/tracing-subscriber/src/layer/context.rs @@ -25,10 +25,10 @@ use crate::{filter::FilterId, registry::Registry}; /// } /// ``` /// -/// [`Layer`]: ../layer/trait.Layer.html -/// [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html -/// [stored data]: ../registry/struct.SpanRef.html -/// [`LookupSpan`]: "../registry/trait.LookupSpan.html +/// [`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>, @@ -99,9 +99,9 @@ where /// check whether the event would be enabled. This allows `Layer`s to /// elide constructing the event if it would not be recorded. /// - /// [register]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html#method.register_callsite - /// [`enabled`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html#method.enabled - /// [`Context::enabled`]: #method.enabled + /// [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 { @@ -206,7 +206,7 @@ where /// declaration</a> for details. /// </pre> /// - /// [stored data]: ../registry/struct.SpanRef.html + /// [stored data]: crate::registry::SpanRef #[inline] pub fn span(&self, id: &span::Id) -> Option<registry::SpanRef<'_, S>> where @@ -251,7 +251,7 @@ where /// declaration</a> for details. /// </pre> /// - /// [stored data]: ../registry/struct.SpanRef.html + /// [stored data]: crate::registry::SpanRef #[inline] pub fn lookup_current(&self) -> Option<registry::SpanRef<'_, S>> where @@ -333,7 +333,7 @@ where /// declaration</a> for details. /// </pre> /// - /// [stored data]: ../registry/struct.SpanRef.html + /// [stored data]: crate::registry::SpanRef pub fn span_scope(&self, id: &span::Id) -> Option<registry::Scope<'_, S>> where S: for<'lookup> LookupSpan<'lookup>, @@ -360,7 +360,7 @@ where /// declaration</a> for details. /// </pre> /// - /// [stored data]: ../registry/struct.SpanRef.html + /// [stored data]: crate::registry::SpanRef pub fn event_scope(&self, event: &Event<'_>) -> Option<registry::Scope<'_, S>> where S: for<'lookup> LookupSpan<'lookup>, diff --git a/vendor/tracing-subscriber-0.3.3/src/layer/layered.rs b/vendor/tracing-subscriber/src/layer/layered.rs index c690764ad..f09c58c97 100644 --- a/vendor/tracing-subscriber-0.3.3/src/layer/layered.rs +++ b/vendor/tracing-subscriber/src/layer/layered.rs @@ -1,9 +1,4 @@ -use tracing_core::{ - metadata::Metadata, - span, - subscriber::{Interest, Subscriber}, - Event, LevelFilter, -}; +use tracing_core::{metadata::Metadata, span, Dispatch, Event, Interest, LevelFilter, Subscriber}; use crate::{ filter, @@ -12,13 +7,17 @@ use crate::{ }; #[cfg(all(feature = "registry", feature = "std"))] use crate::{filter::FilterId, registry::Registry}; -use core::{any::TypeId, cmp, fmt, marker::PhantomData}; +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`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html +/// [`Subscriber`]: tracing_core::Subscriber #[derive(Clone)] pub struct Layered<L, I, S = I> { /// The layer. @@ -63,6 +62,30 @@ pub struct Layered<L, I, S = I> { // === 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>, @@ -92,7 +115,11 @@ where } fn max_level_hint(&self) -> Option<LevelFilter> { - self.pick_level_hint(self.layer.max_level_hint(), self.inner.max_level_hint()) + self.pick_level_hint( + self.layer.max_level_hint(), + self.inner.max_level_hint(), + super::subscriber_is_none(&self.inner), + ) } fn new_span(&self, span: &span::Attributes<'_>) -> span::Id { @@ -111,6 +138,16 @@ where 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()); @@ -152,7 +189,7 @@ where #[cfg(all(feature = "registry", feature = "std"))] { if let Some(g) = guard.as_mut() { - g.is_closing() + g.set_closing() }; } @@ -207,6 +244,11 @@ where B: Layer<S>, S: Subscriber, { + fn on_register_dispatch(&self, subscriber: &Dispatch) { + self.layer.on_register_dispatch(subscriber); + self.inner.on_register_dispatch(subscriber); + } + fn on_layer(&mut self, subscriber: &mut S) { self.layer.on_layer(subscriber); self.inner.on_layer(subscriber); @@ -229,7 +271,11 @@ where } fn max_level_hint(&self) -> Option<LevelFilter> { - self.pick_level_hint(self.layer.max_level_hint(), self.inner.max_level_hint()) + self.pick_level_hint( + self.layer.max_level_hint(), + self.inner.max_level_hint(), + super::layer_is_none(&self.inner), + ) } #[inline] @@ -251,6 +297,17 @@ where } #[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); @@ -386,7 +443,7 @@ where // (rather than calling into the inner type), clear the current // per-layer filter interest state. #[cfg(feature = "registry")] - drop(filter::FilterState::take_interest()); + filter::FilterState::take_interest(); return outer; } @@ -421,6 +478,7 @@ where &self, outer_hint: Option<LevelFilter>, inner_hint: Option<LevelFilter>, + inner_is_none: bool, ) -> Option<LevelFilter> { if self.inner_is_registry { return outer_hint; @@ -438,6 +496,31 @@ where return None; } + // If the layer is `Option::None`, then we + // want to short-circuit the layer underneath, if it + // returns `None`, to override the `None` layer returning + // `Some(OFF)`, which should ONLY apply when there are + // no other layers that return `None`. Note this + // `None` does not == `Some(TRACE)`, it means + // something more like: "whatever all the other + // layers agree on, default to `TRACE` if none + // have an opinion". We also choose do this AFTER + // we check for per-layer filters, which + // have their own logic. + // + // Also note that this does come at some perf cost, but + // this function is only called on initialization and + // subscriber reloading. + if super::layer_is_none(&self.layer) { + return cmp::max(outer_hint, Some(inner_hint?)); + } + + // Similarly, if the layer on the inside is `None` and it returned an + // `Off` hint, we want to override that with the outer hint. + if inner_is_none && inner_hint == Some(LevelFilter::OFF) { + return outer_hint; + } + cmp::max(outer_hint, inner_hint) } } diff --git a/vendor/tracing-subscriber-0.3.3/src/layer/mod.rs b/vendor/tracing-subscriber/src/layer/mod.rs index f3f994490..bdc154301 100644 --- a/vendor/tracing-subscriber-0.3.3/src/layer/mod.rs +++ b/vendor/tracing-subscriber/src/layer/mod.rs @@ -19,7 +19,7 @@ //! [`Subscriber`] behavior; it can _observe_ events and spans, but does not //! assign IDs. //! -//! ## Composing Layers +//! # 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 @@ -135,9 +135,245 @@ //! [`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 +//! # Recording Traces //! //! The [`Layer`] trait defines a set of methods for consuming notifications from //! tracing instrumentation, which are generally equivalent to the similarly @@ -146,7 +382,7 @@ //! information provided by the wrapped subscriber (such as [the current span]) //! to the layer. //! -//! ## Filtering with `Layer`s +//! # 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 @@ -158,7 +394,7 @@ //! combined with _per-layer filters_ that control what spans and events are //! recorded by those layers. //! -//! ### Global Filtering +//! ## Global Filtering //! //! A `Layer` that implements a filtering strategy should override the //! [`register_callsite`] and/or [`enabled`] methods. It may also choose to implement @@ -179,7 +415,29 @@ //! [`Interest::never()`] from its [`register_callsite`] method, filter //! evaluation will short-circuit and the span or event will be disabled. //! -//! ### Per-Layer Filtering +//! ### 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. @@ -393,94 +651,16 @@ //! # Ok(()) } //! ``` //! -//! ## Runtime Configuration With Layers -//! -//! 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`]s 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, sync::Arc}; -//! 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)); -//! subscriber.with(layer) -//! } else { -//! subscriber -//! }; -//! -//! 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, sync::Arc}; -//! 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(Arc::new(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(()) } -//! ``` -//! -//! [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html -//! [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html +//! [`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()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.never -//! [option-impl]: crate::layer::Layer#impl-Layer<S>-for-Option<L> +//! [`Interest::never()`]: tracing_core::subscriber::Interest::never() //! [`Filtered`]: crate::filter::Filtered //! [`filter`]: crate::filter //! [`Targets`]: crate::filter::Targets @@ -498,7 +678,7 @@ use tracing_core::{ metadata::Metadata, span, subscriber::{Interest, Subscriber}, - Event, LevelFilter, + Dispatch, Event, LevelFilter, }; use core::any::TypeId; @@ -531,6 +711,31 @@ where S: Subscriber, Self: 'static, { + /// Performs late initialization when installing this layer as a + /// [`Subscriber`]. + /// + /// ## Avoiding Memory Leaks + /// + /// `Layer`s should not store the [`Dispatch`] pointing to the [`Subscriber`] + /// that they are a part of. Because the `Dispatch` owns the `Subscriber`, + /// storing the `Dispatch` within the `Subscriber` will create a reference + /// count cycle, preventing the `Dispatch` from ever being dropped. + /// + /// Instead, when it is necessary to store a cyclical reference to the + /// `Dispatch` within a `Layer`, use [`Dispatch::downgrade`] to convert a + /// `Dispatch` into a [`WeakDispatch`]. This type is analogous to + /// [`std::sync::Weak`], and does not create a reference count cycle. A + /// [`WeakDispatch`] can be stored within a subscriber without causing a + /// memory leak, and can be [upgraded] into a `Dispatch` temporarily when + /// the `Dispatch` must be accessed by the subscriber. + /// + /// [`WeakDispatch`]: tracing_core::dispatcher::WeakDispatch + /// [upgraded]: tracing_core::dispatcher::WeakDispatch::upgrade + /// [`Subscriber`]: tracing_core::Subscriber + fn on_register_dispatch(&self, collector: &Dispatch) { + let _ = collector; + } + /// Performs late initialization when attaching a `Layer` to a /// [`Subscriber`]. /// @@ -592,15 +797,15 @@ where /// globally enable or disable those callsites, it should always return /// [`Interest::always()`]. /// - /// [`Interest`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Interest.html - /// [`Subscriber::register_callsite`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html#method.register_callsite - /// [`Interest::never()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.never - /// [`Interest::always()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.always - /// [`self.enabled`]: #method.enabled - /// [`Layer::enabled`]: #method.enabled - /// [`on_event`]: #method.on_event - /// [`on_enter`]: #method.on_enter - /// [`on_exit`]: #method.on_exit + /// [`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()) { @@ -635,13 +840,12 @@ where /// See [the trait-level documentation] for more information on filtering /// with `Layer`s. /// - /// [`Interest`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Interest.html - /// [`Context`]: ../struct.Context.html - /// [`Subscriber::enabled`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html#method.enabled - /// [`Layer::register_callsite`]: #method.register_callsite - /// [`on_event`]: #method.on_event - /// [`on_enter`]: #method.on_enter - /// [`on_exit`]: #method.on_exit + /// [`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); @@ -676,6 +880,31 @@ where // 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>) {} @@ -840,7 +1069,7 @@ where /// .with_subscriber(MySubscriber::new()); ///``` /// - /// [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html + /// [`Subscriber`]: tracing_core::Subscriber fn with_subscriber(mut self, mut inner: S) -> Layered<Self, S> where Self: Sized, @@ -857,7 +1086,7 @@ where /// per-layer filtering. /// /// [`Filtered`]: crate::filter::Filtered - /// [plf]: #per-layer-filtering + /// [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> @@ -868,6 +1097,131 @@ where 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>() { @@ -880,6 +1234,7 @@ where feature! { #![all(feature = "registry", feature = "std")] + /// A per-[`Layer`] filter that determines whether a span or event is enabled /// for an individual layer. /// @@ -1022,6 +1377,26 @@ feature! { Interest::sometimes() } + /// Called before the filtered [`Layer]'s [`on_event`], to determine if + /// `on_event` should be called. + /// + /// This gives a chance to filter events based on their fields. Note, + /// however, that this *does not* override [`enabled`], and is not even + /// called if [`enabled`] returns `false`. + /// + /// ## Default Implementation + /// + /// By default, this method returns `true`, indicating that no events are + /// filtered out based on their fields. + /// + /// [`enabled`]: crate::layer::Filter::enabled + /// [`on_event`]: crate::layer::Layer::on_event + #[inline] // collapse this to a constant please mrs optimizer + fn event_enabled(&self, event: &Event<'_>, cx: &Context<'_, S>) -> bool { + let _ = (event, cx); + true + } + /// Returns an optional hint of the highest [verbosity level][level] that /// this `Filter` will enable. /// @@ -1054,6 +1429,51 @@ feature! { 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); + } } } @@ -1077,6 +1497,47 @@ pub struct Identity { // === impl Layer === +#[derive(Clone, Copy)] +pub(crate) struct NoneLayerMarker(()); +static NONE_LAYER_MARKER: NoneLayerMarker = NoneLayerMarker(()); + +/// Is a type implementing `Layer` `Option::<_>::None`? +pub(crate) fn layer_is_none<L, S>(layer: &L) -> bool +where + L: Layer<S>, + S: Subscriber, +{ + unsafe { + // Safety: we're not actually *doing* anything with this pointer --- + // this only care about the `Option`, which is essentially being used + // as a bool. We can rely on the pointer being valid, because it is + // a crate-private type, and is only returned by the `Layer` impl + // for `Option`s. However, even if the layer *does* decide to be + // evil and give us an invalid pointer here, that's fine, because we'll + // never actually dereference it. + layer.downcast_raw(TypeId::of::<NoneLayerMarker>()) + } + .is_some() +} + +/// Is a type implementing `Subscriber` `Option::<_>::None`? +pub(crate) fn subscriber_is_none<S>(subscriber: &S) -> bool +where + S: Subscriber, +{ + unsafe { + // Safety: we're not actually *doing* anything with this pointer --- + // this only care about the `Option`, which is essentially being used + // as a bool. We can rely on the pointer being valid, because it is + // a crate-private type, and is only returned by the `Layer` impl + // for `Option`s. However, even if the subscriber *does* decide to be + // evil and give us an invalid pointer here, that's fine, because we'll + // never actually dereference it. + subscriber.downcast_raw(TypeId::of::<NoneLayerMarker>()) + } + .is_some() +} + impl<L, S> Layer<S> for Option<L> where L: Layer<S>, @@ -1115,7 +1576,11 @@ where fn max_level_hint(&self) -> Option<LevelFilter> { match self { Some(ref inner) => inner.max_level_hint(), - None => None, + None => { + // There is no inner layer, so this layer will + // never enable anything. + Some(LevelFilter::OFF) + } } } @@ -1134,6 +1599,14 @@ where } #[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); @@ -1173,6 +1646,8 @@ where unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { if id == TypeId::of::<Self>() { Some(self as *const _ as *const ()) + } else if id == TypeId::of::<NoneLayerMarker>() && self.is_none() { + Some(&NONE_LAYER_MARKER as *const _ as *const ()) } else { self.as_ref().and_then(|inner| inner.downcast_raw(id)) } @@ -1181,10 +1656,17 @@ where feature! { #![any(feature = "std", feature = "alloc")] + #[cfg(not(feature = "std"))] + use alloc::vec::Vec; macro_rules! layer_impl_body { () => { #[inline] + fn on_register_dispatch(&self, subscriber: &Dispatch) { + self.deref().on_register_dispatch(subscriber); + } + + #[inline] fn on_layer(&mut self, subscriber: &mut S) { self.deref_mut().on_layer(subscriber); } @@ -1220,6 +1702,11 @@ feature! { } #[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) } @@ -1266,6 +1753,125 @@ feature! { { 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 === diff --git a/vendor/tracing-subscriber-0.3.3/src/layer/tests.rs b/vendor/tracing-subscriber/src/layer/tests.rs index d7ad61769..d7ad61769 100644 --- a/vendor/tracing-subscriber-0.3.3/src/layer/tests.rs +++ b/vendor/tracing-subscriber/src/layer/tests.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/lib.rs b/vendor/tracing-subscriber/src/lib.rs index 563a86dee..808923007 100644 --- a/vendor/tracing-subscriber-0.3.3/src/lib.rs +++ b/vendor/tracing-subscriber/src/lib.rs @@ -10,7 +10,7 @@ //! `tracing-subscriber` is intended for use by both `Subscriber` authors and //! application authors using `tracing` to instrument their applications. //! -//! *Compiler support: [requires `rustc` 1.42+][msrv]* +//! *Compiler support: [requires `rustc` 1.50+][msrv]* //! //! [msrv]: #supported-rust-versions //! @@ -60,9 +60,11 @@ //! **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` +//! - `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` @@ -80,7 +82,7 @@ //! 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 [`Subscriber`] trait, can still be used in +//! 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 @@ -102,10 +104,41 @@ //! 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.42. The current Tracing version is not guaranteed to build on +//! version is 1.50. 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 @@ -116,17 +149,18 @@ //! supported compiler version is not considered a semver breaking change as //! long as doing so complies with this policy. //! -//! [`tracing`]: https://docs.rs/tracing/latest/tracing/ -//! [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html -//! [`EnvFilter`]: filter/struct.EnvFilter.html -//! [`fmt`]: fmt/index.html +//! [`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 -//! [`liballoc`]: https://doc.rust-lang.org/alloc/index.html -#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.3.1")] +//! [`libstd`]: std +//! [`liballoc`]: alloc +#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.3.15")] #![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/" diff --git a/vendor/tracing-subscriber-0.3.3/src/macros.rs b/vendor/tracing-subscriber/src/macros.rs index 81351132f..81351132f 100644 --- a/vendor/tracing-subscriber-0.3.3/src/macros.rs +++ b/vendor/tracing-subscriber/src/macros.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/prelude.rs b/vendor/tracing-subscriber/src/prelude.rs index c2230907b..c2230907b 100644 --- a/vendor/tracing-subscriber-0.3.3/src/prelude.rs +++ b/vendor/tracing-subscriber/src/prelude.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/registry/extensions.rs b/vendor/tracing-subscriber/src/registry/extensions.rs index 899e1549f..ff76fb599 100644 --- a/vendor/tracing-subscriber-0.3.3/src/registry/extensions.rs +++ b/vendor/tracing-subscriber/src/registry/extensions.rs @@ -78,7 +78,7 @@ impl<'a> ExtensionsMut<'a> { /// should be able to reuse timestamp _x_. /// /// Therefore, extensions should generally be newtypes, rather than common - /// types like [`String`](https://doc.rust-lang.org/std/string/struct.String.html), to avoid accidental + /// types like [`String`](std::string::String), to avoid accidental /// cross-`Layer` clobbering. /// /// ## Panics diff --git a/vendor/tracing-subscriber-0.3.3/src/registry/mod.rs b/vendor/tracing-subscriber/src/registry/mod.rs index f3b77b6a9..38af53e8a 100644 --- a/vendor/tracing-subscriber-0.3.3/src/registry/mod.rs +++ b/vendor/tracing-subscriber/src/registry/mod.rs @@ -55,8 +55,7 @@ //! require the root subscriber to be a registry. //! //! [`Layer`]: crate::layer::Layer -//! [`Subscriber`]: -//! https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html +//! [`Subscriber`]: tracing_core::Subscriber //! [ctx]: crate::layer::Context //! [lookup]: crate::layer::Context::span() use tracing_core::{field::FieldSet, span::Id, Metadata}; @@ -87,9 +86,9 @@ feature! { /// implement this trait; if they do, any [`Layer`]s wrapping them can look up /// metadata via the [`Context`] type's [`span()`] method. /// -/// [`Layer`]: ../layer/trait.Layer.html -/// [`Context`]: ../layer/struct.Context.html -/// [`span()`]: ../layer/struct.Context.html#method.span +/// [`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>; @@ -104,7 +103,6 @@ pub trait LookupSpan<'a> { /// capable of performing more sophisiticated queries. /// </pre> /// - /// [`SpanData`]: trait.SpanData.html fn span_data(&'a self, id: &Id) -> Option<Self::Data>; /// Returns a [`SpanRef`] for the span with the given `Id`, if it exists. @@ -116,9 +114,7 @@ pub trait LookupSpan<'a> { /// rather than the [`span_data`] method; while _implementors_ of this trait /// should only implement `span_data`. /// - /// [`SpanRef`]: struct.SpanRef.html - /// [`SpanData`]: trait.SpanData.html - /// [`span_data`]: #method.span_data + /// [`span_data`]: LookupSpan::span_data() fn span(&'a self, id: &Id) -> Option<SpanRef<'_, Self>> where Self: Sized, @@ -208,8 +204,8 @@ pub trait SpanData<'a> { /// provides additional methods for querying the registry based on values from /// the span. /// -/// [span data]: trait.SpanData.html -/// [registry]: trait.LookupSpan.html +/// [span data]: SpanData +/// [registry]: LookupSpan #[derive(Debug)] pub struct SpanRef<'a, R: LookupSpan<'a>> { registry: &'a R, @@ -360,7 +356,7 @@ where /// Returns a list of [fields] defined by the span. /// - /// [fields]: https://docs.rs/tracing-core/latest/tracing_core/field/index.html + /// [fields]: tracing_core::field pub fn fields(&self) -> &FieldSet { self.data.metadata().fields() } diff --git a/vendor/tracing-subscriber-0.3.3/src/registry/sharded.rs b/vendor/tracing-subscriber/src/registry/sharded.rs index a6311cb71..797899767 100644 --- a/vendor/tracing-subscriber-0.3.3/src/registry/sharded.rs +++ b/vendor/tracing-subscriber/src/registry/sharded.rs @@ -75,16 +75,16 @@ use tracing_core::{ /// the distributed tracing system. These IDs can be associated with /// `tracing` spans using [fields] and/or [stored span data]. /// -/// [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html -/// [slab]: https://docs.rs/crate/sharded-slab/ +/// [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]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html#method.try_close +/// [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]: https://docs.rs/tracing-core/latest/tracing-core/field/index.html +/// [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"))))] @@ -102,9 +102,8 @@ pub struct Registry { /// [`Layer`s], such as formatted fields, metrics, or distributed traces should /// be stored in the [extensions] typemap. /// -/// [`Registry`]: struct.Registry.html -/// [`Layer`s]: ../layer/trait.Layer.html -/// [extensions]: struct.Extensions.html +/// [`Layer`s]: crate::layer::Layer +/// [extensions]: Extensions #[cfg(feature = "registry")] #[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))] #[derive(Debug)] @@ -115,10 +114,11 @@ pub struct Data<'a> { /// 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. +/// 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, @@ -173,7 +173,6 @@ fn id_to_idx(id: &Id) -> usize { /// greater than 0, `CloseGuard` decrements the counter by one and /// _does not_ remove the span from the [`Registry`]. /// -/// [`Registry`]: ./struct.Registry.html pub(crate) struct CloseGuard<'a> { id: Id, registry: &'a Registry, @@ -189,7 +188,6 @@ impl Registry { /// processed an `on_close` notification via the `CLOSE_COUNT` thread-local. /// For additional details, see [`CloseGuard`]. /// - /// [`CloseGuard`]: ./struct.CloseGuard.html pub(crate) fn start_close(&self, id: Id) -> CloseGuard<'_> { CLOSE_COUNT.with(|count| { let c = count.get(); @@ -216,7 +214,6 @@ thread_local! { /// track how many layers have processed the close. /// For additional details, see [`CloseGuard`]. /// - /// [`CloseGuard`]: ./struct.CloseGuard.html static CLOSE_COUNT: Cell<usize> = Cell::new(0); } @@ -278,6 +275,13 @@ impl Subscriber for Registry { fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {} + fn event_enabled(&self, _event: &Event<'_>) -> bool { + if self.has_per_layer_filters() { + return FilterState::event_enabled(); + } + true + } + /// This is intentionally not implemented, as recording events /// is the responsibility of layers atop of this registry. fn event(&self, _: &Event<'_>) {} @@ -380,7 +384,7 @@ impl<'a> LookupSpan<'a> for Registry { // === impl CloseGuard === impl<'a> CloseGuard<'a> { - pub(crate) fn is_closing(&mut self) { + pub(crate) fn set_closing(&mut self) { self.is_closing = true; } } diff --git a/vendor/tracing-subscriber-0.3.3/src/registry/stack.rs b/vendor/tracing-subscriber/src/registry/stack.rs index 4a3f7e59d..4a3f7e59d 100644 --- a/vendor/tracing-subscriber-0.3.3/src/registry/stack.rs +++ b/vendor/tracing-subscriber/src/registry/stack.rs diff --git a/vendor/tracing-subscriber/src/reload.rs b/vendor/tracing-subscriber/src/reload.rs new file mode 100644 index 000000000..096f83d38 --- /dev/null +++ b/vendor/tracing-subscriber/src/reload.rs @@ -0,0 +1,384 @@ +//! 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 core::any::TypeId; +use std::{ + error, fmt, + marker::PhantomData, + sync::{Arc, Weak}, +}; +use tracing_core::{ + callsite, span, + subscriber::{Interest, Subscriber}, + Dispatch, Event, LevelFilter, 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_register_dispatch(&self, subscriber: &Dispatch) { + try_lock!(self.inner.read()).on_register_dispatch(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) + } + + #[inline] + fn max_level_hint(&self) -> Option<LevelFilter> { + try_lock!(self.inner.read(), else return None).max_level_hint() + } + + #[doc(hidden)] + unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { + // Safety: it is generally unsafe to downcast through a reload, because + // the pointer can be invalidated after the lock is dropped. + // `NoneLayerMarker` is a special case because it + // is never dereferenced. + // + // Additionally, even if the marker type *is* dereferenced (which it + // never will be), the pointer should be valid even if the subscriber + // is reloaded, because all `NoneLayerMarker` pointers that we return + // actually point to the global static singleton `NoneLayerMarker`, + // rather than to a field inside the lock. + if id == TypeId::of::<layer::NoneLayerMarker>() { + return try_lock!(self.inner.read(), else return None).downcast_raw(id); + } + + None + } +} + +// ===== 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) + } + + #[inline] + fn max_level_hint(&self) -> Option<LevelFilter> { + try_lock!(self.inner.read(), else return None).max_level_hint() + } +} + +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-0.3.3/src/sync.rs b/vendor/tracing-subscriber/src/sync.rs index ec42b834a..ec42b834a 100644 --- a/vendor/tracing-subscriber-0.3.3/src/sync.rs +++ b/vendor/tracing-subscriber/src/sync.rs diff --git a/vendor/tracing-subscriber-0.3.3/src/util.rs b/vendor/tracing-subscriber/src/util.rs index 1c98aa4d2..1c98aa4d2 100644 --- a/vendor/tracing-subscriber-0.3.3/src/util.rs +++ b/vendor/tracing-subscriber/src/util.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs index 00e98a994..00e98a994 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs +++ b/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs b/vendor/tracing-subscriber/tests/duplicate_spans.rs index c4a736f74..5d4dc6a85 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs +++ b/vendor/tracing-subscriber/tests/duplicate_spans.rs @@ -1,5 +1,4 @@ #![cfg(all(feature = "env-filter", feature = "fmt"))] -mod support; use tracing::{self, subscriber::with_default, Span}; use tracing_subscriber::{filter::EnvFilter, FmtSubscriber}; diff --git a/vendor/tracing-subscriber/tests/env_filter/main.rs b/vendor/tracing-subscriber/tests/env_filter/main.rs new file mode 100644 index 000000000..3c3d4868b --- /dev/null +++ b/vendor/tracing-subscriber/tests/env_filter/main.rs @@ -0,0 +1,547 @@ +#![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 new file mode 100644 index 000000000..8bf5698a4 --- /dev/null +++ b/vendor/tracing-subscriber/tests/env_filter/per_layer.rs @@ -0,0 +1,305 @@ +//! 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 new file mode 100644 index 000000000..8f67cfcba --- /dev/null +++ b/vendor/tracing-subscriber/tests/event_enabling.rs @@ -0,0 +1,81 @@ +#![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-0.3.3/tests/field_filter.rs b/vendor/tracing-subscriber/tests/field_filter.rs index 12b4053b6..f14a0626d 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/field_filter.rs +++ b/vendor/tracing-subscriber/tests/field_filter.rs @@ -1,7 +1,7 @@ #![cfg(feature = "env-filter")] -mod support; -use self::support::*; + use tracing::{self, subscriber::with_default, Level}; +use tracing_mock::*; use tracing_subscriber::{filter::EnvFilter, prelude::*}; #[test] diff --git a/vendor/tracing-subscriber-0.3.3/tests/filter_log.rs b/vendor/tracing-subscriber/tests/filter_log.rs index 28e742501..8d57ed600 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/filter_log.rs +++ b/vendor/tracing-subscriber/tests/filter_log.rs @@ -1,7 +1,7 @@ #![cfg(all(feature = "env-filter", feature = "tracing-log"))] -mod support; -use self::support::*; + use tracing::{self, Level}; +use tracing_mock::*; use tracing_subscriber::{filter::EnvFilter, prelude::*}; mod my_module { diff --git a/vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs b/vendor/tracing-subscriber/tests/fmt_max_level_hint.rs index 57a0f6e3f..57a0f6e3f 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs +++ b/vendor/tracing-subscriber/tests/fmt_max_level_hint.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs index 897dae282..897dae282 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs +++ b/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs b/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs index d89d3bf17..d89d3bf17 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs +++ b/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs b/vendor/tracing-subscriber/tests/layer_filters/boxed.rs index 0fe37188e..0fe37188e 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs +++ b/vendor/tracing-subscriber/tests/layer_filters/boxed.rs diff --git a/vendor/tracing-subscriber/tests/layer_filters/combinators.rs b/vendor/tracing-subscriber/tests/layer_filters/combinators.rs new file mode 100644 index 000000000..6052a2d00 --- /dev/null +++ b/vendor/tracing-subscriber/tests/layer_filters/combinators.rs @@ -0,0 +1,42 @@ +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-0.3.3/tests/layer_filters/downcast_raw.rs b/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs index b5f7e35ce..b5f7e35ce 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/downcast_raw.rs +++ b/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs b/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs index 7fd7d843b..7fd7d843b 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs +++ b/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs b/vendor/tracing-subscriber/tests/layer_filters/main.rs index 2359584d7..10f06c24c 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs +++ b/vendor/tracing-subscriber/tests/layer_filters/main.rs @@ -5,11 +5,13 @@ use self::support::*; mod boxed; mod downcast_raw; mod filter_scopes; +mod per_event; mod targets; mod trees; +mod vec; use tracing::{level_filters::LevelFilter, Level}; -use tracing_subscriber::{filter, prelude::*}; +use tracing_subscriber::{filter, prelude::*, Layer}; #[test] fn basic_layer_filters() { diff --git a/vendor/tracing-subscriber/tests/layer_filters/per_event.rs b/vendor/tracing-subscriber/tests/layer_filters/per_event.rs new file mode 100644 index 000000000..9c785f9a2 --- /dev/null +++ b/vendor/tracing-subscriber/tests/layer_filters/per_event.rs @@ -0,0 +1,61 @@ +use crate::support::*; +use tracing::Level; +use tracing_subscriber::{field::Visit, layer::Filter, prelude::*}; + +struct FilterEvent; + +impl<S> Filter<S> for FilterEvent { + fn enabled( + &self, + _meta: &tracing::Metadata<'_>, + _cx: &tracing_subscriber::layer::Context<'_, S>, + ) -> bool { + true + } + + fn event_enabled( + &self, + event: &tracing::Event<'_>, + _cx: &tracing_subscriber::layer::Context<'_, S>, + ) -> bool { + struct ShouldEnable(bool); + impl Visit for ShouldEnable { + fn record_bool(&mut self, field: &tracing_core::Field, value: bool) { + if field.name() == "enable" { + self.0 = value; + } + } + + fn record_debug( + &mut self, + _field: &tracing_core::Field, + _value: &dyn core::fmt::Debug, + ) { + } + } + let mut should_enable = ShouldEnable(false); + event.record(&mut should_enable); + should_enable.0 + } +} + +#[test] +fn per_subscriber_event_field_filtering() { + let (expect, handle) = layer::mock() + .event(event::mock().at_level(Level::TRACE)) + .event(event::mock().at_level(Level::INFO)) + .done() + .run_with_handle(); + + let _subscriber = tracing_subscriber::registry() + .with(expect.with_filter(FilterEvent)) + .set_default(); + + tracing::trace!(enable = true, "hello trace"); + tracing::debug!("hello debug"); + tracing::info!(enable = true, "hello info"); + tracing::warn!(enable = false, "hello warn"); + tracing::error!("hello error"); + + handle.assert_finished(); +} diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs b/vendor/tracing-subscriber/tests/layer_filters/targets.rs index c8133044b..c8133044b 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs +++ b/vendor/tracing-subscriber/tests/layer_filters/targets.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs b/vendor/tracing-subscriber/tests/layer_filters/trees.rs index 18cdd8ccc..18cdd8ccc 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs +++ b/vendor/tracing-subscriber/tests/layer_filters/trees.rs diff --git a/vendor/tracing-subscriber/tests/layer_filters/vec.rs b/vendor/tracing-subscriber/tests/layer_filters/vec.rs new file mode 100644 index 000000000..87244e4ab --- /dev/null +++ b/vendor/tracing-subscriber/tests/layer_filters/vec.rs @@ -0,0 +1,120 @@ +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-0.3.3/tests/multiple_layer_filter_interests_cached.rs b/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs index 5c25e7f03..5c25e7f03 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/multiple_layer_filter_interests_cached.rs +++ b/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs diff --git a/vendor/tracing-subscriber/tests/option.rs b/vendor/tracing-subscriber/tests/option.rs new file mode 100644 index 000000000..c87519c30 --- /dev/null +++ b/vendor/tracing-subscriber/tests/option.rs @@ -0,0 +1,262 @@ +#![cfg(feature = "registry")] +use tracing_core::{subscriber::Interest, LevelFilter, Metadata, Subscriber}; +use tracing_subscriber::{layer, prelude::*}; + +// A basic layer that returns its inner for `max_level_hint` +#[derive(Debug)] +struct BasicLayer(Option<LevelFilter>); +impl<S: Subscriber> tracing_subscriber::Layer<S> for BasicLayer { + fn register_callsite(&self, _m: &Metadata<'_>) -> Interest { + Interest::sometimes() + } + + fn enabled(&self, _m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool { + true + } + + fn max_level_hint(&self) -> Option<LevelFilter> { + self.0 + } +} + +// 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)); +} + +/// Tests that the logic tested in `doesnt_override_none` works through the reload subscriber +#[test] +fn just_option_none_layer() { + let subscriber = tracing_subscriber::registry().with(Some(LevelFilter::ERROR)); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR)); +} + +// Test that the `None` max level hint only applies if its the only layer +#[test] +fn none_outside_doesnt_override_max_level() { + // None means the other layer takes control + let subscriber = tracing_subscriber::registry() + .with(BasicLayer(None)) + .with(None::<LevelFilter>); + assert_eq!( + subscriber.max_level_hint(), + None, + "\n stack: {:#?}", + subscriber + ); + + // The `None`-returning layer still wins + let subscriber = tracing_subscriber::registry() + .with(BasicLayer(None)) + .with(Some(LevelFilter::ERROR)); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::ERROR), + "\n stack: {:#?}", + subscriber + ); + + // Check that we aren't doing anything truly wrong + let subscriber = tracing_subscriber::registry() + .with(BasicLayer(Some(LevelFilter::DEBUG))) + .with(None::<LevelFilter>); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::DEBUG), + "\n stack: {:#?}", + subscriber + ); + + // Test that per-subscriber filters aren't affected + + // One layer is None so it "wins" + let subscriber = tracing_subscriber::registry() + .with(BasicLayer(None)) + .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG)); + assert_eq!( + subscriber.max_level_hint(), + None, + "\n stack: {:#?}", + subscriber + ); + + // The max-levels wins + let subscriber = tracing_subscriber::registry() + .with(BasicLayer(Some(LevelFilter::INFO))) + .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG)); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::DEBUG), + "\n stack: {:#?}", + subscriber + ); + + // Test filter on the other layer + let subscriber = tracing_subscriber::registry() + .with(BasicLayer(Some(LevelFilter::INFO)).with_filter(LevelFilter::DEBUG)) + .with(None::<LevelFilter>); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::DEBUG), + "\n stack: {:#?}", + subscriber + ); + let subscriber = tracing_subscriber::registry() + .with(BasicLayer(None).with_filter(LevelFilter::DEBUG)) + .with(None::<LevelFilter>); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::DEBUG), + "\n stack: {:#?}", + subscriber + ); + + // The `OFF` from `None` over overridden. + let subscriber = tracing_subscriber::registry() + .with(BasicLayer(Some(LevelFilter::INFO))) + .with(None::<LevelFilter>); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::INFO), + "\n stack: {:#?}", + subscriber + ); +} + +// Test that the `None` max level hint only applies if its the only layer +#[test] +fn none_inside_doesnt_override_max_level() { + // None means the other layer takes control + let subscriber = tracing_subscriber::registry() + .with(None::<LevelFilter>) + .with(BasicLayer(None)); + assert_eq!( + subscriber.max_level_hint(), + None, + "\n stack: {:#?}", + subscriber + ); + + // The `None`-returning layer still wins + let subscriber = tracing_subscriber::registry() + .with(Some(LevelFilter::ERROR)) + .with(BasicLayer(None)); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::ERROR), + "\n stack: {:#?}", + subscriber + ); + + // Check that we aren't doing anything truly wrong + let subscriber = tracing_subscriber::registry() + .with(None::<LevelFilter>) + .with(BasicLayer(Some(LevelFilter::DEBUG))); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::DEBUG), + "\n stack: {:#?}", + subscriber + ); + + // Test that per-subscriber filters aren't affected + + // One layer is None so it "wins" + let subscriber = tracing_subscriber::registry() + .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG)) + .with(BasicLayer(None)); + assert_eq!( + subscriber.max_level_hint(), + None, + "\n stack: {:#?}", + subscriber + ); + + // The max-levels wins + let subscriber = tracing_subscriber::registry() + .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG)) + .with(BasicLayer(Some(LevelFilter::INFO))); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::DEBUG), + "\n stack: {:#?}", + subscriber + ); + + // Test filter on the other layer + let subscriber = tracing_subscriber::registry() + .with(None::<LevelFilter>) + .with(BasicLayer(Some(LevelFilter::INFO)).with_filter(LevelFilter::DEBUG)); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::DEBUG), + "\n stack: {:#?}", + subscriber + ); + let subscriber = tracing_subscriber::registry() + .with(None::<LevelFilter>) + .with(BasicLayer(None).with_filter(LevelFilter::DEBUG)); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::DEBUG), + "\n stack: {:#?}", + subscriber + ); + + // The `OFF` from `None` over overridden. + let subscriber = tracing_subscriber::registry() + .with(None::<LevelFilter>) + .with(BasicLayer(Some(LevelFilter::INFO))); + assert_eq!( + subscriber.max_level_hint(), + Some(LevelFilter::INFO), + "\n stack: {:#?}", + subscriber + ); +} + +/// Tests that the logic tested in `doesnt_override_none` works through the reload layer +#[test] +fn reload_works_with_none() { + let (layer1, handle1) = tracing_subscriber::reload::Layer::new(None::<BasicLayer>); + let (layer2, _handle2) = tracing_subscriber::reload::Layer::new(None::<BasicLayer>); + + let subscriber = tracing_subscriber::registry().with(layer1).with(layer2); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF)); + + // reloading one should pass through correctly. + handle1.reload(Some(BasicLayer(None))).unwrap(); + assert_eq!(subscriber.max_level_hint(), None); + + // Check pass-through of an actual level as well + handle1 + .reload(Some(BasicLayer(Some(LevelFilter::DEBUG)))) + .unwrap(); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG)); +} diff --git a/vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs b/vendor/tracing-subscriber/tests/registry_max_level_hint.rs index f94c8a1fb..f94c8a1fb 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs +++ b/vendor/tracing-subscriber/tests/registry_max_level_hint.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs b/vendor/tracing-subscriber/tests/registry_with_subscriber.rs index 3f8d99b1d..50d2f551d 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs +++ b/vendor/tracing-subscriber/tests/registry_with_subscriber.rs @@ -4,7 +4,7 @@ use tracing_subscriber::prelude::*; #[tokio::test] async fn future_with_subscriber() { - let _default = tracing_subscriber::registry().init(); + tracing_subscriber::registry().init(); let span = tracing::info_span!("foo"); let _e = span.enter(); let span = tracing::info_span!("bar"); diff --git a/vendor/tracing-subscriber/tests/reload.rs b/vendor/tracing-subscriber/tests/reload.rs new file mode 100644 index 000000000..28662e2e6 --- /dev/null +++ b/vendor/tracing-subscriber/tests/reload.rs @@ -0,0 +1,155 @@ +#![cfg(feature = "registry")] +use std::sync::atomic::{AtomicUsize, Ordering}; +use tracing_core::{ + span::{Attributes, Id, Record}, + subscriber::Interest, + Event, LevelFilter, Metadata, Subscriber, +}; +use tracing_subscriber::{layer, prelude::*, reload::*}; + +pub struct NopSubscriber; +fn event() { + tracing::info!("my event"); +} + +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 max_level_hint(&self) -> Option<LevelFilter> { + match self { + Filter::One => Some(LevelFilter::INFO), + Filter::Two => Some(LevelFilter::DEBUG), + } + } + } + + 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); + + assert_eq!(LevelFilter::current(), LevelFilter::INFO); + handle.reload(Filter::Two).expect("should reload"); + assert_eq!(LevelFilter::current(), LevelFilter::DEBUG); + + event(); + + assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); + assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1); + }) +} + +#[test] +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 max_level_hint(&self) -> Option<LevelFilter> { + match self { + Filter::One => Some(LevelFilter::INFO), + Filter::Two => Some(LevelFilter::DEBUG), + } + } + } + + 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); + + assert_eq!(LevelFilter::current(), LevelFilter::INFO); + handle.reload(Filter::Two).expect("should reload"); + assert_eq!(LevelFilter::current(), LevelFilter::DEBUG); + + event(); + + assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); + assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1); + }) +} diff --git a/vendor/tracing-subscriber-0.3.3/tests/same_len_filters.rs b/vendor/tracing-subscriber/tests/same_len_filters.rs index b525ea6fd..879e578d7 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/same_len_filters.rs +++ b/vendor/tracing-subscriber/tests/same_len_filters.rs @@ -1,9 +1,9 @@ // These tests include field filters with no targets, so they have to go in a // separate file. #![cfg(feature = "env-filter")] -mod support; -use self::support::*; + use tracing::{self, subscriber::with_default, Level}; +use tracing_mock::*; use tracing_subscriber::{filter::EnvFilter, prelude::*}; #[test] diff --git a/vendor/tracing-subscriber-0.3.3/tests/support.rs b/vendor/tracing-subscriber/tests/support.rs index 848ebdc63..50e0e6669 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/support.rs +++ b/vendor/tracing-subscriber/tests/support.rs @@ -1,20 +1,15 @@ #![allow(missing_docs, dead_code)] -pub use self::support::{event, field, span, subscriber}; -// This has to have the same name as the module in `tracing`. -// path attribute requires referenced module to have same name so allow module inception here -#[allow(clippy::module_inception)] -#[path = "../../tracing/tests/support/mod.rs"] -mod support; - -use self::{ - event::MockEvent, - span::{MockSpan, NewSpan}, - subscriber::{Expect, MockHandle}, -}; +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}, diff --git a/vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs index 9fa5c6bd4..9fa5c6bd4 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs +++ b/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs diff --git a/vendor/tracing-subscriber-0.3.3/tests/utils.rs b/vendor/tracing-subscriber/tests/utils.rs index ff025a2a2..e95868d5e 100644 --- a/vendor/tracing-subscriber-0.3.3/tests/utils.rs +++ b/vendor/tracing-subscriber/tests/utils.rs @@ -1,6 +1,6 @@ #![cfg(feature = "std")] -mod support; -use self::support::*; + +use tracing_mock::*; use tracing_subscriber::prelude::*; #[test] diff --git a/vendor/tracing-subscriber/tests/vec.rs b/vendor/tracing-subscriber/tests/vec.rs new file mode 100644 index 000000000..92abf0bff --- /dev/null +++ b/vendor/tracing-subscriber/tests/vec.rs @@ -0,0 +1,19 @@ +#![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 new file mode 100644 index 000000000..10467cb7d --- /dev/null +++ b/vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs @@ -0,0 +1,117 @@ +#![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(); +} |