Add websocket telemetry metrics and labels (#10316)

Summary
- expose websocket telemetry hooks through the responses client so
request durations and event processing can be reported
- record websocket request/event metrics and emit runtime telemetry
events that the history UI now surfaces
- improve tests to cover websocket telemetry reporting and guard runtime
summary updates


<img width="824" height="79" alt="Screenshot 2026-01-31 at 5 28 12 PM"
src="https://github.com/user-attachments/assets/ea9a7965-d8b4-4e3c-a984-ef4fdc44c81d"
/>
This commit is contained in:
Anton Panasenko
2026-01-31 19:16:44 -08:00
committed by GitHub
Unverified
parent aab3705c7e
commit 101d359cd7
14 changed files with 335 additions and 11 deletions
+25 -1
View File
@@ -2028,6 +2028,13 @@ fn runtime_metrics_label(summary: RuntimeMetricsSummary) -> Option<String> {
summary.api_calls.count
));
}
if summary.websocket_calls.count > 0 {
let duration = format_duration_ms(summary.websocket_calls.duration_ms);
parts.push(format!(
"WebSocket: {} events send ({duration})",
summary.websocket_calls.count
));
}
if summary.streaming_events.count > 0 {
let duration = format_duration_ms(summary.streaming_events.duration_ms);
let stream_label = pluralize(summary.streaming_events.count, "Stream", "Streams");
@@ -2037,6 +2044,13 @@ fn runtime_metrics_label(summary: RuntimeMetricsSummary) -> Option<String> {
summary.streaming_events.count
));
}
if summary.websocket_events.count > 0 {
let duration = format_duration_ms(summary.websocket_events.duration_ms);
parts.push(format!(
"{} events received ({duration})",
summary.websocket_events.count
));
}
if parts.is_empty() {
None
} else {
@@ -2181,15 +2195,25 @@ mod tests {
count: 6,
duration_ms: 900,
},
websocket_calls: RuntimeMetricTotals {
count: 1,
duration_ms: 700,
},
websocket_events: RuntimeMetricTotals {
count: 4,
duration_ms: 1_200,
},
};
let cell = FinalMessageSeparator::new(Some(12), Some(summary));
let rendered = render_lines(&cell.display_lines(120));
let rendered = render_lines(&cell.display_lines(200));
assert_eq!(rendered.len(), 1);
assert!(rendered[0].contains("Worked for 12s"));
assert!(rendered[0].contains("Local tools: 3 calls (2.5s)"));
assert!(rendered[0].contains("Inference: 2 calls (1.2s)"));
assert!(rendered[0].contains("WebSocket: 1 events send (700ms)"));
assert!(rendered[0].contains("Streams: 6 events (900ms)"));
assert!(rendered[0].contains("4 events received (1.2s)"));
}
#[test]