diff --git a/go.mod b/go.mod index 02abfd896f..0bf78cecf2 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( github.com/google/certtostore v1.0.7 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.1 github.com/intel/goresctrl v0.13.0 github.com/klauspost/compress v1.20.1 github.com/mdlayher/vsock v1.3.0 diff --git a/go.sum b/go.sum index f919d48440..1024ec1032 100644 --- a/go.sum +++ b/go.sum @@ -171,8 +171,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.1 h1:E4CBXV5a/63B3ugXigjU28gr4HHM/BuMa1DtOYWhEz8= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.1/go.mod h1:4c5LkgQnrWyJl9pvs2+nPRS12n3g/93FAQg8IzhEgnY= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 h1:/Tnpcb2E0Pz/tN9s3bfEY2Q8ePCEX9iuS+cneUwncnw= diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_metrics.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_metrics.go index 5c8ba20765..44eecf535d 100644 --- a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_metrics.go +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_metrics.go @@ -23,42 +23,64 @@ type ClientMetrics struct { clientStreamRecvHistogram *prometheus.HistogramVec // clientStreamSendHistogram can be nil clientStreamSendHistogram *prometheus.HistogramVec + + // contextLabelNames stores the names of context labels + contextLabelNames []string } // NewClientMetrics returns a new ClientMetrics object. // NOTE: Remember to register ClientMetrics object using prometheus registry // e.g. prometheus.MustRegister(myClientMetrics). func NewClientMetrics(opts ...ClientMetricsOption) *ClientMetrics { - var config clientMetricsConfig + config := &clientMetricsConfig{ + clientHandledHistogramFn: func() *prometheus.HistogramVec { return nil }, + clientStreamRecvHistogramFn: func() *prometheus.HistogramVec { return nil }, + clientStreamSendHistogramFn: func() *prometheus.HistogramVec { return nil }, + } config.apply(opts) + + // Build label names by combining default labels with context labels + defaultLabels := []string{"grpc_type", "grpc_service", "grpc_method"} + defaultLabelsWithCode := []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"} + + startedLabels := append(defaultLabels, config.contextLabels...) + handledLabels := append(defaultLabelsWithCode, config.contextLabels...) + streamLabels := append(defaultLabels, config.contextLabels...) + return &ClientMetrics{ clientStartedCounter: prometheus.NewCounterVec( config.counterOpts.apply(prometheus.CounterOpts{ Name: "grpc_client_started_total", Help: "Total number of RPCs started on the client.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), + }), startedLabels, + ), clientHandledCounter: prometheus.NewCounterVec( config.counterOpts.apply(prometheus.CounterOpts{ Name: "grpc_client_handled_total", Help: "Total number of RPCs completed by the client, regardless of success or failure.", - }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), + }), handledLabels, + ), clientStreamMsgReceived: prometheus.NewCounterVec( config.counterOpts.apply(prometheus.CounterOpts{ Name: "grpc_client_msg_received_total", Help: "Total number of RPC stream messages received by the client.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), + }), streamLabels, + ), clientStreamMsgSent: prometheus.NewCounterVec( config.counterOpts.apply(prometheus.CounterOpts{ Name: "grpc_client_msg_sent_total", Help: "Total number of gRPC stream messages sent by the client.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), + }), streamLabels, + ), - clientHandledHistogram: config.clientHandledHistogram, - clientStreamRecvHistogram: config.clientStreamRecvHistogram, - clientStreamSendHistogram: config.clientStreamSendHistogram, + clientHandledHistogram: config.clientHandledHistogramFn(), + clientStreamRecvHistogram: config.clientStreamRecvHistogramFn(), + clientStreamSendHistogram: config.clientStreamSendHistogramFn(), + + contextLabelNames: config.contextLabels, } } diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_options.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_options.go index c2671679c6..1ed8e61686 100644 --- a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_options.go +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_options.go @@ -9,12 +9,14 @@ import ( type clientMetricsConfig struct { counterOpts counterOptions - // clientHandledHistogram can be nil. - clientHandledHistogram *prometheus.HistogramVec - // clientStreamRecvHistogram can be nil. - clientStreamRecvHistogram *prometheus.HistogramVec - // clientStreamSendHistogram can be nil. - clientStreamSendHistogram *prometheus.HistogramVec + // clientHandledHistogramFn can be nil. + clientHandledHistogramFn func() *prometheus.HistogramVec + // clientStreamRecvHistogramFn can be nil. + clientStreamRecvHistogramFn func() *prometheus.HistogramVec + // clientStreamSendHistogramFn can be nil. + clientStreamSendHistogramFn func() *prometheus.HistogramVec + // contextLabels defines the names of dynamic labels to be extracted from context + contextLabels []string } type ClientMetricsOption func(*clientMetricsConfig) @@ -35,14 +37,19 @@ func WithClientCounterOptions(opts ...CounterOption) ClientMetricsOption { // Histogram metrics can be very expensive for Prometheus to retain and query. func WithClientHandlingTimeHistogram(opts ...HistogramOption) ClientMetricsOption { return func(o *clientMetricsConfig) { - o.clientHandledHistogram = prometheus.NewHistogramVec( - histogramOptions(opts).apply(prometheus.HistogramOpts{ - Name: "grpc_client_handling_seconds", - Help: "Histogram of response latency (seconds) of the gRPC until it is finished by the application.", - Buckets: prometheus.DefBuckets, - }), - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) + o.clientHandledHistogramFn = func() *prometheus.HistogramVec { + defaultLabels := []string{"grpc_type", "grpc_service", "grpc_method"} + allLabels := append(defaultLabels, o.contextLabels...) + + return prometheus.NewHistogramVec( + histogramOptions(opts).apply(&prometheus.HistogramOpts{ + Name: "grpc_client_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC until it is finished by the application.", + Buckets: prometheus.DefBuckets, + }), + allLabels, + ) + } } } @@ -50,14 +57,19 @@ func WithClientHandlingTimeHistogram(opts ...HistogramOption) ClientMetricsOptio // Histogram metrics can be very expensive for Prometheus to retain and query. func WithClientStreamRecvHistogram(opts ...HistogramOption) ClientMetricsOption { return func(o *clientMetricsConfig) { - o.clientStreamRecvHistogram = prometheus.NewHistogramVec( - histogramOptions(opts).apply(prometheus.HistogramOpts{ - Name: "grpc_client_msg_recv_handling_seconds", - Help: "Histogram of response latency (seconds) of the gRPC single message receive.", - Buckets: prometheus.DefBuckets, - }), - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) + o.clientStreamRecvHistogramFn = func() *prometheus.HistogramVec { + defaultLabels := []string{"grpc_type", "grpc_service", "grpc_method"} + allLabels := append(defaultLabels, o.contextLabels...) + + return prometheus.NewHistogramVec( + histogramOptions(opts).apply(&prometheus.HistogramOpts{ + Name: "grpc_client_msg_recv_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC single message receive.", + Buckets: prometheus.DefBuckets, + }), + allLabels, + ) + } } } @@ -65,13 +77,27 @@ func WithClientStreamRecvHistogram(opts ...HistogramOption) ClientMetricsOption // Histogram metrics can be very expensive for Prometheus to retain and query. func WithClientStreamSendHistogram(opts ...HistogramOption) ClientMetricsOption { return func(o *clientMetricsConfig) { - o.clientStreamSendHistogram = prometheus.NewHistogramVec( - histogramOptions(opts).apply(prometheus.HistogramOpts{ - Name: "grpc_client_msg_send_handling_seconds", - Help: "Histogram of response latency (seconds) of the gRPC single message send.", - Buckets: prometheus.DefBuckets, - }), - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) + o.clientStreamSendHistogramFn = func() *prometheus.HistogramVec { + defaultLabels := []string{"grpc_type", "grpc_service", "grpc_method"} + allLabels := append(defaultLabels, o.contextLabels...) + + return prometheus.NewHistogramVec( + histogramOptions(opts).apply(&prometheus.HistogramOpts{ + Name: "grpc_client_msg_send_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC single message send.", + Buckets: prometheus.DefBuckets, + }), + allLabels, + ) + } + } +} + +// WithClientContextLabels configures the server metrics to include dynamic labels extracted from context. +// The provided label names will be added to all server metrics as dynamic labels. +// Use WithLabelsFromContext in the interceptor options to specify how to extract these labels from context. +func WithClientContextLabels(labelNames ...string) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.contextLabels = labelNames } } diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/options.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/options.go index 2047b5fe41..eabb466779 100644 --- a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/options.go +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/options.go @@ -59,11 +59,11 @@ type HistogramOption func(*prometheus.HistogramOpts) type histogramOptions []HistogramOption -func (ho histogramOptions) apply(o prometheus.HistogramOpts) prometheus.HistogramOpts { +func (ho histogramOptions) apply(o *prometheus.HistogramOpts) prometheus.HistogramOpts { for _, f := range ho { - f(&o) + f(o) } - return o + return *o } // WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on. diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/reporter.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/reporter.go index 268beb3e61..41fe639e5b 100644 --- a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/reporter.go +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/reporter.go @@ -39,37 +39,53 @@ func (r *reporter) PostCall(err error, rpcDuration time.Duration) { } case KindClient: - r.incrementWithExemplar(r.clientMetrics.clientHandledCounter, string(r.typ), r.service, r.method, code.String()) + baseLabels := []string{string(r.typ), r.service, r.method, code.String()} + allLabels := append(baseLabels, r.contextLabels...) + r.incrementWithExemplar(r.clientMetrics.clientHandledCounter, allLabels...) if r.clientMetrics.clientHandledHistogram != nil { - r.observeWithExemplar(r.clientMetrics.clientHandledHistogram, rpcDuration.Seconds(), string(r.typ), r.service, r.method) + histLabels := []string{string(r.typ), r.service, r.method} + allHistLabels := append(histLabels, r.contextLabels...) + r.observeWithExemplar(r.clientMetrics.clientHandledHistogram, rpcDuration.Seconds(), allHistLabels...) } } } -func (r *reporter) PostMsgSend(_ any, _ error, sendDuration time.Duration) { +func (r *reporter) PostMsgSend(_ any, err error, sendDuration time.Duration) { switch r.kind { case KindServer: baseLabels := []string{string(r.typ), r.service, r.method} allLabels := append(baseLabels, r.contextLabels...) - r.incrementWithExemplar(r.serverMetrics.serverStreamMsgSent, allLabels...) + if err == nil { + r.incrementWithExemplar(r.serverMetrics.serverStreamMsgSent, allLabels...) + } case KindClient: - r.incrementWithExemplar(r.clientMetrics.clientStreamMsgSent, string(r.typ), r.service, r.method) + baseLabels := []string{string(r.typ), r.service, r.method} + allLabels := append(baseLabels, r.contextLabels...) + if err == nil { + r.incrementWithExemplar(r.clientMetrics.clientStreamMsgSent, allLabels...) + } if r.clientMetrics.clientStreamSendHistogram != nil { - r.observeWithExemplar(r.clientMetrics.clientStreamSendHistogram, sendDuration.Seconds(), string(r.typ), r.service, r.method) + r.observeWithExemplar(r.clientMetrics.clientStreamSendHistogram, sendDuration.Seconds(), allLabels...) } } } -func (r *reporter) PostMsgReceive(_ any, _ error, recvDuration time.Duration) { +func (r *reporter) PostMsgReceive(_ any, err error, recvDuration time.Duration) { switch r.kind { case KindServer: baseLabels := []string{string(r.typ), r.service, r.method} allLabels := append(baseLabels, r.contextLabels...) - r.incrementWithExemplar(r.serverMetrics.serverStreamMsgReceived, allLabels...) + if err == nil { + r.incrementWithExemplar(r.serverMetrics.serverStreamMsgReceived, allLabels...) + } case KindClient: - r.incrementWithExemplar(r.clientMetrics.clientStreamMsgReceived, string(r.typ), r.service, r.method) + baseLabels := []string{string(r.typ), r.service, r.method} + allLabels := append(baseLabels, r.contextLabels...) + if err == nil { + r.incrementWithExemplar(r.clientMetrics.clientStreamMsgReceived, allLabels...) + } if r.clientMetrics.clientStreamRecvHistogram != nil { - r.observeWithExemplar(r.clientMetrics.clientStreamRecvHistogram, recvDuration.Seconds(), string(r.typ), r.service, r.method) + r.observeWithExemplar(r.clientMetrics.clientStreamRecvHistogram, recvDuration.Seconds(), allLabels...) } } } @@ -105,11 +121,18 @@ func (rep *reportable) reporter(ctx context.Context, sm *ServerMetrics, cm *Clie } // Extract context labels if labelsFn is configured and we're on server side - if c.labelsFn != nil && kind == KindServer && sm != nil { + if c.labelsFn != nil { + var contextLabelNames []string + if kind == KindServer && sm != nil { + contextLabelNames = sm.contextLabelNames + } else if kind == KindClient && cm != nil { + contextLabelNames = cm.contextLabelNames + } + contextLabelMap := c.labelsFn(ctx) // Extract context label values in the order defined by the server metrics - r.contextLabels = make([]string, len(sm.contextLabelNames)) - for i, labelName := range sm.contextLabelNames { + r.contextLabels = make([]string, len(contextLabelNames)) + for i, labelName := range contextLabelNames { if value, exists := contextLabelMap[labelName]; exists { r.contextLabels[i] = value } else { @@ -121,7 +144,9 @@ func (rep *reportable) reporter(ctx context.Context, sm *ServerMetrics, cm *Clie switch kind { case KindClient: - r.incrementWithExemplar(r.clientMetrics.clientStartedCounter, string(r.typ), r.service, r.method) + baseLabels := []string{string(r.typ), r.service, r.method} + allLabels := append(baseLabels, r.contextLabels...) + r.incrementWithExemplar(r.clientMetrics.clientStartedCounter, allLabels...) case KindServer: baseLabels := []string{string(r.typ), r.service, r.method} allLabels := append(baseLabels, r.contextLabels...) diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_metrics.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_metrics.go index 358d574caf..9c31433915 100644 --- a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_metrics.go +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_metrics.go @@ -43,7 +43,7 @@ func NewServerMetrics(opts ...ServerMetricsOption) *ServerMetrics { if config.enableHistogram { histogramLabels := append(defaultLabels, config.contextLabels...) serverHandledHistogram = prometheus.NewHistogramVec( - histogramOptions(config.histogramOpts).apply(prometheus.HistogramOpts{ + histogramOptions(config.histogramOpts).apply(&prometheus.HistogramOpts{ Name: "grpc_server_handling_seconds", Help: "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.", Buckets: prometheus.DefBuckets, @@ -57,22 +57,26 @@ func NewServerMetrics(opts ...ServerMetricsOption) *ServerMetrics { config.counterOpts.apply(prometheus.CounterOpts{ Name: "grpc_server_started_total", Help: "Total number of RPCs started on the server.", - }), startedLabels), + }), startedLabels, + ), serverHandledCounter: prometheus.NewCounterVec( config.counterOpts.apply(prometheus.CounterOpts{ Name: "grpc_server_handled_total", Help: "Total number of RPCs completed on the server, regardless of success or failure.", - }), handledLabels), + }), handledLabels, + ), serverStreamMsgReceived: prometheus.NewCounterVec( config.counterOpts.apply(prometheus.CounterOpts{ Name: "grpc_server_msg_received_total", Help: "Total number of RPC stream messages received on the server.", - }), streamLabels), + }), streamLabels, + ), serverStreamMsgSent: prometheus.NewCounterVec( config.counterOpts.apply(prometheus.CounterOpts{ Name: "grpc_server_msg_sent_total", Help: "Total number of gRPC stream messages sent by the server.", - }), streamLabels), + }), streamLabels, + ), serverHandledHistogram: serverHandledHistogram, contextLabelNames: config.contextLabels, } @@ -130,7 +134,6 @@ func (m *ServerMetrics) preRegisterMethod(serviceName string, mInfo *grpc.Method // Build complete label value arrays startedLabels := append([]string{methodType, serviceName, methodName}, contextLabels...) - handledLabels := append([]string{methodType, serviceName, methodName}, contextLabels...) streamLabels := append([]string{methodType, serviceName, methodName}, contextLabels...) // These are just references (no increments), as just referencing will create the labels but not set values. @@ -141,7 +144,7 @@ func (m *ServerMetrics) preRegisterMethod(serviceName string, mInfo *grpc.Method _, _ = m.serverHandledHistogram.GetMetricWithLabelValues(streamLabels...) } for _, code := range interceptors.AllCodes { - handledLabelsWithCode := append(handledLabels, code.String()) + handledLabelsWithCode := append([]string{methodType, serviceName, methodName, code.String()}, contextLabels...) _, _ = m.serverHandledCounter.GetMetricWithLabelValues(handledLabelsWithCode...) } } diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_options.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_options.go index 14340637d1..c4e43fe4fb 100644 --- a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_options.go +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_options.go @@ -9,8 +9,10 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -type exemplarFromCtxFn func(ctx context.Context) prometheus.Labels -type labelsFromCtxFn func(metadata context.Context) prometheus.Labels +type ( + exemplarFromCtxFn func(ctx context.Context) prometheus.Labels + labelsFromCtxFn func(metadata context.Context) prometheus.Labels +) type serverMetricsConfig struct { counterOpts counterOptions diff --git a/vendor/modules.txt b/vendor/modules.txt index 928826413d..f1f0927903 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -395,8 +395,8 @@ github.com/google/uuid # github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 ## explicit; go 1.20 github.com/gorilla/websocket -# github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 -## explicit; go 1.21 +# github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.1 +## explicit; go 1.23.0 github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus # github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 ## explicit; go 1.19