Description
Per-PoP traffic, top ASNs and which paths error are useful but unbounded. Other exporters gate colo breakdowns to an allow-listed set of hosts and normalise numeric, UUID and hex path segments into placeholders before using a path as a label.
Acceptance Criteria
- #1 Colo and ASN dimensions are off by default and enabled per config, optionally limited to a host allowlist
- #2 An opt-in 4xx/5xx-by-path metric normalises numeric, UUID and hex path segments, with unit tests for the normaliser
- #3 The ASN description field is live-verified on the HTTP groups dataset before use (doc-0003 records it rejected on the firewall dataset)
- #4 Every new signal and attribute is declared in internal/semconv, listed in docs/signals.md, and has a panel in grafana/build_dashboard.py
Definition of Done
- #1 just check (fmt-check, lint, vet, test, tidy-check, build, vuln)
- #2 just ci before a change that touches the Dockerfile, goreleaser or the image (adds snapshot + image)
- #3 Every new signal or attribute name declared in internal/semconv and listed in docs/signals.md
Implementation Plan
Loop15 E46C initial implementation: keep existing HTTP metrics window collector, SDK/buffer/checkpoint interfaces unchanged. Add off-by-default colo/asn/error_path breakdown toggles; grouped counts only, current per-zone advertised-field discovery and source policy. ASN strings/descriptions use the eligible live-verified shape from doc-0003 section18 and are omitted on unentitled zones, preserving base metrics. Error paths normalize numeric/UUID/hex segments internally, then map exact normalized templates to explicitly configured safe route names; only configured names and bounded remainder enums are metric attributes, never raw/normalized paths, identifiers, email or IP values. Empty enabled route map or ambiguous normalized templates is a config error. Optional exact host allowlist filters only these high-cardinality features, without altering existing metrics. New bounded per-metric aggregation/remainder is local; all output still counts toward the existing complete-window HTTP series failure cap. Own HTTP package/config/semconv/docs/API contract rows only; dashboard later. Frozen names in root current state before source dispatch; public Register/real HTTP GraphQL/real SDK and normalizer branching proof required.
Correction after exact selector verification: ONLY error_path GraphQL selection adds integer edgeResponseStatus_geq=400 and edgeResponseStatus_leq=599 merged into an independent copy of existing requestSource filter. Colo/ASN and legacy selections unchanged. Local integer/range/status-class validation remains defensive. The old frozen assertion prohibiting ANY range filter is superseded solely because intended query behavior now changes on verified schema/live-selection evidence; name the assertion and reason when repairing it.
Implementation Notes
Loop15 current HTTP-groups ASN-description prerequisite cleared: exact advertised eligible-zone selection HTTP200/GraphQL errors0/five typed populated rows with non-empty descriptions. ASN and description are strings. Colo/host/path/status advertised on all23 enabled HTTP zones; ASN fields only one. API reference doc-0003 section18 records the live-value proof and paging/counter/privacy limits. No source implementation admitted yet. Raw or normalized path values remain prohibited metric attributes by the standing model; root is mapping an internal normalizer with explicitly configured safe route names as output labels, not granting a path-label exception.
E46C I1 stopped uncommitted/staged at tree cb03db69a687a73c1b61581fc1cf2f21edebace9, patch2610b174465c01d07e2ea831a089885794dea15dbc26ee2fb343a93b12c38523. Real HTTP/Register/Scheduler/file-checkpoint/SDK narrow race proof passed, compiled base assertion reds preserved; full delivery gate not run. CodeRabbit1 complete15/15 with one major: error-path query must narrow 400-599 upstream to avoid non-error path/status groups saturating the query. Prior frozen local-only filter prevented an unverified selector; worker correctly returned rather than waive. Changed premise: exact HTTP-groups input introspection verified edgeResponseStatus_geq/leq as uint16, and a live same-source eyeball query with those bounds returned five typed in-range rows at08:43, HTTP200/GraphQL0. Root now authorizes this verified source predicate for error_path ONLY, keeping local status validation, existing source filters, other query semantics, caps and atomic checkpoint behavior. I2 goes to lane-worker-retry on the same branch; discriminating local HTTP fixture must exercise many non-error path groups, show error-only predicate and successful error counts, preserve unrelated metrics/no-filter selections, then satisfy CodeRabbit major and complete required gate. I1 consumed; I2 commissioned, two implementation attempts remain after I2; review-repair1 used for this finding; infrastructure0. No self-I2, scope reset, test weakening or major waiver.
E46C I2 returned delivery-gate FAIL at lint QF1001 high_cardinality_test.go66: De Morgan Boolean expression. No self-I3 or commit. Staged candidate b943e5174126f4621e4c1287687184fefecd7cef, patch8bc4a1c566b74f8891c15627849149082547e0984bb5279fd7e77f3be3b96658 preserved. New healthy-path-saturation registered HTTP/Scheduler/SDK reproduction failed against I1 and passed after verified error-only source predicate; earlier narrow green is pre-CR2 page-limit correction, not final-tree pass. CR2 complete15/15 found a page-limit major; worker applied effective limit=min(10000, positive MaxPageSize) to selection and saturation guard, with real existing cfapi batch six-case protection checks, but final delivery then failed lint. No CR3 and no claim the post-correction tree was CR-reviewed. I3 rescue-sol commissioned on the same candidate: correct equivalent Boolean expression only, independently verify page-limit/saturation and filter-copy fixes against both findings, run final-tree local proof, required gate and compiled CLI, then commit only owned files. Fresh exact-leaf independent REV remains required. I1/I2 consumed; I3 leaves one implementation attempt; review-repair1 used; inherited I2 launch infra1/2 distinct from implementation lint failure. No gate/test weakening or mandatory-major waiver.
Final Summary
Delivered source at ea8e9d8c1743b6638f6bec442895a867bbe55177 and panels at88b4379e923ffe35c1830a92eca8c52ab21c923e. Default-off colo/ASN/error-route options, feature-only host allowlist, internal numeric/UUID/hex normalization to explicitly configured safe route names, grouped counters with count-preserving remainder and unchanged atomic global window cap. No raw or normalized path metric attribute. Exact-source independent reviews passed311261640185993e8b899ac1c95aa688931ebaf3 andbe7001766cb57e65fb11f1429922607e68be86fa, including genuine compiled-base reds, real shared HTTP/Register/Scheduler/file-checkpoint/SDK proofs, page-limit and source-filter reproduction, compiled CLI configuration/environment behavior and clean leaf-version builds. CR1/CR2 each covered15 source files before their major corrections; both majors fixed and independently exercised/reviewed in final source, no CR3 or false final-tree CR claim. DASH CR covered2 Python sources; one minor about generated panels left because actual committed JSON contained them and generation checks passed. Generated JSON used the explicit packet exemption. Required source/integration gates and unchanged strict net/all-new-history raw-empty scans passed before each push. B8 CI36990281197/B9 CI36992731954 all6 jobs passed;9 and8 applicable workflows respectively successful; B9 Grafana sync36992731892 passed. Root current HTTP ASN prerequisite5 typed populated rows with nonempty descriptions on one eligible zone is recorded in doc-0003; not universal entitlement or complete counter/paging proof. Actual panel2065/2066/2067 GET10:06:32.491594Z raw source/config/layout/keys exact MATCH, hashab60b6072f89b323ceb1f18c1039bcea5db8cba4b90d2d23b7547a0a1749610d. Source criteria are Done; features remain off on the deploy host by frozen authority. No release/deployed counter, browser/production-frame or sustained-hour claim.