Repository navigation
feat(provider): MTP posture and acceptance counters on the local /metrics endpoint - #619
Merged
Merged
Conversation
…rics endpoint
Bug 2 from mlx-swift-lm#106 'Discovered bugs': MTP acceptance existed only
in-engine (CBv2MTPMetrics via EngineV2Bridge.mtpStatusSnapshot) and in the
engine_v2_slot_posture telemetry event — i.e. Datadog Logs. A headless
operator (no os_log store in sandboxes) could not observe acceptance, or
that MTP silently never activated (inline_artifact_invalid).
- LocalMetricsResponder serves GET /metrics: the upstream MLXLMServer
ServerMetrics body (same public prometheusMetrics() entry point) plus
provider-owned per-model lines in the same Prometheus text style:
mtp_enabled, mtp_active, mtp_rounds_total, mtp_tokens_proposed_total,
mtp_tokens_accepted_total, and mtp_inactive_reason{reason=...} carrying
the MTPFallbackReason enum (inline_artifact_invalid, inert_kv_unsupported,
...) whenever MTP is not productively running.
- Wired through both local endpoints via a mtpSlots closure: StandaloneServer
slot cache and the unified ProviderLoop modelSlots — the same bridge
snapshot the capacity tick feeds DaemonSlotPostureBuilder.
- Coordinator telemetry wire types untouched (3-language sync out of scope);
daemon-state SlotPosture already carries the mtp posture trio.
- Pure provider-swift change; no submodule field added by #106 is required
(counters predate it), so it is pin-independent of the #616 bump.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Gajesh2007
had a problem deploying
to
benchmarks
August 13, 2026 22:54 — with
GitHub Actions
Failure
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8678aa4af8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Gajesh2007
had a problem deploying
to
benchmarks
August 13, 2026 23:31 — with
GitHub Actions
Failure
The MTP block was appended to MLXLMServer's prometheusMetrics() body by
bare string concatenation, silently relying on the upstream body's
trailing newline — an implementation detail of ServerMetrics
.prometheusText()'s multiline literal. A submodule bump dropping that
newline would fuse the final upstream sample and the first MTP header
into one invalid line (mlx_server_uptime_seconds 12# TYPE mtp_enabled
gauge), making Prometheus reject the whole scrape.
MTPPrometheusRenderer.joinedBody now makes the seam explicit: exactly
one newline between a non-empty upstream body and the MTP block, empty
upstream yields the MTP block alone, empty MTP block leaves the
upstream body byte-identical, and the joined body keeps the single
trailing newline the text format expects.
Tests: the /metrics route tests now assert line-level exposition
validity (every non-empty line is a # TYPE/# HELP header or a complete
name{labels} value sample) instead of substring checks alone, plus a
regression case for an unterminated upstream body + resident slot.
Verified the regression test fails against the pre-fix bare concat.
Gajesh2007
had a problem deploying
to
benchmarks
August 13, 2026 23:41 — with
GitHub Actions
Failure
This branch had an error being deployed
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.
Problem
Bug 2 from Layr-Labs/mlx-swift-lm#106's Discovered bugs: MTP acceptance is unobservable outside Datadog Logs. The counters exist in-engine (
CBv2MTPMetrics, polled viaEngineV2Bridge.mtpStatusSnapshot()), but the only surface was theengine_v2_slot_posturetelemetry event → Datadog Logs. The provider's local HTTP server exposes/metricswith no MTP counters at all, and the os_log store is inaccessible in sandboxes — so a headless operator could not observe whether MTP is producing drafts, what the acceptance ratio is, or that MTP silently never activated (inline_artifact_invalid, the sibling bug fixed in #618;inert_kv_unsupported; …).Change
/metricsnow appends provider-owned per-model lines behind the upstreamMLXLMServerbody, in the same Prometheus text style (# TYPE+ bare lines):Counters are cumulative per slot lifetime (standard counter contract, matching the telemetry event); acceptance rate =
accepted_total / proposed_total.mtp_inactive_reasoncarries the existingMTPFallbackReasonenum — the same statusinline_artifact_invalidrides in — so a silently-disabled drafter is operationally visible.Mechanics: the upstream
/metricsroute lives inMLXLMServer(ServerMetrics.prometheusText()), whose router is already built when the provider wraps it — so a newLocalMetricsResponderserves GET/metricsitself (same publicMLXOpenAIService.prometheusMetrics()entry point + the MTP lines), exactly the interception patternLocalChatUploadResponderestablished. Wired through both local endpoints via amtpSlotsclosure: theStandaloneServerslot cache (--local) and the unifiedProviderLoop.modelSlots(--local-endpoint) — the same bridge snapshot the capacity tick already feeds intoDaemonSlotPostureBuilder, so/metrics, daemon-state, and telemetry cannot describe a slot differently.Deliberately not touched: the coordinator telemetry wire types (Go/Swift/TS three-language sync — out of scope); the daemon-state
SlotPosturealready carriesmtpEnabled/mtpActive/mtpInactiveReason, sodarkbloom statusneeded no change.Behavior
flowchart LR subgraph Before A1["CBv2MTPMetrics (in-engine)"] --> B1["engine_v2_slot_posture event"] --> C1["Datadog Logs ONLY<br/>headless/sandboxed operator: blind<br/>silently-disabled MTP invisible"] D1["GET /metrics"] --> E1["upstream mlx_server_* counters only"] end subgraph After A2["CBv2MTPMetrics (in-engine)"] --> B2["engine_v2_slot_posture event -> Datadog (unchanged)"] A2 --> D2["GET /metrics"] --> E2["mlx_server_* body +<br/>mtp_enabled / mtp_active / mtp_rounds_total /<br/>mtp_tokens_proposed_total / mtp_tokens_accepted_total /<br/>mtp_inactive_reason{reason=…}"] endCode
flowchart LR subgraph Before R1["auth -> CORS -> chat-upload -> upstream router"] --> M1["/metrics = ServerMetrics.prometheusText() verbatim"] end subgraph After R2["auth -> CORS -> LocalMetricsResponder -> chat-upload -> upstream router"] --> M2["/metrics = prometheusMetrics() + MTPPrometheusRenderer.render(mtpSlots())"] S2[StandaloneServer.mtpSlotMetricsSamples] --> M2 P2[ProviderLoop.mtpSlotMetricsSamplesForLocal] --> M2 endPin independence (#616)
Pure provider-swift change, based on
master(which already carries the #616 pin bump to mlx-swift-lmd06da67). It uses no field introduced by mlx-swift-lm#106 —CBv2MTPMetrics.rounds/draftedTokens/acceptedTokens/activeandMLXOpenAIService.prometheusMetrics()all predate it — so it also compiles against the pre-#106 pin (c04afb4); no availability gating needed.Tests
Targeted filters green (
swift test, debug, with source-matched metallib permake provider-test):mtpPrometheusRendererEmitsPostureAndCounters— stubbed active snapshot (7 rounds, 21 proposed, 14 accepted) and a stubbedinline_artifact_invalidslot: all six families render, healthy slots omitmtp_inactive_reason, label values are Prometheus-escaped, empty slot list renders nothing (upstream body stays byte-identical).localMetricsEndpointAppendsMTPLinesToUpstreamBody— full responder stack viamakeLocalInferenceApplicationwith a stubbedmtpSlotsclosure: GET/metricsreturns 200text/plain, the upstreammlx_server_*body intact, and the stubbed counters (3/9/6) appear.standaloneServerMetricsWithoutSlotsServesUpstreamBodyOnly— cold standalone server: upstream body only, nomtp_lines.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.