├── .cargo
└── audit.toml
├── .config
└── nextest.toml
├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
├── labeler.yml
└── workflows
│ ├── CI.yml
│ ├── audit.yml
│ └── release.yml
├── .gitignore
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE
├── README.md
├── SECURITY.md
├── assets
├── logo-type.png
├── logo.svg
└── splash.svg
├── bin
└── publish
├── clippy.toml
├── examples
├── Cargo.toml
├── README.md
└── examples
│ ├── all-levels.rs
│ ├── appender-multifile.rs
│ ├── async-fn.rs
│ ├── attrs-args.rs
│ ├── attrs-basic.rs
│ ├── attrs-literal-field-names.rs
│ ├── counters.rs
│ ├── custom-error.rs
│ ├── echo.rs
│ ├── env-filter-explorer.rs
│ ├── fmt-compact.rs
│ ├── fmt-custom-event.rs
│ ├── fmt-custom-field.rs
│ ├── fmt-json.rs
│ ├── fmt-multiple-writers.rs
│ ├── fmt-pretty.rs
│ ├── fmt-source-locations.rs
│ ├── fmt-stderr.rs
│ ├── fmt.rs
│ ├── fmt
│ └── yak_shave.rs
│ ├── futures-proxy-server.rs
│ ├── hyper-echo.rs
│ ├── inferno-flame.rs
│ ├── instrumented-error.rs
│ ├── journald.rs
│ ├── log.rs
│ ├── panic_hook.rs
│ ├── serde-yak-shave.rs
│ ├── sloggish
│ ├── main.rs
│ └── sloggish_subscriber.rs
│ ├── spawny-thing.rs
│ ├── subscriber-filter.rs
│ ├── thread-info.rs
│ ├── toggle-layers.rs
│ ├── tokio-spawny-thing.rs
│ ├── tokio_panic_hook.rs
│ ├── tower-client.rs
│ ├── tower-load.rs
│ ├── tower-server.rs
│ ├── valuable.rs
│ ├── valuable_instrument.rs
│ └── valuable_json.rs
├── netlify.toml
├── tracing-appender
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── benches
│ └── bench.rs
└── src
│ ├── lib.rs
│ ├── non_blocking.rs
│ ├── rolling.rs
│ ├── rolling
│ └── builder.rs
│ ├── sync.rs
│ └── worker.rs
├── tracing-attributes
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│ ├── attr.rs
│ ├── expand.rs
│ └── lib.rs
└── tests
│ ├── async_fn.rs
│ ├── dead_code.rs
│ ├── destructuring.rs
│ ├── err.rs
│ ├── fields.rs
│ ├── follows_from.rs
│ ├── instrument.rs
│ ├── levels.rs
│ ├── names.rs
│ ├── parents.rs
│ ├── ret.rs
│ ├── targets.rs
│ ├── ui.rs
│ └── ui
│ ├── async_instrument.rs
│ ├── async_instrument.stderr
│ ├── const_instrument.rs
│ └── const_instrument.stderr
├── tracing-core
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│ ├── callsite.rs
│ ├── dispatcher.rs
│ ├── event.rs
│ ├── field.rs
│ ├── lazy.rs
│ ├── lib.rs
│ ├── metadata.rs
│ ├── parent.rs
│ ├── span.rs
│ ├── spin
│ │ ├── LICENSE
│ │ ├── mod.rs
│ │ ├── mutex.rs
│ │ └── once.rs
│ ├── stdlib.rs
│ └── subscriber.rs
└── tests
│ ├── common
│ └── mod.rs
│ ├── dispatch.rs
│ ├── global_dispatch.rs
│ ├── local_dispatch_before_init.rs
│ ├── macros.rs
│ └── missed_register_callsite.rs
├── tracing-error
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
└── src
│ ├── backtrace.rs
│ ├── error.rs
│ ├── layer.rs
│ └── lib.rs
├── tracing-flame
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│ ├── error.rs
│ └── lib.rs
└── tests
│ ├── collapsed.rs
│ └── concurrent.rs
├── tracing-futures
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│ ├── executor
│ │ ├── futures_01.rs
│ │ ├── futures_03.rs
│ │ └── mod.rs
│ ├── lib.rs
│ └── stdlib.rs
└── tests
│ └── std_future.rs
├── tracing-journald
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│ ├── lib.rs
│ ├── memfd.rs
│ └── socket.rs
└── tests
│ └── journal.rs
├── tracing-log
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── benches
│ └── logging.rs
├── src
│ ├── interest_cache.rs
│ ├── lib.rs
│ └── log_tracer.rs
└── tests
│ ├── log_tracer.rs
│ └── reexport_log_crate.rs
├── tracing-macros
├── Cargo.toml
├── LICENSE
├── examples
│ └── factorial.rs
└── src
│ └── lib.rs
├── tracing-mock
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│ ├── ancestry.rs
│ ├── event.rs
│ ├── expect.rs
│ ├── field.rs
│ ├── layer.rs
│ ├── lib.rs
│ ├── metadata.rs
│ ├── span.rs
│ └── subscriber.rs
└── tests
│ ├── event_ancestry.rs
│ └── span_ancestry.rs
├── tracing-serde
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
└── src
│ ├── fields.rs
│ └── lib.rs
├── tracing-subscriber
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── benches
│ ├── enter.rs
│ ├── filter.rs
│ ├── filter_log.rs
│ ├── fmt.rs
│ └── support
│ │ └── mod.rs
├── src
│ ├── field
│ │ ├── debug.rs
│ │ ├── delimited.rs
│ │ ├── display.rs
│ │ └── mod.rs
│ ├── filter
│ │ ├── directive.rs
│ │ ├── env
│ │ │ ├── builder.rs
│ │ │ ├── directive.rs
│ │ │ ├── field.rs
│ │ │ └── mod.rs
│ │ ├── filter_fn.rs
│ │ ├── layer_filters
│ │ │ ├── combinator.rs
│ │ │ └── mod.rs
│ │ ├── level.rs
│ │ ├── mod.rs
│ │ └── targets.rs
│ ├── fmt
│ │ ├── fmt_layer.rs
│ │ ├── format
│ │ │ ├── json.rs
│ │ │ ├── mod.rs
│ │ │ └── pretty.rs
│ │ ├── mod.rs
│ │ ├── time
│ │ │ ├── chrono_crate.rs
│ │ │ ├── datetime.rs
│ │ │ ├── mod.rs
│ │ │ └── time_crate.rs
│ │ └── writer.rs
│ ├── layer
│ │ ├── context.rs
│ │ ├── layered.rs
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── lib.rs
│ ├── macros.rs
│ ├── prelude.rs
│ ├── registry
│ │ ├── extensions.rs
│ │ ├── mod.rs
│ │ ├── sharded.rs
│ │ └── stack.rs
│ ├── reload.rs
│ ├── sync.rs
│ └── util.rs
└── tests
│ ├── cached_layer_filters_dont_break_other_layers.rs
│ ├── duplicate_spans.rs
│ ├── env_filter
│ ├── main.rs
│ └── per_layer.rs
│ ├── event_enabling.rs
│ ├── field_filter.rs
│ ├── filter_log.rs
│ ├── fmt_max_level_hint.rs
│ ├── hinted_layer_filters_dont_break_other_layers.rs
│ ├── layer_filter_interests_are_cached.rs
│ ├── layer_filters
│ ├── boxed.rs
│ ├── combinators.rs
│ ├── downcast_raw.rs
│ ├── filter_scopes.rs
│ ├── main.rs
│ ├── option.rs
│ ├── per_event.rs
│ ├── targets.rs
│ ├── trees.rs
│ └── vec.rs
│ ├── multiple_layer_filter_interests_cached.rs
│ ├── option.rs
│ ├── option_filter_interest_caching.rs
│ ├── registry_max_level_hint.rs
│ ├── registry_with_subscriber.rs
│ ├── reload.rs
│ ├── reload_max_log_level.rs
│ ├── same_len_filters.rs
│ ├── unhinted_layer_filters_dont_break_other_layers.rs
│ ├── utils.rs
│ ├── vec.rs
│ └── vec_subscriber_filter_interests_cached.rs
├── tracing-test
├── Cargo.toml
├── LICENSE
├── README.md
└── src
│ └── lib.rs
├── tracing-tower
├── Cargo.toml
├── LICENSE
└── src
│ ├── http.rs
│ ├── lib.rs
│ ├── request_span.rs
│ └── service_span.rs
└── tracing
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── benches
├── baseline.rs
├── dispatch_get_clone.rs
├── dispatch_get_ref.rs
├── empty_span.rs
├── enter_span.rs
├── event.rs
├── shared.rs
├── span_fields.rs
├── span_no_fields.rs
└── span_repeated.rs
├── src
├── dispatcher.rs
├── field.rs
├── instrument.rs
├── level_filters.rs
├── lib.rs
├── macros.rs
├── span.rs
├── stdlib.rs
└── subscriber.rs
├── test-log-support
├── Cargo.toml
├── src
│ └── lib.rs
└── tests
│ ├── log_move_arg.rs
│ ├── log_no_trace.rs
│ ├── log_with_trace.rs
│ ├── span_activity_filtered_separately.rs
│ ├── span_lifecycle_can_be_enabled.rs
│ ├── span_lifecycle_defaults_off.rs
│ └── span_lifecycle_is_trace.rs
├── test_static_max_level_features
├── Cargo.toml
└── tests
│ └── test.rs
└── tests
├── enabled.rs
├── event.rs
├── filter_caching_is_lexically_scoped.rs
├── filters_are_not_reevaluated_for_the_same_span.rs
├── filters_are_reevaluated_for_different_call_sites.rs
├── filters_dont_leak.rs
├── future_send.rs
├── instrument.rs
├── macro_imports.rs
├── macros.rs
├── macros_incompatible_concat.rs
├── max_level_hint.rs
├── missed_register_callsite.rs
├── multiple_max_level_hints.rs
├── no_subscriber.rs
├── register_callsite_deadlock.rs
├── scoped_clobbers_default.rs
├── span.rs
└── subscriber.rs
/.cargo/audit.toml:
--------------------------------------------------------------------------------
1 | [advisories]
2 | ignore = [
3 | # Unmaintained advisory for the `net2` crate.
4 | #
5 | # We ignore this, because `net2` is a transitive dependency of older
6 | # versions of `mio`, which we depend on via `tokio` 0.1. `tokio` 0.1 won't
7 | # be updated, so as long as `tracing-futures` supports tokio 0.1, we can't
8 | # really get rid of the `net2` dependency.
9 | #
10 | # So, just ignore the warning. It only effects users who are using
11 | # compatibility features for *other* unmaintained libraries, anyway.
12 | #
13 | # TODO: when `tracing-futures` drops support for `tokio` 0.1, we can remove
14 | # the `ignore` for this warning, as we will no longer pull `net2`.
15 | "RUSTSEC-2020-0016"
16 | ]
--------------------------------------------------------------------------------
/.config/nextest.toml:
--------------------------------------------------------------------------------
1 | # recommended nextest profile for CI jobs (from
2 | # https://nexte.st/book/configuration.html#profiles)
3 | [profile.ci]
4 | # Print out output for failing tests as soon as they fail, and also at the end
5 | # of the run (for easy scrollability).
6 | failure-output = "immediate-final"
7 | # Do not cancel the test run on the first failure.
8 | fail-fast = false
9 |
10 | # TODO(eliza): uncomment this when we can get nicer JUnit output from nextest...
11 | # [profile.ci.junit]
12 | # path = "junit.xml"
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Eliza should review everything unassigned.
2 | * @hawkw @tokio-rs/tracing
3 |
4 | # tracing-error and tracing-flame were contributed by Jane.
5 | /tracing-error/ @yaahc @tokio-rs/tracing
6 | /tracing-flame/ @yaahc @tokio-rs/tracing
7 |
8 | # David contributed the Registry implementation.
9 | /tracing-subscriber/registry @davidbarsky @hawkw @tokio-rs/tracing
10 |
11 | # Zeki contributed the TracingAppender implementation
12 | /tracing-appender/ @zekisherif @tokio-rs/tracing
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐛 Bug Report
3 | about: If something isn't working as expected 🤔.
4 |
5 | ---
6 |
7 | ## Bug Report
8 |
13 |
14 | ### Version
15 |
16 |
27 |
28 | ### Platform
29 |
30 |
33 |
34 | ### Crates
35 |
36 |
40 |
41 | ### Description
42 |
43 |
59 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 💡 Feature Request
3 | about: I have a suggestion (and may want to implement it 🙂)!
4 |
5 | ---
6 |
7 | ## Feature Request
8 |
9 | ### Crates
10 |
11 |
15 |
16 | ### Motivation
17 |
18 |
21 |
22 | ### Proposal
23 |
24 |
28 |
29 | ### Alternatives
30 |
31 |
36 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
9 |
10 | ## Motivation
11 |
12 |
17 |
18 | ## Solution
19 |
20 |
24 |
--------------------------------------------------------------------------------
/.github/labeler.yml:
--------------------------------------------------------------------------------
1 | crate/tracing: tracing/**
2 | crate/core: tracing-core/**
3 | crate/proc-macros:
4 | - tracing-attributes/**
5 | - tracing-macros/**
6 | crate/futures: tracing-futures/**
7 | crate/log: tracing-log/**
8 | crate/subscriber: tracing-subscriber/**
9 | kind/docs: README.md
10 |
--------------------------------------------------------------------------------
/.github/workflows/audit.yml:
--------------------------------------------------------------------------------
1 | name: Security audit
2 |
3 | on:
4 | schedule:
5 | - cron: '0 0 * * *'
6 |
7 | env:
8 | # Disable incremental compilation.
9 | #
10 | # Incremental compilation is useful as part of an edit-build-test-edit cycle,
11 | # as it lets the compiler avoid recompiling code that hasn't changed. However,
12 | # on CI, we're not making small edits; we're almost always building the entire
13 | # project from scratch. Thus, incremental compilation on CI actually
14 | # introduces *additional* overhead to support making future builds
15 | # faster...but no future builds will ever occur in any given CI environment.
16 | #
17 | # See https://matklad.github.io/2021/09/04/fast-rust-builds.html#ci-workflow
18 | # for details.
19 | CARGO_INCREMENTAL: 0
20 | # Allow more retries for network requests in cargo (downloading crates) and
21 | # rustup (installing toolchains). This should help to reduce flaky CI failures
22 | # from transient network timeouts or other issues.
23 | CARGO_NET_RETRY: 10
24 | RUSTUP_MAX_RETRIES: 10
25 | # Don't emit giant backtraces in the CI logs.
26 | RUST_BACKTRACE: short
27 |
28 | jobs:
29 | security_audit:
30 | runs-on: ubuntu-latest
31 | steps:
32 | - uses: actions/checkout@v4
33 | - uses: actions-rs/audit-check@v1
34 | with:
35 | token: ${{ secrets.GITHUB_TOKEN }}
36 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - tracing-[0-9]+.*
7 | - tracing-[a-z]+-[0-9]+.*
8 |
9 | jobs:
10 | create-release:
11 | name: Create GitHub release
12 | # only publish from the origin repository
13 | if: github.repository_owner == 'tokio-rs'
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | - uses: taiki-e/create-gh-release-action@v1
18 | with:
19 | prefix: tracing(-[a-z]+)?
20 | changelog: "$prefix/CHANGELOG.md"
21 | title: "$prefix $version"
22 | branch: main
23 | env:
24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/rust,macos,visualstudiocode
3 |
4 | ### macOS ###
5 | # General
6 | .DS_Store
7 | .AppleDouble
8 | .LSOverride
9 |
10 | # Icon must end with two \r
11 | Icon
12 |
13 | # Thumbnails
14 | ._*
15 |
16 | # Files that might appear in the root of a volume
17 | .DocumentRevisions-V100
18 | .fseventsd
19 | .Spotlight-V100
20 | .TemporaryItems
21 | .Trashes
22 | .VolumeIcon.icns
23 | .com.apple.timemachine.donotpresent
24 |
25 | # Directories potentially created on remote AFP share
26 | .AppleDB
27 | .AppleDesktop
28 | Network Trash Folder
29 | Temporary Items
30 | .apdisk
31 |
32 | ### Rust ###
33 | # Generated by Cargo
34 | # will have compiled files and executables
35 | target/
36 |
37 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
38 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
39 | Cargo.lock
40 |
41 | # These are backup files generated by rustfmt
42 | **/*.rs.bk
43 |
44 | ### VisualStudioCode ###
45 | .vscode/*
46 | !.vscode/settings.json
47 | !.vscode/tasks.json
48 | !.vscode/launch.json
49 | !.vscode/extensions.json
50 |
51 |
52 | # End of https://www.gitignore.io/api/rust,macos,visualstudiocode
53 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = [
4 | "tracing",
5 | "tracing-core",
6 | "tracing-attributes",
7 | "tracing-error",
8 | "tracing-flame",
9 | "tracing-futures",
10 | "tracing-tower",
11 | "tracing-log",
12 | "tracing-macros",
13 | "tracing-mock",
14 | "tracing-subscriber",
15 | "tracing-serde",
16 | "tracing-test",
17 | "tracing-appender",
18 | "tracing-journald",
19 | "examples"
20 | ]
21 |
22 | # This will be ignored with Rust older than 1.74, but for now that's okay;
23 | # we're only using it to fix check-cfg issues that first appeared in Rust 1.80.
24 | [workspace.lints.rust]
25 | unexpected_cfgs = { level = "warn", check-cfg = ["cfg(flaky_tests)", "cfg(tracing_unstable)", "cfg(unsound_local_offset)"] }
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | Tracing is part of the Tokio project and uses the same security policy as [Tokio][tokio-security].
4 |
5 | ## Report a security issue
6 |
7 | The process for reporting an issue is the same as for [Tokio][tokio-security]. This includes private reporting via security@tokio.rs.
8 |
9 | [tokio-security]: https://github.com/tokio-rs/tokio/security/policy
10 |
--------------------------------------------------------------------------------
/assets/logo-type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tokio-rs/tracing/e4df76127538aa8370d7dee32a6f84bbec6bbf10/assets/logo-type.png
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/clippy.toml:
--------------------------------------------------------------------------------
1 | disallowed-names = []
2 | cognitive-complexity-threshold = 100
3 | too-many-arguments-threshold = 8
4 | type-complexity-threshold = 375
5 |
--------------------------------------------------------------------------------
/examples/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-examples"
3 | version = "0.0.0"
4 | publish = false
5 | edition = "2018"
6 | rust-version = "1.64.0"
7 |
8 | [features]
9 | default = []
10 |
11 | [dev-dependencies]
12 |
13 | # tracing crates
14 | tracing = { path = "../tracing", version = "0.1.35" }
15 | tracing-core = { path = "../tracing-core", version = "0.1.28" }
16 | tracing-error = { path = "../tracing-error" }
17 | tracing-flame = { path = "../tracing-flame" }
18 | tracing-tower = { version = "0.1.0", path = "../tracing-tower" }
19 | tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", features = ["json", "env-filter"] }
20 | tracing-futures = { version = "0.2.1", path = "../tracing-futures", features = ["futures-01"] }
21 | tracing-attributes = { path = "../tracing-attributes", version = "0.1.22" }
22 | tracing-serde = { path = "../tracing-serde" }
23 | tracing-appender = { path = "../tracing-appender", version = "0.2.0" }
24 | tracing-journald = { path = "../tracing-journald" }
25 |
26 | # serde example
27 | serde_json = "1.0.82"
28 |
29 | futures = "0.3.21"
30 | tokio = { version = "1.20.1", features = ["full"] }
31 |
32 | # tower examples
33 | tower = { version = "0.4.13", features = ["full"] }
34 | http = "0.2.8"
35 | hyper = { version = "0.14.20", features = ["full"] }
36 | rand = "0.7.3"
37 | bytes = "1"
38 | argh = "0.1.8"
39 |
40 | # sloggish example
41 | nu-ansi-term = "0.50.0"
42 | humantime = "2.1.0"
43 | log = "0.4.17"
44 |
45 | # inferno example
46 | inferno = "0.11.6"
47 | tempfile = "3"
48 |
49 | # fmt examples
50 | snafu = "0.6.10"
51 | thiserror = "2"
52 |
53 | # env-filter-explorer example
54 | ansi-to-tui = "7.0.0"
55 | ratatui = "0.29.0"
56 | crossterm = "0.28.1"
57 | tui-textarea = "0.7.0"
58 |
59 | # valuable examples
60 | valuable = { version = "0.1.0", features = ["derive"] }
61 |
62 | [target.'cfg(tracing_unstable)'.dependencies]
63 | tracing-core = { path = "../tracing-core", version = "0.1.28", features = ["valuable"]}
64 | tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", features = ["json", "env-filter", "valuable"]}
65 |
66 | [lints]
67 | workspace = true
68 |
--------------------------------------------------------------------------------
/examples/examples/all-levels.rs:
--------------------------------------------------------------------------------
1 | use tracing::Level;
2 |
3 | fn main() {
4 | tracing_subscriber::fmt()
5 | // all spans/events with a level higher than TRACE (e.g, info, warn, etc.)
6 | // will be written to stdout.
7 | .with_max_level(Level::TRACE)
8 | // sets this to be the default, global subscriber for this application.
9 | .init();
10 |
11 | tracing::error!("SOMETHING IS SERIOUSLY WRONG!!!");
12 | tracing::warn!("important informational messages; might indicate an error");
13 | tracing::info!("general informational messages relevant to users");
14 | tracing::debug!("diagnostics used for internal debugging of a library or application");
15 | tracing::trace!("very verbose diagnostic events");
16 | }
17 |
--------------------------------------------------------------------------------
/examples/examples/appender-multifile.rs:
--------------------------------------------------------------------------------
1 | //! This example demonstrates the use of multiple files with
2 | //! `tracing-appender`'s `RollingFileAppender`
3 | //!
4 | use tracing_appender::rolling;
5 | use tracing_subscriber::fmt::writer::MakeWriterExt;
6 |
7 | #[path = "fmt/yak_shave.rs"]
8 | mod yak_shave;
9 |
10 | fn main() {
11 | // Log all `tracing` events to files prefixed with `debug`. Since these
12 | // files will be written to very frequently, roll the log file every minute.
13 | let debug_file = rolling::minutely("./logs", "debug");
14 | // Log warnings and errors to a separate file. Since we expect these events
15 | // to occur less frequently, roll that file on a daily basis instead.
16 | let warn_file = rolling::daily("./logs", "warnings").with_max_level(tracing::Level::WARN);
17 | let all_files = debug_file.and(warn_file);
18 |
19 | tracing_subscriber::fmt()
20 | .with_writer(all_files)
21 | .with_ansi(false)
22 | .with_max_level(tracing::Level::TRACE)
23 | .init();
24 |
25 | yak_shave::shave_all(6);
26 | tracing::info!("sleeping for a minute...");
27 |
28 | std::thread::sleep(std::time::Duration::from_secs(60));
29 |
30 | tracing::info!("okay, time to shave some more yaks!");
31 | yak_shave::shave_all(10);
32 | }
33 |
--------------------------------------------------------------------------------
/examples/examples/async-fn.rs:
--------------------------------------------------------------------------------
1 | //! Demonstrates using the `trace` attribute macro to instrument `async`
2 | //! functions.
3 | //!
4 | //! This is based on the [`hello_world`] example from `tokio`. and implements a
5 | //! simple client that opens a TCP stream, writes "hello world\n", and closes
6 | //! the connection.
7 | //!
8 | //! You can test this out by running:
9 | //!
10 | //! ncat -l 6142
11 | //!
12 | //! And then in another terminal run:
13 | //!
14 | //! cargo +nightly run --example async_fn
15 | //!
16 | //! [`hello_world`]: https://github.com/tokio-rs/tokio/blob/132e9f1da5965530b63554d7a1c59824c3de4e30/tokio/examples/hello_world.rs
17 | #![deny(rust_2018_idioms)]
18 |
19 | use tokio::io::AsyncWriteExt;
20 | use tokio::net::TcpStream;
21 |
22 | use tracing::info;
23 | use tracing_attributes::instrument;
24 |
25 | use std::{error::Error, io, net::SocketAddr};
26 |
27 | #[instrument]
28 | async fn connect(addr: &SocketAddr) -> io::Result {
29 | let stream = TcpStream::connect(&addr).await;
30 | tracing::info!("created stream");
31 | stream
32 | }
33 |
34 | #[instrument]
35 | async fn write(stream: &mut TcpStream) -> io::Result {
36 | let result = stream.write(b"hello world\n").await;
37 | info!("wrote to stream; success={:?}", result.is_ok());
38 | result
39 | }
40 |
41 | #[tokio::main]
42 | pub async fn main() -> Result<(), Box> {
43 | let addr = "127.0.0.1:6142".parse()?;
44 |
45 | tracing_subscriber::fmt()
46 | .with_env_filter("async_fn=trace")
47 | .try_init()?;
48 |
49 | // Open a TCP stream to the socket address.
50 | //
51 | // Note that this is the Tokio TcpStream, which is fully async.
52 | let mut stream = connect(&addr).await?;
53 |
54 | write(&mut stream).await?;
55 |
56 | Ok(())
57 | }
58 |
--------------------------------------------------------------------------------
/examples/examples/attrs-args.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 |
3 | use tracing::{debug, info};
4 | use tracing_attributes::instrument;
5 |
6 | #[instrument]
7 | fn nth_fibonacci(n: u64) -> u64 {
8 | if n == 0 || n == 1 {
9 | debug!("Base case");
10 | 1
11 | } else {
12 | debug!("Recursing");
13 | nth_fibonacci(n - 1) + nth_fibonacci(n - 2)
14 | }
15 | }
16 |
17 | #[instrument]
18 | fn fibonacci_seq(to: u64) -> Vec {
19 | let mut sequence = vec![];
20 |
21 | for n in 0..=to {
22 | debug!("Pushing {n} fibonacci", n = n);
23 | sequence.push(nth_fibonacci(n));
24 | }
25 |
26 | sequence
27 | }
28 |
29 | fn main() {
30 | let subscriber = tracing_subscriber::fmt()
31 | .with_env_filter("attrs_args=trace")
32 | .finish();
33 |
34 | tracing::subscriber::with_default(subscriber, || {
35 | let n = 5;
36 | let sequence = fibonacci_seq(n);
37 | info!("The first {} fibonacci numbers are {:?}", n, sequence);
38 | })
39 | }
40 |
--------------------------------------------------------------------------------
/examples/examples/attrs-basic.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 |
3 | use tracing::{debug, info, span, Level};
4 | use tracing_attributes::instrument;
5 |
6 | #[instrument]
7 | #[inline]
8 | fn suggest_band() -> String {
9 | debug!("Suggesting a band.");
10 | String::from("Wild Pink")
11 | }
12 |
13 | fn main() {
14 | let subscriber = tracing_subscriber::fmt()
15 | .with_env_filter("attrs_basic=trace")
16 | .finish();
17 | tracing::subscriber::with_default(subscriber, || {
18 | let num_recs = 1;
19 |
20 | let span = span!(Level::TRACE, "get_band_rec", ?num_recs);
21 | let _enter = span.enter();
22 | let band = suggest_band();
23 | info!(message = "Got a recommendation!", %band);
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/examples/examples/attrs-literal-field-names.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 |
3 | use tracing::{debug, span, Level};
4 | use tracing_attributes::instrument;
5 |
6 | #[instrument]
7 | #[inline]
8 | fn suggest_band() -> String {
9 | debug!("Suggesting a band.");
10 | String::from("Wild Pink")
11 | }
12 |
13 | fn main() {
14 | let subscriber = tracing_subscriber::fmt()
15 | .with_env_filter("attrs_literal_field_names=trace")
16 | .finish();
17 | tracing::subscriber::with_default(subscriber, || {
18 | let span = span!(Level::TRACE, "get_band_rec", "guid:x-request-id" = "abcdef");
19 | let _enter = span.enter();
20 | suggest_band();
21 | });
22 | }
23 |
--------------------------------------------------------------------------------
/examples/examples/custom-error.rs:
--------------------------------------------------------------------------------
1 | //! This example demonstrates using the `tracing-error` crate's `SpanTrace` type
2 | //! to attach a trace context to a custom error type.
3 | #![deny(rust_2018_idioms)]
4 | use std::error::Error;
5 | use std::fmt;
6 | use tracing_error::{ErrorLayer, SpanTrace};
7 | use tracing_subscriber::prelude::*;
8 | #[derive(Debug)]
9 | struct FooError {
10 | message: &'static str,
11 | // This struct captures the current `tracing` span context when it is
12 | // constructed. Later, when we display this error, we will format this
13 | // captured span trace.
14 | context: SpanTrace,
15 | }
16 |
17 | impl FooError {
18 | fn new(message: &'static str) -> Self {
19 | Self {
20 | message,
21 | context: SpanTrace::capture(),
22 | }
23 | }
24 | }
25 |
26 | impl Error for FooError {}
27 |
28 | impl fmt::Display for FooError {
29 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 | f.pad(self.message)?;
31 | write!(f, "\n\nspan backtrace:\n{}", self.context)?;
32 | write!(f, "\n\ndebug span backtrace: {:?}", self.context)?;
33 | write!(f, "\n\nalt debug span backtrace: {:#?}", self.context)?;
34 | Ok(())
35 | }
36 | }
37 |
38 | #[tracing::instrument]
39 | fn do_something(foo: &str) -> Result<&'static str, impl Error + Send + Sync + 'static> {
40 | do_another_thing(42, false)
41 | }
42 |
43 | #[tracing::instrument]
44 | fn do_another_thing(
45 | answer: usize,
46 | will_succeed: bool,
47 | ) -> Result<&'static str, impl Error + Send + Sync + 'static> {
48 | Err(FooError::new("something broke, lol"))
49 | }
50 |
51 | #[tracing::instrument]
52 | fn main() {
53 | tracing_subscriber::registry()
54 | .with(tracing_subscriber::fmt::layer())
55 | // The `ErrorLayer` subscriber layer enables the use of `SpanTrace`.
56 | .with(ErrorLayer::default())
57 | .init();
58 | match do_something("hello world") {
59 | Ok(result) => println!("did something successfully: {}", result),
60 | Err(e) => eprintln!("error: {}", e),
61 | };
62 | }
63 |
--------------------------------------------------------------------------------
/examples/examples/fmt-compact.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | #[path = "fmt/yak_shave.rs"]
3 | mod yak_shave;
4 |
5 | fn main() {
6 | tracing_subscriber::fmt()
7 | .compact()
8 | // enable everything
9 | .with_max_level(tracing::Level::TRACE)
10 | // sets this to be the default, global subscriber for this application.
11 | .init();
12 |
13 | let number_of_yaks = 3;
14 | // this creates a new event, outside of any spans.
15 | tracing::info!(number_of_yaks, "preparing to shave yaks");
16 |
17 | let number_shaved = yak_shave::shave_all(number_of_yaks);
18 | tracing::info!(
19 | all_yaks_shaved = number_shaved == number_of_yaks,
20 | "yak shaving completed"
21 | );
22 | }
23 |
--------------------------------------------------------------------------------
/examples/examples/fmt-custom-event.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | #[path = "fmt/yak_shave.rs"]
3 | mod yak_shave;
4 |
5 | fn main() {
6 | use tracing_subscriber::fmt;
7 |
8 | // Configure a custom event formatter
9 | let format = fmt::format()
10 | .compact() // use an abbreviated format for logging spans
11 | .with_level(false) // don't include levels in formatted output
12 | .with_target(false); // don't include targets
13 |
14 | // Create a `fmt` subscriber that uses our custom event format, and set it
15 | // as the default.
16 | tracing_subscriber::fmt().event_format(format).init();
17 |
18 | // Shave some yaks!
19 | let number_of_yaks = 3;
20 | // this creates a new event, outside of any spans.
21 | tracing::info!(number_of_yaks, "preparing to shave yaks");
22 |
23 | let number_shaved = yak_shave::shave_all(number_of_yaks);
24 | tracing::info!(
25 | all_yaks_shaved = number_shaved == number_of_yaks,
26 | "yak shaving completed."
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/examples/examples/fmt-custom-field.rs:
--------------------------------------------------------------------------------
1 | //! This example demonstrates overriding the way `tracing-subscriber`'s
2 | //! `FmtSubscriber` formats fields on spans and events, using a closure.
3 | //!
4 | //! We'll create a custom format that prints key-value pairs separated by
5 | //! colons rather than equals signs, and separates fields with commas.
6 | //!
7 | //! For an event like
8 | //! ```rust
9 | //! tracing::info!(hello = "world", answer = 42);
10 | //! ```
11 | //!
12 | //! the default formatter will format the fields like this:
13 | //! ```not_rust
14 | //! hello="world" answer=42
15 | //! ```
16 | //! while our custom formatter will output
17 | //! ```not_rust
18 | //! hello: "world", answer: 42
19 | //! ```
20 | #![deny(rust_2018_idioms)]
21 |
22 | #[path = "fmt/yak_shave.rs"]
23 | mod yak_shave;
24 |
25 | fn main() {
26 | use tracing_subscriber::{fmt::format, prelude::*};
27 |
28 | // Format fields using the provided closure.
29 | let format = format::debug_fn(|writer, field, value| {
30 | // We'll format the field name and value separated with a colon.
31 | write!(writer, "{}: {:?}", field, value)
32 | })
33 | // Separate each field with a comma.
34 | // This method is provided by an extension trait in the
35 | // `tracing-subscriber` prelude.
36 | .delimited(", ");
37 |
38 | // Create a `fmt` subscriber that uses our custom event format, and set it
39 | // as the default.
40 | tracing_subscriber::fmt().fmt_fields(format).init();
41 |
42 | // Shave some yaks!
43 | let number_of_yaks = 3;
44 | // this creates a new event, outside of any spans.
45 | tracing::info!(number_of_yaks, "preparing to shave yaks");
46 |
47 | let number_shaved = yak_shave::shave_all(number_of_yaks);
48 | tracing::info!(
49 | all_yaks_shaved = number_shaved == number_of_yaks,
50 | "yak shaving completed."
51 | );
52 | }
53 |
--------------------------------------------------------------------------------
/examples/examples/fmt-json.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | #[path = "fmt/yak_shave.rs"]
3 | mod yak_shave;
4 |
5 | fn main() {
6 | tracing_subscriber::fmt()
7 | .json()
8 | .with_max_level(tracing::Level::TRACE)
9 | .with_current_span(false)
10 | .init();
11 |
12 | let number_of_yaks = 3;
13 | // this creates a new event, outside of any spans.
14 | tracing::info!(number_of_yaks, "preparing to shave yaks");
15 |
16 | let number_shaved = yak_shave::shave_all(number_of_yaks);
17 | tracing::info!(
18 | all_yaks_shaved = number_shaved == number_of_yaks,
19 | "yak shaving completed"
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/examples/examples/fmt-multiple-writers.rs:
--------------------------------------------------------------------------------
1 | //! An example demonstrating how `fmt::Layer` can write to multiple
2 | //! destinations (in this instance, `stdout` and a file) simultaneously.
3 |
4 | #[path = "fmt/yak_shave.rs"]
5 | mod yak_shave;
6 |
7 | use std::io;
8 | use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter};
9 |
10 | fn main() {
11 | let dir = tempfile::tempdir().expect("Failed to create tempdir");
12 |
13 | let file_appender = tracing_appender::rolling::hourly(dir, "example.log");
14 | let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
15 |
16 | let subscriber = tracing_subscriber::registry()
17 | .with(EnvFilter::from_default_env().add_directive(tracing::Level::TRACE.into()))
18 | .with(fmt::Layer::new().with_writer(io::stdout))
19 | .with(fmt::Layer::new().with_writer(non_blocking));
20 | tracing::subscriber::set_global_default(subscriber).expect("Unable to set a global subscriber");
21 |
22 | let number_of_yaks = 3;
23 | // this creates a new event, outside of any spans.
24 | tracing::info!(number_of_yaks, "preparing to shave yaks");
25 |
26 | let number_shaved = yak_shave::shave_all(number_of_yaks);
27 | tracing::info!(
28 | all_yaks_shaved = number_shaved == number_of_yaks,
29 | "yak shaving completed."
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/examples/examples/fmt-pretty.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | #[path = "fmt/yak_shave.rs"]
3 | mod yak_shave;
4 |
5 | fn main() {
6 | tracing_subscriber::fmt()
7 | .pretty()
8 | .with_thread_names(true)
9 | // enable everything
10 | .with_max_level(tracing::Level::TRACE)
11 | // sets this to be the default, global subscriber for this application.
12 | .init();
13 |
14 | let number_of_yaks = 3;
15 | // this creates a new event, outside of any spans.
16 | tracing::info!(number_of_yaks, "preparing to shave yaks");
17 |
18 | let number_shaved = yak_shave::shave_all(number_of_yaks);
19 | tracing::info!(
20 | all_yaks_shaved = number_shaved == number_of_yaks,
21 | "yak shaving completed"
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/examples/examples/fmt-source-locations.rs:
--------------------------------------------------------------------------------
1 | //! Demonstrates displaying events' source code locations with the `fmt`
2 | //! subscriber.
3 | #![deny(rust_2018_idioms)]
4 | #[path = "fmt/yak_shave.rs"]
5 | mod yak_shave;
6 |
7 | fn main() {
8 | tracing_subscriber::fmt()
9 | // enable everything
10 | .with_max_level(tracing::Level::TRACE)
11 | // display source code file paths
12 | .with_file(true)
13 | // display source code line numbers
14 | .with_line_number(true)
15 | // disable targets
16 | .with_target(false)
17 | // sets this to be the default, global subscriber for this application.
18 | .init();
19 |
20 | let number_of_yaks = 3;
21 | // this creates a new event, outside of any spans.
22 | tracing::info!(number_of_yaks, "preparing to shave yaks");
23 |
24 | let number_shaved = yak_shave::shave_all(number_of_yaks);
25 | tracing::info!(
26 | all_yaks_shaved = number_shaved == number_of_yaks,
27 | "yak shaving completed."
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/examples/examples/fmt-stderr.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | use std::io;
3 | use tracing::error;
4 |
5 | fn main() {
6 | let subscriber = tracing_subscriber::fmt().with_writer(io::stderr).finish();
7 |
8 | tracing::subscriber::with_default(subscriber, || {
9 | error!("This event will be printed to `stderr`.");
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/examples/examples/fmt.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | #[path = "fmt/yak_shave.rs"]
3 | mod yak_shave;
4 |
5 | fn main() {
6 | tracing_subscriber::fmt()
7 | // enable everything
8 | .with_max_level(tracing::Level::TRACE)
9 | // sets this to be the default, global subscriber for this application.
10 | .init();
11 |
12 | let number_of_yaks = 3;
13 | // this creates a new event, outside of any spans.
14 | tracing::info!(number_of_yaks, "preparing to shave yaks");
15 |
16 | let number_shaved = yak_shave::shave_all(number_of_yaks);
17 | tracing::info!(
18 | all_yaks_shaved = number_shaved == number_of_yaks,
19 | "yak shaving completed."
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/examples/examples/inferno-flame.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | env,
3 | fs::File,
4 | io::{BufReader, BufWriter},
5 | path::{Path, PathBuf},
6 | thread::sleep,
7 | time::Duration,
8 | };
9 | use tracing::{span, Level};
10 | use tracing_flame::FlameLayer;
11 | use tracing_subscriber::{prelude::*, registry::Registry};
12 |
13 | static PATH: &str = "flame.folded";
14 |
15 | fn setup_global_subscriber(dir: &Path) -> impl Drop {
16 | let (flame_layer, _guard) = FlameLayer::with_file(dir.join(PATH)).unwrap();
17 |
18 | let subscriber = Registry::default().with(flame_layer);
19 |
20 | tracing::subscriber::set_global_default(subscriber).unwrap();
21 |
22 | _guard
23 | }
24 |
25 | fn make_flamegraph(tmpdir: &Path, out: &Path) {
26 | println!("outputting flamegraph to {}", out.display());
27 | let inf = File::open(tmpdir.join(PATH)).unwrap();
28 | let reader = BufReader::new(inf);
29 |
30 | let out = File::create(out).unwrap();
31 | let writer = BufWriter::new(out);
32 |
33 | let mut opts = inferno::flamegraph::Options::default();
34 | inferno::flamegraph::from_reader(&mut opts, reader, writer).unwrap();
35 | }
36 |
37 | fn main() {
38 | let out = if let Some(arg) = env::args().nth(1) {
39 | PathBuf::from(arg)
40 | } else {
41 | let mut path = env::current_dir().expect("failed to read current directory");
42 | path.push("tracing-flame-inferno.svg");
43 | path
44 | };
45 |
46 | // setup the flame layer
47 | let tmp_dir = tempfile::Builder::new()
48 | .prefix("flamegraphs")
49 | .tempdir()
50 | .expect("failed to create temporary directory");
51 | let guard = setup_global_subscriber(tmp_dir.path());
52 |
53 | // do a bunch of span entering and exiting to simulate a program running
54 | span!(Level::ERROR, "outer").in_scope(|| {
55 | sleep(Duration::from_millis(10));
56 | span!(Level::ERROR, "Inner").in_scope(|| {
57 | sleep(Duration::from_millis(50));
58 | span!(Level::ERROR, "Innermost").in_scope(|| {
59 | sleep(Duration::from_millis(50));
60 | });
61 | });
62 | sleep(Duration::from_millis(5));
63 | });
64 | sleep(Duration::from_millis(500));
65 |
66 | // drop the guard to make sure the layer flushes its output then read the
67 | // output to create the flamegraph
68 | drop(guard);
69 | make_flamegraph(tmp_dir.path(), out.as_ref());
70 | }
71 |
--------------------------------------------------------------------------------
/examples/examples/journald.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | use tracing::{error, info};
3 | use tracing_subscriber::prelude::*;
4 |
5 | #[path = "fmt/yak_shave.rs"]
6 | mod yak_shave;
7 |
8 | fn main() {
9 | let registry =
10 | tracing_subscriber::registry().with(tracing_subscriber::fmt::layer().with_target(false));
11 | match tracing_journald::layer() {
12 | Ok(layer) => {
13 | registry.with(layer).init();
14 | }
15 | // journald is typically available on Linux systems, but nowhere else. Portable software
16 | // should handle its absence gracefully.
17 | Err(e) => {
18 | registry.init();
19 | error!("couldn't connect to journald: {}", e);
20 | }
21 | }
22 |
23 | let number_of_yaks = 3;
24 | // this creates a new event, outside of any spans.
25 | info!(number_of_yaks, "preparing to shave yaks");
26 |
27 | let number_shaved = yak_shave::shave_all(number_of_yaks);
28 | info!(
29 | all_yaks_shaved = number_shaved == number_of_yaks,
30 | "yak shaving completed."
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/examples/examples/log.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | tracing_subscriber::fmt()
3 | .with_max_level(tracing::Level::TRACE)
4 | .init();
5 |
6 | log::debug!("this is a log line");
7 | tracing::debug!("this is a tracing line");
8 | }
9 |
--------------------------------------------------------------------------------
/examples/examples/panic_hook.rs:
--------------------------------------------------------------------------------
1 | //! This example demonstrates how `tracing` events can be recorded from within a
2 | //! panic hook, capturing the span context in which the program panicked.
3 | //!
4 | //! A custom panic hook can also be used to record panics that are captured
5 | //! using `catch_unwind`, such as when Tokio catches panics in spawned async
6 | //! tasks. See the `tokio_panic_hook.rs` example for an example of this.
7 |
8 | fn main() {
9 | let subscriber = tracing_subscriber::fmt()
10 | .with_max_level(tracing::Level::TRACE)
11 | .finish();
12 |
13 | // NOTE: Using `tracing` in a panic hook requires the use of the *global*
14 | // trace dispatcher (`tracing::subscriber::set_global_default`), rather than
15 | // the per-thread scoped dispatcher
16 | // (`tracing::subscriber::with_default`/`set_default`). With the scoped trace
17 | // dispatcher, the subscriber's thread-local context may already have been
18 | // torn down by unwinding by the time the panic handler is reached.
19 | tracing::subscriber::set_global_default(subscriber).unwrap();
20 |
21 | // Set a panic hook that records the panic as a `tracing` event at the
22 | // `ERROR` verbosity level.
23 | //
24 | // If we are currently in a span when the panic occurred, the logged event
25 | // will include the current span, allowing the context in which the panic
26 | // occurred to be recorded.
27 | std::panic::set_hook(Box::new(|panic| {
28 | // If the panic has a source location, record it as structured fields.
29 | if let Some(location) = panic.location() {
30 | // On nightly Rust, where the `PanicInfo` type also exposes a
31 | // `message()` method returning just the message, we could record
32 | // just the message instead of the entire `fmt::Display`
33 | // implementation, avoiding the duplicated location
34 | tracing::error!(
35 | message = %panic,
36 | panic.file = location.file(),
37 | panic.line = location.line(),
38 | panic.column = location.column(),
39 | );
40 | } else {
41 | tracing::error!(message = %panic);
42 | }
43 | }));
44 |
45 | for i in 0..10 {
46 | check_number(i);
47 | }
48 | }
49 |
50 | #[tracing::instrument]
51 | fn check_number(x: i32) {
52 | if x % 2 == 0 {
53 | panic!("I don't work with even numbers!");
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/examples/examples/sloggish/main.rs:
--------------------------------------------------------------------------------
1 | //! A simple example demonstrating how one might implement a custom
2 | //! subscriber.
3 | //!
4 | //! This subscriber implements a tree-structured logger similar to
5 | //! the "compact" formatter in [`slog-term`]. The demo mimics the
6 | //! example output in the screenshot in the [`slog` README].
7 | //!
8 | //! Note that this logger isn't ready for actual production use.
9 | //! Several corners were cut to make the example simple.
10 | //!
11 | //! [`slog-term`]: https://docs.rs/slog-term/2.4.0/slog_term/
12 | //! [`slog` README]: https://github.com/slog-rs/slog#terminal-output-example
13 | #![deny(rust_2018_idioms)]
14 |
15 | use tracing::{debug, info, span, warn, Level};
16 |
17 | mod sloggish_subscriber;
18 | use self::sloggish_subscriber::SloggishSubscriber;
19 |
20 | fn main() {
21 | let subscriber = SloggishSubscriber::new(2);
22 | tracing::subscriber::set_global_default(subscriber).unwrap();
23 |
24 | let app_span = span!(Level::TRACE, "", version = %5.0);
25 | let _e = app_span.enter();
26 |
27 | let server_span = span!(Level::TRACE, "server", host = "localhost", port = 8080);
28 | let _e2 = server_span.enter();
29 | info!("starting");
30 | info!("listening");
31 | let peer1 = span!(Level::TRACE, "conn", peer_addr = "82.9.9.9", port = 42381);
32 | peer1.in_scope(|| {
33 | debug!("connected");
34 | debug!(length = 2, "message received");
35 | });
36 | let peer2 = span!(Level::TRACE, "conn", peer_addr = "8.8.8.8", port = 18230);
37 | peer2.in_scope(|| {
38 | debug!("connected");
39 | });
40 | peer1.in_scope(|| {
41 | warn!(algo = "xor", "weak encryption requested");
42 | debug!(length = 8, "response sent");
43 | debug!("disconnected");
44 | });
45 | peer2.in_scope(|| {
46 | debug!(length = 5, "message received");
47 | debug!(length = 8, "response sent");
48 | debug!("disconnected");
49 | });
50 | warn!("internal error");
51 | info!("exit");
52 | }
53 |
--------------------------------------------------------------------------------
/examples/examples/spawny-thing.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 |
3 | /// This is a example showing how information is scoped.
4 | ///
5 | /// You can run this example by running the following command in a terminal
6 | ///
7 | /// ```
8 | /// cargo run --example spawny_thing
9 | /// ```
10 | use futures::future::join_all;
11 | use std::error::Error;
12 | use tracing::{debug, info};
13 | use tracing_attributes::instrument;
14 |
15 | #[instrument]
16 | async fn parent_task(subtasks: usize) {
17 | info!("spawning subtasks...");
18 | let subtasks = (1..=subtasks)
19 | .map(|number| {
20 | debug!(message = "creating subtask;", number);
21 | subtask(number)
22 | })
23 | .collect::>();
24 |
25 | let result = join_all(subtasks).await;
26 |
27 | debug!("all subtasks completed");
28 | let sum: usize = result.into_iter().sum();
29 | info!(sum);
30 | }
31 |
32 | #[instrument]
33 | async fn subtask(number: usize) -> usize {
34 | info!("polling subtask...");
35 | number
36 | }
37 |
38 | #[tokio::main]
39 | async fn main() -> Result<(), Box> {
40 | tracing_subscriber::fmt()
41 | .with_max_level(tracing::Level::DEBUG)
42 | .try_init()?;
43 | parent_task(10).await;
44 | Ok(())
45 | }
46 |
--------------------------------------------------------------------------------
/examples/examples/subscriber-filter.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | #[path = "fmt/yak_shave.rs"]
3 | mod yak_shave;
4 |
5 | fn main() {
6 | use tracing_subscriber::{fmt, EnvFilter};
7 |
8 | let subscriber = fmt::Subscriber::builder()
9 | .with_env_filter(EnvFilter::from_default_env())
10 | .finish();
11 |
12 | tracing::subscriber::with_default(subscriber, || {
13 | let number_of_yaks = 3;
14 | tracing::debug!("preparing to shave {} yaks", number_of_yaks);
15 |
16 | let number_shaved = yak_shave::shave_all(number_of_yaks);
17 |
18 | tracing::debug!(
19 | message = "yak shaving completed.",
20 | all_yaks_shaved = number_shaved == number_of_yaks,
21 | );
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/examples/examples/thread-info.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | /// This is a example showing how thread info can be displayed when
3 | /// formatting events with `tracing_subscriber::fmt`. This is useful
4 | /// as `tracing` spans can be entered by multicple threads concurrently,
5 | /// or move across threads freely.
6 | ///
7 | /// You can run this example by running the following command in a terminal
8 | ///
9 | /// ```
10 | /// cargo run --example thread-info
11 | /// ```
12 | ///
13 | /// Example output:
14 | ///
15 | /// ```not_rust
16 | /// Jul 17 00:38:07.177 INFO ThreadId(02) thread_info: i=9
17 | /// Jul 17 00:38:07.177 INFO thread 1 ThreadId(03) thread_info: i=9
18 | /// Jul 17 00:38:07.177 INFO large name thread 2 ThreadId(04) thread_info: i=9
19 | /// ```
20 | use std::thread;
21 | use std::time::Duration;
22 | use tracing::info;
23 |
24 | fn main() {
25 | tracing_subscriber::fmt()
26 | .with_max_level(tracing::Level::DEBUG)
27 | // enable thread id to be emitted
28 | .with_thread_ids(true)
29 | // enabled thread name to be emitted
30 | .with_thread_names(true)
31 | .init();
32 |
33 | let do_work = || {
34 | for i in 1..10 {
35 | info!(i);
36 | thread::sleep(Duration::from_millis(1));
37 | }
38 | };
39 |
40 | let thread_with_no_name = thread::spawn(do_work);
41 | let thread_one = thread::Builder::new()
42 | .name("thread 1".to_string())
43 | .spawn(do_work)
44 | .expect("could not spawn a new thread");
45 | let thread_two = thread::Builder::new()
46 | .name("large name thread 2".to_string())
47 | .spawn(do_work)
48 | .expect("could not spawn a new thread");
49 |
50 | thread_with_no_name
51 | .join()
52 | .expect("could not wait for a thread");
53 | thread_one.join().expect("could not wait for a thread");
54 | thread_two.join().expect("could not wait for a thread");
55 | }
56 |
--------------------------------------------------------------------------------
/examples/examples/toggle-layers.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | /// This is a example showing how `Layer` can be enabled or disabled by
3 | /// by wrapping them with an `Option`. This example shows `fmt` and `json`
4 | /// being toggled based on the `json` command line flag.
5 | ///
6 | /// You can run this example by running the following command in a terminal
7 | ///
8 | /// ```
9 | /// cargo run --example toggle-subscribers -- --json
10 | /// ```
11 | ///
12 | use argh::FromArgs;
13 | use tracing::info;
14 | use tracing_subscriber::{prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt};
15 |
16 | #[path = "fmt/yak_shave.rs"]
17 | mod yak_shave;
18 |
19 | #[derive(FromArgs)]
20 | /// Subscriber toggling example.
21 | struct Args {
22 | /// enable JSON log format
23 | #[argh(switch, short = 'j')]
24 | json: bool,
25 | }
26 |
27 | fn main() {
28 | let args: Args = argh::from_env();
29 |
30 | let (json, plain) = if args.json {
31 | (Some(tracing_subscriber::fmt::layer().json()), None)
32 | } else {
33 | (None, Some(tracing_subscriber::fmt::layer()))
34 | };
35 |
36 | tracing_subscriber::registry().with(json).with(plain).init();
37 |
38 | let number_of_yaks = 3;
39 | // this creates a new event, outside of any spans.
40 | info!(number_of_yaks, "preparing to shave yaks");
41 |
42 | let number_shaved = yak_shave::shave_all(number_of_yaks);
43 | info!(
44 | all_yaks_shaved = number_shaved == number_of_yaks,
45 | "yak shaving completed."
46 | );
47 | }
48 |
--------------------------------------------------------------------------------
/examples/examples/tokio-spawny-thing.rs:
--------------------------------------------------------------------------------
1 | #![deny(rust_2018_idioms)]
2 | /// This is a example showing how information is scoped with tokio's
3 | /// `task::spawn`.
4 | ///
5 | /// You can run this example by running the following command in a terminal
6 | ///
7 | /// ```
8 | /// cargo run --example tokio-spawny-thing
9 | /// ```
10 | use futures::future::try_join_all;
11 | use tracing::{debug, info, instrument, span, Instrument as _, Level};
12 |
13 | type Error = Box;
14 |
15 | #[instrument]
16 | async fn parent_task(subtasks: usize) -> Result<(), Error> {
17 | info!("spawning subtasks...");
18 | let subtasks = (1..=subtasks)
19 | .map(|number| {
20 | let span = span!(Level::INFO, "subtask", %number);
21 | debug!(message = "creating subtask;", number);
22 | tokio::spawn(subtask(number).instrument(span))
23 | })
24 | .collect::>();
25 |
26 | // the returnable error would be if one of the subtasks panicked.
27 | let sum: usize = try_join_all(subtasks).await?.iter().sum();
28 | info!(%sum, "all subtasks completed; calculated sum");
29 | Ok(())
30 | }
31 |
32 | async fn subtask(number: usize) -> usize {
33 | info!(%number, "polling subtask");
34 | number
35 | }
36 |
37 | #[tokio::main]
38 | async fn main() -> Result<(), Error> {
39 | tracing_subscriber::fmt()
40 | .with_max_level(tracing::Level::DEBUG)
41 | .try_init()?;
42 | parent_task(10).await?;
43 | Ok(())
44 | }
45 |
--------------------------------------------------------------------------------
/examples/examples/tokio_panic_hook.rs:
--------------------------------------------------------------------------------
1 | //! This example demonstrates that a custom panic hook can be used to log panic
2 | //! messages even when panics are captured (such as when a Tokio task panics).
3 | //!
4 | //! This is essentially the same as the `panic_hook.rs` example, but modified to
5 | //! spawn async tasks using the Tokio runtime rather than panicking in a
6 | //! synchronous function. See the `panic_hook.rs` example for details on using
7 | //! custom panic hooks.
8 | #[tokio::main]
9 | async fn main() {
10 | let subscriber = tracing_subscriber::fmt()
11 | .with_max_level(tracing::Level::TRACE)
12 | .finish();
13 |
14 | // NOTE: Using `tracing` in a panic hook requires the use of the *global*
15 | // trace dispatcher (`tracing::subscriber::set_global_default`), rather than
16 | // the per-thread scoped dispatcher
17 | // (`tracing::subscriber::with_default`/`set_default`). With the scoped trace
18 | // dispatcher, the subscriber's thread-local context may already have been
19 | // torn down by unwinding by the time the panic handler is reached.
20 | tracing::subscriber::set_global_default(subscriber).unwrap();
21 |
22 | std::panic::set_hook(Box::new(|panic| {
23 | if let Some(location) = panic.location() {
24 | tracing::error!(
25 | message = %panic,
26 | panic.file = location.file(),
27 | panic.line = location.line(),
28 | panic.column = location.column(),
29 | );
30 | } else {
31 | tracing::error!(message = %panic);
32 | }
33 | }));
34 |
35 | // Spawn tasks to check the numbers from 1-10.
36 | let tasks = (0..10)
37 | .map(|i| tokio::spawn(check_number(i)))
38 | .collect::>();
39 | futures::future::join_all(tasks).await;
40 |
41 | tracing::trace!("all tasks done");
42 | }
43 |
44 | #[tracing::instrument]
45 | async fn check_number(x: i32) {
46 | tracing::trace!("checking number...");
47 | tokio::task::yield_now().await;
48 |
49 | if x % 2 == 0 {
50 | panic!("I don't work with even numbers!");
51 | }
52 |
53 | tracing::info!("number checks out!")
54 | }
55 |
--------------------------------------------------------------------------------
/examples/examples/tower-client.rs:
--------------------------------------------------------------------------------
1 | use http::{Method, Request, Uri};
2 | use hyper::{client::Client, Body};
3 | use std::time::Duration;
4 | use tower::{Service, ServiceBuilder};
5 | use tracing::info;
6 | use tracing_tower::request_span;
7 |
8 | type Err = Box;
9 |
10 | fn req_span(req: &Request) -> tracing::Span {
11 | let span = tracing::info_span!(
12 | "request",
13 | req.method = ?req.method(),
14 | req.uri = ?req.uri(),
15 | req.version = ?req.version(),
16 | headers = ?req.headers()
17 | );
18 | tracing::info!(parent: &span, "sending request");
19 | span
20 | }
21 |
22 | #[tokio::main]
23 | async fn main() -> Result<(), Err> {
24 | tracing_subscriber::fmt()
25 | .with_env_filter("tower=trace")
26 | .try_init()?;
27 |
28 | let mut svc = ServiceBuilder::new()
29 | .timeout(Duration::from_millis(250))
30 | .layer(request_span::layer(req_span))
31 | .service(Client::new());
32 |
33 | let uri = Uri::from_static("http://httpbin.org");
34 |
35 | let req = Request::builder()
36 | .method(Method::GET)
37 | .uri(uri)
38 | .body(Body::empty())
39 | .expect("Unable to build request; this is a bug.");
40 |
41 | let res = svc.call(req).await?;
42 | info!(message = "got a response", res.headers = ?res.headers());
43 |
44 | Ok(())
45 | }
46 |
--------------------------------------------------------------------------------
/examples/examples/valuable.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 | //! This example shows how a field value may be recorded using the `valuable`
3 | //! crate (https://crates.io/crates/valuable).
4 | //!
5 | //! `valuable` provides a lightweight but flexible way to record structured data, allowing
6 | //! visitors to extract individual fields or elements of structs, maps, arrays, and other
7 | //! nested structures.
8 | //!
9 | //! `tracing`'s support for `valuable` is currently feature flagged. Additionally, `valuable`
10 | //! support is considered an *unstable feature*: in order to use `valuable` with `tracing`,
11 | //! the project must be built with `RUSTFLAGS="--cfg tracing_unstable`.
12 | //!
13 | //! Therefore, when `valuable` support is not enabled, this example falls back to using
14 | //! `fmt::Debug` to record fields that implement `valuable::Valuable`.
15 | use tracing::{info, info_span};
16 | use valuable::Valuable;
17 |
18 | #[derive(Clone, Debug, Valuable)]
19 | struct User {
20 | name: String,
21 | age: u32,
22 | address: Address,
23 | }
24 |
25 | #[derive(Clone, Debug, Valuable)]
26 | struct Address {
27 | country: String,
28 | city: String,
29 | street: String,
30 | }
31 |
32 | fn main() {
33 | tracing_subscriber::fmt()
34 | .with_max_level(tracing::Level::TRACE)
35 | .init();
36 |
37 | let user = User {
38 | name: "Arwen Undomiel".to_string(),
39 | age: 3000,
40 | address: Address {
41 | country: "Middle Earth".to_string(),
42 | city: "Rivendell".to_string(),
43 | street: "leafy lane".to_string(),
44 | },
45 | };
46 |
47 | // If the `valuable` feature is enabled, record `user` using its'
48 | // `valuable::Valuable` implementation:
49 | #[cfg(tracing_unstable)]
50 | let span = info_span!("Processing", user = user.as_value());
51 |
52 | // Otherwise, record `user` using its `fmt::Debug` implementation:
53 | #[cfg(not(tracing_unstable))]
54 | let span = info_span!("Processing", user = ?user);
55 |
56 | let _handle = span.enter();
57 | info!("Nothing to do");
58 | }
59 |
--------------------------------------------------------------------------------
/examples/examples/valuable_instrument.rs:
--------------------------------------------------------------------------------
1 | #[cfg(tracing_unstable)]
2 | mod app {
3 | use std::collections::HashMap;
4 | use tracing::field::valuable;
5 | use tracing::{info, instrument};
6 | use valuable::Valuable;
7 |
8 | #[derive(Valuable)]
9 | struct Headers<'a> {
10 | headers: HashMap<&'a str, &'a str>,
11 | }
12 |
13 | // Current there's no way to automatically apply valuable to a type, so we need to make use of
14 | // the fields argument for instrument
15 | #[instrument(fields(headers=valuable(&headers)))]
16 | fn process(headers: Headers) {
17 | info!("Handle request")
18 | }
19 |
20 | pub fn run() {
21 | let headers = [
22 | ("content-type", "application/json"),
23 | ("content-length", "568"),
24 | ("server", "github.com"),
25 | ]
26 | .iter()
27 | .cloned()
28 | .collect::>();
29 |
30 | let http_headers = Headers { headers };
31 |
32 | process(http_headers);
33 | }
34 | }
35 |
36 | fn main() {
37 | tracing_subscriber::fmt()
38 | .with_max_level(tracing::Level::TRACE)
39 | .init();
40 |
41 | #[cfg(tracing_unstable)]
42 | app::run();
43 | #[cfg(not(tracing_unstable))]
44 | println!("Nothing to do, this example needs --cfg=tracing_unstable to run");
45 | }
46 |
--------------------------------------------------------------------------------
/examples/examples/valuable_json.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 | //! This example shows how a field value may be recorded using the `valuable`
3 | //! crate (https://crates.io/crates/valuable).
4 | //!
5 | //! `valuable` provides a lightweight but flexible way to record structured data, allowing
6 | //! visitors to extract individual fields or elements of structs, maps, arrays, and other
7 | //! nested structures.
8 | //!
9 | //! `tracing`'s support for `valuable` is currently feature flagged. Additionally, `valuable`
10 | //! support is considered an *unstable feature*: in order to use `valuable` with `tracing`,
11 | //! the project must be built with `RUSTFLAGS="--cfg tracing_unstable`.
12 | //!
13 | //! Therefore, when `valuable` support is not enabled, this example falls back to using
14 | //! `fmt::Debug` to record fields that implement `valuable::Valuable`.
15 | #[cfg(tracing_unstable)]
16 | use tracing::field::valuable;
17 | use valuable::Valuable;
18 |
19 | #[derive(Clone, Debug, Valuable)]
20 | struct User {
21 | name: String,
22 | age: u32,
23 | address: Address,
24 | }
25 |
26 | #[derive(Clone, Debug, Valuable)]
27 | struct Address {
28 | country: String,
29 | city: String,
30 | street: String,
31 | }
32 |
33 | fn main() {
34 | tracing_subscriber::fmt()
35 | .with_max_level(tracing::Level::TRACE)
36 | .json()
37 | .init();
38 |
39 | let user = User {
40 | name: "Arwen Undomiel".to_string(),
41 | age: 3000,
42 | address: Address {
43 | country: "Middle Earth".to_string(),
44 | city: "Rivendell".to_string(),
45 | street: "leafy lane".to_string(),
46 | },
47 | };
48 |
49 | // for comparison, record `user` without using its `Valuable`
50 | // implementation:
51 | tracing::info!(valuable = false, user = ?user);
52 |
53 | // If the `valuable` feature is enabled, record `user` using its'
54 | // `valuable::Valuable` implementation:
55 | #[cfg(tracing_unstable)]
56 | tracing::info!(valuable = true, user = valuable(&user));
57 |
58 | #[cfg(not(tracing_unstable))]
59 | tracing::warn!(
60 | "note: this example was run without `valuable` support enabled!\n\
61 | rerun with `RUSTFLAGS=\"--cfg tracing_unstable\" to enable `valuable`",
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | command = """
3 | rustup install nightly --profile minimal \
4 | && cargo doc --no-deps --all-features
5 | """
6 | publish = "target/doc"
7 |
8 | [build.environment]
9 | RUSTDOCFLAGS="""
10 | -D warnings \
11 | --force-warn rustdoc::redundant-explicit-links \
12 | --force-warn renamed-and-removed-lints \
13 | --cfg docsrs \
14 | --cfg tracing_unstable
15 | """
16 | RUSTFLAGS="--cfg tracing_unstable"
17 |
18 | [[redirects]]
19 | from = "/"
20 | to = "/tracing"
21 |
--------------------------------------------------------------------------------
/tracing-appender/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-appender"
3 | version = "0.2.3"
4 | authors = [
5 | "Zeki Sherif ",
6 | "Tokio Contributors "
7 | ]
8 | license = "MIT"
9 | readme = "README.md"
10 | repository = "https://github.com/tokio-rs/tracing"
11 | homepage = "https://tokio.rs"
12 | description = """
13 | Provides utilities for file appenders and making non-blocking writers.
14 | """
15 | categories = [
16 | "development-tools::debugging",
17 | "asynchronous",
18 | ]
19 | keywords = ["logging", "tracing", "file-appender", "non-blocking-writer"]
20 | edition = "2018"
21 | rust-version = "1.63.0"
22 |
23 | [dependencies]
24 | crossbeam-channel = "0.5.6"
25 | time = { version = "0.3.2", default-features = false, features = ["formatting", "parsing"] }
26 | parking_lot = { optional = true, version = "0.12.1" }
27 | thiserror = "2"
28 |
29 | [dependencies.tracing-subscriber]
30 | path = "../tracing-subscriber"
31 | version = "0.3.18"
32 | default-features = false
33 | features = ["fmt", "std"]
34 |
35 | [dev-dependencies]
36 | criterion = { version = "0.3.6", default-features = false }
37 | tracing = { path = "../tracing", version = "0.1.35" }
38 | tempfile = "3"
39 |
40 | [[bench]]
41 | name = "bench"
42 | harness = false
43 |
--------------------------------------------------------------------------------
/tracing-appender/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-appender/src/sync.rs:
--------------------------------------------------------------------------------
1 | //! Abstracts over sync primitive implementations.
2 | //!
3 | //! Optionally, we allow the Rust standard library's `RwLock` to be replaced
4 | //! with the `parking_lot` crate's implementation. This may provide improved
5 | //! performance in some cases. However, the `parking_lot` dependency is an
6 | //! opt-in feature flag. Because `parking_lot::RwLock` has a slightly different
7 | //! API than `std::sync::RwLock` (it does not support poisoning on panics), we
8 | //! wrap the `std::sync` version to ignore poisoning.
9 |
10 | #[allow(unused_imports)] // may be used later;
11 | #[cfg(feature = "parking_lot")]
12 | pub(crate) use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
13 |
14 | #[cfg(not(feature = "parking_lot"))]
15 | pub(crate) use self::std_impl::*;
16 |
17 | #[cfg(not(feature = "parking_lot"))]
18 | mod std_impl {
19 | use std::sync::{self, PoisonError, TryLockError};
20 | pub(crate) use std::sync::{RwLockReadGuard, RwLockWriteGuard};
21 |
22 | #[derive(Debug)]
23 | pub(crate) struct RwLock {
24 | inner: sync::RwLock,
25 | }
26 |
27 | impl RwLock {
28 | pub(crate) fn new(val: T) -> Self {
29 | Self {
30 | inner: sync::RwLock::new(val),
31 | }
32 | }
33 |
34 | #[inline]
35 | pub(crate) fn get_mut(&mut self) -> &mut T {
36 | self.inner.get_mut().unwrap_or_else(PoisonError::into_inner)
37 | }
38 |
39 | #[inline]
40 | pub(crate) fn read(&self) -> RwLockReadGuard<'_, T> {
41 | self.inner.read().unwrap_or_else(PoisonError::into_inner)
42 | }
43 |
44 | #[inline]
45 | #[allow(dead_code)] // may be used later;
46 | pub(crate) fn try_read(&self) -> Option> {
47 | match self.inner.try_read() {
48 | Ok(guard) => Some(guard),
49 | Err(TryLockError::Poisoned(e)) => Some(e.into_inner()),
50 | Err(TryLockError::WouldBlock) => None,
51 | }
52 | }
53 |
54 | #[inline]
55 | pub(crate) fn write(&self) -> RwLockWriteGuard<'_, T> {
56 | self.inner.write().unwrap_or_else(PoisonError::into_inner)
57 | }
58 |
59 | #[inline]
60 | #[allow(dead_code)] // may be used later;
61 | pub(crate) fn try_write(&self) -> Option> {
62 | match self.inner.try_write() {
63 | Ok(guard) => Some(guard),
64 | Err(TryLockError::Poisoned(e)) => Some(e.into_inner()),
65 | Err(TryLockError::WouldBlock) => None,
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/tracing-attributes/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-attributes"
3 | # When releasing to crates.io:
4 | # - Remove path dependencies
5 | # - Update doc url in README.md.
6 | # - Update CHANGELOG.md.
7 | # - Create "tracing-attributes-0.1.x" git tag.
8 | version = "0.1.29"
9 | authors = [
10 | "Tokio Contributors ",
11 | "Eliza Weisman ",
12 | "David Barsky ",
13 | ]
14 | repository = "https://github.com/tokio-rs/tracing"
15 | homepage = "https://tokio.rs"
16 | description = """
17 | Procedural macro attributes for automatically instrumenting functions.
18 | """
19 | categories = [
20 | "development-tools::debugging",
21 | "development-tools::profiling",
22 | "asynchronous",
23 | ]
24 | keywords = ["logging", "tracing", "macro", "instrument", "log"]
25 | license = "MIT"
26 | readme = "README.md"
27 | edition = "2018"
28 | rust-version = "1.65.0"
29 |
30 | [lib]
31 | proc-macro = true
32 |
33 | [features]
34 |
35 | # This feature flag is no longer necessary.
36 | async-await = []
37 |
38 | [dependencies]
39 | proc-macro2 = "1.0.60"
40 | syn = { version = "2.0", default-features = false, features = [
41 | "full",
42 | "parsing",
43 | "printing",
44 | "visit-mut",
45 | "clone-impls",
46 | "extra-traits",
47 | "proc-macro",
48 | ] }
49 | quote = "1.0.20"
50 |
51 | [dev-dependencies]
52 | tracing = { path = "../tracing", version = "0.1.35" }
53 | tracing-mock = { path = "../tracing-mock" }
54 | tokio-test = "0.4.2"
55 | tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", features = [
56 | "env-filter",
57 | ] }
58 | tracing-test = { path = "../tracing-test" }
59 | async-trait = "0.1.67"
60 | trybuild = "1.0.64"
61 | rustversion = "1.0.9"
62 |
63 | [badges]
64 | maintenance = { status = "experimental" }
65 |
66 | [lints]
67 | workspace = true
68 |
--------------------------------------------------------------------------------
/tracing-attributes/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-attributes/tests/dead_code.rs:
--------------------------------------------------------------------------------
1 | use tracing_attributes::instrument;
2 |
3 | #[deny(unfulfilled_lint_expectations)]
4 | #[expect(dead_code)]
5 | #[instrument]
6 | fn unused() {}
7 |
8 | #[expect(dead_code)]
9 | #[instrument]
10 | async fn unused_async() {}
11 |
--------------------------------------------------------------------------------
/tracing-attributes/tests/names.rs:
--------------------------------------------------------------------------------
1 | use tracing::subscriber::with_default;
2 | use tracing_attributes::instrument;
3 | use tracing_mock::*;
4 |
5 | #[instrument]
6 | fn default_name() {}
7 |
8 | #[instrument(name = "my_name")]
9 | fn custom_name() {}
10 |
11 | // XXX: it's weird that we support both of these forms, but apparently we
12 | // managed to release a version that accepts both syntax, so now we have to
13 | // support it! yay!
14 | #[instrument("my_other_name")]
15 | fn custom_name_no_equals() {}
16 |
17 | #[test]
18 | fn default_name_test() {
19 | let (subscriber, handle) = subscriber::mock()
20 | .new_span(expect::span().named("default_name"))
21 | .enter(expect::span().named("default_name"))
22 | .exit(expect::span().named("default_name"))
23 | .only()
24 | .run_with_handle();
25 |
26 | with_default(subscriber, || {
27 | default_name();
28 | });
29 |
30 | handle.assert_finished();
31 | }
32 |
33 | #[test]
34 | fn custom_name_test() {
35 | let (subscriber, handle) = subscriber::mock()
36 | .new_span(expect::span().named("my_name"))
37 | .enter(expect::span().named("my_name"))
38 | .exit(expect::span().named("my_name"))
39 | .only()
40 | .run_with_handle();
41 |
42 | with_default(subscriber, || {
43 | custom_name();
44 | });
45 |
46 | handle.assert_finished();
47 | }
48 |
49 | #[test]
50 | fn custom_name_no_equals_test() {
51 | let (subscriber, handle) = subscriber::mock()
52 | .new_span(expect::span().named("my_other_name"))
53 | .enter(expect::span().named("my_other_name"))
54 | .exit(expect::span().named("my_other_name"))
55 | .only()
56 | .run_with_handle();
57 |
58 | with_default(subscriber, || {
59 | custom_name_no_equals();
60 | });
61 |
62 | handle.assert_finished();
63 | }
64 |
--------------------------------------------------------------------------------
/tracing-attributes/tests/ui.rs:
--------------------------------------------------------------------------------
1 | // Only test on nightly, since UI tests are bound to change over time
2 | #[rustversion::stable]
3 | #[test]
4 | fn async_instrument() {
5 | let t = trybuild::TestCases::new();
6 | t.compile_fail("tests/ui/async_instrument.rs");
7 | }
8 |
9 | #[rustversion::stable]
10 | #[test]
11 | fn const_instrument() {
12 | let t = trybuild::TestCases::new();
13 | t.compile_fail("tests/ui/const_instrument.rs");
14 | }
15 |
--------------------------------------------------------------------------------
/tracing-attributes/tests/ui/async_instrument.rs:
--------------------------------------------------------------------------------
1 | #![allow(unreachable_code)]
2 |
3 | #[tracing::instrument]
4 | async fn unit() {
5 | ""
6 | }
7 |
8 | #[tracing::instrument]
9 | async fn simple_mismatch() -> String {
10 | ""
11 | }
12 |
13 | #[tracing::instrument]
14 | async fn opaque_unsatisfied() -> impl std::fmt::Display {
15 | ("",)
16 | }
17 |
18 | struct Wrapper(T);
19 |
20 | #[tracing::instrument]
21 | async fn mismatch_with_opaque() -> Wrapper {
22 | ""
23 | }
24 |
25 | #[tracing::instrument]
26 | async fn early_return_unit() {
27 | if true {
28 | return "";
29 | }
30 | }
31 |
32 | #[tracing::instrument]
33 | async fn early_return() -> String {
34 | if true {
35 | return "";
36 | }
37 | String::new()
38 | }
39 |
40 | #[tracing::instrument]
41 | async fn extra_semicolon() -> i32 {
42 | 1;
43 | }
44 |
45 | fn main() {}
46 |
--------------------------------------------------------------------------------
/tracing-attributes/tests/ui/const_instrument.rs:
--------------------------------------------------------------------------------
1 | #![allow(unreachable_code)]
2 |
3 | #[tracing::instrument]
4 | const fn unit() {
5 | ""
6 | }
7 |
8 | fn main() {}
9 |
--------------------------------------------------------------------------------
/tracing-attributes/tests/ui/const_instrument.stderr:
--------------------------------------------------------------------------------
1 | error: macros that expand to items must be delimited with braces or followed by a semicolon
2 | --> tests/ui/const_instrument.rs:3:1
3 | |
4 | 3 | #[tracing::instrument]
5 | | ^^^^^^^^^^^^^^^^^^^^^^
6 | |
7 | = note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)
8 |
9 | error: the `#[instrument]` attribute may not be used with `const fn`s
10 | --> tests/ui/const_instrument.rs:3:1
11 | |
12 | 3 | #[tracing::instrument]
13 | | ^^^^^^^^^^^^^^^^^^^^^^
14 | |
15 | = note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)
16 |
--------------------------------------------------------------------------------
/tracing-core/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-core"
3 | # When releasing to crates.io:
4 | # - Remove path dependencies
5 | # - Update html_root_url.
6 | # - Update doc url in README.md.
7 | # - Update CHANGELOG.md.
8 | # - Create "tracing-core-0.1.x" git tag.
9 | version = "0.1.34"
10 | authors = ["Tokio Contributors "]
11 | license = "MIT"
12 | readme = "README.md"
13 | repository = "https://github.com/tokio-rs/tracing"
14 | homepage = "https://tokio.rs"
15 | description = """
16 | Core primitives for application-level tracing.
17 | """
18 | categories = [
19 | "development-tools::debugging",
20 | "development-tools::profiling",
21 | "asynchronous",
22 | ]
23 | keywords = ["logging", "tracing", "profiling"]
24 | edition = "2018"
25 | rust-version = "1.65.0"
26 |
27 | [features]
28 | default = ["std", "valuable?/std"]
29 | std = ["once_cell"]
30 |
31 | [badges]
32 | maintenance = { status = "actively-developed" }
33 |
34 | [dependencies]
35 | once_cell = { version = "1.13.0", optional = true }
36 |
37 | [target.'cfg(tracing_unstable)'.dependencies]
38 | valuable = { version = "0.1.0", optional = true, default-features = false }
39 |
40 | [package.metadata.docs.rs]
41 | all-features = true
42 | # enable unstable features in the documentation
43 | rustdoc-args = ["--cfg", "docsrs", "--cfg", "tracing_unstable"]
44 | # it's necessary to _also_ pass `--cfg tracing_unstable` to rustc, or else
45 | # dependencies will not be enabled, and the docs build will fail.
46 | rustc-args = ["--cfg", "tracing_unstable"]
47 |
48 | [lints]
49 | workspace = true
50 |
--------------------------------------------------------------------------------
/tracing-core/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-core/src/parent.rs:
--------------------------------------------------------------------------------
1 | use crate::span::Id;
2 |
3 | #[derive(Debug)]
4 | pub(crate) enum Parent {
5 | /// The new span will be a root span.
6 | Root,
7 | /// The new span will be rooted in the current span.
8 | Current,
9 | /// The new span has an explicitly-specified parent.
10 | Explicit(Id),
11 | }
12 |
--------------------------------------------------------------------------------
/tracing-core/src/spin/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Mathijs van de Nes
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/tracing-core/src/spin/mod.rs:
--------------------------------------------------------------------------------
1 | //! Synchronization primitives based on spinning
2 |
3 | pub(crate) use mutex::*;
4 | pub(crate) use once::Once;
5 |
6 | mod mutex;
7 | mod once;
8 |
--------------------------------------------------------------------------------
/tracing-core/tests/common/mod.rs:
--------------------------------------------------------------------------------
1 | use tracing_core::{metadata::Metadata, span, subscriber::Subscriber, Event};
2 |
3 | pub struct TestSubscriberA;
4 | impl Subscriber for TestSubscriberA {
5 | fn enabled(&self, _: &Metadata<'_>) -> bool {
6 | true
7 | }
8 | fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
9 | span::Id::from_u64(1)
10 | }
11 | fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
12 | fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
13 | fn event(&self, _: &Event<'_>) {}
14 | fn enter(&self, _: &span::Id) {}
15 | fn exit(&self, _: &span::Id) {}
16 | }
17 | pub struct TestSubscriberB;
18 | impl Subscriber for TestSubscriberB {
19 | fn enabled(&self, _: &Metadata<'_>) -> bool {
20 | true
21 | }
22 | fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
23 | span::Id::from_u64(1)
24 | }
25 | fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
26 | fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
27 | fn event(&self, _: &Event<'_>) {}
28 | fn enter(&self, _: &span::Id) {}
29 | fn exit(&self, _: &span::Id) {}
30 | }
31 |
--------------------------------------------------------------------------------
/tracing-core/tests/dispatch.rs:
--------------------------------------------------------------------------------
1 | #![cfg(feature = "std")]
2 | mod common;
3 |
4 | use common::*;
5 | use tracing_core::dispatcher::*;
6 |
7 | #[test]
8 | fn set_default_dispatch() {
9 | set_global_default(Dispatch::new(TestSubscriberA)).expect("global dispatch set failed");
10 | get_default(|current| {
11 | assert!(
12 | current.is::(),
13 | "global dispatch get failed"
14 | )
15 | });
16 |
17 | let guard = set_default(&Dispatch::new(TestSubscriberB));
18 | get_default(|current| assert!(current.is::(), "set_default get failed"));
19 |
20 | // Drop the guard, setting the dispatch back to the global dispatch
21 | drop(guard);
22 |
23 | get_default(|current| {
24 | assert!(
25 | current.is::(),
26 | "global dispatch get failed"
27 | )
28 | });
29 | }
30 |
31 | #[test]
32 | fn nested_set_default() {
33 | let _guard = set_default(&Dispatch::new(TestSubscriberA));
34 | get_default(|current| {
35 | assert!(
36 | current.is::(),
37 | "set_default for outer subscriber failed"
38 | )
39 | });
40 |
41 | let inner_guard = set_default(&Dispatch::new(TestSubscriberB));
42 | get_default(|current| {
43 | assert!(
44 | current.is::(),
45 | "set_default inner subscriber failed"
46 | )
47 | });
48 |
49 | drop(inner_guard);
50 | get_default(|current| {
51 | assert!(
52 | current.is::(),
53 | "set_default outer subscriber failed"
54 | )
55 | });
56 | }
57 |
--------------------------------------------------------------------------------
/tracing-core/tests/global_dispatch.rs:
--------------------------------------------------------------------------------
1 | mod common;
2 |
3 | use common::*;
4 | use tracing_core::dispatcher::*;
5 | #[test]
6 | fn global_dispatch() {
7 | set_global_default(Dispatch::new(TestSubscriberA)).expect("global dispatch set failed");
8 | get_default(|current| {
9 | assert!(
10 | current.is::(),
11 | "global dispatch get failed"
12 | )
13 | });
14 |
15 | #[cfg(feature = "std")]
16 | with_default(&Dispatch::new(TestSubscriberB), || {
17 | get_default(|current| {
18 | assert!(
19 | current.is::(),
20 | "thread-local override of global dispatch failed"
21 | )
22 | });
23 | });
24 |
25 | get_default(|current| {
26 | assert!(
27 | current.is::(),
28 | "reset to global override failed"
29 | )
30 | });
31 |
32 | set_global_default(Dispatch::new(TestSubscriberA))
33 | .expect_err("double global dispatch set succeeded");
34 | }
35 |
--------------------------------------------------------------------------------
/tracing-core/tests/local_dispatch_before_init.rs:
--------------------------------------------------------------------------------
1 | mod common;
2 |
3 | use common::*;
4 | use tracing_core::{
5 | dispatcher::{self, Dispatch},
6 | subscriber::NoSubscriber,
7 | };
8 |
9 | /// This test reproduces the following issues:
10 | /// - https://github.com/tokio-rs/tracing/issues/2587
11 | /// - https://github.com/tokio-rs/tracing/issues/2411
12 | /// - https://github.com/tokio-rs/tracing/issues/2436
13 | #[test]
14 | fn local_dispatch_before_init() {
15 | dispatcher::get_default(|current| assert!(dbg!(current).is::()));
16 |
17 | // Temporarily override the default dispatcher with a scoped dispatcher.
18 | // Using a scoped dispatcher makes the thread local state attempt to cache
19 | // the scoped default.
20 | #[cfg(feature = "std")]
21 | {
22 | dispatcher::with_default(&Dispatch::new(TestSubscriberB), || {
23 | dispatcher::get_default(|current| {
24 | assert!(
25 | dbg!(current).is::(),
26 | "overriden subscriber not set",
27 | );
28 | })
29 | })
30 | }
31 |
32 | dispatcher::get_default(|current| assert!(current.is::()));
33 |
34 | dispatcher::set_global_default(Dispatch::new(TestSubscriberA))
35 | .expect("set global dispatch failed");
36 |
37 | dispatcher::get_default(|current| {
38 | assert!(
39 | dbg!(current).is::(),
40 | "default subscriber not set"
41 | );
42 | });
43 | }
44 |
--------------------------------------------------------------------------------
/tracing-core/tests/macros.rs:
--------------------------------------------------------------------------------
1 | use tracing_core::{
2 | callsite::Callsite,
3 | metadata,
4 | metadata::{Kind, Level, Metadata},
5 | subscriber::Interest,
6 | };
7 |
8 | #[test]
9 | fn metadata_macro_api() {
10 | // This test should catch any inadvertent breaking changes
11 | // caused by changes to the macro.
12 | struct TestCallsite;
13 |
14 | impl Callsite for TestCallsite {
15 | fn set_interest(&self, _: Interest) {
16 | unimplemented!("test")
17 | }
18 | fn metadata(&self) -> &Metadata<'_> {
19 | unimplemented!("test")
20 | }
21 | }
22 |
23 | static CALLSITE: TestCallsite = TestCallsite;
24 | let _metadata = metadata! {
25 | name: "test_metadata",
26 | target: "test_target",
27 | level: Level::DEBUG,
28 | fields: &["foo", "bar", "baz"],
29 | callsite: &CALLSITE,
30 | kind: Kind::SPAN,
31 | };
32 | let _metadata = metadata! {
33 | name: "test_metadata",
34 | target: "test_target",
35 | level: Level::TRACE,
36 | fields: &[],
37 | callsite: &CALLSITE,
38 | kind: Kind::EVENT,
39 | };
40 | let _metadata = metadata! {
41 | name: "test_metadata",
42 | target: "test_target",
43 | level: Level::INFO,
44 | fields: &[],
45 | callsite: &CALLSITE,
46 | kind: Kind::EVENT
47 | };
48 | }
49 |
--------------------------------------------------------------------------------
/tracing-error/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 0.2.1 (November 29, 2024)
2 |
3 | [ [crates.io][crate-0.2.1] ] | [ [docs.rs][docs-0.2.1] ]
4 |
5 | ### Changed
6 |
7 | - Bump MSRV to 1.63 ([#2793])
8 |
9 | ### Documented
10 |
11 | - Use intra-doc links instead of relative file paths ([#2068])
12 | - More intra-doc links ([#2077])
13 | - Add missing backtick to `prelude` docs ([#2120])
14 |
15 | [#2068]: https://github.com/tokio-rs/tracing/pull/2068
16 | [#2077]: https://github.com/tokio-rs/tracing/pull/2077
17 | [#2120]: https://github.com/tokio-rs/tracing/pull/2120
18 | [#2793]: https://github.com/tokio-rs/tracing/pull/2793
19 | [docs-0.2.1]: https://docs.rs/tracing-error/0.2.1/tracing_error/
20 | [crate-0.2.1]: https://crates.io/crates/tracing-error/0.2.1
21 |
22 | # 0.2.0 (October 23, 2021)
23 |
24 | This is a breaking change release in order to update the `tracing-subscriber`
25 | dependency version to [the v0.3.x release series][v03].
26 |
27 | ### Changed
28 |
29 | - Updated `tracing-subscriber` dependency to [v0.3.0][v03] ([#1677])
30 |
31 | ### Fixed
32 |
33 | - Disabled default features of the `tracing` dependency so that proc-macro
34 | dependencies are not enabled ([#1144])
35 | - Documentation fixes and improvements ([#635], [#695])
36 |
37 | ### Added
38 |
39 | - **SpanTrace**: Added `SpanTrace::new` constructor for constructing a
40 | `SpanTrace` from a `Span` passed as an argument (rather than capturing the
41 | current span) ([#1492])
42 |
43 | Thanks to @CAD97 for contributing to this release!
44 |
45 | [v03]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.0
46 | [#635]: https://github.com/tokio-rs/tracing/pull/635
47 | [#695]: https://github.com/tokio-rs/tracing/pull/695
48 | [#1144]: https://github.com/tokio-rs/tracing/pull/1144
49 | [#1492]: https://github.com/tokio-rs/tracing/pull/1492
50 | [#1677]: https://github.com/tokio-rs/tracing/pull/1677
51 |
52 | # 0.1.2 (March 3, 2020)
53 |
54 | ### Added
55 |
56 | - **TracedError**: `TracedError`, an error type wrapper that annotates an error
57 | with the current span.
58 | - **SpanTrace**:`SpanTrace::status` method and `SpanTraceStatus` type for
59 | determining whether a `SpanTrace` was successfully captured (#614)
60 |
61 | ### Changed
62 |
63 | - **SpanTrace**: Made backtrace formatting more consistent with upstream changes
64 | to `std::backtrace` (#584)
65 |
66 | # 0.1.1 (February 5, 2020)
67 |
68 | ### Fixed
69 |
70 | - Fixed a typo in the crate description
71 |
72 | ### Changed
73 |
74 | - the maintenance badge from active to experimental
75 |
76 | # 0.1.0 (February 5, 2020)
77 |
78 | - Initial release
79 |
--------------------------------------------------------------------------------
/tracing-error/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-error"
3 | # When releasing to crates.io:
4 | # - Remove path dependencies
5 | # - Update doc url in README.md.
6 | # - Update CHANGELOG.md.
7 | # - Create "v0.2.x" git tag
8 | version = "0.2.1"
9 | authors = [
10 | "Eliza Weisman ",
11 | "Jane Lusby ",
12 | "Tokio Contributors "
13 | ]
14 | license = "MIT"
15 | readme = "README.md"
16 | repository = "https://github.com/tokio-rs/tracing"
17 | homepage = "https://tokio.rs"
18 | description = """
19 | Utilities for enriching errors with `tracing`.
20 | """
21 | categories = [
22 | "development-tools::debugging",
23 | "rust-patterns"
24 | ]
25 | keywords = [
26 | "tracing",
27 | "error-handling",
28 | "exception-reporting",
29 | "backtrace"
30 | ]
31 | edition = "2018"
32 | rust-version = "1.65.0"
33 |
34 | [features]
35 | default = ["traced-error"]
36 | traced-error = []
37 |
38 | [dependencies]
39 | tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", default-features = false, features = ["registry", "fmt"] }
40 | tracing = { path = "../tracing", version = "0.1.35", default-features = false, features = ["std"] }
41 |
42 | [badges]
43 | maintenance = { status = "experimental" }
44 |
45 | [package.metadata.docs.rs]
46 | all-features = true
47 | rustdoc-args = ["--cfg", "docsrs"]
48 |
--------------------------------------------------------------------------------
/tracing-error/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-flame/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-flame"
3 | version = "0.2.0"
4 | authors = [
5 | "Jane Lusby ",
6 | "Tokio Contributors "
7 | ]
8 | edition = "2018"
9 | license = "MIT"
10 | readme = "README.md"
11 | repository = "https://github.com/tokio-rs/tracing"
12 | homepage = "https://tokio.rs"
13 | description = """
14 | Tracing layer for creating flamegraphs from span timings
15 | """
16 | categories = [
17 | "development-tools::debugging",
18 | "development-tools::profiling",
19 | "asynchronous",
20 | ]
21 | keywords = ["tracing", "subscriber", "flamegraph", "profiling"]
22 | rust-version = "1.65.0"
23 |
24 | [features]
25 | default = ["smallvec"]
26 | smallvec = ["tracing-subscriber/smallvec"]
27 |
28 | [dependencies]
29 | tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", default-features = false, features = ["registry", "fmt"] }
30 | tracing = { path = "../tracing", version = "0.1.35", default-features = false, features = ["std"] }
31 | once_cell = "1.13.0"
32 |
33 |
34 | [dev-dependencies]
35 | tempfile = "3"
36 |
--------------------------------------------------------------------------------
/tracing-flame/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-flame/src/error.rs:
--------------------------------------------------------------------------------
1 | use std::fmt;
2 | use std::path::PathBuf;
3 |
4 | /// The error type for `tracing-flame`
5 | #[derive(Debug)]
6 | pub struct Error(pub(crate) Kind);
7 |
8 | impl Error {
9 | pub(crate) fn report(&self) {
10 | let current_error: &dyn std::error::Error = self;
11 | let mut current_error = Some(current_error);
12 | let mut ind = 0;
13 |
14 | eprintln!("Error:");
15 |
16 | while let Some(error) = current_error {
17 | eprintln!(" {}: {}", ind, error);
18 | ind += 1;
19 | current_error = error.source();
20 | }
21 | }
22 | }
23 |
24 | impl fmt::Display for Error {
25 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 | fmt::Display::fmt(&self.0, f)
27 | }
28 | }
29 |
30 | impl std::error::Error for Error {
31 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
32 | match &self.0 {
33 | Kind::CreateFile { ref source, .. } => Some(source),
34 | Kind::FlushFile(ref source) => Some(source),
35 | }
36 | }
37 | }
38 |
39 | #[derive(Debug)]
40 | pub(crate) enum Kind {
41 | CreateFile {
42 | source: std::io::Error,
43 | path: PathBuf,
44 | },
45 | FlushFile(std::io::Error),
46 | }
47 |
48 | impl fmt::Display for Kind {
49 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 | match self {
51 | Self::CreateFile { path, .. } => {
52 | write!(f, "cannot create output file. path={}", path.display())
53 | }
54 | Self::FlushFile { .. } => write!(f, "cannot flush output buffer"),
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tracing-flame/tests/collapsed.rs:
--------------------------------------------------------------------------------
1 | use std::thread::sleep;
2 | use std::time::Duration;
3 | use tracing::{span, Level};
4 | use tracing_flame::FlameLayer;
5 | use tracing_subscriber::{prelude::*, registry::Registry};
6 |
7 | #[test]
8 | fn capture_supported() {
9 | {
10 | let tmp_dir = tempfile::Builder::new()
11 | .prefix("tracing-flamegraph-test-")
12 | .tempdir()
13 | .expect("failed to create tempdir");
14 | let (flame_layer, _guard) =
15 | FlameLayer::with_file(tmp_dir.path().join("tracing.folded")).unwrap();
16 |
17 | let subscriber = Registry::default().with(flame_layer);
18 |
19 | tracing::subscriber::set_global_default(subscriber).expect("Could not set global default");
20 |
21 | {
22 | let span = span!(Level::ERROR, "outer");
23 | let _guard = span.enter();
24 | sleep(Duration::from_millis(10));
25 |
26 | {
27 | let span = span!(Level::ERROR, "Inner");
28 | let _guard = span.enter();
29 | sleep(Duration::from_millis(50));
30 |
31 | {
32 | let span = span!(Level::ERROR, "Innermost");
33 | let _guard = span.enter();
34 | sleep(Duration::from_millis(50));
35 | }
36 | }
37 |
38 | sleep(Duration::from_millis(5));
39 | }
40 |
41 | sleep(Duration::from_millis(500));
42 |
43 | tmp_dir.close().expect("failed to delete tempdir");
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tracing-flame/tests/concurrent.rs:
--------------------------------------------------------------------------------
1 | use std::thread::sleep;
2 | use std::time::Duration;
3 | use tracing::{span, Level};
4 | use tracing_flame::FlameLayer;
5 | use tracing_subscriber::{prelude::*, registry::Registry};
6 |
7 | #[test]
8 | fn capture_supported() {
9 | let tmp_dir = tempfile::Builder::new()
10 | .prefix("tracing-flamegraph-test-")
11 | .tempdir()
12 | .expect("failed to create tempdir");
13 | let path = tmp_dir.path().join("tracing.folded");
14 | let (flame_layer, flame_guard) = FlameLayer::with_file(&path).unwrap();
15 |
16 | let subscriber = Registry::default().with(flame_layer);
17 |
18 | tracing::subscriber::set_global_default(subscriber).expect("Could not set global default");
19 | let span = span!(Level::ERROR, "main");
20 | let _guard = span.enter();
21 |
22 | let thread = span!(Level::ERROR, "outer").in_scope(|| {
23 | sleep(Duration::from_millis(10));
24 | let span = span!(Level::ERROR, "Inner");
25 | let thread = std::thread::spawn(move || {
26 | span.in_scope(|| {
27 | sleep(Duration::from_millis(50));
28 | });
29 | });
30 | sleep(Duration::from_millis(20));
31 | thread
32 | });
33 |
34 | sleep(Duration::from_millis(100));
35 |
36 | thread.join().unwrap();
37 | flame_guard.flush().unwrap();
38 |
39 | let traces = std::fs::read_to_string(&path).unwrap();
40 | println!("{}", traces);
41 | assert_eq!(5, traces.lines().count());
42 |
43 | tmp_dir.close().expect("failed to delete tempdir");
44 | }
45 |
--------------------------------------------------------------------------------
/tracing-futures/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 0.2.5 (February 16, 2021)
2 |
3 | ### Changed
4 |
5 | - Updated `pin-project` dependency to 1.0 ([#1038])
6 |
7 | ### Fixed
8 |
9 | - Several documentation fixes and improvements ([#832], [#911], [#913], [#941],
10 | [#953], [#981])
11 |
12 | [#1038]: https://github.com/tokio-rs/tracing/pulls/1038
13 | [#832]: https://github.com/tokio-rs/tracing/pulls/832
14 | [#911]: https://github.com/tokio-rs/tracing/pulls/911
15 | [#913]: https://github.com/tokio-rs/tracing/pulls/913
16 | [#941]: https://github.com/tokio-rs/tracing/pulls/941
17 | [#953]: https://github.com/tokio-rs/tracing/pulls/953
18 | [#981]: https://github.com/tokio-rs/tracing/pulls/981
19 | # 0.2.4 (April 21, 2020)
20 |
21 | ### Fixed
22 |
23 | - docs.rs build failures (#618)
24 | - Spelling in documentation skins -> sinks (#643)
25 |
26 | # 0.2.3 (Feb 26, 2020)
27 |
28 | ### Added
29 |
30 | - `WithDispatch::inner` and `WithDispatch::inner_mut` methods to allow borrowing
31 | the wrapped type (#589)
32 | - `WithDispatch::with_dispatch` method, to propagate the subscriber to another
33 | type (#589)
34 | - `inner_pin_ref` and `inner_pin_mut` methods to `Instrumented` and
35 | `WithDispatch` to project to the inner future when pinned (#590)
36 |
37 | # 0.2.2 (Feb 14, 2020)
38 |
39 | ### Added
40 |
41 | - Support for `futures` 0.3 `Stream`s and `Sink`s (#544)
42 |
43 | ### Fixed
44 |
45 | - Compilation errors when using the `futures-03` feature (#576)
46 |
47 | Thanks to @obergner and @najamelan for their contributions to this release!
48 |
49 | # 0.2.1 (Jan 15, 2020)
50 |
51 | ### Added
52 |
53 | - API documentation now shows which features are required by feature-flagged items (#523)
54 | - `no_std` support (#498)
55 |
56 | # 0.2.0 (Dec 3, 2019)
57 |
58 | ### Changed
59 |
60 | - **Breaking Change**: the default `Future` implementation comes from the `std-future` feature.
61 | Compatibility with futures v0.1 is available via the `futures-01` feature.
62 |
63 | # 0.1.1 (Oct 25, 2019)
64 |
65 | ### Added
66 |
67 | - `Instrumented::inner` and `inner_mut` methods that expose access to the
68 | instrumented future (#386)
69 |
70 | # 0.1.0 (Oct 8, 2019)
71 |
72 | - Initial release
73 |
--------------------------------------------------------------------------------
/tracing-futures/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-futures"
3 | version = "0.2.5"
4 | authors = ["Eliza Weisman ", "Tokio Contributors "]
5 | edition = "2018"
6 | repository = "https://github.com/tokio-rs/tracing"
7 | readme = "README.md"
8 | homepage = "https://tokio.rs"
9 | description = """
10 | Utilities for instrumenting `futures` with `tracing`.
11 | """
12 | categories = [
13 | "development-tools::debugging",
14 | "development-tools::profiling",
15 | "asynchronous",
16 | ]
17 | keywords = ["logging", "profiling", "tracing", "futures", "async"]
18 | license = "MIT"
19 | rust-version = "1.65.0"
20 |
21 | [features]
22 | default = ["std-future", "std"]
23 | futures-01 = ["futures_01", "std"]
24 | futures-03 = ["std-future", "futures", "futures-task", "std"]
25 | std-future = ["pin-project-lite"]
26 | tokio = ["tokio_01"]
27 | std = ["tracing/std"]
28 |
29 | [dependencies]
30 | futures_01 = { package = "futures", version = "0.1.31", optional = true }
31 | futures = { version = "0.3.21", optional = true }
32 | futures-task = { version = "0.3.21", optional = true }
33 | pin-project-lite = { version = "0.2.9", optional = true }
34 | tracing = { path = "../tracing", version = "0.1.35", default-features = false }
35 | tokio-executor = { version = "0.1.10", optional = true }
36 | tokio_01 = { package = "tokio", version = "0.1.22", optional = true }
37 |
38 | # Fix minimal-versions
39 | tokio-threadpool = { version = "0.1.18", optional = true }
40 | mio = { version = "0.6.23", optional = true }
41 |
42 | [dev-dependencies]
43 | futures = "0.3.21"
44 | tokio-test = "0.4.2"
45 | tracing-core = { path = "../tracing-core", version = "0.1.28" }
46 | tracing-mock = { path = "../tracing-mock" }
47 | tracing-test = { path = "../tracing-test" }
48 |
49 | [badges]
50 | maintenance = { status = "actively-developed" }
51 |
52 | [package.metadata.docs.rs]
53 | all-features = true
54 | rustdoc-args = ["--cfg", "docsrs"]
55 |
56 | [lints]
57 | workspace = true
58 |
--------------------------------------------------------------------------------
/tracing-futures/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-futures/src/executor/mod.rs:
--------------------------------------------------------------------------------
1 | #[cfg(feature = "futures-01")]
2 | mod futures_01;
3 |
4 | #[cfg(feature = "futures-03")]
5 | mod futures_03;
6 | #[allow(unreachable_pub, unused_imports)]
7 | #[cfg(feature = "futures-03")]
8 | pub use futures_03::*;
9 |
--------------------------------------------------------------------------------
/tracing-futures/src/stdlib.rs:
--------------------------------------------------------------------------------
1 | //! Re-exports either the Rust `std` library or `core` and `alloc` when `std` is
2 | //! disabled.
3 | //!
4 | //! `crate::stdlib::...` should be used rather than `std::` when adding code that
5 | //! will be available with the standard library disabled.
6 | //!
7 | //! Note that this module is called `stdlib` rather than `std`, as Rust 1.34.0
8 | //! does not permit redefining the name `stdlib` (although this works on the
9 | //! latest stable Rust).
10 | #[cfg(feature = "std")]
11 | pub(crate) use std::*;
12 |
13 | #[cfg(not(feature = "std"))]
14 | pub(crate) use self::no_std::*;
15 |
16 | #[cfg(not(feature = "std"))]
17 | mod no_std {
18 | // We pre-emptively export everything from libcore/liballoc, (even modules
19 | // we aren't using currently) to make adding new code easier. Therefore,
20 | // some of these imports will be unused.
21 | #![allow(unused_imports)]
22 |
23 | pub(crate) use core::{
24 | any, array, ascii, cell, char, clone, cmp, convert, default, f32, f64, ffi, future, hash,
25 | hint, i128, i16, i8, isize, iter, marker, mem, num, ops, option, pin, ptr, result, task,
26 | time, u128, u16, u32, u8, usize,
27 | };
28 |
29 | pub(crate) mod borrow {
30 | pub(crate) use core::borrow::*;
31 | }
32 |
33 | pub(crate) mod fmt {
34 | pub(crate) use core::fmt::*;
35 | }
36 |
37 | pub(crate) mod slice {
38 | pub(crate) use core::slice::*;
39 | }
40 |
41 | pub(crate) mod str {
42 | pub(crate) use core::str::*;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tracing-journald/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-journald"
3 | version = "0.3.1"
4 | authors = ["Benjamin Saunders "]
5 | edition = "2018"
6 | license = "MIT"
7 | readme = "README.md"
8 | repository = "https://github.com/tokio-rs/tracing"
9 | homepage = "https://tokio.rs"
10 | description = "rich journald subscriber for `tracing`"
11 | categories = [
12 | "development-tools::debugging",
13 | "development-tools::profiling",
14 | ]
15 | keywords = ["tracing", "journald"]
16 | rust-version = "1.65.0"
17 |
18 | [dependencies]
19 | libc = "0.2.126"
20 | tracing-core = { path = "../tracing-core", version = "0.1.28" }
21 | tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", default-features = false, features = ["registry"] }
22 |
23 | [dev-dependencies]
24 | serde_json = "1.0.82"
25 | serde = { version = "1.0.140", features = ["derive"] }
26 | tracing = { path = "../tracing", version = "0.1.35" }
27 |
28 | [lints]
29 | workspace = true
30 |
--------------------------------------------------------------------------------
/tracing-journald/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-journald/src/memfd.rs:
--------------------------------------------------------------------------------
1 | //! memfd helpers.
2 |
3 | use libc::*;
4 | use std::fs::File;
5 | use std::io::Error;
6 | use std::io::Result;
7 | use std::os::raw::c_uint;
8 | use std::os::unix::prelude::{FromRawFd, RawFd};
9 |
10 | fn create(flags: c_uint) -> Result {
11 | let fd = memfd_create_syscall(flags);
12 | if fd < 0 {
13 | Err(Error::last_os_error())
14 | } else {
15 | Ok(unsafe { File::from_raw_fd(fd as RawFd) })
16 | }
17 | }
18 |
19 | /// Make the `memfd_create` syscall ourself instead of going through `libc`;
20 | /// `memfd_create` isn't supported on `glibc<2.27` so this allows us to
21 | /// support old-but-still-used distros like Ubuntu Xenial, Debian Stretch,
22 | /// RHEL 7, etc.
23 | ///
24 | /// See: https://github.com/tokio-rs/tracing/issues/1879
25 | fn memfd_create_syscall(flags: c_uint) -> c_int {
26 | unsafe {
27 | syscall(
28 | SYS_memfd_create,
29 | "tracing-journald\0".as_ptr() as *const c_char,
30 | flags,
31 | ) as c_int
32 | }
33 | }
34 |
35 | pub fn create_sealable() -> Result {
36 | create(MFD_ALLOW_SEALING | MFD_CLOEXEC)
37 | }
38 |
39 | pub fn seal_fully(fd: RawFd) -> Result<()> {
40 | let all_seals = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL;
41 | let result = unsafe { fcntl(fd, F_ADD_SEALS, all_seals) };
42 | if result < 0 {
43 | Err(Error::last_os_error())
44 | } else {
45 | Ok(())
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/tracing-log/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-log"
3 | version = "0.2.0"
4 | authors = ["Tokio Contributors "]
5 | edition = "2018"
6 | repository = "https://github.com/tokio-rs/tracing"
7 | homepage = "https://tokio.rs"
8 | description = """
9 | Provides compatibility between `tracing` and the `log` crate.
10 | """
11 | categories = [
12 | "development-tools::debugging",
13 | "asynchronous",
14 | ]
15 | keywords = ["logging", "tracing", "log"]
16 | license = "MIT"
17 | readme = "README.md"
18 | rust-version = "1.65.0"
19 |
20 | [features]
21 | default = ["log-tracer", "std"]
22 | std = ["log/std"]
23 | log-tracer = []
24 | interest-cache = ["lru", "ahash"]
25 |
26 | [dependencies]
27 | tracing-core = { path = "../tracing-core", version = "0.1.28"}
28 | log = { version = "0.4.17" }
29 | once_cell = "1.13.0"
30 | lru = { version = "0.7.7", optional = true }
31 | ahash = { version = "0.7.7", optional = true }
32 |
33 | [dev-dependencies]
34 | tracing = { path = "../tracing", version = "0.1.35"}
35 | tracing-subscriber = { path = "../tracing-subscriber" }
36 | criterion = { version = "0.3.6", default-features = false }
37 |
38 | [badges]
39 | maintenance = { status = "actively-maintained" }
40 |
41 | [package.metadata.docs.rs]
42 | all-features = true
43 | rustdoc-args = ["--cfg", "docsrs"]
44 |
45 | [[bench]]
46 | name = "logging"
47 | harness = false
48 |
49 | [lints]
50 | workspace = true
51 |
--------------------------------------------------------------------------------
/tracing-log/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-log/tests/reexport_log_crate.rs:
--------------------------------------------------------------------------------
1 | use tracing_log::{log::LevelFilter, LogTracer};
2 |
3 | /// This test makes sure we can access `log::LevelFilter` through the `tracing_log` crate and don't
4 | /// have to depend on `log` separately.
5 | ///
6 | /// See https://github.com/tokio-rs/tracing/issues/552.
7 | #[test]
8 | fn can_initialize_log_tracer_with_level() {
9 | LogTracer::init_with_filter(LevelFilter::Error).unwrap();
10 | }
11 |
--------------------------------------------------------------------------------
/tracing-macros/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-macros"
3 | version = "0.1.0"
4 | authors = ["Eliza Weisman "]
5 | edition = "2018"
6 | repository = "https://github.com/tokio-rs/tracing"
7 | homepage = "https://tokio.rs"
8 | description = """
9 | Macros for emitting trace events
10 | """
11 | categories = [
12 | "development-tools::debugging",
13 | "development-tools::profiling",
14 | "asynchronous",
15 | ]
16 | keywords = ["logging", "tracing"]
17 | license = "MIT"
18 | rust-version = "1.65.0"
19 |
20 | [dependencies]
21 | tracing = { path = "../tracing", version = "0.1.35" }
22 |
23 | [dev-dependencies]
24 | tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", features = ["env-filter"] }
25 |
26 | [badges]
27 | maintenance = { status = "experimental" }
28 |
29 | [lints]
30 | workspace = true
31 |
--------------------------------------------------------------------------------
/tracing-macros/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-macros/examples/factorial.rs:
--------------------------------------------------------------------------------
1 | //! Compare to the example given in the documentation for the `std::dbg` macro.
2 | #![deny(rust_2018_idioms)]
3 |
4 | use tracing_macros::dbg;
5 | use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter};
6 |
7 | fn factorial(n: u32) -> u32 {
8 | if dbg!(n <= 1) {
9 | dbg!(1)
10 | } else {
11 | dbg!(n * factorial(n - 1))
12 | }
13 | }
14 |
15 | fn main() {
16 | let subscriber = tracing_subscriber::registry()
17 | .with(EnvFilter::from_default_env().add_directive(tracing::Level::TRACE.into()))
18 | .with(fmt::Layer::new());
19 |
20 | tracing::subscriber::set_global_default(subscriber).expect("Unable to set a global subscriber");
21 | dbg!(factorial(4));
22 | }
23 |
--------------------------------------------------------------------------------
/tracing-macros/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
2 | #[doc(hidden)]
3 | pub use tracing;
4 |
5 | /// Alias of `dbg!` for avoiding conflicts with the `std::dbg!` macro.
6 | #[macro_export]
7 | macro_rules! trace_dbg {
8 | (target: $target:expr, level: $level:expr, $ex:expr) => {
9 | $crate::dbg!(target: $target, level: $level, $ex)
10 | };
11 | (level: $level:expr, $ex:expr) => {
12 | $crate::dbg!(target: module_path!(), level: $level, $ex)
13 | };
14 | (target: $target:expr, $ex:expr) => {
15 | $crate::dbg!(target: $target, level: $crate::tracing::Level::DEBUG, $ex)
16 | };
17 | ($ex:expr) => {
18 | $crate::dbg!(level: $crate::tracing::Level::DEBUG, $ex)
19 | };
20 | }
21 |
22 | /// Similar to the `std::dbg!` macro, but generates `tracing` events rather
23 | /// than printing to stdout.
24 | ///
25 | /// By default, the verbosity level for the generated events is `DEBUG`, but
26 | /// this can be customized.
27 | #[macro_export]
28 | macro_rules! dbg {
29 | (target: $target:expr, level: $level:expr, $ex:expr) => {{
30 | match $ex {
31 | value => {
32 | $crate::tracing::event!(target: $target, $level, ?value, stringify!($ex));
33 | value
34 | }
35 | }
36 | }};
37 | (level: $level:expr, $ex:expr) => {
38 | $crate::dbg!(target: module_path!(), level: $level, $ex)
39 | };
40 | (target: $target:expr, $ex:expr) => {
41 | $crate::dbg!(target: $target, level: $crate::tracing::Level::DEBUG, $ex)
42 | };
43 | ($ex:expr) => {
44 | $crate::dbg!(level: $crate::tracing::Level::DEBUG, $ex)
45 | };
46 | }
47 |
--------------------------------------------------------------------------------
/tracing-mock/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 0.1.0-beta.1 (November 29, 2024)
2 |
3 | [ [crates.io][crate-0.1.0-beta.1] ] | [ [docs.rs][docs-0.1.0-beta.1] ]
4 |
5 | `tracing-mock` provides tools for making assertions about what `tracing`
6 | diagnostics are emitted by code under test.
7 |
8 | - Initial beta release
9 |
10 | [docs-0.1.0-beta.1]: https://docs.rs/tracing-mock/0.1.0-beta.1
11 | [crate-0.1.0-beta.1]: https://crates.io/crates/tracing-mock/0.1.0-beta.1
12 |
--------------------------------------------------------------------------------
/tracing-mock/Cargo.toml:
--------------------------------------------------------------------------------
1 | ## BIG SCARY NOTE
2 | # This Cargo.toml does not match the repo conventions YET
3 | # Before releasing to crates.io: make it so!
4 |
5 | [package]
6 | name = "tracing-mock"
7 | version = "0.1.0-beta.1"
8 | authors = [
9 | "Eliza Weisman ",
10 | "Hayden Stainsby ",
11 | "Tokio Contributors ",
12 | ]
13 | license = "MIT"
14 | readme = "README.md"
15 | repository = "https://github.com/tokio-rs/tracing"
16 | homepage = "https://tokio.rs"
17 | description = """
18 | Utilities for testing `tracing` and crates that uses it.
19 | """
20 | categories = [
21 | "development-tools::testing"
22 | ]
23 | keywords = [
24 | "tracing",
25 | "mock",
26 | "testing"
27 | ]
28 | edition = "2018"
29 | rust-version = "1.65.0"
30 |
31 | [dependencies]
32 | tracing = { path = "../tracing", version = "0.1.41", features = ["std", "attributes"], default-features = false }
33 | tracing-core = { path = "../tracing-core", version = "0.1.28", default-features = false }
34 | tracing-subscriber = { path = "../tracing-subscriber", version = "0.3", default-features = false, features = ["registry"], optional = true }
35 |
36 | # Fix minimal-versions; tokio-test fails with otherwise acceptable 0.1.0
37 | tokio-stream = { version = "0.1.9", optional = true }
38 |
39 | [package.metadata.docs.rs]
40 | all-features = true
41 | rustdoc-args = ["--cfg", "docsrs"]
42 |
43 | [lints]
44 | workspace = true
45 |
--------------------------------------------------------------------------------
/tracing-mock/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-mock/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![doc = include_str!("../README.md")]
2 | #![cfg_attr(
3 | docsrs,
4 | // Allows displaying cfgs/feature flags in the documentation.
5 | feature(doc_cfg),
6 | // Fail the docs build if any intra-docs links are broken
7 | deny(rustdoc::broken_intra_doc_links),
8 | )]
9 | #![doc(
10 | html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/main/assets/logo-type.png",
11 | html_favicon_url = "https://raw.githubusercontent.com/tokio-rs/tracing/main/assets/favicon.ico",
12 | issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
13 | )]
14 | #![warn(
15 | missing_debug_implementations,
16 | missing_docs,
17 | rust_2018_idioms,
18 | unreachable_pub,
19 | bad_style,
20 | dead_code,
21 | improper_ctypes,
22 | non_shorthand_field_patterns,
23 | no_mangle_generic_items,
24 | overflowing_literals,
25 | path_statements,
26 | patterns_in_fns_without_body,
27 | private_interfaces,
28 | private_bounds,
29 | unconditional_recursion,
30 | unused,
31 | unused_allocation,
32 | unused_comparisons,
33 | unused_parens,
34 | while_true
35 | )]
36 |
37 | pub mod ancestry;
38 | pub mod event;
39 | pub mod expect;
40 | pub mod field;
41 | mod metadata;
42 | pub mod span;
43 | pub mod subscriber;
44 |
45 | #[cfg(feature = "tracing-subscriber")]
46 | pub mod layer;
47 |
--------------------------------------------------------------------------------
/tracing-serde/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 0.2.0 (November 27, 2024)
2 |
3 | [ [crates.io][crate-0.2.0] ] | [ [docs.rs][docs-0.2.0] ]
4 |
5 |
6 | ### Breaking Changes
7 |
8 | - Correct SerializeField definition and doc formatting ([#3040])
9 | `SerializeField` has gained a generic lifetime parameter.
10 |
11 | ### Fixed
12 |
13 | - Implement `AsSerde` for `FieldSet` ([#2241])
14 | - [**breaking**](#0.2.0-breaking) Correct SerializeField definition and doc formatting ([#3040])
15 |
16 | ### Changed
17 |
18 | - Bump MSRV to 1.63 ([#2793])
19 |
20 | [#2241]: https://github.com/tokio-rs/tracing/pull/2241
21 | [#3040]: https://github.com/tokio-rs/tracing/pull/3040
22 | [docs-0.2.0]: https://docs.rs/tracing-serde/0.2.0/tracing-serde/
23 | [crate-0.2.0]: https://crates.io/crates/tracing-serde/0.2.0
24 |
25 | # 0.1.3 (February 4, 2022)
26 |
27 | This release adds *experimental* support for recording structured field
28 | values using the [`valuable`] crate. See [this blog post][post] for
29 | details on `valuable`.
30 |
31 | Note that `valuable` support currently requires `--cfg
32 | tracing_unstable`. See the documentation for details.
33 |
34 | ### Added
35 |
36 | - **valuable**: Experimental support for serializing user-defined types using
37 | [`valuable`] and [`valuable-serde`] ([#1862])
38 | - Support for serializing `f64` values ([#1507])
39 |
40 | ### Fixed
41 |
42 | - Fixed incorrect size hint in `SerializeFieldSet` ([#1333])
43 | - A number of documentation fixes
44 |
45 | Thanks to @akinnane and @maxburke for contributing to this release!
46 |
47 | [`valuable`]: https://crates.io/crates/valuable
48 | [`valuable-serde`]: https://crates.io/crates/valuable-serde
49 | [post]: https://tokio.rs/blog/2021-05-valuable
50 | [#1862]: https://github.com/tokio-rs/tracing/pull/1862
51 | [#1507]: https://github.com/tokio-rs/tracing/pull/1507
52 | [#1333]: https://github.com/tokio-rs/tracing/pull/1333
53 |
54 | # 0.1.2 (September 11, 2020)
55 |
56 | ### Added
57 |
58 | - `SerdeMapVisitor::finish` to complete serializing the visited objects
59 | (#892)
60 | - `SerdeMapVisitor::take_serializer` to return the serializer wrapped by
61 | a `SerdeMapVisitor` (#892)
62 |
63 | # 0.1.1 (February 27, 2020)
64 |
65 | ### Added
66 |
67 | - Made `SerdeMapVisitor` public (#599)
68 | - Made `SerdeStructVisitor` public (#599)
69 |
70 | # 0.1.0 (November 18, 2019)
71 |
72 | - Initial release
73 |
--------------------------------------------------------------------------------
/tracing-serde/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-serde"
3 | version = "0.2.0"
4 | authors = ["Tokio Contributors "]
5 | license = "MIT"
6 | edition = "2018"
7 | repository = "https://github.com/tokio-rs/tracing"
8 | homepage = "https://tokio.rs"
9 | description = """
10 | A compatibility layer for serializing trace data with `serde`
11 | """
12 | categories = [
13 | "development-tools::debugging",
14 | "development-tools::profiling",
15 | "asynchronous",
16 | "encoding",
17 | ]
18 | keywords = ["logging", "tracing", "serialization"]
19 | rust-version = "1.65.0"
20 |
21 | [features]
22 | valuable = ["valuable_crate", "valuable-serde", "tracing-core/valuable"]
23 |
24 | [dependencies]
25 | serde = "1"
26 | tracing-core = { path = "../tracing-core", version = "0.1.28"}
27 |
28 | [dev-dependencies]
29 | serde_json = "1"
30 |
31 | [target.'cfg(tracing_unstable)'.dependencies]
32 | valuable_crate = { package = "valuable", version = "0.1.0", optional = true, default-features = false }
33 | valuable-serde = { version = "0.1.0", optional = true, default-features = false }
34 |
35 | [badges]
36 | maintenance = { status = "experimental" }
37 |
38 | [lints]
39 | workspace = true
40 |
--------------------------------------------------------------------------------
/tracing-serde/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-serde/src/fields.rs:
--------------------------------------------------------------------------------
1 | //! Support for serializing fields as `serde` structs or maps.
2 | use super::*;
3 |
4 | #[derive(Debug)]
5 | pub struct SerializeFieldMap<'a, T>(&'a T);
6 |
7 | pub trait AsMap: Sized + sealed::Sealed {
8 | fn field_map(&self) -> SerializeFieldMap<'_, Self> {
9 | SerializeFieldMap(self)
10 | }
11 | }
12 |
13 | impl AsMap for Event<'_> {}
14 | impl AsMap for Attributes<'_> {}
15 | impl AsMap for Record<'_> {}
16 |
17 | // === impl SerializeFieldMap ===
18 |
19 | impl Serialize for SerializeFieldMap<'_, Event<'_>> {
20 | fn serialize(&self, serializer: S) -> Result
21 | where
22 | S: Serializer,
23 | {
24 | let len = self.0.fields().count();
25 | let serializer = serializer.serialize_map(Some(len))?;
26 | let mut visitor = SerdeMapVisitor::new(serializer);
27 | self.0.record(&mut visitor);
28 | visitor.finish()
29 | }
30 | }
31 |
32 | impl Serialize for SerializeFieldMap<'_, Attributes<'_>> {
33 | fn serialize(&self, serializer: S) -> Result
34 | where
35 | S: Serializer,
36 | {
37 | let len = self.0.metadata().fields().len();
38 | let serializer = serializer.serialize_map(Some(len))?;
39 | let mut visitor = SerdeMapVisitor::new(serializer);
40 | self.0.record(&mut visitor);
41 | visitor.finish()
42 | }
43 | }
44 |
45 | impl Serialize for SerializeFieldMap<'_, Record<'_>> {
46 | fn serialize(&self, serializer: S) -> Result
47 | where
48 | S: Serializer,
49 | {
50 | let serializer = serializer.serialize_map(None)?;
51 | let mut visitor = SerdeMapVisitor::new(serializer);
52 | self.0.record(&mut visitor);
53 | visitor.finish()
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tracing-subscriber/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-subscriber/benches/enter.rs:
--------------------------------------------------------------------------------
1 | use criterion::{criterion_group, criterion_main, Criterion};
2 | use tracing_subscriber::prelude::*;
3 |
4 | fn enter(c: &mut Criterion) {
5 | let mut group = c.benchmark_group("enter");
6 | let _subscriber = tracing_subscriber::fmt()
7 | .with_max_level(tracing::Level::INFO)
8 | .finish()
9 | .set_default();
10 | group.bench_function("enabled", |b| {
11 | let span = tracing::info_span!("foo");
12 | b.iter_with_large_drop(|| span.enter())
13 | });
14 | group.bench_function("disabled", |b| {
15 | let span = tracing::debug_span!("foo");
16 | b.iter_with_large_drop(|| span.enter())
17 | });
18 | }
19 |
20 | fn enter_exit(c: &mut Criterion) {
21 | let mut group = c.benchmark_group("enter_exit");
22 | let _subscriber = tracing_subscriber::fmt()
23 | .with_max_level(tracing::Level::INFO)
24 | .finish()
25 | .set_default();
26 | group.bench_function("enabled", |b| {
27 | let span = tracing::info_span!("foo");
28 | b.iter(|| span.enter())
29 | });
30 | group.bench_function("disabled", |b| {
31 | let span = tracing::debug_span!("foo");
32 | b.iter(|| span.enter())
33 | });
34 | }
35 |
36 | fn enter_many(c: &mut Criterion) {
37 | let mut group = c.benchmark_group("enter_many");
38 | let _subscriber = tracing_subscriber::fmt()
39 | .with_max_level(tracing::Level::INFO)
40 | .finish()
41 | .set_default();
42 | group.bench_function("enabled", |b| {
43 | let span1 = tracing::info_span!("span1");
44 | let _e1 = span1.enter();
45 | let span2 = tracing::info_span!("span2");
46 | let _e2 = span2.enter();
47 | let span3 = tracing::info_span!("span3");
48 | let _e3 = span3.enter();
49 | let span = tracing::info_span!("foo");
50 | b.iter_with_large_drop(|| span.enter())
51 | });
52 | group.bench_function("disabled", |b| {
53 | let span1 = tracing::info_span!("span1");
54 | let _e1 = span1.enter();
55 | let span2 = tracing::info_span!("span2");
56 | let _e2 = span2.enter();
57 | let span3 = tracing::info_span!("span3");
58 | let _e3 = span3.enter();
59 | let span = tracing::debug_span!("foo");
60 | b.iter_with_large_drop(|| span.enter())
61 | });
62 | }
63 | criterion_group!(benches, enter, enter_exit, enter_many);
64 | criterion_main!(benches);
65 |
--------------------------------------------------------------------------------
/tracing-subscriber/benches/support/mod.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | sync::{Arc, Barrier},
3 | thread,
4 | time::{Duration, Instant},
5 | };
6 | use tracing::dispatcher::Dispatch;
7 |
8 | #[derive(Clone)]
9 | pub(super) struct MultithreadedBench {
10 | start: Arc,
11 | end: Arc,
12 | dispatch: Dispatch,
13 | }
14 |
15 | impl MultithreadedBench {
16 | pub(super) fn new(dispatch: Dispatch) -> Self {
17 | Self {
18 | start: Arc::new(Barrier::new(5)),
19 | end: Arc::new(Barrier::new(5)),
20 | dispatch,
21 | }
22 | }
23 |
24 | pub(super) fn thread(&self, f: impl FnOnce() + Send + 'static) -> &Self {
25 | self.thread_with_setup(|start| {
26 | start.wait();
27 | f()
28 | })
29 | }
30 |
31 | pub(super) fn thread_with_setup(&self, f: impl FnOnce(&Barrier) + Send + 'static) -> &Self {
32 | let this = self.clone();
33 | thread::spawn(move || {
34 | let dispatch = this.dispatch.clone();
35 | tracing::dispatcher::with_default(&dispatch, move || {
36 | f(&this.start);
37 | this.end.wait();
38 | })
39 | });
40 | self
41 | }
42 |
43 | pub(super) fn run(&self) -> Duration {
44 | self.start.wait();
45 | let t0 = Instant::now();
46 | self.end.wait();
47 | t0.elapsed()
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tracing-subscriber/src/filter/level.rs:
--------------------------------------------------------------------------------
1 | use tracing_core::{
2 | subscriber::{Interest, Subscriber},
3 | Metadata,
4 | };
5 |
6 | #[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
7 | pub use tracing_core::metadata::{LevelFilter, ParseLevelFilterError as ParseError};
8 |
9 | // === impl LevelFilter ===
10 |
11 | impl crate::Layer for LevelFilter {
12 | fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
13 | if self >= metadata.level() {
14 | Interest::always()
15 | } else {
16 | Interest::never()
17 | }
18 | }
19 |
20 | fn enabled(&self, metadata: &Metadata<'_>, _: crate::layer::Context<'_, S>) -> bool {
21 | self >= metadata.level()
22 | }
23 |
24 | fn max_level_hint(&self) -> Option {
25 | Some(*self)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tracing-subscriber/src/filter/mod.rs:
--------------------------------------------------------------------------------
1 | //! [`Layer`]s that control which spans and events are enabled by the wrapped
2 | //! subscriber.
3 | //!
4 | //! This module contains a number of types that provide implementations of
5 | //! various strategies for filtering which spans and events are enabled. For
6 | //! details on filtering spans and events using [`Layer`]s, see the
7 | //! [`layer` module's documentation].
8 | //!
9 | //! [`layer` module's documentation]: crate::layer#filtering-with-layers
10 | //! [`Layer`]: crate::layer
11 | mod filter_fn;
12 |
13 | feature! {
14 | #![all(feature = "env-filter", feature = "std")]
15 | mod env;
16 | pub use self::env::*;
17 | }
18 |
19 | feature! {
20 | #![all(feature = "registry", feature = "std")]
21 | mod layer_filters;
22 | pub use self::layer_filters::*;
23 | }
24 |
25 | mod level;
26 |
27 | pub use self::filter_fn::*;
28 | pub use self::level::{LevelFilter, ParseError as LevelParseError};
29 |
30 | #[cfg(not(all(feature = "registry", feature = "std")))]
31 | pub(crate) use self::has_plf_stubs::*;
32 |
33 | feature! {
34 | #![any(feature = "std", feature = "alloc")]
35 | pub mod targets;
36 | pub use self::targets::Targets;
37 |
38 | mod directive;
39 | pub use self::directive::ParseError;
40 | }
41 |
42 | /// Stub implementations of the per-layer-filter detection functions for when the
43 | /// `registry` feature is disabled.
44 | #[cfg(not(all(feature = "registry", feature = "std")))]
45 | mod has_plf_stubs {
46 | pub(crate) fn is_plf_downcast_marker(_: core::any::TypeId) -> bool {
47 | false
48 | }
49 |
50 | /// Does a type implementing `Subscriber` contain any per-layer filters?
51 | pub(crate) fn subscriber_has_plf(_: &S) -> bool
52 | where
53 | S: tracing_core::Subscriber,
54 | {
55 | false
56 | }
57 |
58 | /// Does a type implementing `Layer` contain any per-layer filters?
59 | pub(crate) fn layer_has_plf(_: &L) -> bool
60 | where
61 | L: crate::Layer,
62 | S: tracing_core::Subscriber,
63 | {
64 | false
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tracing-subscriber/src/macros.rs:
--------------------------------------------------------------------------------
1 | #[cfg(feature = "std")]
2 | macro_rules! try_lock {
3 | ($lock:expr) => {
4 | try_lock!($lock, else return)
5 | };
6 | ($lock:expr, else $els:expr) => {
7 | if let ::core::result::Result::Ok(l) = $lock {
8 | l
9 | } else if std::thread::panicking() {
10 | $els
11 | } else {
12 | panic!("lock poisoned")
13 | }
14 | };
15 | }
16 |
17 | macro_rules! feature {
18 | (
19 | #![$meta:meta]
20 | $($item:item)*
21 | ) => {
22 | $(
23 | #[cfg($meta)]
24 | #[cfg_attr(docsrs, doc(cfg($meta)))]
25 | $item
26 | )*
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tracing-subscriber/src/prelude.rs:
--------------------------------------------------------------------------------
1 | //! The `tracing-subscriber` prelude.
2 | //!
3 | //! This brings into scope a number of extension traits that define methods on
4 | //! types defined here and in other crates.
5 |
6 | pub use crate::field::{
7 | MakeExt as __tracing_subscriber_field_MakeExt,
8 | RecordFields as __tracing_subscriber_field_RecordFields,
9 | };
10 | pub use crate::layer::{
11 | Layer as __tracing_subscriber_Layer, SubscriberExt as __tracing_subscriber_SubscriberExt,
12 | };
13 |
14 | pub use crate::util::SubscriberInitExt as _;
15 |
16 | feature! {
17 | #![all(feature = "fmt", feature = "std")]
18 | pub use crate::fmt::writer::MakeWriterExt as _;
19 | }
20 |
--------------------------------------------------------------------------------
/tracing-subscriber/src/registry/stack.rs:
--------------------------------------------------------------------------------
1 | pub(crate) use tracing_core::span::Id;
2 |
3 | #[derive(Debug)]
4 | struct ContextId {
5 | id: Id,
6 | duplicate: bool,
7 | }
8 |
9 | /// `SpanStack` tracks what spans are currently executing on a thread-local basis.
10 | ///
11 | /// A "separate current span" for each thread is a semantic choice, as each span
12 | /// can be executing in a different thread.
13 | #[derive(Debug, Default)]
14 | pub(crate) struct SpanStack {
15 | stack: Vec,
16 | }
17 |
18 | impl SpanStack {
19 | #[inline]
20 | pub(super) fn push(&mut self, id: Id) -> bool {
21 | let duplicate = self.stack.iter().any(|i| i.id == id);
22 | self.stack.push(ContextId { id, duplicate });
23 | !duplicate
24 | }
25 |
26 | #[inline]
27 | pub(super) fn pop(&mut self, expected_id: &Id) -> bool {
28 | if let Some((idx, _)) = self
29 | .stack
30 | .iter()
31 | .enumerate()
32 | .rev()
33 | .find(|(_, ctx_id)| ctx_id.id == *expected_id)
34 | {
35 | let ContextId { id: _, duplicate } = self.stack.remove(idx);
36 | return !duplicate;
37 | }
38 | false
39 | }
40 |
41 | #[inline]
42 | pub(crate) fn iter(&self) -> impl Iterator- {
43 | self.stack
44 | .iter()
45 | .rev()
46 | .filter_map(|ContextId { id, duplicate }| if !*duplicate { Some(id) } else { None })
47 | }
48 |
49 | #[inline]
50 | pub(crate) fn current(&self) -> Option<&Id> {
51 | self.iter().next()
52 | }
53 | }
54 |
55 | #[cfg(test)]
56 | mod tests {
57 | use super::{Id, SpanStack};
58 |
59 | #[test]
60 | fn pop_last_span() {
61 | let mut stack = SpanStack::default();
62 | let id = Id::from_u64(1);
63 | stack.push(id.clone());
64 |
65 | assert!(stack.pop(&id));
66 | }
67 |
68 | #[test]
69 | fn pop_first_span() {
70 | let mut stack = SpanStack::default();
71 | stack.push(Id::from_u64(1));
72 | stack.push(Id::from_u64(2));
73 |
74 | let id = Id::from_u64(1);
75 | assert!(stack.pop(&id));
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/tracing-subscriber/src/sync.rs:
--------------------------------------------------------------------------------
1 | //! Abstracts over sync primitive implementations.
2 | //!
3 | //! Optionally, we allow the Rust standard library's `RwLock` to be replaced
4 | //! with the `parking_lot` crate's implementation. This may provide improved
5 | //! performance in some cases. However, the `parking_lot` dependency is an
6 | //! opt-in feature flag. Because `parking_lot::RwLock` has a slightly different
7 | //! API than `std::sync::RwLock` (it does not support poisoning on panics), we
8 | //! wrap it with a type that provides the same method signatures. This allows us
9 | //! to transparently swap `parking_lot` in without changing code at the callsite.
10 | #[allow(unused_imports)] // may be used later;
11 | pub(crate) use std::sync::{LockResult, PoisonError, TryLockResult};
12 |
13 | #[cfg(not(feature = "parking_lot"))]
14 | pub(crate) use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
15 |
16 | #[cfg(feature = "parking_lot")]
17 | pub(crate) use self::parking_lot_impl::*;
18 |
19 | #[cfg(feature = "parking_lot")]
20 | mod parking_lot_impl {
21 | pub(crate) use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
22 | use std::sync::{LockResult, TryLockError, TryLockResult};
23 |
24 | #[derive(Debug)]
25 | pub(crate) struct RwLock {
26 | inner: parking_lot::RwLock,
27 | }
28 |
29 | impl RwLock {
30 | pub(crate) fn new(val: T) -> Self {
31 | Self {
32 | inner: parking_lot::RwLock::new(val),
33 | }
34 | }
35 |
36 | #[inline]
37 | pub(crate) fn get_mut(&mut self) -> LockResult<&mut T> {
38 | Ok(self.inner.get_mut())
39 | }
40 |
41 | #[inline]
42 | pub(crate) fn read(&self) -> LockResult> {
43 | Ok(self.inner.read())
44 | }
45 |
46 | #[inline]
47 | #[allow(dead_code)] // may be used later;
48 | pub(crate) fn try_read(&self) -> TryLockResult> {
49 | self.inner.try_read().ok_or(TryLockError::WouldBlock)
50 | }
51 |
52 | #[inline]
53 | pub(crate) fn write(&self) -> LockResult> {
54 | Ok(self.inner.write())
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/duplicate_spans.rs:
--------------------------------------------------------------------------------
1 | #![cfg(all(feature = "env-filter", feature = "fmt"))]
2 | use tracing::{self, subscriber::with_default, Span};
3 | use tracing_subscriber::{filter::EnvFilter, FmtSubscriber};
4 |
5 | #[test]
6 | fn duplicate_spans() {
7 | let subscriber = FmtSubscriber::builder()
8 | .with_env_filter(EnvFilter::new("[root]=debug"))
9 | .finish();
10 |
11 | with_default(subscriber, || {
12 | let root = tracing::debug_span!("root");
13 | root.in_scope(|| {
14 | // root:
15 | assert_eq!(root, Span::current(), "Current span must be 'root'");
16 | let leaf = tracing::debug_span!("leaf");
17 | leaf.in_scope(|| {
18 | // root:leaf:
19 | assert_eq!(leaf, Span::current(), "Current span must be 'leaf'");
20 | root.in_scope(|| {
21 | // root:leaf:
22 | assert_eq!(
23 | leaf,
24 | Span::current(),
25 | "Current span must be 'leaf' after entering twice the 'root' span"
26 | );
27 | })
28 | });
29 | // root:
30 | assert_eq!(
31 | root,
32 | Span::current(),
33 | "Current span must be root ('leaf' exited, nested 'root' exited)"
34 | );
35 |
36 | root.in_scope(|| {
37 | assert_eq!(root, Span::current(), "Current span must be root");
38 | });
39 | // root:
40 | assert_eq!(
41 | root,
42 | Span::current(),
43 | "Current span must still be root after exiting nested 'root'"
44 | );
45 | });
46 | });
47 | }
48 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/event_enabling.rs:
--------------------------------------------------------------------------------
1 | #![cfg(feature = "registry")]
2 |
3 | use std::sync::{Arc, Mutex};
4 | use tracing::{subscriber::with_default, Event, Metadata, Subscriber};
5 | use tracing_subscriber::{layer::Context, prelude::*, registry, Layer};
6 |
7 | struct TrackingLayer {
8 | enabled: bool,
9 | event_enabled_count: Arc>,
10 | event_enabled: bool,
11 | on_event_count: Arc>,
12 | }
13 |
14 | impl Layer for TrackingLayer
15 | where
16 | C: Subscriber + Send + Sync + 'static,
17 | {
18 | fn enabled(&self, _metadata: &Metadata<'_>, _ctx: Context<'_, C>) -> bool {
19 | self.enabled
20 | }
21 |
22 | fn event_enabled(&self, _event: &Event<'_>, _ctx: Context<'_, C>) -> bool {
23 | *self.event_enabled_count.lock().unwrap() += 1;
24 | self.event_enabled
25 | }
26 |
27 | fn on_event(&self, _event: &Event<'_>, _ctx: Context<'_, C>) {
28 | *self.on_event_count.lock().unwrap() += 1;
29 | }
30 | }
31 |
32 | #[test]
33 | fn event_enabled_is_only_called_once() {
34 | let event_enabled_count = Arc::new(Mutex::default());
35 | let count = event_enabled_count.clone();
36 | let subscriber = registry().with(TrackingLayer {
37 | enabled: true,
38 | event_enabled_count,
39 | event_enabled: true,
40 | on_event_count: Arc::new(Mutex::default()),
41 | });
42 | with_default(subscriber, || {
43 | tracing::error!("hiya!");
44 | });
45 |
46 | assert_eq!(1, *count.lock().unwrap());
47 | }
48 |
49 | #[test]
50 | fn event_enabled_not_called_when_not_enabled() {
51 | let event_enabled_count = Arc::new(Mutex::default());
52 | let count = event_enabled_count.clone();
53 | let subscriber = registry().with(TrackingLayer {
54 | enabled: false,
55 | event_enabled_count,
56 | event_enabled: true,
57 | on_event_count: Arc::new(Mutex::default()),
58 | });
59 | with_default(subscriber, || {
60 | tracing::error!("hiya!");
61 | });
62 |
63 | assert_eq!(0, *count.lock().unwrap());
64 | }
65 |
66 | #[test]
67 | fn event_disabled_does_disable_event() {
68 | let on_event_count = Arc::new(Mutex::default());
69 | let count = on_event_count.clone();
70 | let subscriber = registry().with(TrackingLayer {
71 | enabled: true,
72 | event_enabled_count: Arc::new(Mutex::default()),
73 | event_enabled: false,
74 | on_event_count,
75 | });
76 | with_default(subscriber, || {
77 | tracing::error!("hiya!");
78 | });
79 |
80 | assert_eq!(0, *count.lock().unwrap());
81 | }
82 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/filter_log.rs:
--------------------------------------------------------------------------------
1 | #![cfg(all(feature = "env-filter", feature = "tracing-log"))]
2 |
3 | use tracing::{self, Level};
4 | use tracing_mock::*;
5 | use tracing_subscriber::{filter::EnvFilter, prelude::*};
6 |
7 | mod my_module {
8 | pub(crate) fn test_records() {
9 | log::trace!("this should be disabled");
10 | log::info!("this shouldn't be");
11 | log::debug!("this should be disabled");
12 | log::warn!("this should be enabled");
13 | log::warn!(target: "something else", "this shouldn't be enabled");
14 | log::error!("this should be enabled too");
15 | }
16 |
17 | pub(crate) fn test_log_enabled() {
18 | assert!(
19 | log::log_enabled!(log::Level::Info),
20 | "info should be enabled inside `my_module`"
21 | );
22 | assert!(
23 | !log::log_enabled!(log::Level::Debug),
24 | "debug should not be enabled inside `my_module`"
25 | );
26 | assert!(
27 | log::log_enabled!(log::Level::Warn),
28 | "warn should be enabled inside `my_module`"
29 | );
30 | }
31 | }
32 |
33 | #[test]
34 | fn log_is_enabled() {
35 | let filter: EnvFilter = "filter_log::my_module=info"
36 | .parse()
37 | .expect("filter should parse");
38 | let (subscriber, finished) = subscriber::mock()
39 | .event(expect::event().at_level(Level::INFO))
40 | .event(expect::event().at_level(Level::WARN))
41 | .event(expect::event().at_level(Level::ERROR))
42 | .only()
43 | .run_with_handle();
44 |
45 | // Note: we have to set the global default in order to set the `log` max
46 | // level, which can only be set once.
47 | subscriber.with(filter).init();
48 |
49 | my_module::test_records();
50 | log::info!("this is disabled");
51 |
52 | my_module::test_log_enabled();
53 | assert!(
54 | !log::log_enabled!(log::Level::Info),
55 | "info should not be enabled outside `my_module`"
56 | );
57 | assert!(
58 | !log::log_enabled!(log::Level::Warn),
59 | "warn should not be enabled outside `my_module`"
60 | );
61 |
62 | finished.assert_finished();
63 | }
64 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/fmt_max_level_hint.rs:
--------------------------------------------------------------------------------
1 | #![cfg(feature = "fmt")]
2 | use tracing_subscriber::filter::LevelFilter;
3 |
4 | #[test]
5 | fn fmt_sets_max_level_hint() {
6 | tracing_subscriber::fmt()
7 | .with_max_level(LevelFilter::DEBUG)
8 | .init();
9 | assert_eq!(LevelFilter::current(), LevelFilter::DEBUG);
10 | }
11 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/layer_filter_interests_are_cached.rs:
--------------------------------------------------------------------------------
1 | #![cfg(feature = "registry")]
2 | use std::{
3 | collections::HashMap,
4 | sync::{Arc, Mutex},
5 | };
6 | use tracing::{Level, Subscriber};
7 | use tracing_mock::{expect, layer};
8 | use tracing_subscriber::{filter, prelude::*};
9 |
10 | #[test]
11 | fn layer_filter_interests_are_cached() {
12 | let seen = Arc::new(Mutex::new(HashMap::new()));
13 | let seen2 = seen.clone();
14 | let filter = filter::filter_fn(move |meta| {
15 | *seen
16 | .lock()
17 | .unwrap()
18 | .entry(meta.callsite())
19 | .or_insert(0usize) += 1;
20 | meta.level() == &Level::INFO
21 | });
22 |
23 | let (expect, handle) = layer::mock()
24 | .event(expect::event().at_level(Level::INFO))
25 | .event(expect::event().at_level(Level::INFO))
26 | .only()
27 | .run_with_handle();
28 |
29 | let subscriber = tracing_subscriber::registry().with(expect.with_filter(filter));
30 | assert!(subscriber.max_level_hint().is_none());
31 |
32 | let _subscriber = subscriber.set_default();
33 |
34 | fn events() {
35 | tracing::trace!("hello trace");
36 | tracing::debug!("hello debug");
37 | tracing::info!("hello info");
38 | tracing::warn!("hello warn");
39 | tracing::error!("hello error");
40 | }
41 |
42 | events();
43 | {
44 | let lock = seen2.lock().unwrap();
45 | for (callsite, &count) in lock.iter() {
46 | assert_eq!(
47 | count, 1,
48 | "callsite {:?} should have been seen 1 time (after first set of events)",
49 | callsite
50 | );
51 | }
52 | }
53 |
54 | events();
55 | {
56 | let lock = seen2.lock().unwrap();
57 | for (callsite, &count) in lock.iter() {
58 | assert_eq!(
59 | count, 1,
60 | "callsite {:?} should have been seen 1 time (after second set of events)",
61 | callsite
62 | );
63 | }
64 | }
65 |
66 | handle.assert_finished();
67 | }
68 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/layer_filters/boxed.rs:
--------------------------------------------------------------------------------
1 | use super::*;
2 | use tracing_mock::layer::MockLayer;
3 | use tracing_subscriber::{filter, prelude::*, Layer};
4 |
5 | fn layer() -> (MockLayer, subscriber::MockHandle) {
6 | layer::mock().only().run_with_handle()
7 | }
8 |
9 | fn filter
() -> filter::DynFilterFn {
10 | // Use dynamic filter fn to disable interest caching and max-level hints,
11 | // allowing us to put all of these tests in the same file.
12 | filter::dynamic_filter_fn(|_, _| false)
13 | }
14 |
15 | /// reproduces https://github.com/tokio-rs/tracing/issues/1563#issuecomment-921363629
16 | #[test]
17 | fn box_works() {
18 | let (layer, handle) = layer();
19 | let layer = Box::new(layer.with_filter(filter()));
20 |
21 | let _guard = tracing_subscriber::registry().with(layer).set_default();
22 |
23 | for i in 0..2 {
24 | tracing::info!(i);
25 | }
26 |
27 | handle.assert_finished();
28 | }
29 |
30 | /// the same as `box_works` but with a type-erased `Box`.
31 | #[test]
32 | fn dyn_box_works() {
33 | let (layer, handle) = layer();
34 | let layer: Box + Send + Sync + 'static> = Box::new(layer.with_filter(filter()));
35 |
36 | let _guard = tracing_subscriber::registry().with(layer).set_default();
37 |
38 | for i in 0..2 {
39 | tracing::info!(i);
40 | }
41 |
42 | handle.assert_finished();
43 | }
44 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/layer_filters/combinators.rs:
--------------------------------------------------------------------------------
1 | use super::*;
2 | use tracing_subscriber::{
3 | filter::{filter_fn, FilterExt, LevelFilter},
4 | prelude::*,
5 | };
6 |
7 | #[test]
8 | fn and() {
9 | let (layer, handle) = layer::mock()
10 | .event(
11 | event::msg("a very interesting event")
12 | .at_level(tracing::Level::INFO)
13 | .with_target("interesting_target"),
14 | )
15 | .only()
16 | .run_with_handle();
17 |
18 | // Enables spans and events with targets starting with `interesting_target`:
19 | let target_filter = filter::filter_fn(|meta| meta.target().starts_with("interesting_target"));
20 |
21 | // Enables spans and events with levels `INFO` and below:
22 | let level_filter = LevelFilter::INFO;
23 |
24 | // Combine the two filters together, returning a filter that only enables
25 | // spans and events that *both* filters will enable:
26 | let filter = target_filter.and(level_filter);
27 |
28 | let _subscriber = tracing_subscriber::registry()
29 | .with(layer.with_filter(filter))
30 | .set_default();
31 |
32 | // This event will *not* be enabled:
33 | tracing::info!("an event with an uninteresting target");
34 |
35 | // This event *will* be enabled:
36 | tracing::info!(target: "interesting_target", "a very interesting event");
37 |
38 | // This event will *not* be enabled:
39 | tracing::debug!(target: "interesting_target", "interesting debug event...");
40 |
41 | handle.assert_finished();
42 | }
43 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/layer_filters/downcast_raw.rs:
--------------------------------------------------------------------------------
1 | use tracing::Subscriber;
2 | use tracing_subscriber::filter::Targets;
3 | use tracing_subscriber::prelude::*;
4 | use tracing_subscriber::Layer;
5 |
6 | #[test]
7 | fn downcast_ref_to_inner_layer_and_filter() {
8 | // Test that a filtered layer gives downcast_ref access to
9 | // both the layer and the filter.
10 |
11 | struct WrappedLayer;
12 |
13 | impl Layer for WrappedLayer
14 | where
15 | S: Subscriber,
16 | S: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>,
17 | {
18 | }
19 |
20 | let layer = WrappedLayer;
21 | let filter = Targets::new().with_default(tracing::Level::INFO);
22 | let registry = tracing_subscriber::registry().with(layer.with_filter(filter));
23 | let dispatch = tracing::dispatcher::Dispatch::new(registry);
24 |
25 | // The filter is available
26 | assert!(dispatch.downcast_ref::().is_some());
27 | // The wrapped layer is available
28 | assert!(dispatch.downcast_ref::().is_some());
29 | }
30 |
31 | #[test]
32 | fn forward_downcast_raw_to_layer() {
33 | // Test that a filtered layer still gives its wrapped layer a chance to
34 | // return a custom struct from downcast_raw.
35 | // https://github.com/tokio-rs/tracing/issues/1618
36 |
37 | struct WrappedLayer {
38 | with_context: WithContext,
39 | }
40 |
41 | struct WithContext;
42 |
43 | impl Layer for WrappedLayer
44 | where
45 | S: Subscriber,
46 | S: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>,
47 | {
48 | unsafe fn downcast_raw(&self, id: std::any::TypeId) -> Option<*const ()> {
49 | match id {
50 | id if id == std::any::TypeId::of::() => Some(self as *const _ as *const ()),
51 | id if id == std::any::TypeId::of::() => {
52 | Some(&self.with_context as *const _ as *const ())
53 | }
54 | _ => None,
55 | }
56 | }
57 | }
58 |
59 | let layer = WrappedLayer {
60 | with_context: WithContext,
61 | };
62 | let filter = Targets::new().with_default(tracing::Level::INFO);
63 | let registry = tracing_subscriber::registry().with(layer.with_filter(filter));
64 | let dispatch = tracing::dispatcher::Dispatch::new(registry);
65 |
66 | // Types from a custom implementation of `downcast_raw` are available
67 | assert!(dispatch.downcast_ref::().is_some());
68 | }
69 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/layer_filters/per_event.rs:
--------------------------------------------------------------------------------
1 | use tracing::Level;
2 | use tracing_mock::{expect, layer};
3 | use tracing_subscriber::{field::Visit, layer::Filter, prelude::*};
4 |
5 | struct FilterEvent;
6 |
7 | impl Filter for FilterEvent {
8 | fn enabled(
9 | &self,
10 | _meta: &tracing::Metadata<'_>,
11 | _cx: &tracing_subscriber::layer::Context<'_, S>,
12 | ) -> bool {
13 | true
14 | }
15 |
16 | fn event_enabled(
17 | &self,
18 | event: &tracing::Event<'_>,
19 | _cx: &tracing_subscriber::layer::Context<'_, S>,
20 | ) -> bool {
21 | struct ShouldEnable(bool);
22 | impl Visit for ShouldEnable {
23 | fn record_bool(&mut self, field: &tracing_core::Field, value: bool) {
24 | if field.name() == "enable" {
25 | self.0 = value;
26 | }
27 | }
28 |
29 | fn record_debug(
30 | &mut self,
31 | _field: &tracing_core::Field,
32 | _value: &dyn core::fmt::Debug,
33 | ) {
34 | }
35 | }
36 | let mut should_enable = ShouldEnable(false);
37 | event.record(&mut should_enable);
38 | should_enable.0
39 | }
40 | }
41 |
42 | #[test]
43 | fn per_layer_event_field_filtering() {
44 | let (expect, handle) = layer::mock()
45 | .event(expect::event().at_level(Level::TRACE))
46 | .event(expect::event().at_level(Level::INFO))
47 | .only()
48 | .run_with_handle();
49 |
50 | let _subscriber = tracing_subscriber::registry()
51 | .with(expect.with_filter(FilterEvent))
52 | .set_default();
53 |
54 | tracing::trace!(enable = true, "hello trace");
55 | tracing::debug!("hello debug");
56 | tracing::info!(enable = true, "hello info");
57 | tracing::warn!(enable = false, "hello warn");
58 | tracing::error!("hello error");
59 |
60 | handle.assert_finished();
61 | }
62 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/layer_filters/targets.rs:
--------------------------------------------------------------------------------
1 | use super::*;
2 | use tracing_subscriber::{
3 | filter::{filter_fn, Targets},
4 | prelude::*,
5 | };
6 |
7 | #[test]
8 | #[cfg_attr(not(feature = "tracing-log"), ignore)]
9 | fn log_events() {
10 | // Reproduces https://github.com/tokio-rs/tracing/issues/1563
11 | mod inner {
12 | pub(super) const MODULE_PATH: &str = module_path!();
13 |
14 | #[tracing::instrument]
15 | pub(super) fn logs() {
16 | log::debug!("inner");
17 | }
18 | }
19 |
20 | let filter = Targets::new()
21 | .with_default(LevelFilter::DEBUG)
22 | .with_target(inner::MODULE_PATH, LevelFilter::WARN);
23 |
24 | let layer =
25 | tracing_subscriber::layer::Identity::new().with_filter(filter_fn(move |_meta| true));
26 |
27 | let _guard = tracing_subscriber::registry()
28 | .with(filter)
29 | .with(layer)
30 | .set_default();
31 |
32 | inner::logs();
33 | }
34 |
35 | #[test]
36 | fn inner_layer_short_circuits() {
37 | // This test ensures that when a global filter short-circuits `Interest`
38 | // evaluation, we aren't left with a "dirty" per-layer filter state.
39 |
40 | let (layer, handle) = layer::mock()
41 | .event(expect::event().with_fields(expect::msg("hello world")))
42 | .only()
43 | .run_with_handle();
44 |
45 | let filter = Targets::new().with_target("magic_target", LevelFilter::DEBUG);
46 |
47 | let _guard = tracing_subscriber::registry()
48 | // Note: we don't just use a `LevelFilter` for the global filter here,
49 | // because it will just return a max level filter, and the chain of
50 | // `register_callsite` calls that would trigger the bug never happens...
51 | .with(filter::filter_fn(|meta| meta.level() <= &Level::INFO))
52 | .with(layer.with_filter(filter))
53 | .set_default();
54 |
55 | tracing::debug!("skip me please!");
56 | tracing::info!(target: "magic_target", "hello world");
57 |
58 | handle.assert_finished();
59 | }
60 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/option_filter_interest_caching.rs:
--------------------------------------------------------------------------------
1 | // A separate test crate for `Option` for isolation from other tests
2 | // that may influence the interest cache.
3 |
4 | use std::sync::{
5 | atomic::{AtomicUsize, Ordering},
6 | Arc,
7 | };
8 | use tracing_mock::{expect, layer};
9 | use tracing_subscriber::{filter, prelude::*, Layer};
10 |
11 | /// A `None` filter should always be interested in events, and it should not
12 | /// needlessly degrade the caching of other filters.
13 | #[test]
14 | fn none_interest_cache() {
15 | let (layer_none, handle_none) = layer::mock()
16 | .event(expect::event())
17 | .event(expect::event())
18 | .only()
19 | .run_with_handle();
20 | let layer_none = layer_none.with_filter(None::>);
21 |
22 | let times_filtered = Arc::new(AtomicUsize::new(0));
23 | let (layer_filter_fn, handle_filter_fn) = layer::mock()
24 | .event(expect::event())
25 | .event(expect::event())
26 | .only()
27 | .run_with_handle();
28 | let layer_filter_fn = layer_filter_fn.with_filter(filter::filter_fn({
29 | let times_filtered = Arc::clone(×_filtered);
30 | move |_| {
31 | times_filtered.fetch_add(1, Ordering::Relaxed);
32 | true
33 | }
34 | }));
35 |
36 | let subscriber = tracing_subscriber::registry()
37 | .with(layer_none)
38 | .with(layer_filter_fn);
39 |
40 | let _guard = subscriber.set_default();
41 | for _ in 0..2 {
42 | tracing::debug!(target: "always_interesting", x="bar");
43 | }
44 |
45 | // The `None` filter is unchanging and performs no filtering, so it should
46 | // be cacheable and always be interested in events. The filter fn is a
47 | // non-dynamic filter fn, which means the result can be cached per callsite.
48 | // The filter fn should only need to be called once, and the `Option` filter
49 | // should not interfere in the caching of that result.
50 | assert_eq!(times_filtered.load(Ordering::Relaxed), 1);
51 | handle_none.assert_finished();
52 | handle_filter_fn.assert_finished();
53 | }
54 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/registry_max_level_hint.rs:
--------------------------------------------------------------------------------
1 | #![cfg(all(feature = "registry", feature = "fmt"))]
2 | use tracing_subscriber::{filter::LevelFilter, prelude::*};
3 |
4 | #[test]
5 | fn registry_sets_max_level_hint() {
6 | tracing_subscriber::registry()
7 | .with(tracing_subscriber::fmt::layer())
8 | .with(LevelFilter::DEBUG)
9 | .init();
10 | assert_eq!(LevelFilter::current(), LevelFilter::DEBUG);
11 | }
12 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/registry_with_subscriber.rs:
--------------------------------------------------------------------------------
1 | #![cfg(feature = "registry")]
2 | use tracing_futures::{Instrument, WithSubscriber};
3 | use tracing_subscriber::prelude::*;
4 |
5 | #[tokio::test]
6 | async fn future_with_subscriber() {
7 | tracing_subscriber::registry().init();
8 | let span = tracing::info_span!("foo");
9 | let _e = span.enter();
10 | let span = tracing::info_span!("bar");
11 | let _e = span.enter();
12 | tokio::spawn(
13 | async {
14 | async {
15 | let span = tracing::Span::current();
16 | println!("{:?}", span);
17 | }
18 | .instrument(tracing::info_span!("hi"))
19 | .await
20 | }
21 | .with_subscriber(tracing_subscriber::registry()),
22 | )
23 | .await
24 | .unwrap();
25 | }
26 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/reload_max_log_level.rs:
--------------------------------------------------------------------------------
1 | #![cfg(all(feature = "env-filter", feature = "tracing-log"))]
2 |
3 | use tracing::{self, Level};
4 | use tracing_mock::{expect, subscriber};
5 | use tracing_subscriber::{filter::LevelFilter, prelude::*, reload};
6 |
7 | #[test]
8 | fn reload_max_log_level() {
9 | let (subscriber, finished) = subscriber::mock()
10 | .event(expect::event().at_level(Level::INFO))
11 | .event(expect::event().at_level(Level::DEBUG))
12 | .event(expect::event().at_level(Level::INFO))
13 | .only()
14 | .run_with_handle();
15 | let (filter, reload_handle) = reload::Layer::new(LevelFilter::INFO);
16 | subscriber.with(filter).init();
17 |
18 | assert!(log::log_enabled!(log::Level::Info));
19 | assert!(!log::log_enabled!(log::Level::Debug));
20 | assert!(!log::log_enabled!(log::Level::Trace));
21 |
22 | log::debug!("i'm disabled");
23 | log::info!("i'm enabled");
24 |
25 | reload_handle
26 | .reload(Level::DEBUG)
27 | .expect("reloading succeeds");
28 |
29 | assert!(log::log_enabled!(log::Level::Info));
30 | assert!(log::log_enabled!(log::Level::Debug));
31 | assert!(!log::log_enabled!(log::Level::Trace));
32 |
33 | log::debug!("i'm enabled now");
34 | log::info!("i'm still enabled, too");
35 |
36 | finished.assert_finished();
37 | }
38 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/utils.rs:
--------------------------------------------------------------------------------
1 | #![cfg(feature = "std")]
2 |
3 | use tracing_mock::*;
4 | use tracing_subscriber::prelude::*;
5 |
6 | #[test]
7 | fn init_ext_works() {
8 | let (subscriber, finished) = subscriber::mock()
9 | .event(
10 | expect::event()
11 | .at_level(tracing::Level::INFO)
12 | .with_target("init_works"),
13 | )
14 | .only()
15 | .run_with_handle();
16 |
17 | let _guard = subscriber.set_default();
18 | tracing::info!(target: "init_works", "it worked!");
19 | finished.assert_finished();
20 | }
21 |
22 | #[test]
23 | #[cfg(feature = "fmt")]
24 | fn builders_are_init_ext() {
25 | tracing_subscriber::fmt().set_default();
26 | let _ = tracing_subscriber::fmt()
27 | .with_target(false)
28 | .compact()
29 | .try_init();
30 | }
31 |
32 | #[test]
33 | #[cfg(all(feature = "fmt", feature = "env-filter"))]
34 | fn layered_is_init_ext() {
35 | tracing_subscriber::registry()
36 | .with(tracing_subscriber::fmt::layer())
37 | .with(tracing_subscriber::EnvFilter::new("foo=info"))
38 | .set_default();
39 | }
40 |
--------------------------------------------------------------------------------
/tracing-subscriber/tests/vec.rs:
--------------------------------------------------------------------------------
1 | #![cfg(feature = "registry")]
2 | use tracing::level_filters::LevelFilter;
3 | use tracing::Subscriber;
4 | use tracing_subscriber::prelude::*;
5 |
6 | #[test]
7 | fn just_empty_vec() {
8 | // Just a None means everything is off
9 | let subscriber = tracing_subscriber::registry().with(Vec::::new());
10 | assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF));
11 | }
12 |
13 | #[test]
14 | fn layer_and_empty_vec() {
15 | let subscriber = tracing_subscriber::registry()
16 | .with(LevelFilter::INFO)
17 | .with(Vec::::new());
18 | assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO));
19 | }
20 |
--------------------------------------------------------------------------------
/tracing-test/Cargo.toml:
--------------------------------------------------------------------------------
1 | ## BIG SCARY NOTE
2 | # This crate is internal and to be used for testing only. It should not
3 | # be published to crates.io ever. If the functionality is needed outside
4 | # the tracing project, it should be moved back to tracing-mock.
5 |
6 | [package]
7 | name = "tracing-test"
8 | version = "0.1.0"
9 | authors = [
10 | "Eliza Weisman ",
11 | "Tokio Contributors ",
12 | ]
13 | license = "MIT"
14 | readme = "README.md"
15 | repository = "https://github.com/tokio-rs/tracing"
16 | homepage = "https://tokio.rs"
17 | edition = "2018"
18 | rust-version = "1.49.0"
19 | publish = false
20 |
21 | [dependencies]
22 | tokio-test = "0.4.2"
23 |
24 | [package.metadata.docs.rs]
25 | all-features = true
26 | rustdoc-args = ["--cfg", "docsrs"]
27 |
--------------------------------------------------------------------------------
/tracing-test/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-test/README.md:
--------------------------------------------------------------------------------
1 | ![Tracing — Structured, application-level diagnostics][splash]
2 |
3 | [splash]: https://raw.githubusercontent.com/tokio-rs/tracing/main/assets/splash.svg
4 |
5 | # tracing-test
6 |
7 | Utilities for testing [`tracing`][tracing] and crates that uses it.
8 |
9 | [![Documentation (v0.2.x)][docs-v0.2.x-badge]][docs-v0.2.x-url]
10 | [![MIT licensed][mit-badge]][mit-url]
11 | [![Build Status][actions-badge]][actions-url]
12 | [![Discord chat][discord-badge]][discord-url]
13 |
14 | [Documentation][docs-v0.2.x-url] | [Chat][discord-url]
15 |
16 | [docs-v0.2.x-badge]: https://img.shields.io/badge/docs-v0.2.x-blue
17 | [docs-v0.2.x-url]: https://tracing.rs/tracing_mock
18 | [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
19 | [mit-url]: https://github.com/tokio-rs/tracing/blog/main/tracing-test/LICENSE
20 | [actions-badge]: https://github.com/tokio-rs/tracing/workflows/CI/badge.svg
21 | [actions-url]:https://github.com/tokio-rs/tracing/actions?query=workflow%3ACI
22 | [discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
23 | [discord-url]: https://discord.gg/EeF3cQw
24 |
25 | ## Overview
26 |
27 | [`tracing`] is a framework for instrumenting Rust programs to collect
28 | structured, event-based diagnostic information. `tracing-test` provides
29 | some reusable tools to aid in testing, but that are only intended for
30 | internal use. For mocks and expectations, see [`tracing-mock`].
31 |
32 | *Compiler support: [requires `rustc` 1.56+][msrv]*
33 |
34 | [msrv]: #supported-rust-versions
35 |
36 | ## Supported Rust Versions
37 |
38 | Tracing is built against the latest stable release. The minimum supported
39 | version is 1.56. The current Tracing version is not guaranteed to build on Rust
40 | versions earlier than the minimum supported version.
41 |
42 | Tracing follows the same compiler support policies as the rest of the Tokio
43 | project. The current stable Rust compiler and the three most recent minor
44 | versions before it will always be supported. For example, if the current stable
45 | compiler version is 1.45, the minimum supported version will not be increased
46 | past 1.42, three minor versions prior. Increasing the minimum supported compiler
47 | version is not considered a semver breaking change as long as doing so complies
48 | with this policy.
49 |
50 | ## License
51 |
52 | This project is licensed under the [MIT license][mit-url].
53 |
54 | ### Contribution
55 |
56 | Unless you explicitly state otherwise, any contribution intentionally submitted
57 | for inclusion in Tracing by you, shall be licensed as MIT, without any additional
58 | terms or conditions.
59 |
--------------------------------------------------------------------------------
/tracing-test/src/lib.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | pin::Pin,
3 | task::{Context, Poll},
4 | };
5 |
6 | #[allow(missing_docs)]
7 | pub struct PollN {
8 | and_return: Option>,
9 | finish_at: usize,
10 | polls: usize,
11 | }
12 |
13 | impl std::future::Future for PollN
14 | where
15 | T: Unpin,
16 | E: Unpin,
17 | {
18 | type Output = Result;
19 | fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll {
20 | let this = self.get_mut();
21 |
22 | this.polls += 1;
23 | if this.polls == this.finish_at {
24 | let value = this.and_return.take().expect("polled after ready");
25 |
26 | Poll::Ready(value)
27 | } else {
28 | cx.waker().wake_by_ref();
29 | Poll::Pending
30 | }
31 | }
32 | }
33 |
34 | impl PollN<(), ()> {
35 | pub fn new_ok(finish_at: usize) -> Self {
36 | Self {
37 | and_return: Some(Ok(())),
38 | finish_at,
39 | polls: 0,
40 | }
41 | }
42 |
43 | pub fn new_err(finish_at: usize) -> Self {
44 | Self {
45 | and_return: Some(Err(())),
46 | finish_at,
47 | polls: 0,
48 | }
49 | }
50 | }
51 |
52 | pub fn block_on_future(future: F) -> F::Output
53 | where
54 | F: std::future::Future,
55 | {
56 | use tokio_test::task;
57 |
58 | let mut task = task::spawn(future);
59 | loop {
60 | if let Poll::Ready(v) = task.poll() {
61 | break v;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/tracing-tower/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tracing-tower"
3 | version = "0.1.0"
4 | authors = ["Eliza Weisman "]
5 | edition = "2018"
6 | repository = "https://github.com/tokio-rs/tracing"
7 | homepage = "https://tokio.rs"
8 | description = """
9 | Compatibility with the `tower` ecosystem.
10 | """
11 | categories = [
12 | "development-tools::debugging",
13 | "development-tools::profiling",
14 | "asynchronous",
15 | ]
16 | keywords = ["logging", "tracing"]
17 | license = "MIT"
18 | rust-version = "1.65.0"
19 |
20 | [features]
21 | default = ["tower-layer", "tower-make"]
22 | tower-make = [
23 | "tower_make",
24 | "pin-project-lite",
25 | ]
26 |
27 | [dependencies]
28 | tracing = { path = "../tracing", version = "0.1.35", default-features = false, features = ["std"] }
29 | tracing-futures = { version = "0.2.1", path = "../tracing-futures", features = ["std-future"] }
30 | futures = "0.3.21"
31 | tower-service = "0.3.2"
32 | tower-layer = { version = "0.3.1", optional = true }
33 | tower_make = { package = "tower-make", version = "0.3.0", optional = true }
34 | pin-project-lite = { version = "0.2.9", optional = true }
35 | http = { version = "0.2.8", optional = true }
36 |
37 | [badges]
38 | maintenance = { status = "experimental" }
39 |
40 | [package.metadata.docs.rs]
41 | all-features = true
42 | rustdoc-args = ["--cfg", "docsrs"]
43 |
44 | [lints]
45 | workspace = true
46 |
--------------------------------------------------------------------------------
/tracing-tower/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing-tower/src/http.rs:
--------------------------------------------------------------------------------
1 | macro_rules! make_req_fns {
2 | ($($name:ident, $level:expr),+) => {
3 | $(
4 | #[inline]
5 | pub fn $name(req: &http::Request) -> tracing::Span {
6 | tracing::span!(
7 | $level,
8 | "request",
9 | method = ?req.method(),
10 | uri = ?req.uri(),
11 | )
12 | }
13 | )+
14 | }
15 | }
16 |
17 | make_req_fns! {
18 | info_request, tracing::Level::INFO,
19 | warn_request, tracing::Level::WARN,
20 | error_request, tracing::Level::ERROR
21 | }
22 |
23 | #[inline]
24 | pub fn debug_request(req: &http::Request) -> tracing::Span {
25 | tracing::span!(
26 | tracing::Level::DEBUG,
27 | "request",
28 | method = ?req.method(),
29 | uri = ?req.uri(),
30 | version = ?req.version(),
31 | )
32 | }
33 |
34 | #[inline]
35 | pub fn trace_request(req: &http::Request) -> tracing::Span {
36 | tracing::span!(
37 | tracing::Level::TRACE,
38 | "request",
39 | method = ?req.method(),
40 | uri = ?req.uri(),
41 | version = ?req.version(),
42 | headers = ?req.headers(),
43 | )
44 | }
45 |
--------------------------------------------------------------------------------
/tracing/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/tracing/benches/baseline.rs:
--------------------------------------------------------------------------------
1 | use criterion::{black_box, criterion_group, criterion_main, Criterion};
2 |
3 | fn bench(c: &mut Criterion) {
4 | use std::sync::atomic::{AtomicUsize, Ordering};
5 |
6 | let mut group = c.benchmark_group("comparison");
7 | group.bench_function("relaxed_load", |b| {
8 | let foo = AtomicUsize::new(1);
9 | b.iter(|| black_box(foo.load(Ordering::Relaxed)));
10 | });
11 | group.bench_function("acquire_load", |b| {
12 | let foo = AtomicUsize::new(1);
13 | b.iter(|| black_box(foo.load(Ordering::Acquire)))
14 | });
15 | group.bench_function("log", |b| {
16 | b.iter(|| {
17 | log::log!(log::Level::Info, "log");
18 | })
19 | });
20 | group.finish();
21 | }
22 |
23 | criterion_group!(benches, bench);
24 | criterion_main!(benches);
25 |
--------------------------------------------------------------------------------
/tracing/benches/dispatch_get_clone.rs:
--------------------------------------------------------------------------------
1 | use criterion::{black_box, criterion_group, criterion_main, Criterion};
2 |
3 | mod shared;
4 |
5 | fn bench(c: &mut Criterion) {
6 | shared::for_all_dispatches(&mut c.benchmark_group("Dispatch::get_clone"), |b| {
7 | b.iter(|| {
8 | let current = tracing::dispatcher::get_default(|current| current.clone());
9 | black_box(current);
10 | })
11 | });
12 | }
13 |
14 | criterion_group!(benches, bench);
15 | criterion_main!(benches);
16 |
--------------------------------------------------------------------------------
/tracing/benches/dispatch_get_ref.rs:
--------------------------------------------------------------------------------
1 | use criterion::{black_box, criterion_group, criterion_main, Criterion};
2 |
3 | mod shared;
4 |
5 | fn bench(c: &mut Criterion) {
6 | shared::for_all_dispatches(&mut c.benchmark_group("Dispatch::get_ref"), |b| {
7 | b.iter(|| {
8 | tracing::dispatcher::get_default(|current| {
9 | black_box(¤t);
10 | })
11 | })
12 | });
13 | }
14 |
15 | criterion_group!(benches, bench);
16 | criterion_main!(benches);
17 |
--------------------------------------------------------------------------------
/tracing/benches/empty_span.rs:
--------------------------------------------------------------------------------
1 | use criterion::{black_box, criterion_group, criterion_main, Criterion};
2 |
3 | mod shared;
4 |
5 | fn bench(c: &mut Criterion) {
6 | let mut group = c.benchmark_group("empty_span");
7 | shared::for_all_dispatches(&mut group, |b| {
8 | b.iter(|| {
9 | let span = tracing::span::Span::none();
10 | black_box(&span);
11 | })
12 | });
13 | group.bench_function("baseline_struct", |b| {
14 | b.iter(|| {
15 | let span = FakeEmptySpan::new();
16 | black_box(&span);
17 | })
18 | });
19 | }
20 |
21 | struct FakeEmptySpan {
22 | inner: Option<(usize, std::sync::Arc<()>)>,
23 | meta: Option<&'static ()>,
24 | }
25 |
26 | impl FakeEmptySpan {
27 | fn new() -> Self {
28 | Self {
29 | inner: None,
30 | meta: None,
31 | }
32 | }
33 | }
34 |
35 | impl Drop for FakeEmptySpan {
36 | fn drop(&mut self) {
37 | black_box(&self.inner);
38 | black_box(&self.meta);
39 | }
40 | }
41 |
42 | criterion_group!(benches, bench);
43 | criterion_main!(benches);
44 |
--------------------------------------------------------------------------------
/tracing/benches/enter_span.rs:
--------------------------------------------------------------------------------
1 | use criterion::{criterion_group, criterion_main, Criterion};
2 | use tracing::{span, Level};
3 |
4 | mod shared;
5 |
6 | fn bench(c: &mut Criterion) {
7 | shared::for_all_dispatches(&mut c.benchmark_group("enter_span"), |b| {
8 | let span = span!(Level::TRACE, "span");
9 | b.iter(|| {
10 | let _span = span.enter();
11 | })
12 | });
13 | }
14 |
15 | criterion_group!(benches, bench);
16 | criterion_main!(benches);
17 |
--------------------------------------------------------------------------------
/tracing/benches/event.rs:
--------------------------------------------------------------------------------
1 | use criterion::{criterion_group, criterion_main, Criterion};
2 |
3 | mod shared;
4 |
5 | fn bench(c: &mut Criterion) {
6 | shared::for_all_recording(&mut c.benchmark_group("event"), |b| {
7 | b.iter(|| tracing::info!("hello world!"))
8 | });
9 | }
10 |
11 | criterion_group!(benches, bench);
12 | criterion_main!(benches);
13 |
--------------------------------------------------------------------------------
/tracing/benches/span_fields.rs:
--------------------------------------------------------------------------------
1 | use criterion::{criterion_group, criterion_main, Criterion};
2 | use tracing::{span, Level};
3 |
4 | mod shared;
5 |
6 | fn bench(c: &mut Criterion) {
7 | shared::for_all_recording(&mut c.benchmark_group("span_fields"), |b| {
8 | b.iter(|| {
9 | let span = span!(
10 | Level::TRACE,
11 | "span",
12 | foo = "foo",
13 | bar = "bar",
14 | baz = 3,
15 | quuux = tracing::field::debug(0.99)
16 | );
17 | criterion::black_box(span)
18 | })
19 | });
20 | }
21 |
22 | criterion_group!(benches, bench);
23 | criterion_main!(benches);
24 |
--------------------------------------------------------------------------------
/tracing/benches/span_no_fields.rs:
--------------------------------------------------------------------------------
1 | use criterion::{criterion_group, criterion_main, Criterion};
2 | use tracing::{span, Level};
3 |
4 | mod shared;
5 |
6 | fn bench(c: &mut Criterion) {
7 | shared::for_all_recording(&mut c.benchmark_group("span_no_fields"), |b| {
8 | b.iter(|| span!(Level::TRACE, "span"))
9 | });
10 | }
11 |
12 | criterion_group!(benches, bench);
13 | criterion_main!(benches);
14 |
--------------------------------------------------------------------------------
/tracing/benches/span_repeated.rs:
--------------------------------------------------------------------------------
1 | use criterion::{black_box, criterion_group, criterion_main, Criterion};
2 | use tracing::{span, Level};
3 |
4 | mod shared;
5 |
6 | fn bench(c: &mut Criterion) {
7 | shared::for_all_recording(&mut c.benchmark_group("span_repeated"), |b| {
8 | let n = black_box(N_SPANS);
9 | b.iter(|| (0..n).fold(mk_span(0), |_, i| mk_span(i as u64)))
10 | });
11 | }
12 |
13 | #[inline]
14 | fn mk_span(i: u64) -> tracing::Span {
15 | span!(Level::TRACE, "span", i = i)
16 | }
17 |
18 | const N_SPANS: usize = 100;
19 | criterion_group!(benches, bench);
20 | criterion_main!(benches);
21 |
--------------------------------------------------------------------------------
/tracing/src/stdlib.rs:
--------------------------------------------------------------------------------
1 | //! Re-exports either the Rust `std` library or `core` and `alloc` when `std` is
2 | //! disabled.
3 | //!
4 | //! `crate::stdlib::...` should be used rather than `std::` when adding code that
5 | //! will be available with the standard library disabled.
6 | //!
7 | //! Note that this module is called `stdlib` rather than `std`, as Rust 1.34.0
8 | //! does not permit redefining the name `stdlib` (although this works on the
9 | //! latest stable Rust).
10 | #[cfg(feature = "std")]
11 | pub(crate) use std::*;
12 |
13 | #[cfg(not(feature = "std"))]
14 | pub(crate) use self::no_std::*;
15 |
16 | #[cfg(not(feature = "std"))]
17 | mod no_std {
18 | // We pre-emptively export everything from libcore/liballoc, (even modules
19 | // we aren't using currently) to make adding new code easier. Therefore,
20 | // some of these imports will be unused.
21 | #![allow(unused_imports)]
22 |
23 | pub(crate) use core::{
24 | any, array, ascii, cell, char, clone, cmp, convert, default, f32, f64, ffi, future, hash,
25 | hint, i128, i16, i8, isize, iter, marker, mem, num, ops, option, pin, ptr, result, task,
26 | time, u128, u16, u32, u8, usize,
27 | };
28 |
29 | pub(crate) use alloc::{boxed, collections, rc, string, vec};
30 |
31 | pub(crate) mod borrow {
32 | pub(crate) use alloc::borrow::*;
33 | pub(crate) use core::borrow::*;
34 | }
35 |
36 | pub(crate) mod fmt {
37 | pub(crate) use alloc::fmt::*;
38 | pub(crate) use core::fmt::*;
39 | }
40 |
41 | pub(crate) mod slice {
42 | pub(crate) use alloc::slice::*;
43 | pub(crate) use core::slice::*;
44 | }
45 |
46 | pub(crate) mod str {
47 | pub(crate) use alloc::str::*;
48 | pub(crate) use core::str::*;
49 | }
50 |
51 | pub(crate) mod sync {
52 | pub(crate) use alloc::sync::*;
53 | pub(crate) use core::sync::*;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tracing/src/subscriber.rs:
--------------------------------------------------------------------------------
1 | //! Collects and records trace data.
2 | pub use tracing_core::subscriber::*;
3 |
4 | #[cfg(feature = "std")]
5 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
6 | pub use tracing_core::dispatcher::DefaultGuard;
7 |
8 | /// Sets this [`Subscriber`] as the default for the current thread for the
9 | /// duration of a closure.
10 | ///
11 | /// The default subscriber is used when creating a new [`Span`] or
12 | /// [`Event`].
13 | ///
14 | ///
15 | /// [`Span`]: super::span::Span
16 | /// [`Subscriber`]: super::subscriber::Subscriber
17 | /// [`Event`]: super::event::Event
18 | #[cfg(feature = "std")]
19 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
20 | pub fn with_default(subscriber: S, f: impl FnOnce() -> T) -> T
21 | where
22 | S: Subscriber + Send + Sync + 'static,
23 | {
24 | crate::dispatcher::with_default(&crate::Dispatch::new(subscriber), f)
25 | }
26 |
27 | /// Sets this subscriber as the global default for the duration of the entire program.
28 | /// Will be used as a fallback if no thread-local subscriber has been set in a thread (using `with_default`.)
29 | ///
30 | /// Can only be set once; subsequent attempts to set the global default will fail.
31 | /// Returns whether the initialization was successful.
32 | ///
33 | /// Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when
34 | /// executables try to set them later.
35 | ///
36 | /// [`Subscriber`]: super::subscriber::Subscriber
37 | /// [`Event`]: super::event::Event
38 | pub fn set_global_default(subscriber: S) -> Result<(), SetGlobalDefaultError>
39 | where
40 | S: Subscriber + Send + Sync + 'static,
41 | {
42 | crate::dispatcher::set_global_default(crate::Dispatch::new(subscriber))
43 | }
44 |
45 | /// Sets the [`Subscriber`] as the default for the current thread for the
46 | /// duration of the lifetime of the returned [`DefaultGuard`].
47 | ///
48 | /// The default subscriber is used when creating a new [`Span`] or [`Event`].
49 | ///
50 | /// [`Span`]: super::span::Span
51 | /// [`Subscriber`]: super::subscriber::Subscriber
52 | /// [`Event`]: super::event::Event
53 | /// [`DefaultGuard`]: super::dispatcher::DefaultGuard
54 | #[cfg(feature = "std")]
55 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
56 | #[must_use = "Dropping the guard unregisters the subscriber."]
57 | pub fn set_default(subscriber: S) -> DefaultGuard
58 | where
59 | S: Subscriber + Send + Sync + 'static,
60 | {
61 | crate::dispatcher::set_default(&crate::Dispatch::new(subscriber))
62 | }
63 |
64 | pub use tracing_core::dispatcher::SetGlobalDefaultError;
65 |
--------------------------------------------------------------------------------
/tracing/test-log-support/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 |
3 | [package]
4 | name = "test-log-support"
5 | version = "0.1.0"
6 | publish = false
7 | edition = "2018"
8 |
9 | [dependencies]
10 | tracing = { path = "..", features = ["log", "log-always"] }
11 | log = { version = "0.4.0", features = ["std"] }
12 |
--------------------------------------------------------------------------------
/tracing/test-log-support/src/lib.rs:
--------------------------------------------------------------------------------
1 | use log::{LevelFilter, Log, Metadata, Record};
2 | use std::sync::{Arc, Mutex};
3 |
4 | pub struct Test {
5 | state: Arc,
6 | }
7 |
8 | struct State {
9 | last_log: Mutex