2025-11-21 22:58:39 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"log"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os/signal"
|
|
|
|
|
"syscall"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/metrics"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Register various metrics.
|
|
|
|
|
// Metric name may contain labels in Prometheus format - see below.
|
|
|
|
|
var (
|
|
|
|
|
// Register counter without labels.
|
|
|
|
|
// requestsTotal = metrics.NewCounter("requests_total")
|
|
|
|
|
|
|
|
|
|
requestsTotal = metrics.GetOrCreateCounter("requests_total")
|
|
|
|
|
|
|
|
|
|
// Register summary with a single label.
|
|
|
|
|
requestDuration = metrics.NewSummary(`requests_duration_seconds{path="/foobar/baz"}`)
|
|
|
|
|
|
|
|
|
|
// Register gauge with two labels.
|
|
|
|
|
// queueSize = metrics.NewGauge(`queue_size{queue="foobar",topic="baz"}`, func() float64 {
|
|
|
|
|
// return float64(foobarQueue.Len())
|
|
|
|
|
// })
|
|
|
|
|
|
|
|
|
|
// Register histogram with a single label.
|
|
|
|
|
// responseSize = metrics.NewHistogram(`response_size{path="/foo/bar"}`)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
metrics.ExposeMetadata(true)
|
|
|
|
|
|
|
|
|
|
http.HandleFunc("/", Recovery(Metrics(rootHandler)))
|
|
|
|
|
|
|
|
|
|
// Expose the registered metrics at `/metrics` path.
|
|
|
|
|
http.HandleFunc("/metrics", Recovery(metricsHandler))
|
|
|
|
|
|
|
|
|
|
http.HandleFunc("/hello", Recovery(Metrics(helloHandler)))
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
if err := http.ListenAndServe(":8080", nil); err != nil {
|
|
|
|
|
log.Fatalln(err)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
|
|
<-ctx.Done()
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func rootHandler(w http.ResponseWriter, req *http.Request) {
|
|
|
|
|
w.Write([]byte("Simple GoLang metrics service"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// metricsHandler ...
|
|
|
|
|
func metricsHandler(w http.ResponseWriter, req *http.Request) {
|
|
|
|
|
metrics.WritePrometheus(w, true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// helloHandler ...
|
|
|
|
|
func helloHandler(w http.ResponseWriter, req *http.Request) {
|
2025-11-24 08:13:19 +00:00
|
|
|
w.Write([]byte("Test /hello location."))
|
2025-11-21 22:58:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Metrics ...
|
|
|
|
|
func Metrics(h http.HandlerFunc) http.HandlerFunc {
|
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
requestsTotal.Inc()
|
|
|
|
|
|
|
|
|
|
startTime := time.Now()
|
|
|
|
|
|
|
|
|
|
h(w, r)
|
|
|
|
|
|
|
|
|
|
requestDuration.UpdateDuration(startTime)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Recovery ...
|
|
|
|
|
func Recovery(h http.HandlerFunc) http.HandlerFunc {
|
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
defer func() {
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
h(w, r)
|
|
|
|
|
}
|
|
|
|
|
}
|