mirror of
https://github.com/zhufuyi/sponge.git
synced 2025-10-06 01:07:08 +08:00
162 lines
4.5 KiB
Go
162 lines
4.5 KiB
Go
// Package metrics is grpc's server-side and client-side metrics can continue to be captured using prometheus.
|
|
package metrics
|
|
|
|
import (
|
|
"net/http"
|
|
"sync"
|
|
|
|
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/collectors"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
// https://github.com/grpc-ecosystem/go-grpc-prometheus/tree/master/examples/grpc-server-with-prometheus
|
|
|
|
var (
|
|
// server side default router
|
|
serverPattern = "/metrics"
|
|
|
|
// create a Registry
|
|
srvReg = prometheus.NewRegistry()
|
|
|
|
// initialize server-side default metrics
|
|
grpcServerMetrics = grpc_prometheus.NewServerMetrics()
|
|
|
|
// go metrics
|
|
goMetrics = collectors.NewGoCollector()
|
|
|
|
// user-defined metrics https://prometheus.io/docs/concepts/metric_types/#histogram
|
|
customizedCounterMetrics = []*prometheus.CounterVec{}
|
|
customizedSummaryMetrics = []*prometheus.SummaryVec{}
|
|
customizedGaugeMetrics = []*prometheus.GaugeVec{}
|
|
customizedHistogramMetrics = []*prometheus.HistogramVec{}
|
|
|
|
srvOnce sync.Once
|
|
)
|
|
|
|
// Option set metrics
|
|
type Option func(*options)
|
|
|
|
type options struct{}
|
|
|
|
func defaultMetricsOptions() *options {
|
|
return &options{}
|
|
}
|
|
|
|
func (o *options) apply(opts ...Option) {
|
|
for _, opt := range opts {
|
|
opt(o)
|
|
}
|
|
}
|
|
|
|
// WithCounterMetrics add Counter type indicator
|
|
func WithCounterMetrics(metrics ...*prometheus.CounterVec) Option {
|
|
return func(o *options) {
|
|
customizedCounterMetrics = append(customizedCounterMetrics, metrics...)
|
|
}
|
|
}
|
|
|
|
// WithSummaryMetrics add Summary type indicator
|
|
func WithSummaryMetrics(metrics ...*prometheus.SummaryVec) Option {
|
|
return func(o *options) {
|
|
customizedSummaryMetrics = append(customizedSummaryMetrics, metrics...)
|
|
}
|
|
}
|
|
|
|
// WithGaugeMetrics add Gauge type indicator
|
|
func WithGaugeMetrics(metrics ...*prometheus.GaugeVec) Option {
|
|
return func(o *options) {
|
|
customizedGaugeMetrics = append(customizedGaugeMetrics, metrics...)
|
|
}
|
|
}
|
|
|
|
// WithHistogramMetrics adding Histogram type indicators
|
|
func WithHistogramMetrics(metrics ...*prometheus.HistogramVec) Option {
|
|
return func(o *options) {
|
|
customizedHistogramMetrics = append(customizedHistogramMetrics, metrics...)
|
|
}
|
|
}
|
|
|
|
func srvRegisterMetrics() {
|
|
srvOnce.Do(func() {
|
|
// enable time record
|
|
grpcServerMetrics.EnableHandlingTimeHistogram()
|
|
|
|
// register go metrics
|
|
srvReg.MustRegister(goMetrics)
|
|
|
|
// register metrics to capture, custom metrics also need to be registered
|
|
srvReg.MustRegister(grpcServerMetrics)
|
|
|
|
// register custom Counter metrics
|
|
for _, metric := range customizedCounterMetrics {
|
|
srvReg.MustRegister(metric)
|
|
}
|
|
for _, metric := range customizedSummaryMetrics {
|
|
srvReg.MustRegister(metric)
|
|
}
|
|
for _, metric := range customizedGaugeMetrics {
|
|
srvReg.MustRegister(metric)
|
|
}
|
|
for _, metric := range customizedHistogramMetrics {
|
|
srvReg.MustRegister(metric)
|
|
}
|
|
})
|
|
}
|
|
|
|
// SetServerPattern set the server pattern
|
|
func SetServerPattern(pattern string) {
|
|
if pattern != "" {
|
|
serverPattern = pattern
|
|
}
|
|
}
|
|
|
|
// Register for http routing and grpc methods
|
|
func Register(mux *http.ServeMux, grpcServer *grpc.Server) {
|
|
// register for http routing
|
|
mux.Handle(serverPattern, promhttp.HandlerFor(srvReg, promhttp.HandlerOpts{}))
|
|
|
|
// register all gRPC methods to metrics
|
|
grpcServerMetrics.InitializeMetrics(grpcServer)
|
|
}
|
|
|
|
// ServerHTTPService initialize the prometheus exporter service on the server side and fetch data using http://ip:port/metrics
|
|
func ServerHTTPService(addr string, grpcServer *grpc.Server) *http.Server {
|
|
httpServer := &http.Server{
|
|
Addr: addr,
|
|
Handler: promhttp.HandlerFor(srvReg, promhttp.HandlerOpts{}),
|
|
}
|
|
|
|
// run http server
|
|
go func() {
|
|
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
panic("listen and serve error: " + err.Error())
|
|
}
|
|
}()
|
|
|
|
// initialize gRPC methods Metrics
|
|
grpcServerMetrics.InitializeMetrics(grpcServer)
|
|
|
|
return httpServer
|
|
}
|
|
|
|
// ---------------------------------- server interceptor ----------------------------------
|
|
|
|
// UnaryServerMetrics metrics unary interceptor
|
|
func UnaryServerMetrics(opts ...Option) grpc.UnaryServerInterceptor {
|
|
o := defaultMetricsOptions()
|
|
o.apply(opts...)
|
|
srvRegisterMetrics()
|
|
return grpcServerMetrics.UnaryServerInterceptor()
|
|
}
|
|
|
|
// StreamServerMetrics metrics stream interceptor
|
|
func StreamServerMetrics(opts ...Option) grpc.StreamServerInterceptor {
|
|
o := defaultMetricsOptions()
|
|
o.apply(opts...)
|
|
srvRegisterMetrics()
|
|
return grpcServerMetrics.StreamServerInterceptor()
|
|
}
|