diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 529c712c1..24c57eba9 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -40,6 +40,8 @@ updates: versions: [ "1.x" ] - dependency-name: "ratelimit" versions: [ "2.x" ] + - dependency-name: "pyroscope" + versions: [ "2.x" ] groups: s3s: update-types: diff --git a/Cargo.lock b/Cargo.lock index 9b1678150..9eed64c50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1492,7 +1492,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.9", ] [[package]] @@ -1511,7 +1511,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.9", ] [[package]] @@ -1730,9 +1730,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.62" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "jobserver", @@ -1834,7 +1834,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.7", + "crypto-common 0.1.6", "inout 0.1.4", ] @@ -2290,7 +2290,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.9", "rand_core 0.6.4", "subtle", "zeroize", @@ -2315,11 +2315,11 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.9", "typenum", ] @@ -3475,9 +3475,9 @@ dependencies = [ [[package]] name = "dial9-tokio-telemetry" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9db20413b8c96577881e6f806970e81d41376236569eaf69f9329e34fc48bd79" +checksum = "226a0d823327c391d9e8234dc3ccc5810d936359ba8ea6af024d57bb15568647" dependencies = [ "arc-swap", "bon", @@ -3536,7 +3536,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid 0.9.6", - "crypto-common 0.1.7", + "crypto-common 0.1.6", "subtle", ] @@ -3764,7 +3764,7 @@ dependencies = [ "crypto-bigint 0.5.5", "digest 0.10.7", "ff", - "generic-array 0.14.7", + "generic-array 0.14.9", "group", "hkdf 0.12.4", "pem-rfc7468 0.7.0", @@ -4214,9 +4214,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -4225,11 +4225,11 @@ dependencies = [ [[package]] name = "generic-array" -version = "1.4.1" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab9e9188e97a93276e1fe7b56401b851e2b45a46d045ca658100c1303ada649" +checksum = "c2e55f16dcf0e9c00efbe2e655ffe45fc98e7066b52bc92f8a79e64060a79351" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.9", "rustversion", "typenum", ] @@ -4946,9 +4946,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb92f162bf56536459fc83c79b974bb12837acfed43d6bc370a7916d0ae15ecc" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -5231,7 +5231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "block-padding 0.3.3", - "generic-array 0.14.7", + "generic-array 0.14.9", ] [[package]] @@ -5936,9 +5936,9 @@ dependencies = [ [[package]] name = "lzma-rust2" -version = "0.16.3" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9ceaec84b54518262de7cf06b8b43e83c808349960f1610b21b0bfc9640f20" +checksum = "ce716bf1a316f47a280fc76295f6495b5bea4752bca01c3b3885e101b1c23c02" dependencies = [ "sha2 0.11.0", ] @@ -6716,7 +6716,7 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "getrandom 0.2.17", "http 1.4.1", @@ -7936,7 +7936,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ "heck", - "itertools 0.13.0", + "itertools 0.14.0", "log", "multimap", "once_cell", @@ -7956,7 +7956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" dependencies = [ "heck", - "itertools 0.13.0", + "itertools 0.14.0", "log", "multimap", "petgraph 0.8.3", @@ -7977,7 +7977,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -7990,7 +7990,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -8141,6 +8141,7 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01ebd83db08e07a69b4291e7043f5f2ca964c8869e0bd0b6d09b8b062de775bd" dependencies = [ + "jemalloc_pprof", "lazy_static", "libc", "libflate", @@ -8887,7 +8888,7 @@ dependencies = [ "enum_dispatch", "flate2", "futures", - "generic-array 1.4.1", + "generic-array 1.4.3", "getrandom 0.2.17", "ghash", "hex-literal", @@ -9702,6 +9703,7 @@ dependencies = [ "dial9-tokio-telemetry", "flate2", "glob", + "jemalloc_pprof", "jiff", "metrics", "num_cpus", @@ -9910,7 +9912,7 @@ dependencies = [ "rustfs-ecstore", "s3s", "serde_json", - "snafu 0.9.0", + "snafu 0.9.1", "tokio", "tokio-util", "tracing", @@ -9930,7 +9932,7 @@ dependencies = [ "parking_lot 0.12.5", "rustfs-s3select-api", "s3s", - "snafu 0.9.0", + "snafu 0.9.1", "tokio", "tracing", ] @@ -10390,15 +10392,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ece8e78b2f38ec51c51f5d475df0a7187ba5111b2a28bdc761ee05b075d40a71" -[[package]] -name = "scc" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" -dependencies = [ - "sdd", -] - [[package]] name = "schannel" version = "0.1.29" @@ -10461,12 +10454,6 @@ dependencies = [ "sha2 0.11.0", ] -[[package]] -name = "sdd" -version = "3.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" - [[package]] name = "sec1" version = "0.7.3" @@ -10475,7 +10462,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", "der 0.7.10", - "generic-array 0.14.7", + "generic-array 0.14.9", "pkcs8 0.10.2", "subtle", "zeroize", @@ -10693,24 +10680,23 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" +checksum = "699f4197115b8a7e7ff19c9a315a4bd6fffec26cc4626ef45ecaea389e081c6d" dependencies = [ "futures-executor", "futures-util", "log", "once_cell", "parking_lot 0.12.5", - "scc", "serial_test_derive", ] [[package]] name = "serial_test_derive" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" +checksum = "94e153fc76e1c6a068703d6d29c508a0b15c061c4b7e43da59cc097bc342673c" dependencies = [ "proc-macro2", "quote", @@ -10810,9 +10796,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook-registry" @@ -10974,12 +10960,11 @@ dependencies = [ [[package]] name = "snafu" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1d4bced6a69f90b2056c03dcff2c4737f98d6fb9e0853493996e1d253ca29c6" +checksum = "d1a012328be2e3f5d5f6f3218147ca02588cea4cb865e876849ab6debcf36522" dependencies = [ - "backtrace", - "snafu-derive 0.9.0", + "snafu-derive 0.9.1", ] [[package]] @@ -10995,9 +10980,9 @@ dependencies = [ [[package]] name = "snafu-derive" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54254b8531cafa275c5e096f62d48c81435d1015405a91198ddb11e967301d40" +checksum = "5f103c50866b8743da9429b8a581d81a27c2d3a9c4ac7df8f8571c1dd7896eda" dependencies = [ "heck", "proc-macro2", @@ -12148,9 +12133,9 @@ checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unarray" @@ -12280,9 +12265,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" dependencies = [ "getrandom 0.4.2", "js-sys", @@ -13068,18 +13053,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.49" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bce33a6288fa3f072a8c2c7d0f2fdbb90e28298f0135c1f99b96c3db2efcc60b" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.49" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd425244944f4ab65ccff928e7323354c5a018c75838362fdce749dfad2ee1e" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 616656282..59116904a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -129,7 +129,7 @@ futures-util = "0.3.32" pollster = "0.4.0" pulsar = { version = "6.8.0", default-features = false, features = ["tokio-rustls-runtime"] } lapin = { version = "4.10.0", default-features = false, features = ["tokio", "rustls", "rustls--aws_lc_rs"] } -hyper = { version = "1.10.0", features = ["http2", "http1", "server"] } +hyper = { version = "1.10.1", features = ["http2", "http1", "server"] } hyper-rustls = { version = "0.27.9", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "http2", "aws-lc-rs", "webpki-roots"] } hyper-util = { version = "0.1.20", features = ["tokio", "server-auto", "server-graceful", "tracing"] } http = "1.4.1" @@ -261,12 +261,12 @@ rustix = { version = "1.1.4", features = ["fs"] } rust-embed = { version = "8.11.0" } rustc-hash = { version = "2.1.2" } s3s = { git = "https://github.com/rustfs/s3s", rev = "507e1312b211c3ddc214b03875d6fabd15d22ed5", features = ["minio"] } -serial_test = "3.4.0" +serial_test = "3.5.0" shadow-rs = { version = "2.0.0", default-features = false } siphasher = "1.0.3" smallvec = { version = "1.15.1", features = ["serde"] } smartstring = "1.0.1" -snafu = "0.9.0" +snafu = "0.9.1" snap = "1.1.1" starshard = { version = "2.2.0", features = ["rayon", "async", "serde"] } strum = { version = "0.28.0", features = ["derive"] } @@ -283,7 +283,7 @@ tracing-subscriber = { version = "0.3.23", features = ["env-filter", "time"] } transform-stream = "0.3.1" url = "2.5.8" urlencoding = "2.1.3" -uuid = { version = "1.23.1", features = ["v4", "fast-rng", "macro-diagnostics"] } +uuid = { version = "1.23.2", features = ["v4", "fast-rng", "macro-diagnostics"] } vaultrs = { version = "0.8.0" } walkdir = "2.5.0" wildmatch = { version = "2.6.1", features = ["serde"] } @@ -301,7 +301,7 @@ opentelemetry-otlp = { version = "0.32.0", features = ["gzip-http", "reqwest-rus opentelemetry_sdk = { version = "0.32.1", features = ["rt-tokio"] } opentelemetry-semantic-conventions = { version = "0.32.0", features = ["semconv_experimental"] } opentelemetry-stdout = { version = "0.32.0" } -pyroscope = { version = "2.0.5", features = ["backend-pprof-rs"] } +pyroscope = { version = "=2.0.5", features = ["backend-pprof-rs", "backend-jemalloc"] } # FTP and SFTP libunftp = { version = "0.23.0", features = ["experimental"] } @@ -324,7 +324,9 @@ tikv-jemalloc-ctl = { version = "0.6", features = ["use_std", "stats", "profilin jemalloc_pprof = { version = "0.8.2", features = ["symbolize", "flamegraph"] } # Used to generate CPU performance analysis data and flame diagrams # pprof = { version = "0.15.0", features = ["flamegraph", "protobuf-codec"] } -# Pyroscope uses a patched pprof, until they merge back upstream, replace all references. Otherwise, two pprof libs with symbol collision. +# Use pprof-pyroscope-fork to match pyroscope 2.0.5's internal pprof dependency (v0.1500.4). +# Cargo unifies them into a single instance, avoiding duplicate perf_signal_handler symbols. +# NOTE: Do NOT upgrade pyroscope to >=2.0.6 — it vendors pprof-rs internally, causing symbol collision. pprof = { package = "pprof-pyroscope-fork", version = "0.1500.4", features = ["flamegraph", "protobuf-codec"] } [workspace.metadata.cargo-shear] diff --git a/crates/obs/Cargo.toml b/crates/obs/Cargo.toml index a0bcbd9ea..34a807204 100644 --- a/crates/obs/Cargo.toml +++ b/crates/obs/Cargo.toml @@ -72,7 +72,8 @@ sysinfo = { workspace = true } nvml-wrapper = { workspace = true, optional = true } [target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] -pyroscope = { workspace = true, features = ["backend-pprof-rs"] } +pyroscope = { workspace = true } +jemalloc_pprof = { workspace = true } [dev-dependencies] diff --git a/crates/obs/src/telemetry/guard.rs b/crates/obs/src/telemetry/guard.rs index 26c868d50..75c23c800 100644 --- a/crates/obs/src/telemetry/guard.rs +++ b/crates/obs/src/telemetry/guard.rs @@ -43,6 +43,8 @@ pub struct OtelGuard { pub(crate) logger_provider: Option, #[cfg(any(target_os = "linux", target_os = "macos"))] pub(crate) profiling_agent: Option>, + #[cfg(any(target_os = "linux", target_os = "macos"))] + pub(crate) memory_profiling_agent: Option>, /// Handle to the background log-cleanup task; aborted on drop. pub(crate) cleanup_handle: Option>, /// Worker guard that keeps the non-blocking `tracing_appender` thread @@ -60,6 +62,8 @@ impl std::fmt::Debug for OtelGuard { .field("logger_provider", &self.logger_provider.is_some()); #[cfg(any(target_os = "linux", target_os = "macos"))] s.field("profiling_agent", &self.profiling_agent.is_some()); + #[cfg(any(target_os = "linux", target_os = "macos"))] + s.field("memory_profiling_agent", &self.memory_profiling_agent.is_some()); s.field("cleanup_handle", &self.cleanup_handle.is_some()) .field("tracing_guard", &self.tracing_guard.is_some()) .field("stdout_guard", &self.stdout_guard.is_some()) @@ -101,6 +105,16 @@ impl Drop for OtelGuard { } } + #[cfg(any(target_os = "linux", target_os = "macos"))] + if let Some(agent) = self.memory_profiling_agent.take() { + match agent.stop() { + Err(err) => eprintln!("Memory profiling agent stop error: {err:?}"), + Ok(stopped) => { + stopped.shutdown(); + } + } + } + if let Some(handle) = self.cleanup_handle.take() { handle.abort(); eprintln!("Log cleanup task stopped"); diff --git a/crates/obs/src/telemetry/local.rs b/crates/obs/src/telemetry/local.rs index 3c972ad50..393748c77 100644 --- a/crates/obs/src/telemetry/local.rs +++ b/crates/obs/src/telemetry/local.rs @@ -157,6 +157,8 @@ fn init_stdout_only(_config: &OtelConfig, logger_level: &str, is_production: boo logger_provider: None, #[cfg(any(target_os = "linux", target_os = "macos"))] profiling_agent: None, + #[cfg(any(target_os = "linux", target_os = "macos"))] + memory_profiling_agent: None, tracing_guard: Some(guard), stdout_guard: None, cleanup_handle: None, @@ -291,6 +293,8 @@ fn init_file_logging_internal( logger_provider: None, #[cfg(any(target_os = "linux", target_os = "macos"))] profiling_agent: None, + #[cfg(any(target_os = "linux", target_os = "macos"))] + memory_profiling_agent: None, tracing_guard: Some(guard), stdout_guard, cleanup_handle: Some(cleanup_handle), diff --git a/crates/obs/src/telemetry/otel.rs b/crates/obs/src/telemetry/otel.rs index 3793ada1d..acba1fb2f 100644 --- a/crates/obs/src/telemetry/otel.rs +++ b/crates/obs/src/telemetry/otel.rs @@ -167,6 +167,9 @@ pub(super) fn init_observability_http( #[cfg(any(target_os = "linux", target_os = "macos"))] let profiling_agent = init_profiler(config); + #[cfg(any(target_os = "linux", target_os = "macos"))] + let memory_profiling_agent = init_memory_profiler(config); + // ── Logger Logic ────────────────────────────────────────────────────────── // Logging is the only signal that may intentionally route to either OTLP // or local files depending on configuration completeness. @@ -316,6 +319,8 @@ pub(super) fn init_observability_http( logger_provider, #[cfg(any(target_os = "linux", target_os = "macos"))] profiling_agent, + #[cfg(any(target_os = "linux", target_os = "macos"))] + memory_profiling_agent, tracing_guard, stdout_guard, cleanup_handle, @@ -516,7 +521,7 @@ fn init_profiler(config: &OtelConfig) -> Option Option Option> { + use pyroscope::backend::jemalloc_backend; + use pyroscope::pyroscope::PyroscopeAgentBuilder; + use rustfs_config::VERSION; + + if !config + .profiling_export_enabled + .unwrap_or(rustfs_config::DEFAULT_OBS_PROFILING_EXPORT_ENABLED) + { + return None; + } + + let endpoint = config.profiling_endpoint.as_ref()?.as_str(); + if endpoint.is_empty() { + return None; + } + + // Verify jemalloc profiling is available and activated + { + let prof_ctl = jemalloc_pprof::PROF_CTL.as_ref()?; + let ctl = prof_ctl.try_lock().ok()?; + if !ctl.activated() { + eprintln!("Memory profiling skipped: jemalloc profiling is not activated"); + return None; + } + } + + let backend = jemalloc_backend(); + let service_name = config.service_name.as_deref().unwrap_or(APP_NAME); + let version = config.service_version.as_deref().unwrap_or(VERSION); + let sample_rate = 100; + + let agent = PyroscopeAgentBuilder::new(endpoint, service_name, sample_rate, "pyroscope-rs", "1.0.1", backend) + .tags(vec![("version", version), ("profile_type", "memory")]) + .build() + .ok()?; + + match agent.start() { + Ok(agent) => Some(agent), + Err(err) => { + eprintln!("Memory profiling agent start error: {err:?}"); + None + } + } +} + /// Create a stdout periodic metrics reader for the given interval. /// /// This helper is primarily used for local development and diagnostics when diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index ce6a1078b..185f83a19 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -173,12 +173,12 @@ hashbrown = { workspace = true } [target.'cfg(target_os = "linux")'.dependencies] libsystemd.workspace = true -[target.'cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))'.dependencies] +[target.'cfg(not(any(target_os = "linux", target_os = "macos")))'.dependencies] mimalloc = { workspace = true } libmimalloc-sys = { version = "0.1.49", features = ["extended"] } -# Only enable pprof-based profiling on linux + gnu + x86_64. -[target.'cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))'.dependencies] +# jemalloc + pprof-based profiling on linux and macos. +[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] tikv-jemallocator = { workspace = true } tikv-jemalloc-ctl = { workspace = true } jemalloc_pprof = { workspace = true } diff --git a/rustfs/src/admin/handlers/profile.rs b/rustfs/src/admin/handlers/profile.rs index 242821b94..be337aca1 100644 --- a/rustfs/src/admin/handlers/profile.rs +++ b/rustfs/src/admin/handlers/profile.rs @@ -15,10 +15,10 @@ use crate::admin::{auth::validate_admin_request, router::Operation}; use crate::auth::{check_key_valid, get_session_token}; use crate::server::RemoteAddr; -#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] +#[cfg(any(target_os = "linux", target_os = "macos"))] use http::HeaderMap; use http::StatusCode; -#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] +#[cfg(any(target_os = "linux", target_os = "macos"))] use http::header::CONTENT_TYPE; use matchit::Params; use rustfs_policy::policy::action::{Action, AdminAction}; @@ -52,7 +52,7 @@ impl Operation for TriggerProfileCPU { authorize_profile_request(&req).await?; info!("Triggering CPU profile dump via S3 request..."); - #[cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))] + #[cfg(not(any(target_os = "linux", target_os = "macos")))] { return Ok(S3Response::new(( StatusCode::NOT_IMPLEMENTED, @@ -64,7 +64,7 @@ impl Operation for TriggerProfileCPU { ))); } - #[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] + #[cfg(any(target_os = "linux", target_os = "macos"))] { let dur = std::time::Duration::from_secs(60); match crate::profiling::dump_cpu_pprof_for(dur).await { @@ -86,7 +86,7 @@ impl Operation for TriggerProfileMemory { authorize_profile_request(&req).await?; info!("Triggering Memory profile dump via S3 request..."); - #[cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))] + #[cfg(not(any(target_os = "linux", target_os = "macos")))] { return Ok(S3Response::new(( StatusCode::NOT_IMPLEMENTED, @@ -94,7 +94,7 @@ impl Operation for TriggerProfileMemory { ))); } - #[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] + #[cfg(any(target_os = "linux", target_os = "macos"))] { match crate::profiling::dump_memory_pprof_now().await { Ok(path) => { diff --git a/rustfs/src/admin/handlers/profile_admin.rs b/rustfs/src/admin/handlers/profile_admin.rs index 9b129b5c5..8741713ae 100644 --- a/rustfs/src/admin/handlers/profile_admin.rs +++ b/rustfs/src/admin/handlers/profile_admin.rs @@ -70,7 +70,7 @@ impl Operation for ProfileHandler { async fn call(&self, req: S3Request, _params: Params<'_, '_>) -> S3Result> { authorize_profile_request(&req).await?; - #[cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))] + #[cfg(not(any(target_os = "linux", target_os = "macos")))] { let requested_url = req.uri.to_string(); let target_os = std::env::consts::OS; @@ -82,7 +82,7 @@ impl Operation for ProfileHandler { return Ok(S3Response::new((StatusCode::NOT_IMPLEMENTED, Body::from(msg)))); } - #[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] + #[cfg(any(target_os = "linux", target_os = "macos"))] { use rustfs_config::{DEFAULT_CPU_FREQ, ENV_CPU_FREQ}; use rustfs_utils::get_env_usize; @@ -172,9 +172,9 @@ impl Operation for ProfileStatusHandler { async fn call(&self, req: S3Request, _params: Params<'_, '_>) -> S3Result> { authorize_profile_request(&req).await?; - #[cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))] + #[cfg(not(any(target_os = "linux", target_os = "macos")))] let message = format!("CPU profiling is not supported on {} platform", std::env::consts::OS); - #[cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))] + #[cfg(not(any(target_os = "linux", target_os = "macos")))] let status = HashMap::from([ ("enabled", "false"), ("status", "not_supported"), @@ -182,7 +182,7 @@ impl Operation for ProfileStatusHandler { ("message", message.as_str()), ]); - #[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] + #[cfg(any(target_os = "linux", target_os = "macos"))] let status = { use rustfs_config::{DEFAULT_ENABLE_PROFILING, ENV_ENABLE_PROFILING}; use rustfs_utils::get_env_bool; diff --git a/rustfs/src/allocator_reclaim.rs b/rustfs/src/allocator_reclaim.rs index 812e8286b..99fe99bd8 100644 --- a/rustfs/src/allocator_reclaim.rs +++ b/rustfs/src/allocator_reclaim.rs @@ -18,15 +18,12 @@ use tokio_util::sync::CancellationToken; use tracing::{debug, warn}; pub fn allocator_backend() -> &'static str { - #[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] + #[cfg(any(target_os = "linux", target_os = "macos"))] { "jemalloc" } - #[cfg(all( - not(target_os = "windows"), - not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")) - ))] + #[cfg(all(not(target_os = "windows"), not(any(target_os = "linux", target_os = "macos"))))] { "mimalloc" } @@ -85,10 +82,7 @@ fn reclaimable_work_snapshot() -> ReclaimableWorkSnapshot { } } -#[cfg(all( - not(target_os = "windows"), - not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")) -))] +#[cfg(all(not(target_os = "windows"), not(any(target_os = "linux", target_os = "macos"))))] #[allow(unsafe_code)] fn collect_allocator_memory(force: bool) -> Result<(), String> { // SAFETY: `mi_collect` is provided by the active global allocator backend @@ -100,9 +94,8 @@ fn collect_allocator_memory(force: bool) -> Result<(), String> { Ok(()) } -#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] +#[cfg(any(target_os = "linux", target_os = "macos"))] fn collect_allocator_memory(_force: bool) -> Result<(), String> { - #[cfg(not(target_os = "macos"))] let _ = tikv_jemalloc_ctl::background_thread::write(true); tikv_jemalloc_ctl::epoch::advance().map_err(|err| err.to_string())?; Ok(()) diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index 7b43b46c5..fca7c75a4 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -73,11 +73,11 @@ const ENV_SCANNER_ENABLED: &str = "RUSTFS_SCANNER_ENABLED"; const ENV_SCANNER_ENABLED_DEPRECATED: &str = "RUSTFS_ENABLE_SCANNER"; const ENV_HEAL_ENABLED: &str = "RUSTFS_HEAL_ENABLED"; const ENV_HEAL_ENABLED_DEPRECATED: &str = "RUSTFS_ENABLE_HEAL"; -#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] +#[cfg(any(target_os = "linux", target_os = "macos"))] #[global_allocator] static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; -#[cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))] +#[cfg(not(any(target_os = "linux", target_os = "macos")))] #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; diff --git a/rustfs/src/profiling.rs b/rustfs/src/profiling.rs index 4770cdeea..03e9df234 100644 --- a/rustfs/src/profiling.rs +++ b/rustfs/src/profiling.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))] +#[cfg(not(any(target_os = "linux", target_os = "macos")))] mod unsupported_impl { use std::path::PathBuf; use std::time::Duration; @@ -57,10 +57,10 @@ mod unsupported_impl { } } -#[cfg(not(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))] +#[cfg(not(any(target_os = "linux", target_os = "macos")))] pub use unsupported_impl::{dump_cpu_pprof_for, dump_memory_pprof_now, init_from_env, shutdown_profiling}; -#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] +#[cfg(any(target_os = "linux", target_os = "macos"))] mod linux_impl { use jemalloc_pprof::PROF_CTL; use pprof::protos::Message; @@ -369,5 +369,5 @@ mod linux_impl { } } -#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] +#[cfg(any(target_os = "linux", target_os = "macos"))] pub use linux_impl::{dump_cpu_pprof_for, dump_memory_pprof_now, init_from_env, shutdown_profiling};