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 the synchronous gauge to the metric API and SDK #5304

Merged
merged 20 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Add `RecordFactory` in `go.opentelemetry.io/otel/log/logtest` to facilitate testing the bridge implementations. (#5263)
- Add `RecordFactory` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing the exporter and processor implementations. (#5258)
- Add example for `go.opentelemetry.io/otel/exporters/stdout/stdoutlog`. (#5242)
- Add the synchronous gauge instrument to `go.opentelemetry.io/otel/metric`. (#5304)
MrAlias marked this conversation as resolved.
Show resolved Hide resolved
- An `int64` or `float64` synchronous gauge instrument can now be created from a `Meter`.
- All implementations of the API (`go.opentelemetry.io/otel/metric/noop`, `go.opentelemetry.io/otel/sdk/metric`) are updated to support this instrument.

### Changed

Expand Down
52 changes: 52 additions & 0 deletions internal/global/instruments.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,32 @@
}
}

type sfGauge struct {
embedded.Float64Gauge

name string
opts []metric.Float64GaugeOption

delegate atomic.Value // metric.Float64Gauge
}

var _ metric.Float64Gauge = (*sfGauge)(nil)

func (i *sfGauge) setDelegate(m metric.Meter) {
ctr, err := m.Float64Gauge(i.name, i.opts...)
if err != nil {
GetErrorHandler().Handle(err)
return

Check warning on line 299 in internal/global/instruments.go

View check run for this annotation

Codecov / codecov/patch

internal/global/instruments.go#L298-L299

Added lines #L298 - L299 were not covered by tests
}
i.delegate.Store(ctr)
}

func (i *sfGauge) Record(ctx context.Context, x float64, opts ...metric.RecordOption) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(metric.Float64Gauge).Record(ctx, x, opts...)
}
}

type siCounter struct {
embedded.Int64Counter

Expand Down Expand Up @@ -358,3 +384,29 @@
ctr.(metric.Int64Histogram).Record(ctx, x, opts...)
}
}

type siGauge struct {
embedded.Int64Gauge

name string
opts []metric.Int64GaugeOption

delegate atomic.Value // metric.Int64Gauge
}

var _ metric.Int64Gauge = (*siGauge)(nil)

func (i *siGauge) setDelegate(m metric.Meter) {
ctr, err := m.Int64Gauge(i.name, i.opts...)
if err != nil {
GetErrorHandler().Handle(err)
return

Check warning on line 403 in internal/global/instruments.go

View check run for this annotation

Codecov / codecov/patch

internal/global/instruments.go#L402-L403

Added lines #L402 - L403 were not covered by tests
}
i.delegate.Store(ctr)
}

func (i *siGauge) Record(ctx context.Context, x int64, opts ...metric.RecordOption) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(metric.Int64Gauge).Record(ctx, x, opts...)
}
}
14 changes: 14 additions & 0 deletions internal/global/instruments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ func TestSyncInstrumentSetDelegateConcurrentSafe(t *testing.T) {
f := func(v float64) { delegate.Record(context.Background(), v) }
testFloat64ConcurrentSafe(f, delegate.setDelegate)
})

t.Run("Gauge", func(t *testing.T) {
delegate := &sfGauge{}
f := func(v float64) { delegate.Record(context.Background(), v) }
testFloat64ConcurrentSafe(f, delegate.setDelegate)
})
})

// Int64 Instruments
Expand All @@ -139,6 +145,12 @@ func TestSyncInstrumentSetDelegateConcurrentSafe(t *testing.T) {
f := func(v int64) { delegate.Record(context.Background(), v) }
testInt64ConcurrentSafe(f, delegate.setDelegate)
})

t.Run("Gauge", func(t *testing.T) {
delegate := &siGauge{}
f := func(v int64) { delegate.Record(context.Background(), v) }
testInt64ConcurrentSafe(f, delegate.setDelegate)
})
})
}

Expand All @@ -149,6 +161,7 @@ type testCountingFloatInstrument struct {
embedded.Float64Counter
embedded.Float64UpDownCounter
embedded.Float64Histogram
embedded.Float64Gauge
embedded.Float64ObservableCounter
embedded.Float64ObservableUpDownCounter
embedded.Float64ObservableGauge
Expand All @@ -173,6 +186,7 @@ type testCountingIntInstrument struct {
embedded.Int64Counter
embedded.Int64UpDownCounter
embedded.Int64Histogram
embedded.Int64Gauge
embedded.Int64ObservableCounter
embedded.Int64ObservableUpDownCounter
embedded.Int64ObservableGauge
Expand Down
22 changes: 22 additions & 0 deletions internal/global/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ func (m *meter) Int64Histogram(name string, options ...metric.Int64HistogramOpti
return i, nil
}

func (m *meter) Int64Gauge(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
if del, ok := m.delegate.Load().(metric.Meter); ok {
return del.Int64Gauge(name, options...)
}
m.mtx.Lock()
defer m.mtx.Unlock()
i := &siGauge{name: name, opts: options}
m.instruments = append(m.instruments, i)
return i, nil
}

func (m *meter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) {
if del, ok := m.delegate.Load().(metric.Meter); ok {
return del.Int64ObservableCounter(name, options...)
Expand Down Expand Up @@ -230,6 +241,17 @@ func (m *meter) Float64Histogram(name string, options ...metric.Float64Histogram
return i, nil
}

func (m *meter) Float64Gauge(name string, options ...metric.Float64GaugeOption) (metric.Float64Gauge, error) {
if del, ok := m.delegate.Load().(metric.Meter); ok {
return del.Float64Gauge(name, options...)
}
m.mtx.Lock()
defer m.mtx.Unlock()
i := &sfGauge{name: name, opts: options}
m.instruments = append(m.instruments, i)
return i, nil
}

func (m *meter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) {
if del, ok := m.delegate.Load().(metric.Meter); ok {
return del.Float64ObservableCounter(name, options...)
Expand Down
6 changes: 6 additions & 0 deletions internal/global/meter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ func TestMeterConcurrentSafe(t *testing.T) {
_, _ = mtr.Float64Counter(name)
_, _ = mtr.Float64UpDownCounter(name)
_, _ = mtr.Float64Histogram(name)
_, _ = mtr.Float64Gauge(name)
_, _ = mtr.Int64Counter(name)
_, _ = mtr.Int64UpDownCounter(name)
_, _ = mtr.Int64Histogram(name)
_, _ = mtr.Int64Gauge(name)
_, _ = mtr.RegisterCallback(zeroCallback)
if !once {
wg.Done()
Expand Down Expand Up @@ -142,13 +144,17 @@ func testSetupAllInstrumentTypes(t *testing.T, m metric.Meter) (metric.Float64Co
assert.NoError(t, err)
_, err = m.Float64Histogram("test_Async_Histogram")
assert.NoError(t, err)
_, err = m.Float64Gauge("test_Sync_Gauge")
assert.NoError(t, err)

_, err = m.Int64Counter("test_Async_Counter")
assert.NoError(t, err)
_, err = m.Int64UpDownCounter("test_Async_UpDownCounter")
assert.NoError(t, err)
_, err = m.Int64Histogram("test_Async_Histogram")
assert.NoError(t, err)
_, err = m.Int64Gauge("test_Sync_Gauge")
assert.NoError(t, err)

return sfcounter, afcounter
}
Expand Down
12 changes: 12 additions & 0 deletions internal/global/meter_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ type testMeter struct {
sfCount int
sfUDCount int
sfHist int
sfGauge int

siCount int
siUDCount int
siHist int
siGauge int

callbacks []metric.Callback
}
Expand All @@ -59,6 +61,11 @@ func (m *testMeter) Int64Histogram(name string, options ...metric.Int64Histogram
return &testCountingIntInstrument{}, nil
}

func (m *testMeter) Int64Gauge(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
m.siGauge++
return &testCountingIntInstrument{}, nil
}

func (m *testMeter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) {
m.aiCount++
return &testCountingIntInstrument{}, nil
Expand Down Expand Up @@ -89,6 +96,11 @@ func (m *testMeter) Float64Histogram(name string, options ...metric.Float64Histo
return &testCountingFloatInstrument{}, nil
}

func (m *testMeter) Float64Gauge(name string, options ...metric.Float64GaugeOption) (metric.Float64Gauge, error) {
m.sfGauge++
return &testCountingFloatInstrument{}, nil
}

func (m *testMeter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) {
m.afCount++
return &testCountingFloatInstrument{}, nil
Expand Down
20 changes: 20 additions & 0 deletions metric/embedded/embedded.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ type Float64Counter interface{ float64Counter() }
// the API package).
type Float64Histogram interface{ float64Histogram() }

// Float64Gauge is embedded in [go.opentelemetry.io/otel/metric.Float64Gauge].
//
// Embed this interface in your implementation of the
// [go.opentelemetry.io/otel/metric.Float64Gauge] if you want users to
// experience a compilation error, signaling they need to update to your latest
// implementation, when the [go.opentelemetry.io/otel/metric.Float64Gauge]
// interface is extended (which is something that can happen without a major
// version bump of the API package).
type Float64Gauge interface{ float64Gauge() }

// Float64ObservableCounter is embedded in
// [go.opentelemetry.io/otel/metric.Float64ObservableCounter].
//
Expand Down Expand Up @@ -174,6 +184,16 @@ type Int64Counter interface{ int64Counter() }
// the API package).
type Int64Histogram interface{ int64Histogram() }

// Int64Gauge is embedded in [go.opentelemetry.io/otel/metric.Int64Gauge].
//
// Embed this interface in your implementation of the
// [go.opentelemetry.io/otel/metric.Int64Gauge] if you want users to experience
// a compilation error, signaling they need to update to your latest
// implementation, when the [go.opentelemetry.io/otel/metric.Int64Gauge]
// interface is extended (which is something that can happen without a major
// version bump of the API package).
type Int64Gauge interface{ int64Gauge() }

// Int64ObservableCounter is embedded in
// [go.opentelemetry.io/otel/metric.Int64ObservableCounter].
//
Expand Down
22 changes: 22 additions & 0 deletions metric/instrument.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ type InstrumentOption interface {
Int64CounterOption
Int64UpDownCounterOption
Int64HistogramOption
Int64GaugeOption
Int64ObservableCounterOption
Int64ObservableUpDownCounterOption
Int64ObservableGaugeOption

Float64CounterOption
Float64UpDownCounterOption
Float64HistogramOption
Float64GaugeOption
Float64ObservableCounterOption
Float64ObservableUpDownCounterOption
Float64ObservableGaugeOption
Expand Down Expand Up @@ -51,6 +53,11 @@ func (o descOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64Histogra
return c
}

func (o descOpt) applyFloat64Gauge(c Float64GaugeConfig) Float64GaugeConfig {
c.description = string(o)
return c
}

func (o descOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
c.description = string(o)
return c
Expand Down Expand Up @@ -81,6 +88,11 @@ func (o descOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfi
return c
}

func (o descOpt) applyInt64Gauge(c Int64GaugeConfig) Int64GaugeConfig {
c.description = string(o)
return c
}

func (o descOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
c.description = string(o)
return c
Expand Down Expand Up @@ -116,6 +128,11 @@ func (o unitOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64Histogra
return c
}

func (o unitOpt) applyFloat64Gauge(c Float64GaugeConfig) Float64GaugeConfig {
c.unit = string(o)
return c
}

func (o unitOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
c.unit = string(o)
return c
Expand Down Expand Up @@ -146,6 +163,11 @@ func (o unitOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfi
return c
}

func (o unitOpt) applyInt64Gauge(c Int64GaugeConfig) Int64GaugeConfig {
c.unit = string(o)
return c
}

func (o unitOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
c.unit = string(o)
return c
Expand Down
8 changes: 8 additions & 0 deletions metric/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ type Meter interface {
// synchronously record the distribution of int64 measurements during a
// computational operation.
Int64Histogram(name string, options ...Int64HistogramOption) (Int64Histogram, error)
// Int64Gauge returns a new Int64Gauge instrument identified by name and
// configured with options. The instrument is used to synchronously record
// instantaneous int64 measurements during a computational operation.
Int64Gauge(name string, options ...Int64GaugeOption) (Int64Gauge, error)
// Int64ObservableCounter returns a new Int64ObservableCounter identified
// by name and configured with options. The instrument is used to
// asynchronously record increasing int64 measurements once per a
Expand Down Expand Up @@ -104,6 +108,10 @@ type Meter interface {
// synchronously record the distribution of float64 measurements during a
// computational operation.
Float64Histogram(name string, options ...Float64HistogramOption) (Float64Histogram, error)
// Float64Gauge returns a new Float64Gauge instrument identified by name and
// configured with options. The instrument is used to synchronously record
// instantaneous float64 measurements during a computational operation.
Float64Gauge(name string, options ...Float64GaugeOption) (Float64Gauge, error)
// Float64ObservableCounter returns a new Float64ObservableCounter
// instrument identified by name and configured with options. The
// instrument is used to asynchronously record increasing float64
Expand Down
28 changes: 28 additions & 0 deletions metric/noop/noop.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ var (
_ metric.Float64UpDownCounter = Float64UpDownCounter{}
_ metric.Int64Histogram = Int64Histogram{}
_ metric.Float64Histogram = Float64Histogram{}
_ metric.Int64Gauge = Int64Gauge{}
_ metric.Float64Gauge = Float64Gauge{}
_ metric.Int64ObservableCounter = Int64ObservableCounter{}
_ metric.Float64ObservableCounter = Float64ObservableCounter{}
_ metric.Int64ObservableGauge = Int64ObservableGauge{}
Expand Down Expand Up @@ -76,6 +78,12 @@ func (Meter) Int64Histogram(string, ...metric.Int64HistogramOption) (metric.Int6
return Int64Histogram{}, nil
}

// Int64Gauge returns a Gauge used to record int64 measurements that
// produces no telemetry.
func (Meter) Int64Gauge(string, ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
return Int64Gauge{}, nil
}

// Int64ObservableCounter returns an ObservableCounter used to record int64
// measurements that produces no telemetry.
func (Meter) Int64ObservableCounter(string, ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) {
Expand Down Expand Up @@ -112,6 +120,12 @@ func (Meter) Float64Histogram(string, ...metric.Float64HistogramOption) (metric.
return Float64Histogram{}, nil
}

// Float64Gauge returns a Gauge used to record int64 measurements that
MrAlias marked this conversation as resolved.
Show resolved Hide resolved
// produces no telemetry.
func (Meter) Float64Gauge(string, ...metric.Float64GaugeOption) (metric.Float64Gauge, error) {
return Float64Gauge{}, nil
}

// Float64ObservableCounter returns an ObservableCounter used to record int64
// measurements that produces no telemetry.
func (Meter) Float64ObservableCounter(string, ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) {
Expand Down Expand Up @@ -197,6 +211,20 @@ type Float64Histogram struct{ embedded.Float64Histogram }
// Record performs no operation.
func (Float64Histogram) Record(context.Context, float64, ...metric.RecordOption) {}

// Int64Gauge is an OpenTelemetry Gauge used to record instantaneous int64
// measurements. It produces no telemetry.
type Int64Gauge struct{ embedded.Int64Gauge }

// Record performs no operation.
func (Int64Gauge) Record(context.Context, int64, ...metric.RecordOption) {}

// Float64Gauge is an OpenTelemetry Gauge used to record instantaneous float64
// measurements. It produces no telemetry.
type Float64Gauge struct{ embedded.Float64Gauge }

// Record performs no operation.
func (Float64Gauge) Record(context.Context, float64, ...metric.RecordOption) {}

// Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record
// int64 measurements. It produces no telemetry.
type Int64ObservableCounter struct {
Expand Down
Loading