From 9ebf0794315dc9ab124b2867692e14ae7b3518e1 Mon Sep 17 00:00:00 2001 From: Zach Reyes Date: Tue, 9 Jul 2024 19:09:19 -0400 Subject: [PATCH] Implemented offline discussion --- experimental/stats/metricregistry.go | 160 +++++++----- experimental/stats/metricregistry_test.go | 298 +++++++++++++++------- experimental/stats/stats.go | 1 - 3 files changed, 300 insertions(+), 159 deletions(-) diff --git a/experimental/stats/metricregistry.go b/experimental/stats/metricregistry.go index f9a56c0fef84..0be95ae9d9e4 100644 --- a/experimental/stats/metricregistry.go +++ b/experimental/stats/metricregistry.go @@ -24,119 +24,120 @@ import ( "google.golang.org/grpc/stats" ) -// DefaultMetrics are the default metrics registered through global instruments -// registry. This is written to at initialization time only, and is read -// only after initialization. +// 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.NewMetrics() // MetricDescriptor is the data for a registered metric. type MetricDescriptor struct { - // Name is the name of this metric. + // Name is the name of this metric. This name must be unique across 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 stats.Metric // Description is the description of this metric. Description string - // Unit is the unit of this metric. + // Unit is the unit of this metric (e.g. entries, milliseconds). Unit string - // Labels are the required label keys for this metric. + // Labels are the required label keys for this metric. These are intended to + // metrics emitted from a stats handler. Labels []string - // OptionalLabels are the optional label keys for this - // metric. + // OptionalLabels are the optional label keys for this metric. These are + // intended to attached to metrics emitted from a stats handler if + // configured. OptionalLabels []string // Default is whether this metric is on by default. Default bool + // Type is 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 } -// Int64CountHandle is a typed handle for a float count instrument. This handle -// is passed at the recording point in order to know which instrument to record +// Int64CountHandle 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 Int64CountHandle struct { MetricDescriptor *MetricDescriptor } -// RecordInt64Count records the int64 count value on the metrics recorder -// provided. -func (h Int64CountHandle) RecordInt64Count(recorder MetricsRecorder, incr int64, labels ...string) { +// Record records the int64 count value on the metrics recorder provided. +func (h Int64CountHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) { recorder.RecordIntCount(h, incr, labels...) } -// Float64CountHandle is a typed handle for a float count instrument. This handle -// is passed at the recording point in order to know which instrument to record -// on. +// 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 struct { MetricDescriptor *MetricDescriptor } -// RecordFloat64Count records the float64 count value on the metrics recorder -// provided. -func (h Float64CountHandle) RecordFloat64Count(recorder MetricsRecorder, incr float64, labels ...string) { +// Record records the float64 count value on the metrics recorder provided. +func (h Float64CountHandle) Record(recorder MetricsRecorder, incr float64, labels ...string) { recorder.RecordFloatCount(h, incr, labels...) } -// Int64HistoHandle is a typed handle for an int histogram instrument. This -// handle is passed at the recording point in order to know which instrument to -// record on. +// 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 struct { MetricDescriptor *MetricDescriptor } -// RecordInt64Histo records the int64 histo value on the metrics recorder -// provided. -func (h Int64HistoHandle) RecordInt64Histo(recorder MetricsRecorder, incr int64, labels ...string) { +// Record records the int64 histo value on the metrics recorder provided. +func (h Int64HistoHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) { recorder.RecordIntHisto(h, incr, labels...) } -// Float64HistoHandle is a typed handle for a float histogram instrument. This -// handle is passed at the recording point in order to know which instrument to +// 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 struct { MetricDescriptor *MetricDescriptor } -// RecordFloat64Histo records the float64 histo value on the metrics recorder -// provided. -func (h Float64HistoHandle) RecordFloat64Histo(recorder MetricsRecorder, incr float64, labels ...string) { +// Record records the float64 histo value on the metrics recorder provided. +func (h Float64HistoHandle) Record(recorder MetricsRecorder, incr float64, labels ...string) { recorder.RecordFloatHisto(h, incr, labels...) } -// Int64GaugeHandle is a typed handle for an int gauge instrument. This handle -// is passed at the recording point in order to know which instrument to record -// on. +// 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 struct { MetricDescriptor *MetricDescriptor } -// RecordInt64Histo records the int64 histo value on the metrics recorder -// provided. -func (h Int64GaugeHandle) RecordInt64Gauge(recorder MetricsRecorder, incr int64, labels ...string) { +// Record records the int64 histo value on the metrics recorder provided. +func (h Int64GaugeHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) { recorder.RecordIntGauge(h, incr, labels...) } -// registeredInsts are the registered instrument descriptor names. -var registeredInsts = make(map[stats.Metric]bool) +// registeredMetrics are the registered metric descriptor names. +var registeredMetrics = make(map[stats.Metric]bool) -// MetricsRegistry is all the registered metrics. +// MetricsRegistry are all of the registered metrics. // // This is written to only at init time, and read only after that. var MetricsRegistry = make(map[stats.Metric]*MetricDescriptor) -func registerInst(name stats.Metric, def bool) { - if registeredInsts[name] { - log.Panicf("instrument %v already registered", name) +func registerMetric(name stats.Metric, def bool) { + if registeredMetrics[name] { + log.Panicf("metric %v already registered", name) } - registeredInsts[name] = true + registeredMetrics[name] = true if def { DefaultMetrics = DefaultMetrics.Add(name) } } -// RegisterInt64Count registers the instrument description onto the global -// registry. It returns a typed handle to use to recording data. +// 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 instruments are +// 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 { - registerInst(descriptor.Name, descriptor.Default) +func RegisterInt64Count(descriptor MetricDescriptor) Int64CountHandle { + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeIntCount handle := Int64CountHandle{ MetricDescriptor: &descriptor, } @@ -144,14 +145,15 @@ func RegisterInt64Count(descriptor MetricDescriptor) Int64CountHandle { return handle } -// RegisterFloat64Count registers the instrument description onto the global +// 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 instruments are +// 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 { - registerInst(descriptor.Name, descriptor.Default) + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeFloatCount handle := Float64CountHandle{ MetricDescriptor: &descriptor, } @@ -159,14 +161,15 @@ func RegisterFloat64Count(descriptor MetricDescriptor) Float64CountHandle { return handle } -// RegisterInt64Histo registers the instrument description onto the global -// registry. It returns a typed handle to use to recording data. +// 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 instruments are +// 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 { - registerInst(descriptor.Name, descriptor.Default) + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeIntHisto handle := Int64HistoHandle{ MetricDescriptor: &descriptor, } @@ -174,14 +177,15 @@ func RegisterInt64Histo(descriptor MetricDescriptor) Int64HistoHandle { return handle } -// RegisterFloat64Histo registers the instrument description onto the global +// 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 instruments are +// 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 { - registerInst(descriptor.Name, descriptor.Default) + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeFloatHisto handle := Float64HistoHandle{ MetricDescriptor: &descriptor, } @@ -189,14 +193,15 @@ func RegisterFloat64Histo(descriptor MetricDescriptor) Float64HistoHandle { return handle } -// RegisterInt64Gauge registers the instrument description onto the global -// registry. It returns a typed handle to use to recording data. +// 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 instruments are +// 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 { - registerInst(descriptor.Name, descriptor.Default) + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeIntGauge handle := Int64GaugeHandle{ MetricDescriptor: &descriptor, } @@ -204,7 +209,32 @@ func RegisterInt64Gauge(descriptor MetricDescriptor) Int64GaugeHandle { return handle } -// Will take a list, write comments and rewrite tests/cleanup and then I think ready to send out... -// How do I even test this really? -// Internal only clear...I don't think it's worth it just for default set to do it in internal... +// MetricType is the type of metric. +type MetricType int + +const ( + MetricTypeIntCount MetricType = iota + MetricTypeFloatCount + MetricTypeIntHisto + MetricTypeFloatHisto + MetricTypeIntGauge +) +// clearMetricsRegistryForTesting clears the global data of the metrics +// registry. It returns a closure to be invoked that sets the metrics registry +// to its original state. Only called in testing functions. +func clearMetricsRegistryForTesting() func() { + oldDefaultMetrics := DefaultMetrics + oldRegisteredMetrics := registeredMetrics + oldMetricsRegistry := MetricsRegistry + + DefaultMetrics = stats.NewMetrics() + registeredMetrics = make(map[stats.Metric]bool) + MetricsRegistry = make(map[stats.Metric]*MetricDescriptor) + + return func() { + DefaultMetrics = oldDefaultMetrics + registeredMetrics = oldRegisteredMetrics + MetricsRegistry = oldMetricsRegistry + } +} diff --git a/experimental/stats/metricregistry_test.go b/experimental/stats/metricregistry_test.go index b9ce3ff1d29e..ba2c0ec7369c 100644 --- a/experimental/stats/metricregistry_test.go +++ b/experimental/stats/metricregistry_test.go @@ -19,132 +19,244 @@ package stats import ( - "google.golang.org/grpc/experimental/stats/metricregistry" "testing" -) - -func (s) TestMetricRegistry(t *testing.T) { - - // Now there's an implied metrics recorder as part of record calls... - - // Component from client conn will satisfy interface... - - // Same thing create instruments, pass a metrics recorder, instrument is expected to call that metrics recorder - - // Register one of each instrument, verify the metrics recorder works with it... -} - -type fakeMetricsRecorder struct { - t *testing.T - - // 5 different or for one for ints/floats...? + "github.com/google/go-cmp/cmp" + "google.golang.org/grpc/internal/grpctest" +) - // Test the maps built out in OTel (mention to Doug this represents it...) - intValues map[*MetricDescriptor]int64 - floatValues map[*MetricDescriptor]float64 +type s struct { + grpctest.Tester } -// MetricsRecorderList layer just looks at labels/optional labels... - -// newFakeMetricsRecorder returns a fake metrics recorder based off the current -// state of global instrument registry. -func newFakeMetricsRecorder(t *testing.T) *fakeMetricsRecorder { - // Access globals, build a map like OTel would - MetricsRegistry // map[stats.Metric]->Pointer to metrics descriptor, yeah let's test this out, make sure pointer can be used as key value... +func Test(t *testing.T) { + grpctest.RunSubTests(t, s{}) } -// verifyLabels verifies that all of the labels keys expected are present in the -// labels received. -func verifyLabels(t *testing.T, labelsWant []string, optionalLabelsWant []string, labelsGot []stats.Label, optionalLabelsGot []stats.Label) { - for i, label := range labelsWant { - if labelsGot[i].Key != label { - t.Fatalf("label key at position %v got %v, want %v", i, labelsGot[i].Key, label) +// TestPanic tests that registering two metrics with the same name across any +// type of metric triggers a panic. +func (s) TestPanic(t *testing.T) { + cleanup := clearMetricsRegistryForTesting() + defer cleanup() + want := "metric simple counter already registered" + defer func() { + if r := recover(); r != "metric simple counter already registered" { + t.Errorf("expected panic %q, got %q", want, r) } + }() + desc := MetricDescriptor{ + // Type is not expected to be set from the registerer, but meant to be + // set by the metric registry. + Name: "simple counter", + Description: "number of times recorded on tests", + Unit: "calls", } - if len(labelsWant) != len(labelsGot) { - t.Fatalf("length of labels expected did not match got %v, want %v", len(labelsGot), len(optionalLabelsWant)) + RegisterInt64Count(desc) + RegisterInt64Gauge(desc) +} + +// TestInstrumentRegistry tests the metric registry. It registers testing only +// metrics using the metric registry, and creates a fake metrics recorder which +// uses these metrics. Using the handles returned from the metric registry, this +// test records stats using the fake metrics recorder. Then, the test verifies +// the persisted metrics data in the metrics recorder is what is expected. Thus, +// this tests the interactions between the metrics recorder and the metrics +// registry. +func (s) TestMetricRegistry(t *testing.T) { + cleanup := clearMetricsRegistryForTesting() + defer cleanup() + intCountHandle1 := RegisterInt64Count(MetricDescriptor{ + Name: "simple counter", + Description: "sum of all emissions from tests", + Unit: "int", + Labels: []string{"int counter label"}, + OptionalLabels: []string{"int counter optional label"}, + Default: false, + }) + floatCountHandle1 := RegisterFloat64Count(MetricDescriptor{ + Name: "float counter", + Description: "sum of all emissions from tests", + Unit: "float", + Labels: []string{"float counter label"}, + OptionalLabels: []string{"float counter optional label"}, + Default: false, + }) + intHistoHandle1 := RegisterInt64Histo(MetricDescriptor{ + Name: "int histo", + Description: "sum of all emissions from tests", + Unit: "int", + Labels: []string{"int histo label"}, + OptionalLabels: []string{"int histo optional label"}, + Default: false, + }) + floatHistoHandle1 := RegisterFloat64Histo(MetricDescriptor{ + Name: "float histo", + Description: "sum of all emissions from tests", + Unit: "float", + Labels: []string{"float histo label"}, + OptionalLabels: []string{"float histo optional label"}, + Default: false, + }) + intGaugeHandle1 := RegisterInt64Gauge(MetricDescriptor{ + Name: "simple gauge", + Description: "the most recent int emitted by test", + Unit: "int", + Labels: []string{"int gauge label"}, + OptionalLabels: []string{"int gauge optional label"}, + Default: false, + }) + + fmr := newFakeMetricsRecorder(t) + + intCountHandle1.Record(fmr, 1, []string{"some label value", "some optional label value"}...) + // The Metric Descriptor in the handle should be able to identify the metric + // information. This is the key passed to metrics recorder to identify + // metric. + if got := fmr.intValues[intCountHandle1.MetricDescriptor]; got != 1 { + t.Fatalf("fmr.intValues[intCountHandle1.MetricDescriptor] got %v, want: %v", got, 1) } - for i, label := range optionalLabelsWant { - if optionalLabelsGot[i].Key != label { - t.Fatalf("optional label key at position %v got %v, want %v", i, optionalLabelsGot[i].Key, label) - } + floatCountHandle1.Record(fmr, 1.2, []string{"some label value", "some optional label value"}...) + if got := fmr.floatValues[floatCountHandle1.MetricDescriptor]; got != 1.2 { + t.Fatalf("fmr.floatValues[floatCountHandle1.MetricDescriptor] got %v, want: %v", got, 1.2) } - if len(optionalLabelsWant) != len(optionalLabelsGot) { - t.Fatalf("length of optional labels expected did not match got %v, want %v", len(optionalLabelsGot), len(optionalLabelsWant)) + + intHistoHandle1.Record(fmr, 3, []string{"some label value", "some optional label value"}...) + if got := fmr.intValues[intHistoHandle1.MetricDescriptor]; got != 3 { + t.Fatalf("fmr.intValues[intHistoHandle1.MetricDescriptor] got %v, want: %v", got, 3) } - // This is essentially now a check of len(labels + optional labels) vs labels provided... + floatHistoHandle1.Record(fmr, 4.3, []string{"some label value", "some optional label value"}...) + if got := fmr.floatValues[floatHistoHandle1.MetricDescriptor]; got != 4.3 { + t.Fatalf("fmr.floatValues[floatHistoHandle1.MetricDescriptor] got %v, want: %v", got, 4.3) + } + intGaugeHandle1.Record(fmr, 7, []string{"some label value", "some optional label value"}...) + if got := fmr.intValues[intGaugeHandle1.MetricDescriptor]; got != 7 { + t.Fatalf("fmr.intValues[intGaugeHandle1.MetricDescriptor] got %v, want: %v", got, 7) + } } -// Test 2 for each? 5 different maps...? - -// All the operations will get a handle with pointer above, make sure it can use to record... - -// Need a clear for testing... +// TestNumerousIntCounts tests numerous int count metrics registered onto the +// metric registry. A component (simulated by test) should be able to record on +// the different registered int count metrics. +func TestNumerousIntCounts(t *testing.T) { + cleanup := clearMetricsRegistryForTesting() + defer cleanup() + intCountHandle1 := RegisterInt64Count(MetricDescriptor{ + Name: "int counter", + Description: "sum of all emissions from tests", + Unit: "int", + Labels: []string{"int counter label"}, + OptionalLabels: []string{"int counter optional label"}, + Default: false, + }) + intCountHandle2 := RegisterInt64Count(MetricDescriptor{ + Name: "int counter 2", + Description: "sum of all emissions from tests", + Unit: "int", + Labels: []string{"int counter label"}, + OptionalLabels: []string{"int counter optional label"}, + Default: false, + }) + intCountHandle3 := RegisterInt64Count(MetricDescriptor{ + Name: "int counter 3", + Description: "sum of all emissions from tests", + Unit: "int", + Labels: []string{"int counter label"}, + OptionalLabels: []string{"int counter optional label"}, + Default: false, + }) + + fmr := newFakeMetricsRecorder(t) + + intCountHandle1.Record(fmr, 1, []string{"some label value", "some optional label value"}...) + got := []int64{fmr.intValues[intCountHandle1.MetricDescriptor], fmr.intValues[intCountHandle2.MetricDescriptor], fmr.intValues[intCountHandle3.MetricDescriptor]} + want := []int64{1, 0, 0} + if diff := cmp.Diff(got, want); diff != "" { + t.Fatalf("fmr.intValues (-got, +want): %v", diff) + } -// It still implements these methods but gets called from handle -func (r *fakeMetricsRecorder) RecordIntCount(handle Int64CountHandle, labels []Label, optionalLabels []Label, incr int64) { // Techncialy this owuld eat labels...verifyLabels too? - // Rather than reading from registry/building out data structures, labels come from handle - handle.MetricDescriptor.Labels // []string also makes sure not nil...MetricDescriptor + intCountHandle2.Record(fmr, 1, []string{"some label value", "some optional label value"}...) + got = []int64{fmr.intValues[intCountHandle1.MetricDescriptor], fmr.intValues[intCountHandle2.MetricDescriptor], fmr.intValues[intCountHandle3.MetricDescriptor]} + want = []int64{1, 1, 0} + if diff := cmp.Diff(got, want); diff != "" { + t.Fatalf("fmr.intValues (-got, +want): %v", diff) + } - handle.MetricDescriptor.OptionalLabels // []string + intCountHandle3.Record(fmr, 1, []string{"some label value", "some optional label value"}...) + got = []int64{fmr.intValues[intCountHandle1.MetricDescriptor], fmr.intValues[intCountHandle2.MetricDescriptor], fmr.intValues[intCountHandle3.MetricDescriptor]} + want = []int64{1, 1, 1} + if diff := cmp.Diff(got, want); diff != "" { + t.Fatalf("fmr.intValues (-got, +want): %v", diff) + } - verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels, optionalLabels) + intCountHandle3.Record(fmr, 1, []string{"some label value", "some optional label value"}...) + got = []int64{fmr.intValues[intCountHandle1.MetricDescriptor], fmr.intValues[intCountHandle2.MetricDescriptor], fmr.intValues[intCountHandle3.MetricDescriptor]} + want = []int64{1, 1, 2} + if diff := cmp.Diff(got, want); diff != "" { + t.Fatalf("fmr.intValues (-got, +want): %v", diff) + } +} - // Overall data structure of the stats handler... - // map[name]->local would create a string comp +type fakeMetricsRecorder struct { + t *testing.T - // map[*MetricDescriptor]->local would just be a pointer comp... + intValues map[*MetricDescriptor]int64 + floatValues map[*MetricDescriptor]float64 +} - // record incr against data structure built out maybe map[name]-> - // No it's a map of metricdescriptor... - // How to build this out? - r.intValues[handle.MetricDescriptor] += incr // have the handle in main use that to verify... +// newFakeMetricsRecorder returns a fake metrics recorder based off the current +// state of global metric registry. +func newFakeMetricsRecorder(t *testing.T) *fakeMetricsRecorder { + fmr := &fakeMetricsRecorder{ + t: t, + intValues: make(map[*MetricDescriptor]int64), + floatValues: make(map[*MetricDescriptor]float64), + } + for _, desc := range MetricsRegistry { + switch desc.Type { + case MetricTypeIntCount: + case MetricTypeIntHisto: + case MetricTypeIntGauge: + fmr.intValues[desc] = 0 + case MetricTypeFloatCount: + case MetricTypeFloatHisto: + fmr.floatValues[desc] = 0 + } + } + return fmr } -func (r *fakeMetricsRecorder) RecordFloatCount(handle Float64CountHandle, labels []Label, optionalLabels []Label, incr float64) { - verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels, optionalLabels) +// verifyLabels verifies that the labels received are of the expected length. +func verifyLabels(t *testing.T, labelsWant []string, optionalLabelsWant []string, labelsGot []string) { + if len(labelsWant)+len(optionalLabelsWant) != len(labelsGot) { + t.Fatalf("length of optional labels expected did not match got %v, want %v", len(labelsGot), len(labelsWant)+len(optionalLabelsWant)) + } +} - handle.MetricDescriptor // *MetricDescriptor - use as key to map if not found then fatalf +func (r *fakeMetricsRecorder) RecordIntCount(handle Int64CountHandle, incr int64, labels ...string) { + verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels) + r.intValues[handle.MetricDescriptor] += incr +} +func (r *fakeMetricsRecorder) RecordFloatCount(handle Float64CountHandle, incr float64, labels ...string) { + verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels) r.floatValues[handle.MetricDescriptor] += incr } -func (r *fakeMetricsRecorder) RecordIntHisto(handle Int64HistoHandle, labels []Label, optionalLabels []Label, incr int64) { - verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels, optionalLabels) - - handle.MetricDescriptor // *MetricDescriptor - use as key to map if not found then fatalf - - r.intValues[handle.MetricDescriptor] += incr // after 5 of these, makes sure they don't collide +func (r *fakeMetricsRecorder) RecordIntHisto(handle Int64HistoHandle, incr int64, labels ...string) { + verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels) + r.intValues[handle.MetricDescriptor] += incr } -func (r *fakeMetricsRecorder) RecordFloatHisto(handle Float64HistoHandle, labels []Label, optionalLabels []Label, incr float64) { - verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels, optionalLabels) - - handle.MetricDescriptor // *MetricDescriptor - use as key to map if not found then fatalf +func (r *fakeMetricsRecorder) RecordFloatHisto(handle Float64HistoHandle, incr float64, labels ...string) { + verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels) + r.floatValues[handle.MetricDescriptor] += incr } -func (r *fakeMetricsRecorder) RecordIntGauge(handle Int64GaugeHandle, labels []Label, optionalLabels []Label, incr int64) { - verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels, optionalLabels) - - handle.MetricDescriptor // *MetricDescriptor - use as key to map if not found then fatalf +func (r *fakeMetricsRecorder) RecordIntGauge(handle Int64GaugeHandle, incr int64, labels ...string) { + verifyLabels(r.t, handle.MetricDescriptor.Labels, handle.MetricDescriptor.OptionalLabels, labels) + r.intValues[handle.MetricDescriptor] += incr } - -// If run out of time just push implementation...otel and metrics recorder list still come after I guess... -// just push the extra file.... - - -// Tests sound good to Doug get this plumbing working... - -// switch the labels to be variadic args based on position, length check on labels + optional labels - -// optional labels are always plumbed up through otel, otel decides whether it -// wants the optional labels or not... - -// on handle and metrics recorder - - diff --git a/experimental/stats/stats.go b/experimental/stats/stats.go index cb4e2b851567..9cfd69dcf71e 100644 --- a/experimental/stats/stats.go +++ b/experimental/stats/stats.go @@ -19,7 +19,6 @@ // Package stats contains experimental metrics/stats API's. package stats - // MetricsRecorder records on metrics derived from instrument registry. type MetricsRecorder interface { // RecordIntCount records the measurement alongside labels on the int count