mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-10 15:16:56 +00:00
cf2da0c44d
The tracker never influenced traversal: walkdir's follow behavior is fixed up front by follow_links(), and should_follow() only gated the tracker's own bookkeeping. Its 'depth limit' compared tree depth (not symlink chain depth), so RUSTFS_CAPACITY_MAX_SYMLINK_DEPTH was a complete no-op while its telemetry claimed symlinks were skipped that walkdir had in fact followed and counted; record_symlink was always called with size 0, so tracked_bytes never left zero (S12). Remove the tracker, its skipped/summary events, the symlink metric and the depth env knob end to end (the env's 'as u8' truncation goes with it), and document the real semantics at the walker: follow_links(true) counts targets with walkdir's ancestor-loop detection breaking cycles, follow_links(false) — the default — counts no symlink targets. The scan root itself is pre-resolved since backlog#1015. Ref: rustfs/backlog#1018 (S12 from audit rustfs/backlog#1010)
188 lines
7.2 KiB
Rust
188 lines
7.2 KiB
Rust
// Copyright 2024 RustFS Team
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//! Capacity metrics recording helpers.
|
|
|
|
use metrics::{counter, gauge, histogram};
|
|
use std::time::Duration;
|
|
|
|
/// Record capacity cache hit.
|
|
#[inline(always)]
|
|
pub fn record_capacity_cache_hit() {
|
|
counter!("rustfs_capacity_cache_hits").increment(1);
|
|
}
|
|
|
|
/// Record capacity cache miss.
|
|
#[inline(always)]
|
|
pub fn record_capacity_cache_miss() {
|
|
counter!("rustfs_capacity_cache_misses").increment(1);
|
|
}
|
|
|
|
/// Record how capacity cache was served to the caller.
|
|
#[inline(always)]
|
|
pub fn record_capacity_cache_served(state: &'static str) {
|
|
counter!("rustfs_capacity_cache_served_total", "state" => state).increment(1);
|
|
}
|
|
|
|
/// Record current capacity gauge.
|
|
#[inline(always)]
|
|
pub fn record_capacity_current_bytes(used_bytes: u64) {
|
|
gauge!("rustfs_capacity_current_bytes").set(used_bytes as f64);
|
|
}
|
|
|
|
/// Record capacity update completion.
|
|
#[inline(always)]
|
|
pub fn record_capacity_update_completed(source: &'static str, duration: Duration, used_bytes: u64, is_estimated: bool) {
|
|
counter!("rustfs_capacity_update_total", "source" => source).increment(1);
|
|
histogram!("rustfs_capacity_update_duration_seconds", "source" => source).record(duration.as_secs_f64());
|
|
histogram!("rustfs_capacity_update_bytes", "source" => source).record(used_bytes as f64);
|
|
counter!(
|
|
"rustfs_capacity_update_estimated_total",
|
|
"source" => source,
|
|
"estimated" => if is_estimated { "true" } else { "false" }
|
|
)
|
|
.increment(1);
|
|
}
|
|
|
|
/// Record a committed capacity reading that is degraded: the refresh behind it
|
|
/// had partial disk failures, so some disks kept last-known values.
|
|
#[inline(always)]
|
|
pub fn record_capacity_degraded_reading(source: &'static str) {
|
|
counter!("rustfs_capacity_degraded_readings_total", "source" => source).increment(1);
|
|
}
|
|
|
|
/// Record failed capacity update.
|
|
#[inline(always)]
|
|
pub fn record_capacity_update_failed(source: &'static str) {
|
|
counter!("rustfs_capacity_update_failures", "source" => source).increment(1);
|
|
}
|
|
|
|
/// Record a capacity refresh request.
|
|
#[inline(always)]
|
|
pub fn record_capacity_refresh_request(mode: &'static str, source: &'static str) {
|
|
counter!("rustfs_capacity_refresh_requests_total", "mode" => mode, "source" => source).increment(1);
|
|
}
|
|
|
|
/// Record a refresh joiner waiting for an inflight refresh.
|
|
#[inline(always)]
|
|
pub fn record_capacity_refresh_joiner(source: &'static str) {
|
|
counter!("rustfs_capacity_refresh_joiners_total", "source" => source).increment(1);
|
|
}
|
|
|
|
/// Record the number of inflight capacity refreshes.
|
|
#[inline(always)]
|
|
pub fn record_capacity_refresh_inflight(count: usize) {
|
|
gauge!("rustfs_capacity_refresh_inflight").set(count as f64);
|
|
}
|
|
|
|
/// Record the final result of a capacity refresh.
|
|
#[inline(always)]
|
|
pub fn record_capacity_refresh_result(source: &'static str, result: &'static str, duration: Duration) {
|
|
counter!("rustfs_capacity_refresh_result_total", "source" => source, "result" => result).increment(1);
|
|
histogram!("rustfs_capacity_refresh_duration_seconds", "source" => source, "result" => result).record(duration.as_secs_f64());
|
|
}
|
|
|
|
/// Record the refresh scope selected for a capacity refresh.
|
|
#[inline(always)]
|
|
pub fn record_capacity_refresh_scope(scope: &'static str, disk_count: usize) {
|
|
counter!("rustfs_capacity_refresh_scope_total", "scope" => scope).increment(1);
|
|
histogram!("rustfs_capacity_refresh_scope_disks", "scope" => scope).record(disk_count as f64);
|
|
}
|
|
|
|
/// Record the current number of dirty disks tracked by capacity management.
|
|
#[inline(always)]
|
|
pub fn record_capacity_dirty_disk_count(count: usize) {
|
|
gauge!("rustfs_capacity_dirty_disks").set(count as f64);
|
|
}
|
|
|
|
/// Record capacity write activity.
|
|
#[inline(always)]
|
|
pub fn record_capacity_write_operation(write_frequency: usize) {
|
|
counter!("rustfs_capacity_write_operations").increment(1);
|
|
gauge!("rustfs_capacity_write_frequency").set(write_frequency as f64);
|
|
}
|
|
|
|
/// Record timeout fallback event.
|
|
#[inline(always)]
|
|
pub fn record_capacity_timeout_fallback() {
|
|
counter!("rustfs_capacity_timeout_fallback").increment(1);
|
|
}
|
|
|
|
/// Record dynamic timeout usage.
|
|
#[inline(always)]
|
|
pub fn record_capacity_dynamic_timeout(timeout: Duration) {
|
|
counter!("rustfs_capacity_timeout_dynamic").increment(1);
|
|
histogram!("rustfs_capacity_timeout_dynamic_seconds").record(timeout.as_secs_f64());
|
|
}
|
|
|
|
/// Record scan sampling outcome.
|
|
#[inline(always)]
|
|
pub fn record_capacity_scan_sampling(sampled_count: usize, estimated: bool) {
|
|
histogram!("rustfs_capacity_scan_sampled_count").record(sampled_count as f64);
|
|
counter!(
|
|
"rustfs_capacity_scan_estimated_total",
|
|
"estimated" => if estimated { "true" } else { "false" }
|
|
)
|
|
.increment(1);
|
|
}
|
|
|
|
/// Record the scan mode used for a capacity result.
|
|
#[inline(always)]
|
|
pub fn record_capacity_scan_mode(mode: &'static str) {
|
|
counter!("rustfs_capacity_scan_mode_total", "mode" => mode).increment(1);
|
|
}
|
|
|
|
/// Record per-disk capacity scan statistics.
|
|
#[inline(always)]
|
|
pub fn record_capacity_scan_disk(
|
|
disk: &str,
|
|
duration: Duration,
|
|
file_count: usize,
|
|
sampled_count: usize,
|
|
estimated: bool,
|
|
partial_errors: bool,
|
|
) {
|
|
histogram!("rustfs_capacity_scan_disk_duration_seconds", "disk" => disk.to_owned()).record(duration.as_secs_f64());
|
|
histogram!("rustfs_capacity_scan_disk_files", "disk" => disk.to_owned()).record(file_count as f64);
|
|
histogram!("rustfs_capacity_scan_disk_sampled", "disk" => disk.to_owned()).record(sampled_count as f64);
|
|
counter!(
|
|
"rustfs_capacity_scan_disk_estimated_total",
|
|
"disk" => disk.to_owned(),
|
|
"estimated" => if estimated { "true" } else { "false" }
|
|
)
|
|
.increment(1);
|
|
if partial_errors {
|
|
counter!("rustfs_capacity_scan_disk_partial_errors_total", "disk" => disk.to_owned()).increment(1);
|
|
}
|
|
}
|
|
|
|
/// Record the outcome of a post-commit old-data-dir cleanup (backlog#898).
|
|
///
|
|
/// This is fired once per committed overwrite that had a previous data dir to
|
|
/// reclaim. `leaked` is the number of disks whose old data dir could not be
|
|
/// removed (a non-ignored, non-not-found failure) and is therefore a residue
|
|
/// that leaks disk space until a heal reclaims it. The leak counter is the
|
|
/// operator-visible backstop for that residue — see backlog#898 §3.4/§5.
|
|
#[inline(always)]
|
|
pub fn record_old_data_dir_cleanup(attempted: usize, reclaimed: usize, leaked: usize, below_quorum: bool) {
|
|
counter!("rustfs_old_data_dir_cleanup_attempted_total").increment(attempted as u64);
|
|
counter!("rustfs_old_data_dir_cleanup_reclaimed_total").increment(reclaimed as u64);
|
|
if leaked > 0 {
|
|
counter!("rustfs_old_data_dir_leaked_total").increment(leaked as u64);
|
|
}
|
|
if below_quorum {
|
|
counter!("rustfs_old_data_dir_cleanup_below_quorum_total").increment(1);
|
|
}
|
|
}
|