From 04bc9e6e8917d198617a9264384a348b36490db5 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 27 Mar 2023 11:24:50 -0700 Subject: [PATCH 1/6] Revert "Revert "Move metric No-Op to metric/noop (#3893)" (#3921)" This reverts commit 795ad971191b0bd7ff0d376a19b00e2e20f3b4b7. --- CHANGELOG.md | 5 + internal/global/instruments_test.go | 5 +- internal/global/meter_test.go | 7 +- internal/global/state_test.go | 5 +- metric/noop.go | 134 --------------- metric/{ => noop}/example_test.go | 2 +- metric/noop/noop.go | 246 ++++++++++++++++++++++++++++ metric/noop/noop_test.go | 184 +++++++++++++++++++++ metric/noop_test.go | 74 --------- metric_test.go | 5 +- 10 files changed, 449 insertions(+), 218 deletions(-) delete mode 100644 metric/noop.go rename metric/{ => noop}/example_test.go (99%) create mode 100644 metric/noop/noop.go create mode 100644 metric/noop/noop_test.go delete mode 100644 metric/noop_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 514dbd447ad..c87d407d829 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +### Changed + +- Move No-Op implementation from `go.opentelemetry.io/otel/metric` into its own package `go.opentelemetry.io/otel/metric/noop`. (#TBD) + - `NewNoopMeterProvider` is replaced with `noop.NewMeterProvider` + ## [1.15.0-rc.2/0.38.0-rc.2] 2023-03-23 This is a release candidate for the v1.15.0/v0.38.0 release. diff --git a/internal/global/instruments_test.go b/internal/global/instruments_test.go index 4bbf23e0afc..66fe8499cf0 100644 --- a/internal/global/instruments_test.go +++ b/internal/global/instruments_test.go @@ -21,6 +21,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/instrument" + "go.opentelemetry.io/otel/metric/noop" ) func testFloat64Race(interact func(context.Context, float64, ...attribute.KeyValue), setDelegate func(metric.Meter)) { @@ -36,7 +37,7 @@ func testFloat64Race(interact func(context.Context, float64, ...attribute.KeyVal } }() - setDelegate(metric.NewNoopMeterProvider().Meter("")) + setDelegate(noop.NewMeterProvider().Meter("")) close(finish) } @@ -53,7 +54,7 @@ func testInt64Race(interact func(context.Context, int64, ...attribute.KeyValue), } }() - setDelegate(metric.NewNoopMeterProvider().Meter("")) + setDelegate(noop.NewMeterProvider().Meter("")) close(finish) } diff --git a/internal/global/meter_test.go b/internal/global/meter_test.go index b7b1ea9d8af..8a9341ab46e 100644 --- a/internal/global/meter_test.go +++ b/internal/global/meter_test.go @@ -25,6 +25,7 @@ import ( "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/instrument" + "go.opentelemetry.io/otel/metric/noop" ) func TestMeterProviderRace(t *testing.T) { @@ -41,7 +42,7 @@ func TestMeterProviderRace(t *testing.T) { } }() - mp.setDelegate(metric.NewNoopMeterProvider()) + mp.setDelegate(noop.NewMeterProvider()) close(finish) } @@ -84,7 +85,7 @@ func TestMeterRace(t *testing.T) { }() wg.Wait() - mtr.setDelegate(metric.NewNoopMeterProvider()) + mtr.setDelegate(noop.NewMeterProvider()) close(finish) } @@ -113,7 +114,7 @@ func TestUnregisterRace(t *testing.T) { _ = reg.Unregister() wg.Wait() - mtr.setDelegate(metric.NewNoopMeterProvider()) + mtr.setDelegate(noop.NewMeterProvider()) close(finish) } diff --git a/internal/global/state_test.go b/internal/global/state_test.go index 1b441660cf5..93bf6b8aae2 100644 --- a/internal/global/state_test.go +++ b/internal/global/state_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" ) @@ -152,7 +153,7 @@ func TestSetMeterProvider(t *testing.T) { t.Run("First Set() should replace the delegate", func(t *testing.T) { ResetForTest(t) - SetMeterProvider(metric.NewNoopMeterProvider()) + SetMeterProvider(noop.NewMeterProvider()) _, ok := MeterProvider().(*meterProvider) if ok { @@ -165,7 +166,7 @@ func TestSetMeterProvider(t *testing.T) { mp := MeterProvider() - SetMeterProvider(metric.NewNoopMeterProvider()) + SetMeterProvider(noop.NewMeterProvider()) dmp := mp.(*meterProvider) diff --git a/metric/noop.go b/metric/noop.go deleted file mode 100644 index 5d1b9d072f5..00000000000 --- a/metric/noop.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright The OpenTelemetry 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 metric // import "go.opentelemetry.io/otel/metric" - -import ( - "context" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" -) - -// NewNoopMeterProvider creates a MeterProvider that does not record any metrics. -func NewNoopMeterProvider() MeterProvider { - return noopMeterProvider{} -} - -type noopMeterProvider struct{} - -func (noopMeterProvider) Meter(string, ...MeterOption) Meter { - return noopMeter{} -} - -type noopMeter struct{} - -func (noopMeter) Int64Counter(string, ...instrument.Int64CounterOption) (instrument.Int64Counter, error) { - return nonrecordingSyncInt64Instrument{}, nil -} - -func (noopMeter) Int64UpDownCounter(string, ...instrument.Int64UpDownCounterOption) (instrument.Int64UpDownCounter, error) { - return nonrecordingSyncInt64Instrument{}, nil -} - -func (noopMeter) Int64Histogram(string, ...instrument.Int64HistogramOption) (instrument.Int64Histogram, error) { - return nonrecordingSyncInt64Instrument{}, nil -} - -func (noopMeter) Int64ObservableCounter(string, ...instrument.Int64ObservableCounterOption) (instrument.Int64ObservableCounter, error) { - return nonrecordingAsyncInt64Instrument{}, nil -} - -func (noopMeter) Int64ObservableUpDownCounter(string, ...instrument.Int64ObservableUpDownCounterOption) (instrument.Int64ObservableUpDownCounter, error) { - return nonrecordingAsyncInt64Instrument{}, nil -} - -func (noopMeter) Int64ObservableGauge(string, ...instrument.Int64ObservableGaugeOption) (instrument.Int64ObservableGauge, error) { - return nonrecordingAsyncInt64Instrument{}, nil -} - -func (noopMeter) Float64Counter(string, ...instrument.Float64CounterOption) (instrument.Float64Counter, error) { - return nonrecordingSyncFloat64Instrument{}, nil -} - -func (noopMeter) Float64UpDownCounter(string, ...instrument.Float64UpDownCounterOption) (instrument.Float64UpDownCounter, error) { - return nonrecordingSyncFloat64Instrument{}, nil -} - -func (noopMeter) Float64Histogram(string, ...instrument.Float64HistogramOption) (instrument.Float64Histogram, error) { - return nonrecordingSyncFloat64Instrument{}, nil -} - -func (noopMeter) Float64ObservableCounter(string, ...instrument.Float64ObservableCounterOption) (instrument.Float64ObservableCounter, error) { - return nonrecordingAsyncFloat64Instrument{}, nil -} - -func (noopMeter) Float64ObservableUpDownCounter(string, ...instrument.Float64ObservableUpDownCounterOption) (instrument.Float64ObservableUpDownCounter, error) { - return nonrecordingAsyncFloat64Instrument{}, nil -} - -func (noopMeter) Float64ObservableGauge(string, ...instrument.Float64ObservableGaugeOption) (instrument.Float64ObservableGauge, error) { - return nonrecordingAsyncFloat64Instrument{}, nil -} - -// RegisterCallback creates a register callback that does not record any metrics. -func (noopMeter) RegisterCallback(Callback, ...instrument.Observable) (Registration, error) { - return noopReg{}, nil -} - -type noopReg struct{} - -func (noopReg) Unregister() error { return nil } - -type nonrecordingAsyncFloat64Instrument struct { - instrument.Float64Observable -} - -var ( - _ instrument.Float64ObservableCounter = nonrecordingAsyncFloat64Instrument{} - _ instrument.Float64ObservableUpDownCounter = nonrecordingAsyncFloat64Instrument{} - _ instrument.Float64ObservableGauge = nonrecordingAsyncFloat64Instrument{} -) - -type nonrecordingAsyncInt64Instrument struct { - instrument.Int64Observable -} - -var ( - _ instrument.Int64ObservableCounter = nonrecordingAsyncInt64Instrument{} - _ instrument.Int64ObservableUpDownCounter = nonrecordingAsyncInt64Instrument{} - _ instrument.Int64ObservableGauge = nonrecordingAsyncInt64Instrument{} -) - -type nonrecordingSyncFloat64Instrument struct{} - -var ( - _ instrument.Float64Counter = nonrecordingSyncFloat64Instrument{} - _ instrument.Float64UpDownCounter = nonrecordingSyncFloat64Instrument{} - _ instrument.Float64Histogram = nonrecordingSyncFloat64Instrument{} -) - -func (nonrecordingSyncFloat64Instrument) Add(context.Context, float64, ...attribute.KeyValue) {} -func (nonrecordingSyncFloat64Instrument) Record(context.Context, float64, ...attribute.KeyValue) {} - -type nonrecordingSyncInt64Instrument struct{} - -var ( - _ instrument.Int64Counter = nonrecordingSyncInt64Instrument{} - _ instrument.Int64UpDownCounter = nonrecordingSyncInt64Instrument{} - _ instrument.Int64Histogram = nonrecordingSyncInt64Instrument{} -) - -func (nonrecordingSyncInt64Instrument) Add(context.Context, int64, ...attribute.KeyValue) {} -func (nonrecordingSyncInt64Instrument) Record(context.Context, int64, ...attribute.KeyValue) {} diff --git a/metric/example_test.go b/metric/noop/example_test.go similarity index 99% rename from metric/example_test.go rename to metric/noop/example_test.go index c909410e9e4..8cd3ac91ebd 100644 --- a/metric/example_test.go +++ b/metric/noop/example_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package metric_test +package noop_test import ( "context" diff --git a/metric/noop/noop.go b/metric/noop/noop.go new file mode 100644 index 00000000000..ce35983aaf8 --- /dev/null +++ b/metric/noop/noop.go @@ -0,0 +1,246 @@ +// Copyright The OpenTelemetry 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 noop provides an implementation of the OpenTelemetry API that +// produces no telemetry and minimizes used computation resources. +// +// The API implementation can be used to effectively disable OpenTelemetry. It +// can also be used as the embedded structs of other OpenTelemetry +// implementations. These alternate implementation that embed this noop +// implementation will default to no-action instead of panicking when methods +// are added to the OpenTelemetry API interfaces. +package noop // import "go.opentelemetry.io/otel/metric/noop" + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/instrument" +) + +var ( + // Compile-time check this implements the OpenTelemetry API. + + _ metric.MeterProvider = MeterProvider{} + _ metric.Meter = Meter{} + _ metric.Observer = Observer{} + _ metric.Registration = Registration{} + _ instrument.Int64Counter = Int64Counter{} + _ instrument.Float64Counter = Float64Counter{} + _ instrument.Int64UpDownCounter = Int64UpDownCounter{} + _ instrument.Float64UpDownCounter = Float64UpDownCounter{} + _ instrument.Int64Histogram = Int64Histogram{} + _ instrument.Float64Histogram = Float64Histogram{} + _ instrument.Int64ObservableCounter = Int64ObservableCounter{} + _ instrument.Float64ObservableCounter = Float64ObservableCounter{} + _ instrument.Int64ObservableGauge = Int64ObservableGauge{} + _ instrument.Float64ObservableGauge = Float64ObservableGauge{} + _ instrument.Int64ObservableUpDownCounter = Int64ObservableUpDownCounter{} + _ instrument.Float64ObservableUpDownCounter = Float64ObservableUpDownCounter{} + _ instrument.Int64Observer = Int64Observer{} + _ instrument.Float64Observer = Float64Observer{} +) + +// MeterProvider is an OpenTelemetry No-Op MeterProvider. +type MeterProvider struct{} + +// NewMeterProvider returns a MeterProvider that does not record any telemetry. +func NewMeterProvider() MeterProvider { + return MeterProvider{} +} + +// Meter returns an OpenTelemetry Meter that does not record any telemetry. +func (MeterProvider) Meter(string, ...metric.MeterOption) metric.Meter { + return Meter{} +} + +// Meter is an OpenTelemetry No-Op Meter. +type Meter struct{} + +// Int64Counter returns a Counter used to record int64 measurements that +// produces no telemetry. +func (Meter) Int64Counter(string, ...instrument.Int64CounterOption) (instrument.Int64Counter, error) { + return Int64Counter{}, nil +} + +// Int64UpDownCounter returns an UpDownCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64UpDownCounter(string, ...instrument.Int64UpDownCounterOption) (instrument.Int64UpDownCounter, error) { + return Int64UpDownCounter{}, nil +} + +// Int64Histogram returns a Histogram used to record int64 measurements that +// produces no telemetry. +func (Meter) Int64Histogram(string, ...instrument.Int64HistogramOption) (instrument.Int64Histogram, error) { + return Int64Histogram{}, nil +} + +// Int64ObservableCounter returns an ObservableCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64ObservableCounter(string, ...instrument.Int64ObservableCounterOption) (instrument.Int64ObservableCounter, error) { + return Int64ObservableCounter{}, nil +} + +// Int64ObservableUpDownCounter returns an ObservableUpDownCounter used to +// record int64 measurements that produces no telemetry. +func (Meter) Int64ObservableUpDownCounter(string, ...instrument.Int64ObservableUpDownCounterOption) (instrument.Int64ObservableUpDownCounter, error) { + return Int64ObservableUpDownCounter{}, nil +} + +// Int64ObservableGauge returns an ObservableGauge used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64ObservableGauge(string, ...instrument.Int64ObservableGaugeOption) (instrument.Int64ObservableGauge, error) { + return Int64ObservableGauge{}, nil +} + +// Float64Counter returns a Counter used to record int64 measurements that +// produces no telemetry. +func (Meter) Float64Counter(string, ...instrument.Float64CounterOption) (instrument.Float64Counter, error) { + return Float64Counter{}, nil +} + +// Float64UpDownCounter returns an UpDownCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64UpDownCounter(string, ...instrument.Float64UpDownCounterOption) (instrument.Float64UpDownCounter, error) { + return Float64UpDownCounter{}, nil +} + +// Float64Histogram returns a Histogram used to record int64 measurements that +// produces no telemetry. +func (Meter) Float64Histogram(string, ...instrument.Float64HistogramOption) (instrument.Float64Histogram, error) { + return Float64Histogram{}, nil +} + +// Float64ObservableCounter returns an ObservableCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64ObservableCounter(string, ...instrument.Float64ObservableCounterOption) (instrument.Float64ObservableCounter, error) { + return Float64ObservableCounter{}, nil +} + +// Float64ObservableUpDownCounter returns an ObservableUpDownCounter used to +// record int64 measurements that produces no telemetry. +func (Meter) Float64ObservableUpDownCounter(string, ...instrument.Float64ObservableUpDownCounterOption) (instrument.Float64ObservableUpDownCounter, error) { + return Float64ObservableUpDownCounter{}, nil +} + +// Float64ObservableGauge returns an ObservableGauge used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64ObservableGauge(string, ...instrument.Float64ObservableGaugeOption) (instrument.Float64ObservableGauge, error) { + return Float64ObservableGauge{}, nil +} + +// RegisterCallback performs no operation. +func (Meter) RegisterCallback(metric.Callback, ...instrument.Observable) (metric.Registration, error) { + return Registration{}, nil +} + +// Observer acts as a recorder of measurements for multiple instruments in a +// Callback, it performing no operation. +type Observer struct{} + +// ObserveFloat64 performs no operation. +func (Observer) ObserveFloat64(instrument.Float64Observable, float64, ...attribute.KeyValue) { +} + +// ObserveInt64 performs no operation. +func (Observer) ObserveInt64(instrument.Int64Observable, int64, ...attribute.KeyValue) { +} + +// Registration is the registration of a Callback with a No-Op Meter. +type Registration struct{} + +// Unregister unregisters the Callback the Registration represents with the +// No-Op Meter. This will always return nil because the No-Op Meter performs no +// operation, including hold any record of registrations. +func (Registration) Unregister() error { return nil } + +// Int64Counter is an OpenTelemetry Counter used to record int64 measurements. +// It produces no telemetry. +type Int64Counter struct{} + +// Add performs no operation. +func (Int64Counter) Add(context.Context, int64, ...attribute.KeyValue) {} + +// Float64Counter is an OpenTelemetry Counter used to record float64 +// measurements. It produces no telemetry. +type Float64Counter struct{} + +// Add performs no operation. +func (Float64Counter) Add(context.Context, float64, ...attribute.KeyValue) {} + +// Int64UpDownCounter is an OpenTelemetry UpDownCounter used to record int64 +// measurements. It produces no telemetry. +type Int64UpDownCounter struct{} + +// Add performs no operation. +func (Int64UpDownCounter) Add(context.Context, int64, ...attribute.KeyValue) {} + +// Float64UpDownCounter is an OpenTelemetry UpDownCounter used to record +// float64 measurements. It produces no telemetry. +type Float64UpDownCounter struct{} + +// Add performs no operation. +func (Float64UpDownCounter) Add(context.Context, float64, ...attribute.KeyValue) {} + +// Int64Histogram is an OpenTelemetry Histogram used to record int64 +// measurements. It produces no telemetry. +type Int64Histogram struct{} + +// Record performs no operation. +func (Int64Histogram) Record(context.Context, int64, ...attribute.KeyValue) {} + +// Float64Histogram is an OpenTelemetry Histogram used to record float64 +// measurements. It produces no telemetry. +type Float64Histogram struct{} + +// Record performs no operation. +func (Float64Histogram) Record(context.Context, float64, ...attribute.KeyValue) {} + +// Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record +// int64 measurements. It produces no telemetry. +type Int64ObservableCounter struct{ instrument.Int64Observable } + +// Float64ObservableCounter is an OpenTelemetry ObservableCounter used to record +// float64 measurements. It produces no telemetry. +type Float64ObservableCounter struct{ instrument.Float64Observable } + +// Int64ObservableGauge is an OpenTelemetry ObservableGauge used to record +// int64 measurements. It produces no telemetry. +type Int64ObservableGauge struct{ instrument.Int64Observable } + +// Float64ObservableGauge is an OpenTelemetry ObservableGauge used to record +// float64 measurements. It produces no telemetry. +type Float64ObservableGauge struct{ instrument.Float64Observable } + +// Int64ObservableUpDownCounter is an OpenTelemetry ObservableUpDownCounter +// used to record int64 measurements. It produces no telemetry. +type Int64ObservableUpDownCounter struct{ instrument.Int64Observable } + +// Float64ObservableUpDownCounter is an OpenTelemetry ObservableUpDownCounter +// used to record float64 measurements. It produces no telemetry. +type Float64ObservableUpDownCounter struct{ instrument.Float64Observable } + +// Int64Observer is a recorder of int64 measurements that performs no operation. +type Int64Observer struct{} + +// Observe performs no operation. +func (Int64Observer) Observe(int64, ...attribute.KeyValue) {} + +// Float64Observer is a recorder of float64 measurements that performs no +// operation. +type Float64Observer struct{} + +// Observe performs no operation. +func (Float64Observer) Observe(float64, ...attribute.KeyValue) {} diff --git a/metric/noop/noop_test.go b/metric/noop/noop_test.go new file mode 100644 index 00000000000..412ee6d957e --- /dev/null +++ b/metric/noop/noop_test.go @@ -0,0 +1,184 @@ +// Copyright The OpenTelemetry 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 noop // import "go.opentelemetry.io/otel/metric/noop" + +import ( + "context" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/instrument" +) + +func TestImplementationNoPanics(t *testing.T) { + // Check that if type has an embedded interface and that interface has + // methods added to it than the No-Op implementation implements them. + t.Run("MeterProvider", assertAllExportedMethodNoPanic( + reflect.ValueOf(MeterProvider{}), + reflect.TypeOf((*metric.MeterProvider)(nil)).Elem(), + )) + t.Run("Meter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Meter{}), + reflect.TypeOf((*metric.Meter)(nil)).Elem(), + )) + t.Run("Observer", assertAllExportedMethodNoPanic( + reflect.ValueOf(Observer{}), + reflect.TypeOf((*metric.Observer)(nil)).Elem(), + )) + t.Run("Registration", assertAllExportedMethodNoPanic( + reflect.ValueOf(Registration{}), + reflect.TypeOf((*metric.Registration)(nil)).Elem(), + )) + t.Run("Int64Counter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Int64Counter{}), + reflect.TypeOf((*instrument.Int64Counter)(nil)).Elem(), + )) + t.Run("Float64Counter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Float64Counter{}), + reflect.TypeOf((*instrument.Float64Counter)(nil)).Elem(), + )) + t.Run("Int64UpDownCounter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Int64UpDownCounter{}), + reflect.TypeOf((*instrument.Int64UpDownCounter)(nil)).Elem(), + )) + t.Run("Float64UpDownCounter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Float64UpDownCounter{}), + reflect.TypeOf((*instrument.Float64UpDownCounter)(nil)).Elem(), + )) + t.Run("Int64Histogram", assertAllExportedMethodNoPanic( + reflect.ValueOf(Int64Histogram{}), + reflect.TypeOf((*instrument.Int64Histogram)(nil)).Elem(), + )) + t.Run("Float64Histogram", assertAllExportedMethodNoPanic( + reflect.ValueOf(Float64Histogram{}), + reflect.TypeOf((*instrument.Float64Histogram)(nil)).Elem(), + )) + t.Run("Int64ObservableCounter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Int64ObservableCounter{}), + reflect.TypeOf((*instrument.Int64ObservableCounter)(nil)).Elem(), + )) + t.Run("Float64ObservableCounter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Float64ObservableCounter{}), + reflect.TypeOf((*instrument.Float64ObservableCounter)(nil)).Elem(), + )) + t.Run("Int64ObservableGauge", assertAllExportedMethodNoPanic( + reflect.ValueOf(Int64ObservableGauge{}), + reflect.TypeOf((*instrument.Int64ObservableGauge)(nil)).Elem(), + )) + t.Run("Float64ObservableGauge", assertAllExportedMethodNoPanic( + reflect.ValueOf(Float64ObservableGauge{}), + reflect.TypeOf((*instrument.Float64ObservableGauge)(nil)).Elem(), + )) + t.Run("Int64ObservableUpDownCounter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Int64ObservableUpDownCounter{}), + reflect.TypeOf((*instrument.Int64ObservableUpDownCounter)(nil)).Elem(), + )) + t.Run("Float64ObservableUpDownCounter", assertAllExportedMethodNoPanic( + reflect.ValueOf(Float64ObservableUpDownCounter{}), + reflect.TypeOf((*instrument.Float64ObservableUpDownCounter)(nil)).Elem(), + )) + t.Run("Int64Observer", assertAllExportedMethodNoPanic( + reflect.ValueOf(Int64Observer{}), + reflect.TypeOf((*instrument.Int64Observer)(nil)).Elem(), + )) + t.Run("Float64Observer", assertAllExportedMethodNoPanic( + reflect.ValueOf(Float64Observer{}), + reflect.TypeOf((*instrument.Float64Observer)(nil)).Elem(), + )) +} + +func assertAllExportedMethodNoPanic(rVal reflect.Value, rType reflect.Type) func(*testing.T) { + return func(t *testing.T) { + for n := 0; n < rType.NumMethod(); n++ { + mType := rType.Method(n) + if !mType.IsExported() { + t.Logf("ignoring unexported %s", mType.Name) + continue + } + m := rVal.MethodByName(mType.Name) + if !m.IsValid() { + t.Errorf("unknown method for %s: %s", rVal.Type().Name(), mType.Name) + } + + numIn := mType.Type.NumIn() + if mType.Type.IsVariadic() { + numIn-- + } + args := make([]reflect.Value, numIn) + for i := range args { + aType := mType.Type.In(i) + args[i] = reflect.New(aType).Elem() + } + + assert.NotPanicsf(t, func() { + _ = m.Call(args) + }, "%s.%s", rVal.Type().Name(), mType.Name) + } + } +} + +func TestNewMeterProvider(t *testing.T) { + mp := NewMeterProvider() + assert.Equal(t, mp, MeterProvider{}) + meter := mp.Meter("") + assert.Equal(t, meter, Meter{}) +} + +func TestSyncFloat64(t *testing.T) { + meter := NewMeterProvider().Meter("test instrumentation") + assert.NotPanics(t, func() { + inst, err := meter.Float64Counter("test instrument") + require.NoError(t, err) + inst.Add(context.Background(), 1.0, attribute.String("key", "value")) + }) + + assert.NotPanics(t, func() { + inst, err := meter.Float64UpDownCounter("test instrument") + require.NoError(t, err) + inst.Add(context.Background(), -1.0, attribute.String("key", "value")) + }) + + assert.NotPanics(t, func() { + inst, err := meter.Float64Histogram("test instrument") + require.NoError(t, err) + inst.Record(context.Background(), 1.0, attribute.String("key", "value")) + }) +} + +func TestSyncInt64(t *testing.T) { + meter := NewMeterProvider().Meter("test instrumentation") + assert.NotPanics(t, func() { + inst, err := meter.Int64Counter("test instrument") + require.NoError(t, err) + inst.Add(context.Background(), 1, attribute.String("key", "value")) + }) + + assert.NotPanics(t, func() { + inst, err := meter.Int64UpDownCounter("test instrument") + require.NoError(t, err) + inst.Add(context.Background(), -1, attribute.String("key", "value")) + }) + + assert.NotPanics(t, func() { + inst, err := meter.Int64Histogram("test instrument") + require.NoError(t, err) + inst.Record(context.Background(), 1, attribute.String("key", "value")) + }) +} diff --git a/metric/noop_test.go b/metric/noop_test.go deleted file mode 100644 index 59695ccd5bc..00000000000 --- a/metric/noop_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright The OpenTelemetry 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 metric - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" -) - -func TestNewNoopMeterProvider(t *testing.T) { - mp := NewNoopMeterProvider() - assert.Equal(t, mp, noopMeterProvider{}) - meter := mp.Meter("") - assert.Equal(t, meter, noopMeter{}) -} - -func TestSyncFloat64(t *testing.T) { - meter := NewNoopMeterProvider().Meter("test instrumentation") - assert.NotPanics(t, func() { - inst, err := meter.Float64Counter("test instrument") - require.NoError(t, err) - inst.Add(context.Background(), 1.0, attribute.String("key", "value")) - }) - - assert.NotPanics(t, func() { - inst, err := meter.Float64UpDownCounter("test instrument") - require.NoError(t, err) - inst.Add(context.Background(), -1.0, attribute.String("key", "value")) - }) - - assert.NotPanics(t, func() { - inst, err := meter.Float64Histogram("test instrument") - require.NoError(t, err) - inst.Record(context.Background(), 1.0, attribute.String("key", "value")) - }) -} - -func TestSyncInt64(t *testing.T) { - meter := NewNoopMeterProvider().Meter("test instrumentation") - assert.NotPanics(t, func() { - inst, err := meter.Int64Counter("test instrument") - require.NoError(t, err) - inst.Add(context.Background(), 1, attribute.String("key", "value")) - }) - - assert.NotPanics(t, func() { - inst, err := meter.Int64UpDownCounter("test instrument") - require.NoError(t, err) - inst.Add(context.Background(), -1, attribute.String("key", "value")) - }) - - assert.NotPanics(t, func() { - inst, err := meter.Int64Histogram("test instrument") - require.NoError(t, err) - inst.Record(context.Background(), 1, attribute.String("key", "value")) - }) -} diff --git a/metric_test.go b/metric_test.go index 646bb108368..cc6f72d76f0 100644 --- a/metric_test.go +++ b/metric_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/noop" ) type testMeterProvider struct{} @@ -27,12 +28,12 @@ type testMeterProvider struct{} var _ metric.MeterProvider = &testMeterProvider{} func (*testMeterProvider) Meter(_ string, _ ...metric.MeterOption) metric.Meter { - return metric.NewNoopMeterProvider().Meter("") + return noop.NewMeterProvider().Meter("") } func TestMultipleGlobalMeterProvider(t *testing.T) { p1 := testMeterProvider{} - p2 := metric.NewNoopMeterProvider() + p2 := noop.NewMeterProvider() SetMeterProvider(&p1) SetMeterProvider(p2) From 43e9e9b39cfd8edee3d59f7f0b527cc046a881f4 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 27 Mar 2023 11:27:56 -0700 Subject: [PATCH 2/6] Add PR number --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c87d407d829..81db1749787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Changed -- Move No-Op implementation from `go.opentelemetry.io/otel/metric` into its own package `go.opentelemetry.io/otel/metric/noop`. (#TBD) +- Move No-Op implementation from `go.opentelemetry.io/otel/metric` into its own package `go.opentelemetry.io/otel/metric/noop`. (#3941) - `NewNoopMeterProvider` is replaced with `noop.NewMeterProvider` ## [1.15.0-rc.2/0.38.0-rc.2] 2023-03-23 From 825c053aff74432a9ca337dbfd001cba043e2163 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 27 Mar 2023 11:31:53 -0700 Subject: [PATCH 3/6] Move example_test back to `otel/metric` --- metric/{noop => }/example_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename metric/{noop => }/example_test.go (99%) diff --git a/metric/noop/example_test.go b/metric/example_test.go similarity index 99% rename from metric/noop/example_test.go rename to metric/example_test.go index 8cd3ac91ebd..c909410e9e4 100644 --- a/metric/noop/example_test.go +++ b/metric/example_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package noop_test +package metric_test import ( "context" From 54f1fd01a0011fb161c291f1099d20206b11cf65 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 27 Mar 2023 11:32:27 -0700 Subject: [PATCH 4/6] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Robert PajÄ…k --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81db1749787..ad9a40d90ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Changed - Move No-Op implementation from `go.opentelemetry.io/otel/metric` into its own package `go.opentelemetry.io/otel/metric/noop`. (#3941) - - `NewNoopMeterProvider` is replaced with `noop.NewMeterProvider` + - `metric.NewNoopMeterProvider` is replaced with `noop.NewMeterProvider` ## [1.15.0-rc.2/0.38.0-rc.2] 2023-03-23 From 3d27353eaa5100a1da14aa4f4d3a9d659255db18 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 27 Mar 2023 12:53:38 -0700 Subject: [PATCH 5/6] Remove redundant panic tests --- metric/noop/noop_test.go | 45 ---------------------------------------- 1 file changed, 45 deletions(-) diff --git a/metric/noop/noop_test.go b/metric/noop/noop_test.go index 412ee6d957e..6ddf50e6214 100644 --- a/metric/noop/noop_test.go +++ b/metric/noop/noop_test.go @@ -15,14 +15,11 @@ package noop // import "go.opentelemetry.io/otel/metric/noop" import ( - "context" "reflect" "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/instrument" ) @@ -140,45 +137,3 @@ func TestNewMeterProvider(t *testing.T) { meter := mp.Meter("") assert.Equal(t, meter, Meter{}) } - -func TestSyncFloat64(t *testing.T) { - meter := NewMeterProvider().Meter("test instrumentation") - assert.NotPanics(t, func() { - inst, err := meter.Float64Counter("test instrument") - require.NoError(t, err) - inst.Add(context.Background(), 1.0, attribute.String("key", "value")) - }) - - assert.NotPanics(t, func() { - inst, err := meter.Float64UpDownCounter("test instrument") - require.NoError(t, err) - inst.Add(context.Background(), -1.0, attribute.String("key", "value")) - }) - - assert.NotPanics(t, func() { - inst, err := meter.Float64Histogram("test instrument") - require.NoError(t, err) - inst.Record(context.Background(), 1.0, attribute.String("key", "value")) - }) -} - -func TestSyncInt64(t *testing.T) { - meter := NewMeterProvider().Meter("test instrumentation") - assert.NotPanics(t, func() { - inst, err := meter.Int64Counter("test instrument") - require.NoError(t, err) - inst.Add(context.Background(), 1, attribute.String("key", "value")) - }) - - assert.NotPanics(t, func() { - inst, err := meter.Int64UpDownCounter("test instrument") - require.NoError(t, err) - inst.Add(context.Background(), -1, attribute.String("key", "value")) - }) - - assert.NotPanics(t, func() { - inst, err := meter.Int64Histogram("test instrument") - require.NoError(t, err) - inst.Record(context.Background(), 1, attribute.String("key", "value")) - }) -} From 3887ef631f63d85774a5d087674130f683cdde3e Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 27 Mar 2023 12:57:07 -0700 Subject: [PATCH 6/6] Update noop pkg docs --- metric/noop/noop.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/metric/noop/noop.go b/metric/noop/noop.go index ce35983aaf8..0b2905da629 100644 --- a/metric/noop/noop.go +++ b/metric/noop/noop.go @@ -12,14 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package noop provides an implementation of the OpenTelemetry API that +// Package noop provides an implementation of the OpenTelemetry metric API that // produces no telemetry and minimizes used computation resources. // -// The API implementation can be used to effectively disable OpenTelemetry. It -// can also be used as the embedded structs of other OpenTelemetry -// implementations. These alternate implementation that embed this noop -// implementation will default to no-action instead of panicking when methods -// are added to the OpenTelemetry API interfaces. +// Using this package to implement the OpenTelemetry metric API will +// effectively disable OpenTelemetry. +// +// This implementation can be embedded in other implementations of the +// OpenTelemetry metric API. Doing so will mean the implementation defaults to +// no operation for methods it does not implement. package noop // import "go.opentelemetry.io/otel/metric/noop" import (