✨ policy: send per-scan statistics with ReportUploadCompleted#3103
Merged
Conversation
Contributor
Design for attaching per-scan statistics to the ReportUploadCompleted RPC via a google.protobuf.Any completion payload (Level 1, keeps the base message generic across upload kinds) carrying a flat, namespaced ScanStatistics metric list (Level 2). Collector seam makes adding metrics (incl. future provider metrics) easy without proto churn. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pleted Adds google.protobuf.Any details field to ReportUploadCompletedReq so upload-kind-specific payloads can be attached without changing the message. Introduces ScanStatistics and Metric messages as the scan-database upload payload. Round-trip tests confirm both stock proto and vtproto marshaling work correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Plumb a scanstats.Collector through the upload path: records scan duration, query executed/errored counts, and upload size (bytes), then packs them as google.protobuf.Any into Details on the ReportUploadCompleted RPC. Stats collection is guarded so a nil or unencodable payload never breaks the upload confirmation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, comment) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ounters Replace inflated write-counters (ExecutedCount/ErroredCount on the wrapper) with per-kind counts derived from the resolved policy via scanstats.CountByKind. Capture the inmemory.Db returned by NewServices so GetResolvedPolicy reads the local resolved policy; stream scores and data from the finalized store. Remove the MetricQueriesExecuted/MetricQueriesErrored constants, the atomic counter fields/getters from ScanDataStoreWrapper, and the obsolete wrapper stats test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… test cases Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The design spec and implementation plan were working artifacts; they should not ship in the product PR. Removed so the PR diff contains only code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ror column) - Add `error TEXT NOT NULL DEFAULT ''` column to the `data` table, populated from `llx.Result.GetError()` on write - Add `ErroredScoreQrIds` query (filter scores by type) and `CountErroredData` query (COUNT on non-empty error column) - Regenerate sqlc: `InsertDataParams` gains `Error string`; new methods `ErroredScoreQrIds(ctx, type_ int64) ([]string, error)` and `CountErroredData(ctx) (int64, error)` - Add `ErroredScoreQrIds` and `ErroredDataCount` wrapper methods on `SqliteScanDataStore` - Add `scan_data_store_counts_test.go` covering both new methods and the empty-store case Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- policy/scanstats: add ContextWithCollector/CollectorFromContext helpers so downstream code can retrieve the stats collector from ctx without signature changes; add RecordKindCounts to write all 7 per-kind metrics in one call. - policy/executor: add countingCollector (ScoreCollector + DatapointCollector) that accumulates per-kind executed counts from the resolved policy and tracks errored checks/data with last-write-wins semantics per qr_id; wire it into ExecuteResolvedPolicy behind a ctx guard — installed only when a scanstats.Collector is present, so existing behavior is fully unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…can DB counting Put the scanstats.Collector in ctx via ContextWithCollector before calling f so the graph executor's countingCollector (added in 95e3296) records per-kind metrics during execution. Remove recordKindMetrics and the now-obsolete Option B DB counting: drop the data.error column, remove InsertData's Error field, delete ErroredScoreQrIds/CountErroredData SQL queries and their generated methods, and remove the corresponding store methods and test file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…mantics Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jaym
force-pushed
the
jdm/scan-statistics
branch
from
July 21, 2026 11:10
1bd37bf to
7cbeb08
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
What
Adds per-scan statistics to the
ReportUploadCompletedRPC so the Mondoo platform receives metrics about each scan upload.google.protobuf.Any details = 3field on the (generic, multi-upload-kind)ReportUploadCompletedReq. For scan-database uploads it carries a newScanStatistics { repeated Metric }, where eachMetricis a namespaced name + unit +oneofvalue (int64/double/bool/string). Adding a new metric — or a new upload kind's payload — needs no change to the base message.policy/scanstatspackage. A concurrency-safeCollector(AddInt/AddDuration/AddDouble/AddBool→ToProto) and aCountByKindclassifier.cnspec.scan.*):duration(ms),upload_size(bytes), per-kind countschecks,data_queries,policies,controls,frameworks, andchecks_errored/data_queries_errored.qr_id, excluding the asset-root aggregate and risk factors) plus the finalized scores/data results — an honest reflection of what was scored, not inflated write-op counts. Wiring is best-effort: a statistics failure logs a warning and never blocks the upload confirmation.Why
We want visibility into scan cost and shape: how long a scan took, how large the upload is, and a per-kind breakdown of what was evaluated (checks, data queries, policies, controls, frameworks) plus error counts. The namespaced
Metricbag inside anAnypayload makes this extensible — future provider-contributed metrics (cloud API calls, throttling, peak memory) can be reported under aprovider.<name>.*namespace with no schema change.Testing
Any(ScanStatistics)payload (de-risks the newAnypattern)scanstats.CollectorandCountByKindunit tests: per-kind counts, error classification, root/risk-factor exclusion,CHECK_AND_DATA_QUERYhandling, nil-safety-raceclean across touched packages;golangci-lintv2 reports 0 issues🤖 Generated with Claude Code