RepoPilotOpen in app →

prometheus/client_golang

Prometheus instrumentation library for Go applications

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 1d ago
  • 15 active contributors
  • Distributed ownership (top contributor 32% of recent commits)
Show all 6 evidence items →
  • Apache-2.0 licensed
  • CI configured
  • Tests present

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/prometheus/client_golang)](https://repopilot.app/r/prometheus/client_golang)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/prometheus/client_golang on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: prometheus/client_golang

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/prometheus/client_golang shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 1d ago
  • 15 active contributors
  • Distributed ownership (top contributor 32% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • Tests present

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live prometheus/client_golang repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/prometheus/client_golang.

What it runs against: a local clone of prometheus/client_golang — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in prometheus/client_golang | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>prometheus/client_golang</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of prometheus/client_golang. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/prometheus/client_golang.git
#   cd client_golang
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of prometheus/client_golang and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "prometheus/client_golang(\\.git)?\\b" \\
  && ok "origin remote is prometheus/client_golang" \\
  || miss "origin remote is not prometheus/client_golang (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "prometheus/collector.go" \\
  && ok "prometheus/collector.go" \\
  || miss "missing critical file: prometheus/collector.go"
test -f "prometheus/registry.go" \\
  && ok "prometheus/registry.go" \\
  || miss "missing critical file: prometheus/registry.go"
test -f "prometheus/counter.go" \\
  && ok "prometheus/counter.go" \\
  || miss "missing critical file: prometheus/counter.go"
test -f "api/prometheus/v1/api.go" \\
  && ok "api/prometheus/v1/api.go" \\
  || miss "missing critical file: api/prometheus/v1/api.go"
test -f "prometheus/promhttp/handler.go" \\
  && ok "prometheus/promhttp/handler.go" \\
  || miss "missing critical file: prometheus/promhttp/handler.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/prometheus/client_golang"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

The official Go client library for Prometheus, a widely-used metrics collection and alerting system. It provides two core capabilities: (1) instrumentation APIs to emit counters, gauges, histograms, and summaries from Go applications, and (2) an HTTP API client to query and interact with Prometheus servers. It's the primary way Go developers integrate Prometheus monitoring into their applications. Three-part structure: (1) prometheus/ directory contains the core instrumentation library with metric types and registry; (2) api/prometheus/v1/ implements the Prometheus HTTP API client; (3) examples/ directory has runnable demos (simple, random, exemplars, nativehistogram, middleware, gocollector). Tests are colocated with source (*_test.go files). Makefile and Makefile.common handle builds and linting.

👥Who it's for

Go application developers and DevOps engineers who need to instrument their services with Prometheus metrics for monitoring, alerting, and observability. Also used by infrastructure teams building tools that interact with Prometheus APIs (e.g., dashboards, automation scripts).

🌱Maturity & risk

Production-ready and actively maintained. The instrumentation library (prometheus/) follows semantic versioning strictly. The API client (api/prometheus/v1/) is explicitly marked experimental and may have breaking changes without major version bumps. CI is comprehensive with GitHub Actions workflows for linting, vulnerability checks, CodeQL analysis, and multi-version Go testing. The project maintains two recent Go major versions per the README.

Low risk for instrumentation features but moderate risk for API client usage. Dependencies are minimal and reputable (prometheus/common, protobuf, klauspost/compress). The codebase is healthy with active CI/CD (test.yml, golangci-lint.yml, govulncheck.yml workflows present). Main risk: the api/prometheus/v1 client is explicitly experimental—breaking changes can occur in minor versions. No single-maintainer risk visible; MAINTAINERS.md and CODEOWNERS enforce review processes.

Active areas of work

Active development visible: workflows for dependabot auto-merging, Go version updates (update-go-versions.yml), and experimental v2 APIs being developed in prometheus/vnext.go. The v2 milestone exists but dev-v2 branch is separate. Recent focus areas include native histograms (examples/nativehistogram/), created timestamps (examples/createdtimestamps/), and exemplar support (examples/exemplars/).

🚀Get running

git clone https://github.com/prometheus/client_golang.git
cd client_golang
make test

Or install as a dependency: go get github.com/prometheus/client_golang/prometheus. Run examples with go run examples/simple/main.go or similar.

Daily commands: Development: make test runs all tests. Build binaries: examples run directly with go run examples/<name>/main.go. For the HTTP API client, examples are in api/prometheus/v1/example_test.go showing live queries. The Dockerfile and .dockerignore suggest containerized testing is supported.

🗺️Map of the codebase

  • prometheus/collector.go — Defines the core Collector interface that all metric collectors must implement; foundational abstraction for the entire instrumentation system.
  • prometheus/registry.go — Implements the Registry pattern for registering and collecting metrics; entry point for metric gathering in applications.
  • prometheus/counter.go — Implements Counter metric type with thread-safe operations; one of the four primary metric types used by 90% of instrumentation code.
  • api/prometheus/v1/api.go — HTTP client for querying Prometheus API; primary interface for retrieving metrics and alerts from a Prometheus server.
  • prometheus/promhttp/handler.go — HTTP handler that serializes collected metrics in Prometheus text format; exposes metrics endpoint used by Prometheus scrapers.
  • prometheus/internal/core/core.go — Core metric storage and marshaling logic shared across all metric types; handles thread-safe metric value updates and serialization.
  • exp/api/remote/remote_api.go — Remote write protocol client for sending metrics to external systems; enables federation and long-term storage integration.

🛠️How to make changes

Add a new metric type (advanced)

  1. Create new file prometheus/mymetric.go implementing the Collector interface with Describe() and Collect() methods (prometheus/mymetric.go)
  2. Add constructor function and thread-safe value update methods (WithLabelValues, Inc, etc.) (prometheus/mymetric.go)
  3. Register test in prometheus/mymetric_test.go verifying Describe/Collect behavior and data races (prometheus/mymetric_test.go)
  4. Add example usage in examples/mymetric/main.go showing registration and instrumentation (examples/mymetric/main.go)

Instrument an HTTP service with metrics

  1. Import prometheus and promhttp packages and create metrics (Counter, Histogram) in main() (your_app/main.go)
  2. Use promhttp.InstrumentHandlerDuration() and InstrumentHandlerCounter() to wrap HTTP handlers (prometheus/promhttp/middleware.go)
  3. Register metrics with default registry via prometheus.MustRegister() (your_app/main.go)
  4. Expose /metrics endpoint using promhttp.Handler() before starting HTTP listener (prometheus/promhttp/handler.go)

Add a custom collector for application-specific data

  1. Create struct implementing Collector interface (Describe() and Collect() methods) (your_app/collectors/custom_collector.go)
  2. In Describe(), create one prometheus.Desc per metric type using prometheus.NewDesc() (prometheus/desc.go)
  3. In Collect(), read live data, create prometheus.Metric values, and send via channel (your_app/collectors/custom_collector.go)
  4. Register custom collector: prometheus.MustRegister(myCollector) in main() (your_app/main.go)

Query Prometheus API from application

  1. Create client with api.NewClient() passing HTTP client configuration (api/client.go)
  2. Call v1.NewAPI(client) to get API wrapper (api/prometheus/v1/api.go)
  3. Use api.Query() or api.QueryRange() with PromQL expression and context timeout (api/prometheus/v1/api.go)
  4. Parse result into model.Value (Vector, Matrix, Scalar, String) (api/prometheus/v1/api.go)

🔧Why these technologies

  • Go (native) — Prometheus is written in Go; client library maintains language consistency and zero-copy metric encoding
  • Protocol Buffers (protobuf v3) — Efficient binary serialization for remote write protocol; reduces bandwidth for metric federation and long-term storage
  • HTTP 1.1 + compression (gzip) — Standard protocol for Prometheus scraping; gzip reduces metric payload by 90%+ for large cardinality services
  • Concurrent maps (sync.Map, RWMutex) — Metrics are read-heavy (scraping) and write-moderate (instrumentation); requires lock-free or minimal-contention access patterns

⚖️Trade-offs already made

  • Push-based instrumentation (via labels) rather than dynamic metric discovery

    • Why: Avoids cardinality explosion; encourages explicit label design at instrumentation time
    • Consequence: Developers must plan label dimensions upfront; no wildcard label values allowed
  • Exemplars (trace correlation) optional; not always exposed by default

    • Why: Adds minimal overhead when enabled but increases complexity for basic instrumentation
    • Consequence: Link metrics to traces requires explicit exemplar storage; off-label SLO queries must specify span_id
  • Registry is global by default; single process = one canonical metric set

    • Why: Simplifies common case (single scrape endpoint per process) and reduces registry management complexity
    • Consequence: Multi-tenant workloads must partition metrics manually or use multiple registry instances
  • Client library does NOT auto-instrument (no bytecode/proxies); explicit opt-in only

    • Why: Predictable overhead, no hidden side effects, easier debugging and testing
    • Consequence: Every instrumentation site requires explicit metric invocation; cannot retroactively instrument third-party code

🚫Non-goals (don't propose these)

  • Real-time metric streaming (batched scraping model only)
  • Client-side aggregation or downsampling (server-side only)
  • OpenTelemetry/OpenMetrics auto-translation (manual protocol selection)
  • Metric storage or persistence (exposition only; server provides storage)
  • Access control / ACL enforcement (delegated to reverse proxy/middleware)

🪤Traps & gotchas

No unusual environment variables or external service requirements, but: (1) The module split (github.com/prometheus/client_golang/exp requires separate go.mod) means some features are in sub-modules—carefully check import paths. (2) Native histograms (examples/nativehistogram/) require specific Prometheus server versions to scrape correctly—not backwards compatible. (3) The api/prometheus/v1 client uses *http.Client injection; callers must provide timeout and TLS configuration themselves. (4) Exemplars (examples/exemplars/) require OpenTelemetry integration and matching Prometheus configuration.

🏗️Architecture

💡Concepts to learn

  • Metric cardinality — Unbounded label values (e.g., user IDs, request paths) explode memory and cause Prometheus performance issues—critical when designing Counter/Gauge with labels in this library
  • Collector interface pattern — Custom metrics in client_golang must implement prometheus.Collector with Describe() and Collect() methods—understanding this enables scraping non-standard metric sources
  • Native histograms — Newer Prometheus histogram format (exemplified in examples/nativehistogram/) that avoids pre-defined buckets and improves cardinality—different from classic bucket-based histograms
  • Exposition format (text and protobuf) — client_golang exports metrics via Prometheus text format (port :2112/metrics) and optional protobuf encoding—understanding both is essential for integrating scrapers
  • Label matching and relabeling — The HTTP API client (api/prometheus/v1/api.go) supports label matchers for queries; Prometheus server applies relabeling rules—this library must emit labels correctly for queries to work
  • Exemplars — Prometheus exemplars link metrics to trace IDs (shown in examples/exemplars/)—bridges metrics and distributed tracing systems for rich debugging
  • Prometheus scrape config and service discovery — This library exposes metrics for Prometheus to scrape; understanding scrape intervals, timeouts, and SD mechanisms helps debug collection failures
  • prometheus/prometheus — The Prometheus server implementation; client_golang scrapes metrics into this and queries its HTTP API
  • prometheus/common — Shared Go utilities (model types, configuration parsers) used as a dependency in client_golang
  • open-telemetry/opentelemetry-go — Complementary observability library for tracing; often used alongside prometheus client for full observability
  • prometheus/alertmanager — Alert routing and deduplication system; receives alerts triggered by Prometheus rules based on metrics from client_golang
  • grafana/cortex — Multi-tenant Prometheus-compatible metrics backend; compatible with client_golang metric exposition format

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for exp/api/remote/remote_headers.go

The remote headers module (remote_headers.go and remote_headers_test.go) is critical for remote write API functionality, but test coverage appears minimal based on the file structure. This module handles HTTP header construction for Prometheus remote API communication, which is security and correctness-sensitive. Adding edge case tests for header validation, authentication scenarios, and protocol version handling would improve reliability.

  • [ ] Examine existing remote_headers_test.go to identify gaps in coverage
  • [ ] Add tests for malformed headers, missing required headers, and header size limits
  • [ ] Add tests for different Prometheus API versions and compatibility scenarios
  • [ ] Add tests for concurrent header generation and thread safety
  • [ ] Run coverage tooling to ensure >90% coverage of remote_headers.go

Add integration tests for exp/api/remote package with mock Prometheus server

The exp/api/remote package (remote_api.go) appears to be experimental code for remote write/read APIs, but there are no visible integration tests. Currently only remote_api_test.go exists with limited scope. Adding integration tests with a mock Prometheus-compatible server would validate end-to-end behavior, error handling, and protocol compliance before this moves to stable.

  • [ ] Create exp/api/remote/integration_test.go with test fixtures
  • [ ] Implement a mock Prometheus remote write/read server (can use httptest package)
  • [ ] Add tests for successful remote write/read round trips with sample data
  • [ ] Add tests for error scenarios (connection failures, invalid responses, timeouts)
  • [ ] Add tests for compression handling with klauspost/compress dependency
  • [ ] Validate protobuf serialization/deserialization via remote_api.go functions

Create GitHub Actions workflow for experimental module (exp/) independent versioning validation

The exp/go.mod has independent dependencies (e.g., Go 1.24.0) and versions distinct from the main module. Currently, no visible GitHub workflow specifically validates the exp/ module's build, tests, and dependency compatibility. Adding a dedicated workflow would prevent experimental features from breaking and ensure the exp/ module can be independently released.

  • [ ] Create .github/workflows/test-exp-module.yml workflow file
  • [ ] Configure job to run in exp/ directory with 'working-directory: exp'
  • [ ] Add steps for 'go mod tidy', 'go test ./...', and 'go build ./...'
  • [ ] Add govulncheck step (reference existing .github/workflows/govulncheck.yml)
  • [ ] Add golangci-lint step for exp/ directory (reference .github/workflows/golangci-lint.yml)
  • [ ] Configure matrix for multiple Go versions (1.24.0 and 2-3 prior versions)
  • [ ] Run on push/PR to validate exp/ changes don't break module independently

🌿Good first issues

  • Add benchmark tests for prometheus/gauge.go and prometheus/counter.go similar to api/prometheus/v1/api_bench_test.go—measure label cardinality impact on performance.
  • Create a middleware example in examples/middleware/ for gRPC (currently only httpmiddleware exists)—add prometheus interceptor wrappers and document in example code.
  • Expand examples/createdtimestamps/main.go with docstrings explaining the created_timestamp Prometheus 2.50+ feature and when to use it instead of up metric.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 0ac87e1 — Merge pull request #1996 from roidelapluie/roidelapluie/remote-write-io-limiter (kakkoyun)
  • 0b88ca2 — exp/api/remote: limit request body size in SnappyDecodeMiddleware (roidelapluie)
  • f695195 — Merge pull request #1995 from prometheus/dependabot/go_modules/exp/github.com/klauspost/compress-1.18.6 (github-actions[bot])
  • eb21b3a — build(deps): bump github.com/klauspost/compress in /exp (dependabot[bot])
  • 8d6cc52 — Merge pull request #1992 from prometheus/dependabot/go_modules/github.com/klauspost/compress-1.18.6 (github-actions[bot])
  • df048ad — Merge pull request #1993 from prometheus/dependabot/go_modules/golang.org/x/sys-0.43.0 (github-actions[bot])
  • 5048e61 — build(deps): bump golang.org/x/sys from 0.42.0 to 0.43.0 (dependabot[bot])
  • b31e5ee — build(deps): bump github.com/klauspost/compress from 1.18.5 to 1.18.6 (dependabot[bot])
  • 79042c6 — Fix bug unit cpu-seconds not a suffix of metric go_cpu_classes_gc_mark_assist_cpu_seconds (#1991) (vesari)
  • 773db0a — Merge pull request #1988 from prometheus/repo_sync (SuperQ)

🔒Security observations

The Prometheus client_golang codebase demonstrates good security practices with CI/CD pipelines (CodeQL, govulncheck, SAST), security policy documentation, and dependency management. However, there are concerns with the incomplete Dockerfile configuration, a suspicious indirect YAML dependency (go.yaml.in instead of gopkg.in), and missing container hardening (non-root user). The Go version (1.24.0) appears to be from an unreleased development branch. Dependencies are relatively current, but the truncated Dockerfile prevents full assessment of runtime security. Recommendations focus on completing Docker configuration, verifying dependency sources, and implementing container best practices.

  • Medium · Incomplete Dockerfile - Missing Base Image — Dockerfile. The Dockerfile is truncated and the final image base (FROM quay.io/prome) is incomplete. This prevents verification that a secure, minimal base image is used. An incomplete or unverified base image could contain vulnerabilities. Fix: Complete the Dockerfile with a specific, pinned base image tag (e.g., 'quay.io/prometheus/busybox:latest' with a full digest hash). Use minimal base images and regularly update them.
  • Low · Go Version Specification Could Be More Specific — exp/go.mod. The go.mod file specifies 'go 1.24.0' which is a future version not yet released. While this may be intentional for development, it could lead to compatibility issues or indicate the file is from an unreleased development branch. Fix: Use a stable, currently released Go version (e.g., go 1.23 or lower). Verify the intended version is appropriate for the project's stability requirements.
  • Low · Indirect Dependency on go.yaml.in/yaml/v2 — exp/go.mod. The dependency includes 'go.yaml.in/yaml/v2 v2.4.3' as an indirect dependency. The domain 'yaml.in' is suspicious and may not be the official YAML library. The canonical Go YAML library is typically 'gopkg.in/yaml.v2'. Fix: Verify this is not a typosquatting or dependency confusion attack. Consider using the official 'gopkg.in/yaml.v2' or 'gopkg.in/yaml.v3' instead. Run 'go mod verify' to ensure integrity.
  • Low · Missing Docker Security Context — Dockerfile. The Dockerfile does not specify a non-root USER directive in the final stage. Running containers as root increases the attack surface if container escape vulnerabilities are discovered. Fix: Add 'USER nobody' or create a dedicated non-privileged user before the CMD/ENTRYPOINT instructions in the final image stage.
  • Low · No Digest Pinning for Base Image — Dockerfile (line: FROM golang:1 AS builder). The builder stage uses 'FROM golang:1' without a specific version or digest. This makes the build non-deterministic and could pull vulnerable or unexpected versions. Fix: Pin to a specific Go version with digest hash, e.g., 'FROM golang:1.23.4@sha256:...' to ensure reproducible builds and control over dependency versions.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · prometheus/client_golang — RepoPilot