This service accepts Prometheus metrics, validetes, aggregates, and exposes them ready for scraping in /metrics
endpoint12.
- consume batch by JSON http body (aggregation gateway)
- consume one by URL Path or Query (hit counter)
- no dependencies
- 400LOC
- 100% coverage
- defensive validation
- histograms3 with fixed buckets
- histograms with t-digest4
Bring it to your own http server
func main() {
var config pag.PromAggGatewayServerConfig
configBytes, _ := os.ReadFile(os.Getenv("PAG_CONFIG_PATH"))
if err := yaml.Unmarshal(configBytes, &config); err != nil {
log.Fatal(err)
}
s := pag.NewPromAggGatewayServer(config)
http.HandleFunc("GET /healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })
http.HandleFunc("GET /hit", s.ConsumeMetricFromURLQuery)
http.HandleFunc("POST /metrics", s.ConsumeMetrics)
http.HandleFunc("GET /metrics", s.GetMetrics)
log.Fatal(http.ListenAndServe(":8080", nil))
}
2025-04-04
URL Query consumes only single metric for simple API (histograms break down into multiple metric names, hence not accepted in URL Query)2024-12-16
not providingmax
,min
aggregations, instead encouraging using histograms2024-12-03
not provideavg
based on totalsum(x)
/count(x)
, to reduce complexity in configuration, keep code flexible and small, and this can be done downstream anyways2024-12-03
using_count
in label naming to match open telemetry histograms2024-12-03
using units in metric name, to keep closer to Prometheus and reduce complexity of API2024-12-02
not usingPrometheus Pushgateway
5, because it does not aggregate metrics2024-12-02
not zapier6 prom aggregation gateway, because: too many 3rd party dependencies (e.g. gin, cobra); no defensive validation;