fix(obs): count scanned versions independent of ILM (#4516)

versions_scanned for both the scanner and ILM collectors was read from
the Lifecycle work source's `checked` counter, which is never recorded on
the production scan path — so rustfs_scanner_versions_scanned_total and
rustfs_ilm_versions_scanned_total sat at zero even while objects_scanned
climbed. The two metrics also have distinct intended meanings that were
conflated: "versions scanned" (all versions, any bucket) vs "versions
checked for ILM actions" (lifecycle-configured buckets only).

Add a lifetime `versions_scanned` counter recorded for every version the
scanner walks (independent of ILM), and record the Lifecycle source's
`checked` counter from the ILM evaluator so the ILM metric reflects the
real checked subset. The scanner collector now reports total scanned
versions; the ILM collector keeps the ILM-checked subset.

Closes backlog#995 (OBS-09).

Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
houseme
2026-07-09 00:50:51 +08:00
committed by GitHub
parent e829430d89
commit 6ab8636734
4 changed files with 85 additions and 1 deletions
+8
View File
@@ -821,6 +821,14 @@ impl ScannerItem {
return;
}
};
// Every version handed to the evaluator counts as an ILM-checked
// version, whether or not a rule matched (NoneAction included). This is
// reached only for buckets with lifecycle rules; it feeds
// rustfs_ilm_versions_scanned_total via the Lifecycle source's checked
// counter.
global_metrics().record_scanner_source_checked(ScannerWorkSource::Lifecycle, object_opts.len() as u64);
let mut to_delete_objs: Vec<ObjectToDelete> = Vec::new();
let mut noncurrent_events: Vec<Event> = Vec::new();
let mut noncurrent_accounting: Vec<PendingScannerAccounting<'_>> = Vec::new();
+6
View File
@@ -1535,6 +1535,12 @@ impl ScannerIODisk for Disk {
let lock_config = object_lock_config_for_scanner_item(&item).await;
// Count every version this object contributes to the scan, independent
// of any lifecycle configuration, so scan-coverage metrics stay honest
// on clusters without ILM rules. Recorded before `apply_actions` moves
// `object_infos`.
global_metrics().record_scanner_versions_scanned(object_infos.len() as u64);
item.apply_actions(object_infos, lock_config, &mut size_summary).await;
if !free_version_infos.is_empty() {