feat(metrics): expose deferred usage freshness (#6449)

This commit is contained in:
cxymds
2026-08-23 19:31:01 +08:00
committed by GitHub
parent b2e60be647
commit a8e4b67d99
8 changed files with 331 additions and 25 deletions
+5
View File
@@ -1375,6 +1375,7 @@ async fn run_data_scanner_cycle_with_budget(
Ok(result) => final_data_usage_publication_defer_reason(storeapi.as_ref(), result.status).await,
Err(_) => Some(ScannerCycleDeferReason::ActivityBaselineUnavailable),
};
let publication_deferred = publication_defer_reason.is_some();
let publication_epoch = scan_result.as_ref().ok().and_then(ScannerCycleResult::publication_epoch);
let budget_elapsed = cycle_budget.budget_elapsed() && !ctx.is_cancelled();
let usage_persist_outcome = match publication_defer_reason {
@@ -1539,6 +1540,9 @@ async fn run_data_scanner_cycle_with_budget(
state = "deferred",
"Scanner cycle deferred before data usage publication"
);
if publication_deferred {
global_metrics().record_scanner_usage_deferred(reason.as_str());
}
emit_scan_cycle_deferred(cycle_start.elapsed());
mark_scan_cycle_idle(cycle_info, &mut cycle_metrics_guard).await;
return ScannerCycleOutcome::Deferred(reason);
@@ -1708,6 +1712,7 @@ async fn run_data_scanner_cycle_with_budget(
state = "deferred",
"Scanner cycle deferred before usage scanning began"
);
global_metrics().record_scanner_usage_deferred(reason.as_str());
emit_scan_cycle_deferred(cycle_start.elapsed());
mark_scan_cycle_idle(cycle_info, &mut cycle_metrics_guard).await;
return ScannerCycleOutcome::Deferred(reason);
+1
View File
@@ -2788,6 +2788,7 @@ async fn test_deferred_usage_save_keeps_last_real_save_metric() {
assert_eq!(after.last_usage_save_result, before.last_usage_save_result);
assert_eq!(after.last_usage_save_result_code, before.last_usage_save_result_code);
assert_eq!(after.last_usage_save_unix_secs, before.last_usage_save_unix_secs);
assert_eq!(after.deferred_total, before.deferred_total.saturating_add(1));
}
#[tokio::test]
+15 -1
View File
@@ -186,6 +186,7 @@ where
state = "publication_blocked_before_reconcile",
"Scanner data usage publication deferred by the pool-state fence"
);
global_metrics().record_scanner_usage_deferred(ScannerCycleDeferReason::DataMovement.as_str());
outcome = DataUsagePersistOutcome::Deferred(ScannerCycleDeferReason::DataMovement);
break;
}
@@ -288,6 +289,7 @@ where
state = "reject_incomplete_snapshot",
"Scanner refused to persist an incomplete data usage snapshot"
);
global_metrics().record_scanner_usage_publication("failed", "incomplete_snapshot");
global_metrics().record_scanner_usage_save_result(ScannerUsageSaveResult::Failed);
outcome = DataUsagePersistOutcome::Failed;
continue;
@@ -306,6 +308,7 @@ where
error = %e,
"Scanner data usage encode failed"
);
global_metrics().record_scanner_usage_publication("failed", "encode_failed");
global_metrics().record_scanner_usage_save_result(ScannerUsageSaveResult::EncodeFailed);
outcome = DataUsagePersistOutcome::Failed;
continue;
@@ -549,6 +552,7 @@ where
replace_bucket_usage_memory_from_info(&data_usage_info).await;
}
global_metrics().record_scanner_usage_save_result(ScannerUsageSaveResult::Success);
global_metrics().record_scanner_usage_durable_success();
outcome = DataUsagePersistOutcome::AlreadyDurable;
}
DataUsagePersistOutcome::PriorCycleDurable => {
@@ -568,9 +572,17 @@ where
invalidate_data_usage_snapshot_cache().await;
}
global_metrics().record_scanner_usage_save_result(ScannerUsageSaveResult::Success);
global_metrics().record_scanner_usage_durable_success();
outcome = DataUsagePersistOutcome::PriorCycleDurable;
}
DataUsagePersistOutcome::Failed | DataUsagePersistOutcome::NoUpdate => {
DataUsagePersistOutcome::NoUpdate => {
global_metrics().record_scanner_usage_publication("no_update", "no_update");
global_metrics().record_scanner_usage_save_result(ScannerUsageSaveResult::Failed);
outcome = DataUsagePersistOutcome::NoUpdate;
continue;
}
DataUsagePersistOutcome::Failed => {
global_metrics().record_scanner_usage_publication("failed", "save_failed");
global_metrics().record_scanner_usage_save_result(ScannerUsageSaveResult::Failed);
outcome = DataUsagePersistOutcome::Failed;
continue;
@@ -579,6 +591,7 @@ where
// A deferred publication is an intentional retryable state, not a
// failed save. Keep the last real save result so admin freshness
// reporting does not turn a pool-recovery fence into a false error.
global_metrics().record_scanner_usage_deferred(reason.as_str());
outcome = DataUsagePersistOutcome::Deferred(reason);
break 'updates;
}
@@ -600,6 +613,7 @@ where
replace_bucket_usage_memory_from_info(&data_usage_info).await;
}
global_metrics().record_scanner_usage_save_result(ScannerUsageSaveResult::Success);
global_metrics().record_scanner_usage_durable_success();
outcome = DataUsagePersistOutcome::Saved;
}
}