
Prometheus Go Code Review
- 109 installs
- 74 repo stars
- Updated July 21, 2026
- existential-birds/beagle
Helps with ai & agent building tasks.
About
prometheus-go-code-review is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- prometheus-go-code-review
- AI & Agent Building
- AI-coding skill
Prometheus Go Code Review by the numbers
- 109 all-time installs (skills.sh)
- Ranked #4,071 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/existential-birds/beagle --skill prometheus-go-code-reviewAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 109 |
|---|---|
| repo stars | ★ 74 |
| Last updated | July 21, 2026 |
| Repository | existential-birds/beagle ↗ |
What it does
Helps with ai & agent building tasks.
Files
Prometheus Go Code Review
Review Checklist
- [ ] Metric types match measurement semantics (Counter/Gauge/Histogram)
- [ ] Labels have low cardinality (no user IDs, timestamps, paths)
- [ ] Metric names follow conventions (snake_case, unit suffix)
- [ ] Histograms use appropriate bucket boundaries
- [ ] Metrics registered once, not per-request
- [ ] Collectors don't panic on race conditions
- [ ] /metrics endpoint exposed and accessible
Hard gates (sequenced)
Complete in order before recording a finding. Skip gates that clearly do not apply to the diff.
1. Evidence scope — Enumerate the files you are reviewing that touch Prometheus (prometheus/client_golang, promauto, promhttp, or MustRegister). Pass: you have a concrete path list (from the diff or an explicit file set); no repo-wide claim without at least one path.
2. Label cardinality — For each *Vec or labeled metric in scope, list label names and where values come from (constants, bounded codes, vs request-derived strings). Pass: no label uses unbounded values (e.g. raw user_id, full URL path, timestamps) unless the code uses a bounded mapping and you cite it.
3. Registration lifecycle — For metric definitions in scope, confirm constructors run once (package-level var, init, or sync.Once), not inside per-request handlers. Pass: no pattern that allocates/registers a new Counter/Histogram/*Vec on every request for the same logical metric.
4. Finding shape — Each finding names a file (and line or symbol where possible), states which gate (2 or 3) would fail if the issue is real, and ties to observed code. Pass: no standalone style nit when gates 2–3 are satisfied for that code.
Metric Type Selection
| Measurement | Type | Example |
|---|---|---|
| Requests processed | Counter | requests_total |
| Items in queue | Gauge | queue_length |
| Request duration | Histogram | request_duration_seconds |
| Concurrent connections | Gauge | active_connections |
| Errors since start | Counter | errors_total |
| Memory usage | Gauge | memory_bytes |
Critical Anti-Patterns
1. High Cardinality Labels
// BAD - unique per user/request
counter := promauto.NewCounterVec(
prometheus.CounterOpts{Name: "requests_total"},
[]string{"user_id", "path"}, // millions of series!
)
counter.WithLabelValues(userID, request.URL.Path).Inc()
// GOOD - bounded label values
counter := promauto.NewCounterVec(
prometheus.CounterOpts{Name: "requests_total"},
[]string{"method", "status_code"}, // <100 series
)
counter.WithLabelValues(r.Method, statusCode).Inc()2. Wrong Metric Type
// BAD - using gauge for monotonic value
requestCount := promauto.NewGauge(prometheus.GaugeOpts{
Name: "http_requests",
})
requestCount.Inc() // should be Counter!
// GOOD
requestCount := promauto.NewCounter(prometheus.CounterOpts{
Name: "http_requests_total",
})
requestCount.Inc()3. Registering Per-Request
// BAD - new metric per request
func handler(w http.ResponseWriter, r *http.Request) {
counter := prometheus.NewCounter(...) // creates new each time!
prometheus.MustRegister(counter) // panics on duplicate!
}
// GOOD - register once
var requestCounter = promauto.NewCounter(prometheus.CounterOpts{
Name: "http_requests_total",
})
func handler(w http.ResponseWriter, r *http.Request) {
requestCounter.Inc()
}4. Missing Unit Suffix
// BAD
duration := promauto.NewHistogram(prometheus.HistogramOpts{
Name: "request_duration", // no unit!
})
// GOOD
duration := promauto.NewHistogram(prometheus.HistogramOpts{
Name: "request_duration_seconds", // unit in name
})Good Patterns
Metric Definition
var (
httpRequests = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: "myapp",
Subsystem: "http",
Name: "requests_total",
Help: "Total HTTP requests processed",
},
[]string{"method", "status"},
)
httpDuration = promauto.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: "myapp",
Subsystem: "http",
Name: "request_duration_seconds",
Help: "HTTP request latencies",
Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
},
[]string{"method"},
)
)Middleware Pattern
func metricsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
timer := prometheus.NewTimer(httpDuration.WithLabelValues(r.Method))
defer timer.ObserveDuration()
wrapped := &responseWriter{ResponseWriter: w, status: 200}
next.ServeHTTP(wrapped, r)
httpRequests.WithLabelValues(r.Method, strconv.Itoa(wrapped.status)).Inc()
})
}Exposing Metrics
import "github.com/prometheus/client_golang/prometheus/promhttp"
func main() {
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":9090", nil)
}Review Questions
1. Are metric types correct (Counter vs Gauge vs Histogram)? 2. Are label values bounded (no UUIDs, timestamps, paths)? 3. Do metric names include units (_seconds, _bytes)? 4. Are metrics registered once (not per-request)? 5. Is /metrics endpoint properly exposed?