Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add embedded private method interfaces in metric API #3916

Merged
merged 23 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Added

- The `go.opentelemetry.io/otel/metric/embedded` package. (#3916)

### Changed

- Update all exported interfaces from `go.opentelemetry.io/otel/metric` to embed their corresponding interface from `go.opentelemetry.io/otel/metric/embedded`.
This adds an implementation requirement to set the interface default behavior for unimplemented methods. (#3916)

### Fixed

- `TracerProvider` allows calling `Tracer()` while it's shutting down.
Expand Down
19 changes: 19 additions & 0 deletions internal/global/instruments.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded"
"go.opentelemetry.io/otel/metric/instrument"
)

Expand All @@ -29,6 +30,7 @@ type unwrapper interface {
}

type afCounter struct {
embedded.Float64ObservableCounter
instrument.Float64Observable

name string
Expand Down Expand Up @@ -57,6 +59,7 @@ func (i *afCounter) Unwrap() instrument.Observable {
}

type afUpDownCounter struct {
embedded.Float64ObservableUpDownCounter
instrument.Float64Observable

name string
Expand Down Expand Up @@ -85,6 +88,7 @@ func (i *afUpDownCounter) Unwrap() instrument.Observable {
}

type afGauge struct {
embedded.Float64ObservableGauge
instrument.Float64Observable

name string
Expand Down Expand Up @@ -113,6 +117,7 @@ func (i *afGauge) Unwrap() instrument.Observable {
}

type aiCounter struct {
embedded.Int64ObservableCounter
instrument.Int64Observable

name string
Expand Down Expand Up @@ -141,6 +146,7 @@ func (i *aiCounter) Unwrap() instrument.Observable {
}

type aiUpDownCounter struct {
embedded.Int64ObservableUpDownCounter
instrument.Int64Observable

name string
Expand Down Expand Up @@ -169,6 +175,7 @@ func (i *aiUpDownCounter) Unwrap() instrument.Observable {
}

type aiGauge struct {
embedded.Int64ObservableGauge
instrument.Int64Observable

name string
Expand Down Expand Up @@ -198,6 +205,8 @@ func (i *aiGauge) Unwrap() instrument.Observable {

// Sync Instruments.
type sfCounter struct {
embedded.Float64Counter

name string
opts []instrument.Float64CounterOption

Expand All @@ -222,6 +231,8 @@ func (i *sfCounter) Add(ctx context.Context, incr float64, attrs ...attribute.Ke
}

type sfUpDownCounter struct {
embedded.Float64UpDownCounter

name string
opts []instrument.Float64UpDownCounterOption

Expand All @@ -246,6 +257,8 @@ func (i *sfUpDownCounter) Add(ctx context.Context, incr float64, attrs ...attrib
}

type sfHistogram struct {
embedded.Float64Histogram

name string
opts []instrument.Float64HistogramOption

Expand All @@ -270,6 +283,8 @@ func (i *sfHistogram) Record(ctx context.Context, x float64, attrs ...attribute.
}

type siCounter struct {
embedded.Int64Counter

name string
opts []instrument.Int64CounterOption

Expand All @@ -294,6 +309,8 @@ func (i *siCounter) Add(ctx context.Context, x int64, attrs ...attribute.KeyValu
}

type siUpDownCounter struct {
embedded.Int64UpDownCounter

name string
opts []instrument.Int64UpDownCounterOption

Expand All @@ -318,6 +335,8 @@ func (i *siUpDownCounter) Add(ctx context.Context, x int64, attrs ...attribute.K
}

type siHistogram struct {
embedded.Int64Histogram

name string
opts []instrument.Int64HistogramOption

Expand Down
13 changes: 13 additions & 0 deletions internal/global/instruments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded"
"go.opentelemetry.io/otel/metric/instrument"
)

Expand Down Expand Up @@ -145,6 +146,12 @@ type testCountingFloatInstrument struct {
count int

instrument.Float64Observable
embedded.Float64Counter
embedded.Float64UpDownCounter
embedded.Float64Histogram
embedded.Float64ObservableCounter
embedded.Float64ObservableUpDownCounter
embedded.Float64ObservableGauge
}

func (i *testCountingFloatInstrument) observe() {
Expand All @@ -161,6 +168,12 @@ type testCountingIntInstrument struct {
count int

instrument.Int64Observable
embedded.Int64Counter
embedded.Int64UpDownCounter
embedded.Int64Histogram
embedded.Int64ObservableCounter
embedded.Int64ObservableUpDownCounter
embedded.Int64ObservableGauge
}

func (i *testCountingIntInstrument) observe() {
Expand Down
7 changes: 7 additions & 0 deletions internal/global/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"sync/atomic"

"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded"
"go.opentelemetry.io/otel/metric/instrument"
)

Expand All @@ -28,6 +29,8 @@ import (
// All MeterProvider functionality is forwarded to a delegate once
// configured.
type meterProvider struct {
embedded.MeterProvider

mtx sync.Mutex
meters map[il]*meter

Expand Down Expand Up @@ -94,6 +97,8 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me
// All Meter functionality is forwarded to a delegate once configured.
// Otherwise, all functionality is forwarded to a NoopMeter.
type meter struct {
embedded.Meter

name string
opts []metric.MeterOption

Expand Down Expand Up @@ -308,6 +313,8 @@ func unwrapInstruments(instruments []instrument.Observable) []instrument.Observa
}

type registration struct {
embedded.Registration

instruments []instrument.Observable
function metric.Callback

Expand Down
11 changes: 10 additions & 1 deletion internal/global/meter_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ import (

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded"
"go.opentelemetry.io/otel/metric/instrument"
)

type testMeterProvider struct {
embedded.MeterProvider

count int
}

Expand All @@ -33,6 +36,8 @@ func (p *testMeterProvider) Meter(name string, opts ...metric.MeterOption) metri
}

type testMeter struct {
embedded.Meter

afCount int
afUDCount int
afGauge int
Expand Down Expand Up @@ -123,6 +128,8 @@ func (m *testMeter) RegisterCallback(f metric.Callback, i ...instrument.Observab
}

type testReg struct {
embedded.Registration

f func()
}

Expand All @@ -134,7 +141,7 @@ func (r testReg) Unregister() error {
// This enables async collection.
func (m *testMeter) collect() {
ctx := context.Background()
o := observationRecorder{ctx}
o := observationRecorder{ctx: ctx}
for _, f := range m.callbacks {
if f == nil {
// Unregister.
Expand All @@ -145,6 +152,8 @@ func (m *testMeter) collect() {
}

type observationRecorder struct {
embedded.Observer

ctx context.Context
}

Expand Down
53 changes: 53 additions & 0 deletions metric/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,59 @@ can then be built from the [Meter]'s instruments. See
[go.opentelemetry.io/otel/metric/instrument] for documentation on each
instrument and its intended use.

# API Implementations

This package does not conform to the standard Go versioning policy, all of its
interfaces may have methods added to them without a package major version bump.
So an implementation author is not surprised by this fact, the API is designed
to require a default behavior be defined for unimplemented interface methods.
There are three behavior choices:

- Compilation failure
- Panic
- Default to another implementation

All interfaces in this API embed a corresponding interface from
[go.opentelemetry.io/otel/metric/embedded]. If an author wants the default
behavior of their implementations to be a compilation failure, signaling to
their users they need to update to the latest version of that implementation,
they need to embed the corresponding interface from
[go.opentelemetry.io/otel/metric/embedded] in their implementation. For
example,

import "go.opentelemetry.io/otel/metric/embedded"

type MeterProvider struct {
embedded.MeterProvider
// ...
}

If an author wants the default behavior of their implementations to a panic,
they need to embed the API interface directly.

import "go.opentelemetry.io/otel/metric"

type MeterProvider struct {
metric.MeterProvider
// ...
}

This is not a recommended behavior as it could lead to publishing packages that
contain runtime panics when users update other package that use newer versions
of [go.opentelemetry.io/otel/metric].

Finally, an author can embed another implementation in theirs. The embedded
implementation will be used for methods not defined by the author. For example,
an author who want to default to silently dropping the call can use
[go.opentelemetry.io/otel/metric/noop]:

import "go.opentelemetry.io/otel/metric/noop"

type MeterProvider struct {
noop.MeterProvider
// ...
}

[GetMeterProvider]: https://pkg.go.dev/go.opentelemetry.io/otel#GetMeterProvider
*/
package metric // import "go.opentelemetry.io/otel/metric"
Loading