Measure Guardian review latency once with a monotonic clock (#55846)

## Why

Guardian review metrics derived duration from wall-clock timestamps, while analytics measured elapsed time when tracking the result. Clock changes and delayed tracking could produce inconsistent latencies.

## What changed

Capture one monotonic duration at review completion and pass it to both metrics and analytics. Preserve wall-clock timestamps for event ordering, and saturate analytics latency conversion at `u64::MAX`.

## Testing

Add a regression test covering skewed wall-clock timestamps and delayed tracking, verifying that the duration metric uses the captured interval and completion timestamps are preserved.

GitOrigin-RevId: 19eafb8e1f1a3d13a751bdc72c218e4cafeae410
This commit is contained in:
ioanbudea-OAI
2026-10-21 09:52:45 +00:00
committed by copyberry
parent af91f6ef2c
commit 2213359bd3
6 changed files with 155 additions and 18 deletions
+2 -1
View File
@@ -472,9 +472,10 @@ impl AnalyticsEventsClient {
tracking: &GuardianReviewTrackContext,
result: GuardianReviewAnalyticsResult,
completed_at_ms: u64,
elapsed: Duration,
) {
self.record_fact(AnalyticsFact::Custom(CustomAnalyticsFact::GuardianReview(
Box::new(tracking.event_params(result, completed_at_ms)),
Box::new(tracking.event_params(result, completed_at_ms, elapsed)),
)));
}
+4 -4
View File
@@ -1,5 +1,5 @@
use std::sync::LazyLock;
use std::time::Instant;
use std::time::Duration;
use crate::facts::AppInvocation;
use crate::facts::ArtifactOperation;
@@ -448,7 +448,6 @@ pub struct GuardianReviewTrackContext {
reviewed_action: GuardianReviewedAction,
review_timeout_ms: u64,
pub started_at_ms: u64,
started_instant: Instant,
}
impl GuardianReviewTrackContext {
@@ -470,7 +469,6 @@ impl GuardianReviewTrackContext {
reviewed_action,
review_timeout_ms,
started_at_ms: now_unix_millis(),
started_instant: Instant::now(),
}
}
@@ -478,7 +476,9 @@ impl GuardianReviewTrackContext {
&self,
result: GuardianReviewAnalyticsResult,
completed_at_ms: u64,
elapsed: Duration,
) -> GuardianReviewEventParams {
let completion_latency_ms = u64::try_from(elapsed.as_millis()).unwrap_or(u64::MAX);
GuardianReviewEventParams {
guardian_context_mode: result.guardian_context_mode,
thread_id: self.thread_id.clone(),
@@ -509,7 +509,7 @@ impl GuardianReviewTrackContext {
// TODO(rhan-oai): plumb nested Guardian review session tool-call counts.
tool_call_count: None,
time_to_first_token_ms: result.time_to_first_token_ms,
completion_latency_ms: Some(self.started_instant.elapsed().as_millis() as u64),
completion_latency_ms: Some(completion_latency_ms),
started_at: self.started_at_ms / 1_000,
completed_at: Some(completed_at_ms / 1_000),
input_tokens: result.token_usage.as_ref().map(|usage| usage.input_tokens),