DEV Community

Cover image for Simplifying Prometheus Metrics in Go with prometric-go
Md Asraful Haque (Sohel)
Md Asraful Haque (Sohel)

Posted on

Simplifying Prometheus Metrics in Go with prometric-go

Effortless observability for your Go applications โ€” without the boilerplate.

๐Ÿง  The Problem

As Go developers, we all want observability โ€” to know how our APIs perform, how many requests we handle, and how our systems behave in production.

Prometheus is fantastic for that โ€” but setting up metrics in Go can quickly turn verbose:

counter := prometheus.NewCounterVec(
    prometheus.CounterOpts{Name: "http_requests_total", Help: "Total HTTP requests"},
    []string{"path", "method", "status"},
)
prometheus.MustRegister(counter)
Enter fullscreen mode Exit fullscreen mode

And soon your code fills with boilerplate.

Thatโ€™s why I built prometric-go โ€” a lightweight, idiomatic helper library that makes exposing Prometheus metrics in Go as simple as possible.

๐Ÿ’ก What is prometric-go?

prometric-go is a minimal Go library that wraps Prometheus client_golang and provides ready-to-use metrics for:

  • ๐ŸŒ HTTP request tracking (latency, size, in-flight)
  • โš™๏ธ CRUD operation metrics (total, duration, object count)
  • โค๏ธ Application health metrics
  • ๐Ÿงฑ Helpers for creating and registering custom metrics easily

Itโ€™s designed to be plug-and-play for HTTP servers and microservices.

๐Ÿ—๏ธ Installation

go get github.com/peek8/prometric-go/prometrics
Enter fullscreen mode Exit fullscreen mode

Then import it in your Go app:

import "github.com/peek8/prometric-go/prometrics"
Enter fullscreen mode Exit fullscreen mode

โš™๏ธ Getting Started

Start by exposing a /metrics endpoint on your existing HTTP server:

package main
import (
    "net/http"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
    mux := http.NewServeMux()
    mux.Handle("/metrics", promhttp.Handler())

    http.ListenAndServe(":7080", mux)
}
Enter fullscreen mode Exit fullscreen mode

You now have a fully working Prometheus endpoint at http://localhost:7080/metrics.

๐Ÿ” Track HTTP Request Metrics Automatically

You can easily wrap your handlers with Prometheus middleware:

handler := prometrics.InstrumentHttpHandler("/person",http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, Prometheus!"))
}))

http.Handle("/", handler)
http.ListenAndServe(":7080", nil)
Enter fullscreen mode Exit fullscreen mode

The library automatically tracks:

  • http_requests_total: Total HTTP requests processed
  • http_request_duration_seconds: Request duration histogram
  • http_requests_in_flight: Current requests being handled
  • http_request_size_bytes: Request payload size
  • http_response_size_bytes: Response size

Example output:

http_requests_total{path="/",method="GET",code="200"} 42
http_request_duration_seconds_bucket{le="0.1",path="/",method="GET",code="200"} 12
http_requests_in_flight{path="/"} 1
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“ฆ Tracking CRUD Operations

The library also provides metrics for tracking your CRUD operations:

// Example: create user in DB here
tracker := prometrics.TrackCRUD("user", "create")
defer tracker(time.Now())
Enter fullscreen mode Exit fullscreen mode

This automatically records:

  • crud_operations_total: Total CRUD operations by object & operation
  • object_operation_duration_seconds: Histogram of CRUD operation durations
  • object_count: Current number of objects

โšก Setting Object Counts

You can manually control the current count of entities in your system:

prometrics.SetObjectCount("user", 100)
prometrics.IncObjectCount("user")
prometrics.DecObjectCount("user")
Enter fullscreen mode Exit fullscreen mode

All labeled and tracked automatically.

๐Ÿง  System Metrics (Optional)

You can also enable lightweight system metric collection in a background goroutine:

// collect health metrics in 10s interval
ctx, cancel := context.WithCancel(context.Background(), 10)
go prometrics.CollectSystemMetricsLoop(ctx)
Enter fullscreen mode Exit fullscreen mode

This will report CPU and memory usage to Prometheus โ€” useful for understanding resource trends.

Its also possible to collect these health metrics using Middleware:

mux := http.NewServeMux()

// Use HealthMiddleware at /metrics endpoint
mux.Handle("/metrics", prometrics.HealthMiddleware(promhttp.Handler()))
Enter fullscreen mode Exit fullscreen mode

Using GIN Framework

If you are using Gin Web framework for your api, you can use the gin middlewares from prometrics.

r := gin.Default()
// For http metrics
r.Use(prometrics.GinMiddleware())
// For health metrics
r.Use(prometrics.GinHealthMiddleware())

r.GET("/ping", func(c *gin.Context) {
  c.JSON(200, gin.H{"msg": "pong"})
})

r.GET("/person", func(c *gin.Context) {
  defer prometrics.TrackCRUD("person", "Get")(time.Now())

  c.JSON(200, gin.H{"name": "asraf"})
})
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“Š Visualizing in Grafana

Once your app exposes /metrics, you can scrape it using Prometheus:

scrape_configs:
  - job_name: 'prometric-go-demo'
    static_configs:
      - targets: ['localhost:7080']
Enter fullscreen mode Exit fullscreen mode

Then build dashboards in Grafana with panels like:

  • Request duration heatmaps
  • Total requests per endpoint
  • In-flight request gauge

โš™๏ธ Behind the Scenes

When I started building small Go microservices, I kept rewriting the same few lines of Prometheus setup code โ€” NewCounterVec, MustRegister, boilerplate handlers, and middleware wrappers.

I wanted:

  • quick start
  • clean, ready-to-use metrics,
  • label conventions that were consistent,
  • and no mental overhead every time I started a new project.

Thatโ€™s where prometric-go was born.

Some internal design goals that shaped it:

  • Quick Start with Metrics: Which metrics are useful to expose for a microservice/http-api and how to expose those. I wanted to start up with something without thinking too much.
  • Self-registration: all metrics are registered automatically using promauto.
  • Safe concurrency: metric operations are goroutine-safe by design.
  • GoDoc first: all exported symbols are documented so the package looks clean on pkg.go.dev.
  • Composable structure: submodules like http.go, crudmetrics.go, and apphealth.go keep responsibilities separate.

The idea wasnโ€™t to replace Prometheus โ€” just to make it nicer and faster to use for everyday Go developers.

๐Ÿš€ Roadmap

Planned future enhancements include:

  • Add more metrics and customization to choose/filter metrics.
  • Integration with OpenTelemetry
  • Customizable metric namespace/prefix
  • Built-in Chi(and probably others) middleware
  • Out-of-the-box Grafana dashboards

Conclusion

prometric-go makes Prometheus metrics in Go simple, standardized, and developer-friendly.

Whether youโ€™re building an HTTP API, a CLI, or a microservice, it helps you focus on business logic โ€” not boilerplate metrics wiring.

Give it a try ๐Ÿ‘‡

๐Ÿ“ฆ github.com/peek8/prometric-go

๐Ÿ“š Documentation
Full API reference available at:
pkg.go.dev/github.com/peek8/prometric-go/prometrics

Top comments (0)