/*
 *
 * 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 (
	

	
	
	
)

func () {
	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 ( *Int64CountHandle) () *MetricDescriptor {
	return (*MetricDescriptor)()
}

// Record records the int64 count value on the metrics recorder provided.
func ( *Int64CountHandle) ( MetricsRecorder,  int64,  ...string) {
	.RecordInt64Count(, , ...)
}

// 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 ( *Float64CountHandle) () *MetricDescriptor {
	return (*MetricDescriptor)()
}

// Record records the float64 count value on the metrics recorder provided.
func ( *Float64CountHandle) ( MetricsRecorder,  float64,  ...string) {
	.RecordFloat64Count(, , ...)
}

// 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 ( *Int64HistoHandle) () *MetricDescriptor {
	return (*MetricDescriptor)()
}

// Record records the int64 histo value on the metrics recorder provided.
func ( *Int64HistoHandle) ( MetricsRecorder,  int64,  ...string) {
	.RecordInt64Histo(, , ...)
}

// 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 ( *Float64HistoHandle) () *MetricDescriptor {
	return (*MetricDescriptor)()
}

// Record records the float64 histo value on the metrics recorder provided.
func ( *Float64HistoHandle) ( MetricsRecorder,  float64,  ...string) {
	.RecordFloat64Histo(, , ...)
}

// 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 ( *Int64GaugeHandle) () *MetricDescriptor {
	return (*MetricDescriptor)()
}

// Record records the int64 histo value on the metrics recorder provided.
func ( *Int64GaugeHandle) ( MetricsRecorder,  int64,  ...string) {
	.RecordInt64Gauge(, , ...)
}

// 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 ( string) *MetricDescriptor {
	return metricsRegistry[]
}

func ( string,  bool) {
	if registeredMetrics[] {
		logger.Fatalf("metric %v already registered", )
	}
	registeredMetrics[] = true
	if  {
		DefaultMetrics = DefaultMetrics.Add()
	}
}

// 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 ( MetricDescriptor) *Int64CountHandle {
	registerMetric(.Name, .Default)
	.Type = MetricTypeIntCount
	 := &
	metricsRegistry[.Name] = 
	return (*Int64CountHandle)()
}

// 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 ( MetricDescriptor) *Float64CountHandle {
	registerMetric(.Name, .Default)
	.Type = MetricTypeFloatCount
	 := &
	metricsRegistry[.Name] = 
	return (*Float64CountHandle)()
}

// 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 ( MetricDescriptor) *Int64HistoHandle {
	registerMetric(.Name, .Default)
	.Type = MetricTypeIntHisto
	 := &
	metricsRegistry[.Name] = 
	return (*Int64HistoHandle)()
}

// 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 ( MetricDescriptor) *Float64HistoHandle {
	registerMetric(.Name, .Default)
	.Type = MetricTypeFloatHisto
	 := &
	metricsRegistry[.Name] = 
	return (*Float64HistoHandle)()
}

// 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 ( MetricDescriptor) *Int64GaugeHandle {
	registerMetric(.Name, .Default)
	.Type = MetricTypeIntGauge
	 := &
	metricsRegistry[.Name] = 
	return (*Int64GaugeHandle)()
}

// snapshotMetricsRegistryForTesting snapshots the global data of the metrics
// registry. Returns a cleanup function that sets the metrics registry to its
// original state.
func () func() {
	 := DefaultMetrics
	 := registeredMetrics
	 := metricsRegistry

	registeredMetrics = make(map[string]bool)
	metricsRegistry = make(map[string]*MetricDescriptor)
	maps.Copy(registeredMetrics, registeredMetrics)
	maps.Copy(metricsRegistry, metricsRegistry)

	return func() {
		DefaultMetrics = 
		registeredMetrics = 
		metricsRegistry = 
	}
}