diff --git a/Cargo.lock b/Cargo.lock index 2c7460687..d1bb9b97c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3790,6 +3790,23 @@ dependencies = [ "cipher 0.5.2", ] +[[package]] +name = "dial9" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b11bce55173f77d9003cce8f129b4af889a4639005c53c3498cef933bc895c" +dependencies = [ + "bon", + "dial9-core", + "dial9-macro", + "dial9-metrique", + "dial9-perf-self-profile", + "dial9-tokio-telemetry", + "dial9-trace-format", + "tokio", + "tracing", +] + [[package]] name = "dial9-core" version = "0.5.0" @@ -3812,6 +3829,31 @@ dependencies = [ "ulid", ] +[[package]] +name = "dial9-macro" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4177b8f8bf95d8e3769c1aad596f5d6fb231953a45c4c3d2a5946fe8e4ec327b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "dial9-metrique" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d42fe0e3e14e8780c4ecf9ee14c183dbcb9b1ae3612cc9a689e7dc83b13adef1" +dependencies = [ + "dial9-core", + "dial9-trace-format", + "metrique", + "metrique-writer", + "tokio", + "tracing", +] + [[package]] name = "dial9-perf-self-profile" version = "0.5.0" @@ -3827,6 +3869,7 @@ dependencies = [ "libc", "perf-event-data", "perf-event-open-sys2", + "tokio", "tracing", ] @@ -10345,7 +10388,7 @@ dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "dial9-tokio-telemetry", + "dial9", "flate2", "futures-util", "glob", diff --git a/Cargo.toml b/Cargo.toml index 5664d6b3e..7e13ba392 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -351,7 +351,7 @@ zstd = "0.14.0" # Observability and Metrics metrics = "0.24.6" metrics-util = "0.20" -dial9-tokio-telemetry = "0.5.0" +dial9 = { version = "0.5.0", default-features = false } opentelemetry = { version = "0.32.0" } opentelemetry-appender-tracing = { version = "0.32.0" } opentelemetry-otlp = { version = "0.32.0" } diff --git a/crates/config/src/constants/runtime.rs b/crates/config/src/constants/runtime.rs index 3e0203a71..5038413c6 100644 --- a/crates/config/src/constants/runtime.rs +++ b/crates/config/src/constants/runtime.rs @@ -39,7 +39,7 @@ pub const ENV_RUNTIME_DIAL9_S3_BUCKET: &str = "RUSTFS_RUNTIME_DIAL9_S3_BUCKET"; /// Accepted but not honoured; see [`ENV_RUNTIME_DIAL9_S3_BUCKET`]. pub const ENV_RUNTIME_DIAL9_S3_PREFIX: &str = "RUSTFS_RUNTIME_DIAL9_S3_PREFIX"; // Note: there are deliberately no task-dump knobs. dial9 only captures task -// dumps for futures spawned through `dial9_tokio_telemetry::spawn`, and RustFS +// dumps for futures spawned through `dial9::spawn`, and RustFS // spawns with `tokio::spawn` throughout, so the switch could never do anything. // Measured: 0 dumps via tokio::spawn vs 14709 via dial9::spawn on an identical // workload. See rustfs/backlog#1157 (D9-16). diff --git a/crates/obs/Cargo.toml b/crates/obs/Cargo.toml index 1304645b9..22fb71dc6 100644 --- a/crates/obs/Cargo.toml +++ b/crates/obs/Cargo.toml @@ -74,11 +74,11 @@ hotpath-cpu = [ # Tokio runtime-level telemetry. Requires a `--cfg tokio_unstable` build; the # build script fails the compile when that flag is missing. Off by default so # ordinary builds neither pay for nor depend on Tokio's unstable API. -dial9 = ["dep:dial9-tokio-telemetry", "dial9-tokio-telemetry/process-resource"] +dial9 = ["dep:dial9"] # # NOTE: there is deliberately no `dial9-taskdump` feature. dial9 only captures a # task dump for futures it wrapped itself, i.e. those spawned via -# `dial9_tokio_telemetry::spawn`. RustFS spawns with `tokio::spawn` throughout, +# `dial9::spawn`. RustFS spawns with `tokio::spawn` throughout, # so enabling `tokio/taskdump` would cost a Linux-only build constraint and # record nothing. Measured on an identical workload: 0 dumps via `tokio::spawn`, # 14709 via `dial9::spawn`. Re-adding this feature only makes sense together @@ -149,7 +149,7 @@ tracing-subscriber = { workspace = true, features = ["fmt", "env-filter", "traci tokio = { workspace = true, features = ["sync", "rt-multi-thread", "time", "macros"] } tokio-util = { workspace = true, features = ["io", "compat"] } url.workspace = true -dial9-tokio-telemetry = { workspace = true, optional = true } +dial9 = { workspace = true, optional = true, features = ["tokio", "process-resource"] } thiserror = { workspace = true } zstd = { workspace = true, features = ["zstdmt"] } sysinfo = { workspace = true } diff --git a/crates/obs/build.rs b/crates/obs/build.rs index aaa13037c..08a7b4210 100644 --- a/crates/obs/build.rs +++ b/crates/obs/build.rs @@ -14,7 +14,7 @@ //! Enforces that the `dial9` feature is paired with `--cfg tokio_unstable`. //! -//! `dial9-tokio-telemetry` hooks Tokio's unstable runtime instrumentation. The +//! `dial9` hooks Tokio's unstable runtime instrumentation. The //! flag lives in `RUSTFLAGS`, which a caller can silently clobber by exporting //! their own value — that used to turn telemetry off with no diagnostic. Fail //! the build instead. diff --git a/crates/obs/src/telemetry/dial9/config.rs b/crates/obs/src/telemetry/dial9/config.rs index 4784e1f74..7ba606865 100644 --- a/crates/obs/src/telemetry/dial9/config.rs +++ b/crates/obs/src/telemetry/dial9/config.rs @@ -14,10 +14,10 @@ //! Configuration for dial9 Tokio runtime telemetry. //! -//! This module carries no dependency on the `dial9-tokio-telemetry` crate, so -//! it compiles identically whether or not the `dial9` feature is enabled. That -//! lets callers read the configured state (and export metrics about it) from a -//! binary that was built without telemetry support. +//! This module carries no dependency on the optional `dial9` crate, so it +//! compiles identically whether or not the `dial9` feature is enabled. That lets +//! callers read the configured state (and export metrics about it) from a binary +//! that was built without telemetry support. use super::state::dial9_runtime_state; use rustfs_config::{ diff --git a/crates/obs/src/telemetry/dial9/disabled.rs b/crates/obs/src/telemetry/dial9/disabled.rs index 613028225..6b1ec236b 100644 --- a/crates/obs/src/telemetry/dial9/disabled.rs +++ b/crates/obs/src/telemetry/dial9/disabled.rs @@ -20,7 +20,7 @@ use crate::TelemetryError; -/// Placeholder for `dial9_tokio_telemetry::telemetry::TelemetryGuard`. +/// Placeholder for `dial9::TelemetryGuard`. /// /// Never constructed: [`build_traced_runtime`] always fails without the /// `dial9` feature. diff --git a/crates/obs/src/telemetry/dial9/enabled.rs b/crates/obs/src/telemetry/dial9/enabled.rs index 912514ee5..7bfa6f9d1 100644 --- a/crates/obs/src/telemetry/dial9/enabled.rs +++ b/crates/obs/src/telemetry/dial9/enabled.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! `dial9-tokio-telemetry` integration, compiled when the `dial9` feature is on. +//! `dial9` integration, compiled when the `dial9` feature is on. //! //! Captures Tokio runtime-level events (poll start/end, worker park/unpark, //! task spawn/terminate) into rotating binary trace segments. This is an @@ -23,9 +23,8 @@ use super::config::Dial9Config; use super::state::{dial9_runtime_state, measure_disk_usage_bytes}; use super::{EVENT_DIAL9_STATE, LOG_COMPONENT_OBS, LOG_SUBSYSTEM_DIAL9}; use crate::TelemetryError; -use dial9_tokio_telemetry::telemetry::{ - Dial9Handle, Dial9HandleTokioExt, DiskBuffer, ProcessResourceUsageConfig, RecorderPerfExt, TokioAttachOptions, recorder, -}; +use dial9::process::ProcessResourceUsageConfig; +use dial9::{Dial9Handle, Dial9HandleTokioExt, DiskBuffer, RecorderPerfExt, TokioAttachOptions, recorder}; use std::time::Duration; use tracing::{info, warn}; @@ -134,7 +133,7 @@ pub fn build_traced_runtime( .map(|runtime| (runtime, guard, shutdown)); // No task dumps here. dial9 captures a task dump only for futures it - // wrapped itself, i.e. those spawned via `dial9_tokio_telemetry::spawn`; + // wrapped itself, i.e. those spawned via `dial9::spawn`; // `tokio::spawn` gets no wrapper. RustFS spawns with `tokio::spawn` // throughout, so enabling task dumps records nothing. Measured on an // identical workload: 0 dumps via `tokio::spawn`, 14709 via `dial9::spawn`. diff --git a/crates/obs/src/telemetry/dial9/mod.rs b/crates/obs/src/telemetry/dial9/mod.rs index a186abf9c..243e64065 100644 --- a/crates/obs/src/telemetry/dial9/mod.rs +++ b/crates/obs/src/telemetry/dial9/mod.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Tokio runtime-level telemetry via `dial9-tokio-telemetry`. +//! Tokio runtime-level telemetry via `dial9`. //! //! This is an on-demand profiler for executor-level faults — long polls that //! stall a worker, park/unpark storms, tasks that never yield — which are diff --git a/docs/operations/dial9-runtime-profiling.md b/docs/operations/dial9-runtime-profiling.md index 4a69e0324..c1b0f2a7b 100644 --- a/docs/operations/dial9-runtime-profiling.md +++ b/docs/operations/dial9-runtime-profiling.md @@ -3,9 +3,8 @@ **Use this when:** you need Tokio runtime-level evidence (which task held a worker, long polls, park/unpark behaviour) that Prometheus metrics and `tracing` spans cannot provide, or you are building or running the opt-in `dial9` profiling binary. **Source of truth:** `crates/obs/src/telemetry/dial9/mod.rs` (session setup), `crates/obs/src/metrics/collectors/dial9.rs` (metrics), `crates/config/src/constants/runtime.rs` (`RUSTFS_RUNTIME_DIAL9_*` and defaults), `.config/make/build.mak` (`build-profiling`), `crates/obs/build.rs` (feature/cfg pairing check). -`dial9-tokio-telemetry` records Tokio runtime-level events — poll start/end, -worker park/unpark, task spawn/terminate, and optionally async backtraces of -stalled tasks — into binary trace segments. +`dial9` records Tokio runtime-level events — poll start/end, worker park/unpark, +task spawn/terminate — into binary trace segments. It answers questions that Prometheus metrics and `tracing` spans cannot: @@ -29,7 +28,7 @@ For drive stalls use the `rustfs_io_*` metrics and the drive-stall budget. dial9 answers a different question: which task held a worker, and for how long. **It cannot tell you where a task was stuck.** That would need a task dump, and -dial9 only captures those for futures spawned through `dial9_tokio_telemetry::spawn`. +dial9 only captures those for futures spawned through `dial9::spawn`. RustFS spawns with `tokio::spawn` throughout, so no task dump is ever recorded and no configuration exposes one. Tracked as D9-16 in rustfs/backlog#1157.