prometheus/prometheus
Patterns and conventions
Conventions repeated across the codebase. Some are encoded in lint rules, some are tribal knowledge from AGENTS.md, and some emerge from reading the code itself.
Code style
The two referenced style guides are:
- Go Code Review Comments
- The "Formatting and style" section of Peter Bourgon's Go: Best Practices for Production Environments
Local enforcement:
gofmt -s(run bymake format).golangci-lintwith.golangci.yml. Linters enabled includegocritic(notable ruleemptyStringTest),errcheck,revive,staticcheck,whitespace,unconvert,usestdlibvars,gocheckcompilerdirectives,loggercheck,perfsprint, andtestifylint.//nolint:linter1[,linter2]is allowed but reviewers will push back if the suppression is not justified.
All exported objects must have a doc comment that begins with the object's name and ends with a full stop. All comments start with a capital letter and end with a full stop.
Interface contracts at the interface
When ownership or buffer-reuse semantics matter, document them on the interface, not the implementation. Examples in the codebase:
storage.Appender(storage/interface.go) documents that callers must not retainlabels.LabelsafterAppendreturns; the appender may copy or intern.tsdb.ChunkReaderdocuments that the returned chunk byte slice is valid only until the next call.prompb.Compress/Decompress(util/compression/) — buffers passed in are reused, callers must copy before the next call.
This is a recurring review comment on PRs that introduce new interfaces.
Goroutine lifecycle
Most subsystems own a Run(ctx context.Context, ...) error method that exits when the context is cancelled. The server's main loop in cmd/prometheus/main.go uses oklog/run.Group to compose them: each member registers a Execute and Interrupt function, and the group cancels everything when any member returns.
Subsystems that hold their own goroutines:
discovery.Manager.Run/discovery.Manager.ApplyConfigscrape.Manager.Runnotifier.Manager.Runrules.Manager.Run(per-group)storage/remote.QueueManager.Start/Stopweb.Handler.Run
Reload is implemented by calling ApplyConfig(*config.Config) on each manager, with the new config. A reload is only successful if every ApplyConfig returns nil.
Error handling
- Wrap with
fmt.Errorf("...: %w", err). Avoiderrors.Wrapfrom pkg/errors — not used here. - Sentinel errors are
var Err... = errors.New(...)at the top of the file. Match witherrors.Is. Seestorage/interface.goandtsdb/head_append.gofor examples. - Long-lived goroutines log and continue; short-lived helpers return up the stack.
- Multi-errors use
errors.Join(Go 1.20+). The TSDB migrated away frommultierrorin#17768.
Metrics hygiene
- Each subsystem owns a
*Metricsstruct, registered via a constructornewXMetrics(reg prometheus.Registerer). Metrics live with their owner — search forprometheus.NewCounter(in any package to find them. - Use the
prometheus_prefix for self-metrics. Subsystem prefix follows:prometheus_tsdb_*,prometheus_scrape_*,prometheus_remote_storage_*,prometheus_rule_*,prometheus_notifications_*,prometheus_sd_*. - Exposing label dimensions has a real cost — be conservative. For instance,
prometheus_remote_storage_samples_failed_total{remote_name, url, reason}was carefully reviewed before thereasonlabel was added.
Hot-path performance rules
AGENTS.md is explicit:
- Reuse allocations on hot paths (slices, buffers, label sets).
- When a buffer is passed across an interface boundary that may retain it, document the contract at the interface and note in commit messages.
- Performance changes need a benchmark and
benchstatbefore/after. Reviewers may ask for a flame graph if the change is non-trivial. - The
util/pool/package wrapssync.Poolwith size-class buckets — used heavily by scraping, remote write, and TSDB compaction. - The
util/zeropool/package provides a genericsync.Poolwith explicit size classes; favour it over rawsync.Poolfor typed slices.
Testing patterns
- Use exported APIs in tests where possible. This both keeps tests close to library users and makes refactoring safer.
- New test files use
testify(require,assert). Older tests use vanillat.Errorfandt.Fatalf; do not migrate them in unrelated PRs. - Time-sensitive tests should use
testing.B's context,synctest, or an injectableclockinterface, nottime.Sleep. - The
storage/teststorageandtsdb/testutilhelpers handle most fixture setup; prefer them over reimplementing.
Configuration parsing
YAML structs use prometheus/common/yaml.in/yaml/v2 and go.yaml.in/yaml/v2. Config validation lives in Validate() methods on each config struct. Defaults are encoded in package-level Default*Config variables and applied in UnmarshalYAML by copying the default first then overlaying the parsed value (config/config.go does this throughout).
When a config field references files (TLS certs, file_sd files), implement discovery.DirectorySetter (or the corresponding interface in your package) so relative paths resolve relative to the config file directory.
Build tags
The codebase uses build tags pervasively:
slicelabels/stringlabels/dedupelabels— pick the labels representation. Default isstringlabels. CI runs all three.forcedirectio— TSDB direct-IO mode, exercised in CI.builtinassets— embed UI assets into the binary. Default in production builds.netgo— pure-Go DNS resolver. Default for portable releases.remove_all_sdandenable_<sd>_sd— configurable subset of service discovery (seeplugins/).fuzzing— only used byutil/fuzzing/corpus_gen.
The configurable SD set is a 3.10 feature (#17736); use it to ship slimmer Prometheus binaries in environments where most SDs are unused.
Commenting
- Every exported symbol needs a doc comment.
- Tag work-in-progress with
TODO(<name>): <description>(the codebase has ~320 of these). XXX:andHACK:are used very sparingly (less than 10 occurrences).- Big design decisions are usually captured in the PR description rather than a
//block — search the PR history when unsure.
Documentation parity
Docs live in docs/ (user docs) and documentation/ (operational examples + Jsonnet mixin). Two kinds of CI checks enforce parity:
make cli-documentationregenerates the flag docs and is checked bymake check-cli-documentation.- The OpenAPI golden test under
web/api/v1/openapi_golden_test.goensures the spec matches the API surface.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.