Count Chromium net::ERR_* failures per VM - #320
Open
ulziibay-kernel wants to merge 1 commit into
Open
Conversation
We can't currently tell how often sessions hit network failures like ERR_HTTP2_PROTOCOL_ERROR. Chrome tracks this in the UMA histogram Net.ErrorCodesForMainFrame4, but that is recorded in the renderer process and so is invisible to Browser.getHistograms on these images, and the cdpmonitor events that do carry errorText only flow when a caller opts into network telemetry. Tap the CDP proxy instead, the one vantage point that is on for every session, and tally Network.loadingFailed by error text and resource type. Cancellations and ERR_ABORTED are dropped so real failures aren't buried; route.abort() with its default reason is reported as ERR_FAILED with canceled false, which is indistinguishable from a genuine failure and is counted in its own series rather than dropped. The counts surface on /metrics as kernel_chromium_net_errors_total, with a throttled log line per error class for per-VM triage. The tap is passive and prescreens each frame with a substring scan before decoding, so non-failure frames cost ~108ns and zero allocations. The "->"/"<-" direction strings the pump already passed to MessageTransform are now named constants, so the tap's upstream-only check reads as intent rather than as a magic string. Co-authored-by: Cursor <[email protected]>
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.
Moved here from kernel/kernel-images-private#319 per @rgarcia's review — this has no private-only dependencies and the public repo owns both the metrics and DevTools proxy infrastructure, so landing upstream avoids fork-only behavior and the sync conflict that PR would have created.
Why
We have no way to answer "how often are our sessions hitting
ERR_HTTP2_PROTOCOL_ERROR?" — the error that keeps showing up in the Akamai/RST_STREAM investigation. The signal exists in three places today, none of which work for fleet-wide tracking:Net.ErrorCodesForMainFrame4record_load_histograms.cc), soBrowser.getHistogramscan't see it on our imagescdpmonitornetwork_loading_failedevents/curltransport errors/curlendpoint, not browser trafficWhat
Tap the DevTools proxy — the one component that is on for every session — and tally
Network.loadingFailedby error text and resource type.server/lib/neterror—Trackeraccumulates counts for the life of the VM.errorTextmust carry thenet::ERR_prefix, so an unexpected protocol string can't consume a label slot. Distinct keys are capped at 256 with an overflow counter.server/lib/devtoolsproxy— the existingMessageTransformhook now also offers upstream→client frames to the tracker. The tap is passive: it never rewrites or injects CDP traffic, so it stays invisible to automation in the browser.server/lib/wsproxy— the"->"/"<-"direction strings the pump already passed toMessageTransformare now exported constants, so the tap's upstream-only check reads as intent rather than a magic string.server/lib/metrics— new collector exposing:Unlike the Chrome collector this touches neither Chrome nor the network on scrape; it just reads the tally. There's also a throttled (1/min per error class)
WARNlog line so a single VM can be triaged from/var/log/supervisord/kernel-images-apiwithout waiting for a scrape.Review feedback from #319
HELP/TYPEwithout a sample isn't a queryable series — correct, the comment claiming otherwise was wrong and is gone. A VM with no failures is now genuinely absent from the labelled family;kernel_chromium_net_errors_dropped_totalis always sampled and is what distinguishes "no failures" from "not scraped".TestNetErrorCollectorWithNoFailuresasserts this.errorTextrequire anet::ERR_prefix? — yes, good catch. Added, withTestObserveRequiresNetErrorPrefix.TestWebSocketProxyHandler_ObservesOnlyUpstreamFrameswith a recording observer. I verified it's not vacuous by flipping the constant and watching it fail.route.abort()isn't fully excluded — accurate, and the old wording oversold the filtering. Playwright's defaultroute.abort()reason surfaces asnet::ERR_FAILEDwithcanceledfalse, which is indistinguishable from a genuine generic failure. I chose to keep counting it rather than drop a real error class: the per-error label means a session blocking images inflates only theERR_FAILEDseries and never the specific ones this exists to track. Documented in the package doc and pinned byTestObserveCountsErrFailedSeparately.Cost
The relay path is hot, so every frame is prescreened with a substring scan and only decoded if the needle is present:
Caveats
Network.enablecontributes nothing. This was the trade for being always-on rather than gated behind telemetry opt-in.Network.loadingFaileddoesn't carry the URL — correlating it means trackingrequestWillBeSentstate on the relay path, and host is too high-cardinality for a Prometheus label anyway. If the counter shows real volume, host attribution is a good follow-up as a log field.cdpmonitor. They hold separate CDP connections and would each see the same failure, so counting both would double.Test plan
go vet ./...clean,gofmtcleango test -racepasses forlib/neterror,lib/metrics,lib/devtoolsproxylib/recorderTestFFmpegArgs_*failures reproduce on cleanmain— pre-existing, unrelated):10002/metricsNote
Medium Risk
Changes the hot WebSocket relay path with per-frame substring scans (mitigated by prescreening) and bounded metric cardinality; behavior is read-only for CDP clients but depends on Network domain being enabled for coverage.
Overview
Adds fleet-visible Prometheus counters for Chromium
net::ERR_*failures by passively tapping relayed CDP traffic on the always-on DevTools WebSocket proxy.A process-wide
neterror.Trackerparses upstream→client frames forNetwork.loadingFailed, counts byerrorTextand resource type (skipping cancellations/ERR_ABORTED, requiring thenet::ERR_prefix), caps distinct label pairs at 256 with an overflow counter, and emits throttled WARN logs. The DevTools proxy wires this through a new optionalNetErrorObserveron the existing message transform (client frames are not scanned)./metricsgainskernel_chromium_net_errors_totaland always-onkernel_chromium_net_errors_dropped_totalviaNetErrorCollector.wsproxyexports direction constants so the upstream-only tap is explicit.Counts are cumulative per VM and only reflect failures when the CDP client has Network enabled; scrape reads in-memory tallies without talking to Chrome.
Reviewed by Cursor Bugbot for commit 693321f. Bugbot is set up for automated code reviews on this repo. Configure here.