Report what each service spent and consumed as records - #5607
Merged
Conversation
markbackman
force-pushed
the
metrics-observer
branch
from
September 2, 2026 20:56
4cdb40d to
81713a0
Compare
Codecov Report✅ All modified and coverable lines are covered by tests.
🚀 New features to boost your workflow:
|
markbackman
force-pushed
the
metrics-observer
branch
3 times, most recently
from
September 2, 2026 21:22
0782416 to
a15fa86
Compare
markbackman
force-pushed
the
metrics-observer
branch
from
September 3, 2026 02:02
a15fa86 to
f7cae9d
Compare
aconchillo
reviewed
Sep 4, 2026
| leading_silence_secs=metrics.leading_silence, | ||
| **common, | ||
| ) | ||
| if isinstance(metrics, TTFATMetricsData): |
aconchillo
reviewed
Sep 4, 2026
| thinking_time_secs=metrics.thinking_time, | ||
| **common, | ||
| ) | ||
| if isinstance(metrics, TTFBMetricsData): |
aconchillo
reviewed
Sep 4, 2026
| return ServiceLatencyRecord( | ||
| kind=ServiceLatencyKind.TTFB, seconds=metrics.value, **common | ||
| ) | ||
| return None |
aconchillo
reviewed
Sep 4, 2026
| ) | ||
| if isinstance(metrics, TTSUsageMetricsData): | ||
| return ServiceUsageRecord(kind=ServiceUsageKind.TTS, characters=metrics.value, **common) | ||
| return None |
aconchillo
approved these changes
Sep 4, 2026
Contributor
|
LGTM. Approving, just minor comments. |
Services publish metrics as they finish work, and MetricsLogObserver writes them out for a person reading a terminal. Nothing turned them into data. ServiceMetricsObserver emits one record per metric: what was measured, which processor and model reported it, and when. A measurement that decomposes keeps its parts, so time to first audio carries the leading silence and time to first answer token carries the thinking that preceded it, and an LLM record carries every token count a model reports. Nothing is summed. A turn that runs two inferences reports twice, so a consumer groups the records by turn, session or model as it needs, and a session that ends abruptly still leaves behind everything up to that point — where a total held in memory would go with it.
markbackman
force-pushed
the
metrics-observer
branch
from
September 4, 2026 21:20
f7cae9d to
9948e2a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ServiceMetricsObserver, which turns each metric a service publishes into a record. TodayMetricsLogObserverwrites them out for a person reading a terminal; nothing turned them into data.on_service_latency→ServiceLatencyRecord:kind(ttfb/ttfa/ttfat),processor,model,timestamp,seconds. A measurement that decomposes keeps its parts —leading_silence_secsbehind a time to first audio,thinking_time_secsbehind a time to first answer token, and thettfb_secsboth build on.on_service_usage→ServiceUsageRecord:kind(stt/llm/tts),processor,model,timestamp, plusaudio_seconds,characters, and every token countLLMTokenUsagereports including cache reads, reasoning and audio tokens.LatencyBreakdown, and the other two describe how work was done rather than what it cost the person waiting.The observer reads a time source a test can supply, and remembers a bounded number of frame IDs so a metric relayed along the pipeline is reported once rather than once per hop.
Testing
uv run pytest tests/test_service_metrics_observer.py— 12 tests, 100% line coverage of the new file: every metric type mapped field by field, the optional LLM token counts, several metrics in one frame, a relayed frame reported once, the two omitted metric types passed over, and the frame memory staying bounded.