go/observability

Free catalog · v0.0.26

Reviews Go logs, traces, metrics, context propagation, and telemetry lifecycle defects.

Checks

RuleSeverityScans for
go-obs.metrics.planned-batch-as-executedMediumAn explicitly successful-work Prometheus counter adds the full input-slice length immediately after a direct work loop whose error branch can break or continue
go-obs.logging.lossy-parse-classificationLowChanged external parser failures immediately collapsed into a package sentinel under an explicit fallback/classification contract while the established context logger discards the original cause
go-obs.logging.normal-cancellation-as-errorMediumA helper classifies context cancellation as normal shutdown but a direct caller logs the returned error at error level
go-obs.metrics.duration-unit-mismatchHighA Prometheus histogram or summary declares a duration unit in its metric name but records a different explicit Go duration unit
go-obs.metrics.success-latency-on-non-success-pathsMediumA metric explicitly documented as latency to a named successful completion is emitted from a defer that also covers a proven skipped/non-success return before that operation
go-obs.metrics.failure-without-denominatorMediumA Prometheus failure/error counter has no comparable same-subject event total
go-obs.metrics.high-cardinalityHighProven Prometheus vector label names, label maps, or WithLabelValues arguments use request- or user-specific dimensions
go-obs.metrics.register-in-requestMediumMetric registration inside a request handler or loop
go-obs.panic.recover-swallowHighrecover() discards the panic without logging or re-reporting it
go-obs.slog.args-mismatchMediumslog call with mismatched key/value pairs or non-string key
go-obs.trace.background-contextMediumSpan or downstream call started from context.Background() inside a request path that has a real context
go-obs.trace.span-not-endedHighSpan started but not ended on all return paths

The lossy parser-classification check is intentionally not a generic request for more logging. It requires one changed, immediate relationship: an imported parser returns an error; an explicit fallback/classification comment explains why the branch maps failure to a package-level errors.New sentinel; a real context.Context and an already-used imported logger prove the local diagnostic convention; and the original error is discarded. It stays quiet for local or shadowed parsers, arbitrary failing calls, returned/wrapped causes, branches with diagnostics, missing logger/context proof, tests, unchanged legacy relationships, unrelated diffs, and comment-only edits. Deletion-only changes without a current semantic anchor fail closed.

The success-latency check requires the complete relationship in prepared Go source: a metric contract names latency or duration to a specific successful completion operation; the same metric is observed from a deferred callback; and a reachable skipped, buffered, duplicate, cached, or otherwise non-success return can run after the defer but before that completion call. It stays quiet for all-outcome duration metrics, emission after successful completion, success-guarded observations, bounded outcome tags, error-only deferred telemetry, statically dead skip paths, missing contract/operation evidence, tests, unchanged legacy relationships, and comment-only edits.

The high-cardinality check does not classify arbitrary slices or maps by vocabulary. Label-name findings require an exact, unshadowed prometheus or promauto import and a vector constructor whose second argument is either a direct []string literal or one uniquely visible, unreassigned slice definition. Label-map findings require the imported prometheus.Labels type, while value findings require the actual WithLabelValues(...) call shape and a syntactically unbounded request URL, user ID, request ID, or error string rather than a bounded string literal. Modified files report only when that semantic metric relationship is new and a changed constructor, import, label, map key, or value supplies a current anchor. Ordinary documentation slices, fake constructors, unrelated Labels types, shadowed imports, unchanged legacy metrics, unrelated edits, tests, parse failures, and comment-only edits stay quiet.

The batch-completion check is a bounded same-file analysis: an imported Prometheus NewCounter with a literal successful-work Help contract, a function's slice input, a direct range loop whose sole work call has an immediate error break/continue, and an unconditional following Add(float64(len(batch))). It does not infer execution history from arbitrary names. Ambiguous completed-work contracts without a success requirement, planned/attempted metrics, return-on-error, guarded emission, per-success counting, opaque control flow, other slices, mutations, shadowed bindings, test files, parse failures, unchanged relationships, unrelated diffs, and comment-only edits stay quiet. Cross-package result-to-telemetry helpers are not resolved by this check.

More from the registry