// Package metrics defines Prometheus metrics for mc-proxy and provides // an HTTP server for the /metrics endpoint. package metrics import ( "context" "errors" "net" "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" ) var ( // ConnectionsTotal counts connections accepted per listener and mode. ConnectionsTotal = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: "mcproxy", Name: "connections_total", Help: "Total connections accepted.", }, []string{"listener", "mode"}) // ConnectionsActive tracks currently active connections per listener. ConnectionsActive = promauto.NewGaugeVec(prometheus.GaugeOpts{ Namespace: "mcproxy", Name: "connections_active", Help: "Currently active connections.", }, []string{"listener"}) // FirewallBlockedTotal counts firewall blocks by reason. FirewallBlockedTotal = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: "mcproxy", Name: "firewall_blocked_total", Help: "Total connections blocked by the firewall.", }, []string{"reason"}) // BackendDialDuration observes backend dial latency in seconds. BackendDialDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{ Namespace: "mcproxy", Name: "backend_dial_duration_seconds", Help: "Backend dial latency in seconds.", Buckets: []float64{0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5}, }, []string{"backend"}) // TransferredBytesTotal counts bytes transferred by direction and hostname. TransferredBytesTotal = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: "mcproxy", Name: "transferred_bytes_total", Help: "Total bytes transferred.", }, []string{"direction", "hostname"}) // L7ResponsesTotal counts L7 HTTP responses by hostname and status code. L7ResponsesTotal = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: "mcproxy", Name: "l7_responses_total", Help: "Total L7 HTTP responses.", }, []string{"hostname", "code"}) // L7PolicyBlocksTotal counts L7 policy blocks by hostname and policy type. L7PolicyBlocksTotal = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: "mcproxy", Name: "l7_policy_blocks_total", Help: "Total L7 policy blocks.", }, []string{"hostname", "policy_type"}) ) // ListenAndServe starts a Prometheus metrics HTTP server. It blocks until // ctx is cancelled, then shuts down gracefully. func ListenAndServe(ctx context.Context, addr, path string) error { if path == "" { path = "/metrics" } mux := http.NewServeMux() mux.Handle(path, promhttp.Handler()) ln, err := net.Listen("tcp", addr) if err != nil { return err } srv := &http.Server{Handler: mux} go func() { <-ctx.Done() _ = srv.Close() }() err = srv.Serve(ln) if errors.Is(err, http.ErrServerClosed) { return nil } return err }