๐Ÿ“ฆ go-chi / metrics

A simple OpenMetrics (Prometheus metrics) interface, HTTP middleware, transport and handler

โ˜… 6 stars โ‘‚ 1 forks ๐Ÿ‘ 6 watching โš–๏ธ MIT License
๐Ÿ“ฅ Clone https://github.com/go-chi/metrics.git
HTTPS git clone https://github.com/go-chi/metrics.git
SSH git clone git@github.com:go-chi/metrics.git
CLI gh repo clone go-chi/metrics
Vojtech Vitek Vojtech Vitek Update to chi@v5.2.2 c2661de 6 months ago ๐Ÿ“ History
๐Ÿ“‚ master View all commits โ†’
๐Ÿ“ _example
๐Ÿ“ grafana
๐Ÿ“„ collector.go
๐Ÿ“„ counter.go
๐Ÿ“„ gauge.go
๐Ÿ“„ go.mod
๐Ÿ“„ go.sum
๐Ÿ“„ handler.go
๐Ÿ“„ histogram.go
๐Ÿ“„ labels_test.go
๐Ÿ“„ labels.go
๐Ÿ“„ LICENSE
๐Ÿ“„ README.md
๐Ÿ“„ transport.go
๐Ÿ“„ README.md

metrics

Go package for metrics collection in OpenMetrics format.

Go Reference Go Report Card MIT License

Features

  • ๐Ÿš€ High Performance: Built on top of Prometheus Go client with minimal overhead.
  • ๐ŸŒ HTTP Middleware: Real-time monitoring of incoming requests.
  • ๐Ÿ”„ HTTP Transport: Client instrumentation for outgoing requests.
  • ๐ŸŽฏ Compatibility: Compatible with OpenMetrics 1.0 collectors, e.g. Prometheus.
  • ๐Ÿ”’ Type Safety: Compile-time type-safe metric labels with struct tags validation.
  • ๐Ÿท๏ธ Data Cardinality: The API helps you keep the metric label cardinality low.
  • ๐Ÿ“Š Complete Metrics: Counter, Gauge, and Histogram metrics with customizable buckets.

Usage

go get github.com/go-chi/metrics@latest

package main

import (
	"github.com/go-chi/metrics"
)

func main() {
	r := chi.NewRouter()

	// Collect metrics for incoming HTTP requests automatically.
	r.Use(metrics.Collector(metrics.CollectorOpts{
		Host:  false,
		Proto: true,
		Skip: func(r *http.Request) bool {
			return r.Method != "OPTIONS"
		},
	}))

	r.Handle("/metrics", metrics.Handler())
	r.Post("/do-work", doWork)

	// Collect metrics for outgoing HTTP requests automatically.
	transport := metrics.Transport(metrics.TransportOpts{
		Host: true,
	})
	http.DefaultClient.Transport = transport(http.DefaultTransport)

	go simulateTraffic()

	log.Println("Server starting on :8022")
	if err := http.ListenAndServe(":8022", r); err != nil {
		log.Fatal(err)
	}
}

// Strongly typed metric labels help maintain low data cardinality
// by enforcing consistent label names across the codebase.
type jobLabels struct {
	Name   string `label:"name"`
	Status string `label:"status"`
}

var jobCounter = metrics.CounterWith[jobLabels]("jobs_processed_total", "Number of jobs processed")

func doWork(w http.ResponseWriter, r *http.Request) {
	time.Sleep(time.Second) // simulate work

	if rand.Intn(100) > 90 { // simulate error
		jobCounter.Inc(jobLabels{Name: "job", Status: "error"})
		w.Write([]byte("Job failed.\n"))
		return
	}

	jobCounter.Inc(jobLabels{Name: "job", Status: "success"})
	w.Write([]byte("Job finished successfully.\n"))
}

func simulateTraffic() {
	for {
		_, _ = client.Get("http://example.com")
		time.Sleep(500 * time.Millisecond)
	}
}

Example

See example/main.go and try it locally:

$ cd _example

$ go run .

TODO: Run Prometheus + Grafana locally.

License

MIT license