forked from toolshed/abra
		
	
		
			
				
	
	
		
			271 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			271 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|  *
 | |
|  * Copyright 2024 gRPC authors.
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| package stats
 | |
| 
 | |
| import (
 | |
| 	"maps"
 | |
| 
 | |
| 	"google.golang.org/grpc/grpclog"
 | |
| 	"google.golang.org/grpc/internal"
 | |
| 	"google.golang.org/grpc/stats"
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	internal.SnapshotMetricRegistryForTesting = snapshotMetricsRegistryForTesting
 | |
| }
 | |
| 
 | |
| var logger = grpclog.Component("metrics-registry")
 | |
| 
 | |
| // DefaultMetrics are the default metrics registered through global metrics
 | |
| // registry. This is written to at initialization time only, and is read only
 | |
| // after initialization.
 | |
| var DefaultMetrics = stats.NewMetricSet()
 | |
| 
 | |
| // MetricDescriptor is the data for a registered metric.
 | |
| type MetricDescriptor struct {
 | |
| 	// The name of this metric. This name must be unique across the whole binary
 | |
| 	// (including any per call metrics). See
 | |
| 	// https://github.com/grpc/proposal/blob/master/A79-non-per-call-metrics-architecture.md#metric-instrument-naming-conventions
 | |
| 	// for metric naming conventions.
 | |
| 	Name string
 | |
| 	// The description of this metric.
 | |
| 	Description string
 | |
| 	// The unit (e.g. entries, seconds) of this metric.
 | |
| 	Unit string
 | |
| 	// The required label keys for this metric. These are intended to
 | |
| 	// metrics emitted from a stats handler.
 | |
| 	Labels []string
 | |
| 	// The optional label keys for this metric. These are intended to attached
 | |
| 	// to metrics emitted from a stats handler if configured.
 | |
| 	OptionalLabels []string
 | |
| 	// Whether this metric is on by default.
 | |
| 	Default bool
 | |
| 	// The type of metric. This is set by the metric registry, and not intended
 | |
| 	// to be set by a component registering a metric.
 | |
| 	Type MetricType
 | |
| 	// Bounds are the bounds of this metric. This only applies to histogram
 | |
| 	// metrics. If unset or set with length 0, stats handlers will fall back to
 | |
| 	// default bounds.
 | |
| 	Bounds []float64
 | |
| }
 | |
| 
 | |
| // MetricType is the type of metric.
 | |
| type MetricType int
 | |
| 
 | |
| // Type of metric supported by this instrument registry.
 | |
| const (
 | |
| 	MetricTypeIntCount MetricType = iota
 | |
| 	MetricTypeFloatCount
 | |
| 	MetricTypeIntHisto
 | |
| 	MetricTypeFloatHisto
 | |
| 	MetricTypeIntGauge
 | |
| )
 | |
| 
 | |
| // Int64CountHandle is a typed handle for a int count metric. This handle
 | |
| // is passed at the recording point in order to know which metric to record
 | |
| // on.
 | |
| type Int64CountHandle MetricDescriptor
 | |
| 
 | |
| // Descriptor returns the int64 count handle typecast to a pointer to a
 | |
| // MetricDescriptor.
 | |
| func (h *Int64CountHandle) Descriptor() *MetricDescriptor {
 | |
| 	return (*MetricDescriptor)(h)
 | |
| }
 | |
| 
 | |
| // Record records the int64 count value on the metrics recorder provided.
 | |
| func (h *Int64CountHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) {
 | |
| 	recorder.RecordInt64Count(h, incr, labels...)
 | |
| }
 | |
| 
 | |
| // Float64CountHandle is a typed handle for a float count metric. This handle is
 | |
| // passed at the recording point in order to know which metric to record on.
 | |
| type Float64CountHandle MetricDescriptor
 | |
| 
 | |
| // Descriptor returns the float64 count handle typecast to a pointer to a
 | |
| // MetricDescriptor.
 | |
| func (h *Float64CountHandle) Descriptor() *MetricDescriptor {
 | |
| 	return (*MetricDescriptor)(h)
 | |
| }
 | |
| 
 | |
| // Record records the float64 count value on the metrics recorder provided.
 | |
| func (h *Float64CountHandle) Record(recorder MetricsRecorder, incr float64, labels ...string) {
 | |
| 	recorder.RecordFloat64Count(h, incr, labels...)
 | |
| }
 | |
| 
 | |
| // Int64HistoHandle is a typed handle for an int histogram metric. This handle
 | |
| // is passed at the recording point in order to know which metric to record on.
 | |
| type Int64HistoHandle MetricDescriptor
 | |
| 
 | |
| // Descriptor returns the int64 histo handle typecast to a pointer to a
 | |
| // MetricDescriptor.
 | |
| func (h *Int64HistoHandle) Descriptor() *MetricDescriptor {
 | |
| 	return (*MetricDescriptor)(h)
 | |
| }
 | |
| 
 | |
| // Record records the int64 histo value on the metrics recorder provided.
 | |
| func (h *Int64HistoHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) {
 | |
| 	recorder.RecordInt64Histo(h, incr, labels...)
 | |
| }
 | |
| 
 | |
| // Float64HistoHandle is a typed handle for a float histogram metric. This
 | |
| // handle is passed at the recording point in order to know which metric to
 | |
| // record on.
 | |
| type Float64HistoHandle MetricDescriptor
 | |
| 
 | |
| // Descriptor returns the float64 histo handle typecast to a pointer to a
 | |
| // MetricDescriptor.
 | |
| func (h *Float64HistoHandle) Descriptor() *MetricDescriptor {
 | |
| 	return (*MetricDescriptor)(h)
 | |
| }
 | |
| 
 | |
| // Record records the float64 histo value on the metrics recorder provided.
 | |
| func (h *Float64HistoHandle) Record(recorder MetricsRecorder, incr float64, labels ...string) {
 | |
| 	recorder.RecordFloat64Histo(h, incr, labels...)
 | |
| }
 | |
| 
 | |
| // Int64GaugeHandle is a typed handle for an int gauge metric. This handle is
 | |
| // passed at the recording point in order to know which metric to record on.
 | |
| type Int64GaugeHandle MetricDescriptor
 | |
| 
 | |
| // Descriptor returns the int64 gauge handle typecast to a pointer to a
 | |
| // MetricDescriptor.
 | |
| func (h *Int64GaugeHandle) Descriptor() *MetricDescriptor {
 | |
| 	return (*MetricDescriptor)(h)
 | |
| }
 | |
| 
 | |
| // Record records the int64 histo value on the metrics recorder provided.
 | |
| func (h *Int64GaugeHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) {
 | |
| 	recorder.RecordInt64Gauge(h, incr, labels...)
 | |
| }
 | |
| 
 | |
| // registeredMetrics are the registered metric descriptor names.
 | |
| var registeredMetrics = make(map[string]bool)
 | |
| 
 | |
| // metricsRegistry contains all of the registered metrics.
 | |
| //
 | |
| // This is written to only at init time, and read only after that.
 | |
| var metricsRegistry = make(map[string]*MetricDescriptor)
 | |
| 
 | |
| // DescriptorForMetric returns the MetricDescriptor from the global registry.
 | |
| //
 | |
| // Returns nil if MetricDescriptor not present.
 | |
| func DescriptorForMetric(metricName string) *MetricDescriptor {
 | |
| 	return metricsRegistry[metricName]
 | |
| }
 | |
| 
 | |
| func registerMetric(metricName string, def bool) {
 | |
| 	if registeredMetrics[metricName] {
 | |
| 		logger.Fatalf("metric %v already registered", metricName)
 | |
| 	}
 | |
| 	registeredMetrics[metricName] = true
 | |
| 	if def {
 | |
| 		DefaultMetrics = DefaultMetrics.Add(metricName)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // RegisterInt64Count registers the metric description onto the global registry.
 | |
| // It returns a typed handle to use to recording data.
 | |
| //
 | |
| // NOTE: this function must only be called during initialization time (i.e. in
 | |
| // an init() function), and is not thread-safe. If multiple metrics are
 | |
| // registered with the same name, this function will panic.
 | |
| func RegisterInt64Count(descriptor MetricDescriptor) *Int64CountHandle {
 | |
| 	registerMetric(descriptor.Name, descriptor.Default)
 | |
| 	descriptor.Type = MetricTypeIntCount
 | |
| 	descPtr := &descriptor
 | |
| 	metricsRegistry[descriptor.Name] = descPtr
 | |
| 	return (*Int64CountHandle)(descPtr)
 | |
| }
 | |
| 
 | |
| // RegisterFloat64Count registers the metric description onto the global
 | |
| // registry. It returns a typed handle to use to recording data.
 | |
| //
 | |
| // NOTE: this function must only be called during initialization time (i.e. in
 | |
| // an init() function), and is not thread-safe. If multiple metrics are
 | |
| // registered with the same name, this function will panic.
 | |
| func RegisterFloat64Count(descriptor MetricDescriptor) *Float64CountHandle {
 | |
| 	registerMetric(descriptor.Name, descriptor.Default)
 | |
| 	descriptor.Type = MetricTypeFloatCount
 | |
| 	descPtr := &descriptor
 | |
| 	metricsRegistry[descriptor.Name] = descPtr
 | |
| 	return (*Float64CountHandle)(descPtr)
 | |
| }
 | |
| 
 | |
| // RegisterInt64Histo registers the metric description onto the global registry.
 | |
| // It returns a typed handle to use to recording data.
 | |
| //
 | |
| // NOTE: this function must only be called during initialization time (i.e. in
 | |
| // an init() function), and is not thread-safe. If multiple metrics are
 | |
| // registered with the same name, this function will panic.
 | |
| func RegisterInt64Histo(descriptor MetricDescriptor) *Int64HistoHandle {
 | |
| 	registerMetric(descriptor.Name, descriptor.Default)
 | |
| 	descriptor.Type = MetricTypeIntHisto
 | |
| 	descPtr := &descriptor
 | |
| 	metricsRegistry[descriptor.Name] = descPtr
 | |
| 	return (*Int64HistoHandle)(descPtr)
 | |
| }
 | |
| 
 | |
| // RegisterFloat64Histo registers the metric description onto the global
 | |
| // registry. It returns a typed handle to use to recording data.
 | |
| //
 | |
| // NOTE: this function must only be called during initialization time (i.e. in
 | |
| // an init() function), and is not thread-safe. If multiple metrics are
 | |
| // registered with the same name, this function will panic.
 | |
| func RegisterFloat64Histo(descriptor MetricDescriptor) *Float64HistoHandle {
 | |
| 	registerMetric(descriptor.Name, descriptor.Default)
 | |
| 	descriptor.Type = MetricTypeFloatHisto
 | |
| 	descPtr := &descriptor
 | |
| 	metricsRegistry[descriptor.Name] = descPtr
 | |
| 	return (*Float64HistoHandle)(descPtr)
 | |
| }
 | |
| 
 | |
| // RegisterInt64Gauge registers the metric description onto the global registry.
 | |
| // It returns a typed handle to use to recording data.
 | |
| //
 | |
| // NOTE: this function must only be called during initialization time (i.e. in
 | |
| // an init() function), and is not thread-safe. If multiple metrics are
 | |
| // registered with the same name, this function will panic.
 | |
| func RegisterInt64Gauge(descriptor MetricDescriptor) *Int64GaugeHandle {
 | |
| 	registerMetric(descriptor.Name, descriptor.Default)
 | |
| 	descriptor.Type = MetricTypeIntGauge
 | |
| 	descPtr := &descriptor
 | |
| 	metricsRegistry[descriptor.Name] = descPtr
 | |
| 	return (*Int64GaugeHandle)(descPtr)
 | |
| }
 | |
| 
 | |
| // snapshotMetricsRegistryForTesting snapshots the global data of the metrics
 | |
| // registry. Returns a cleanup function that sets the metrics registry to its
 | |
| // original state.
 | |
| func snapshotMetricsRegistryForTesting() func() {
 | |
| 	oldDefaultMetrics := DefaultMetrics
 | |
| 	oldRegisteredMetrics := registeredMetrics
 | |
| 	oldMetricsRegistry := metricsRegistry
 | |
| 
 | |
| 	registeredMetrics = make(map[string]bool)
 | |
| 	metricsRegistry = make(map[string]*MetricDescriptor)
 | |
| 	maps.Copy(registeredMetrics, registeredMetrics)
 | |
| 	maps.Copy(metricsRegistry, metricsRegistry)
 | |
| 
 | |
| 	return func() {
 | |
| 		DefaultMetrics = oldDefaultMetrics
 | |
| 		registeredMetrics = oldRegisteredMetrics
 | |
| 		metricsRegistry = oldMetricsRegistry
 | |
| 	}
 | |
| }
 |