mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-25 05:26:50 +00:00
feat(metrics): expose deferred usage freshness (#6449)
This commit is contained in:
@@ -302,10 +302,28 @@ pub struct ScannerUsageFreshnessSnapshot {
|
||||
pub last_usage_save_result: String,
|
||||
#[serde(rename = "last_usage_save_result_code", default)]
|
||||
pub last_usage_save_result_code: u64,
|
||||
#[serde(rename = "last_durable_success_unix_secs", default)]
|
||||
pub last_durable_success_unix_secs: u64,
|
||||
#[serde(rename = "last_publication_unix_secs", default)]
|
||||
pub last_publication_unix_secs: u64,
|
||||
#[serde(rename = "last_publication_state", default)]
|
||||
pub last_publication_state: String,
|
||||
#[serde(rename = "last_publication_reason", default)]
|
||||
pub last_publication_reason: String,
|
||||
#[serde(rename = "deferred_pending", default)]
|
||||
pub deferred_pending: bool,
|
||||
#[serde(rename = "deferred_total", default)]
|
||||
pub deferred_total: u64,
|
||||
#[serde(rename = "last_deferred_unix_secs", default)]
|
||||
pub last_deferred_unix_secs: u64,
|
||||
#[serde(rename = "last_deferred_reason", default)]
|
||||
pub last_deferred_reason: String,
|
||||
}
|
||||
|
||||
impl ScannerUsageFreshnessSnapshot {
|
||||
fn merge(&mut self, other: &Self) {
|
||||
let self_deferred_state_at = self.last_deferred_unix_secs.max(self.last_durable_success_unix_secs);
|
||||
let other_deferred_state_at = other.last_deferred_unix_secs.max(other.last_durable_success_unix_secs);
|
||||
self.dirty_pending_buckets = self.dirty_pending_buckets.saturating_add(other.dirty_pending_buckets);
|
||||
self.last_dirty_mark_unix_secs = self.last_dirty_mark_unix_secs.max(other.last_dirty_mark_unix_secs);
|
||||
self.last_dirty_clear_unix_secs = self.last_dirty_clear_unix_secs.max(other.last_dirty_clear_unix_secs);
|
||||
@@ -318,6 +336,22 @@ impl ScannerUsageFreshnessSnapshot {
|
||||
self.last_usage_save_result = other.last_usage_save_result.clone();
|
||||
self.last_usage_save_result_code = other.last_usage_save_result_code;
|
||||
}
|
||||
self.last_durable_success_unix_secs = self.last_durable_success_unix_secs.max(other.last_durable_success_unix_secs);
|
||||
if other.last_publication_unix_secs > self.last_publication_unix_secs {
|
||||
self.last_publication_unix_secs = other.last_publication_unix_secs;
|
||||
self.last_publication_state = other.last_publication_state.clone();
|
||||
self.last_publication_reason = other.last_publication_reason.clone();
|
||||
}
|
||||
self.deferred_total = self.deferred_total.saturating_add(other.deferred_total);
|
||||
if other_deferred_state_at > self_deferred_state_at {
|
||||
self.deferred_pending = other.deferred_pending;
|
||||
} else if other_deferred_state_at == self_deferred_state_at {
|
||||
self.deferred_pending |= other.deferred_pending;
|
||||
}
|
||||
if other.last_deferred_unix_secs > self.last_deferred_unix_secs {
|
||||
self.last_deferred_unix_secs = other.last_deferred_unix_secs;
|
||||
self.last_deferred_reason = other.last_deferred_reason.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1566,6 +1600,47 @@ mod tests {
|
||||
assert_eq!(explicit_false.current_cycle_active, Some(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_freshness_deferred_fields_are_backward_compatible_and_merge() {
|
||||
let legacy: ScannerUsageFreshnessSnapshot = serde_json::from_value(serde_json::json!({
|
||||
"dirty_pending_buckets": 2,
|
||||
"last_usage_save_result": "success"
|
||||
}))
|
||||
.expect("legacy usage freshness should decode");
|
||||
assert!(!legacy.deferred_pending);
|
||||
assert_eq!(legacy.deferred_total, 0);
|
||||
|
||||
let mut merged = ScannerUsageFreshnessSnapshot::default();
|
||||
merged.merge(&ScannerUsageFreshnessSnapshot {
|
||||
deferred_pending: true,
|
||||
deferred_total: 2,
|
||||
last_deferred_unix_secs: 20,
|
||||
last_deferred_reason: "data_movement".to_string(),
|
||||
..Default::default()
|
||||
});
|
||||
merged.merge(&ScannerUsageFreshnessSnapshot {
|
||||
deferred_total: 1,
|
||||
last_deferred_unix_secs: 10,
|
||||
last_deferred_reason: "older".to_string(),
|
||||
..Default::default()
|
||||
});
|
||||
assert!(merged.deferred_pending);
|
||||
assert_eq!(merged.deferred_total, 3);
|
||||
assert_eq!(merged.last_deferred_unix_secs, 20);
|
||||
assert_eq!(merged.last_deferred_reason, "data_movement");
|
||||
|
||||
merged.merge(&ScannerUsageFreshnessSnapshot {
|
||||
deferred_pending: false,
|
||||
last_durable_success_unix_secs: 30,
|
||||
last_publication_unix_secs: 30,
|
||||
last_publication_state: "success".to_string(),
|
||||
..Default::default()
|
||||
});
|
||||
assert!(!merged.deferred_pending);
|
||||
assert_eq!(merged.last_durable_success_unix_secs, 30);
|
||||
assert_eq!(merged.last_publication_state, "success");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scanner_metrics_merge_prefers_an_active_first_cycle() {
|
||||
let collected_at = Timestamp::now();
|
||||
|
||||
Reference in New Issue
Block a user