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 single instrument callback and split metric instrument configuration #3507

Merged
merged 39 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d82fb9a
Split metric inst config
MrAlias Dec 2, 2022
119bfdc
Use Async/Sync opt for appropriate inst
MrAlias Dec 2, 2022
72f6984
Update noop inst providers
MrAlias Dec 2, 2022
66189ec
Update internal global impl
MrAlias Dec 2, 2022
6cc8177
Update sdk
MrAlias Dec 2, 2022
8cec5ab
Remove unused method for callbackOption
MrAlias Dec 2, 2022
978cbe2
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 2, 2022
b985bb3
Test instrument configuration
MrAlias Dec 2, 2022
3051332
Lint imports
MrAlias Dec 2, 2022
1867a8f
Add changes to changelog
MrAlias Dec 2, 2022
d996dca
Refactor callbacks and further split opts
MrAlias Dec 2, 2022
3990d79
Update noop impl
MrAlias Dec 2, 2022
5784949
Fix example_test.go
MrAlias Dec 2, 2022
4b05788
Fix internal impl
MrAlias Dec 2, 2022
9f11bcc
Update Callbacks
MrAlias Dec 2, 2022
342def0
Refactor common code in sdk/metric inst provider
MrAlias Dec 4, 2022
82d0fda
Update examples and prom exporter
MrAlias Dec 4, 2022
747fbcd
Generalize callback
MrAlias Dec 4, 2022
ac57568
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 6, 2022
a75bb93
Update changelog
MrAlias Dec 6, 2022
1b1c31b
Add unit tests for callback
MrAlias Dec 6, 2022
e49c9c9
Add meter tests for cbacks on creation
MrAlias Dec 6, 2022
a8ca279
Rename Observations to Measurements
MrAlias Dec 6, 2022
420da6e
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 7, 2022
89075df
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 8, 2022
1d3d3a8
Update Callback to accept an Observer
MrAlias Dec 10, 2022
3557ea8
Update SDK impl
MrAlias Dec 10, 2022
42206bb
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 15, 2022
48289ac
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 16, 2022
54b3a4c
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 16, 2022
9bfea0e
Move conf to instrument pkg
MrAlias Dec 16, 2022
5373e3e
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 19, 2022
36753e0
Merge branch 'main' into metric-inst-conf-split
MrAlias Dec 24, 2022
792dde0
Merge branch 'main' into metric-inst-conf-split
MrAlias Jan 3, 2023
9644c28
Merge branch 'main' into metric-inst-conf-split
MrAlias Jan 3, 2023
013a228
Merge branch 'main' into metric-inst-conf-split
MrAlias Jan 4, 2023
2fcf8cd
Apply suggestions from code review
MrAlias Jan 5, 2023
4585799
Merge branch 'main' into metric-inst-conf-split
MrAlias Jan 5, 2023
25693fb
Merge branch 'main' into metric-inst-conf-split
MrAlias Jan 6, 2023
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Added

- The `WithInt64Callback` option is added to `go.opentelemetry.io/otel/metric/instrument` to configure int64 Observer callbacks during their creation. (#3507)
- The `WithFloat64Callback` option is added to `go.opentelemetry.io/otel/metric/instrument` to configure float64 Observer callbacks during their creation. (#3507)
- Return a `Registration` from the `RegisterCallback` method of a `Meter` in the `go.opentelemetry.io/otel/metric` package.
This `Registration` can be used to unregister callbacks. (#3522)
- Add `Producer` interface and `Reader.RegisterProducer(Producer)` to `go.opentelemetry.io/otel/sdk/metric` to enable external metric Producers. (#3524)

### Changed

- Instrument configuration in `go.opentelemetry.io/otel/metric/instrument` is split into specific options and confguration based on the instrument type. (#3507)
- Use the added `Int64Option` type to configure instruments from `go.opentelemetry.io/otel/metric/instrument/syncint64`.
- Use the added `Float64Option` type to configure instruments from `go.opentelemetry.io/otel/metric/instrument/syncfloat64`.
- Use the added `Int64ObserverOption` type to configure instruments from `go.opentelemetry.io/otel/metric/instrument/asyncint64`.
- Use the added `Float64ObserverOption` type to configure instruments from `go.opentelemetry.io/otel/metric/instrument/asyncfloat64`.
- The `InstrumentProvider` from `go.opentelemetry.io/otel/sdk/metric/asyncint64` is removed.
Use the new creation methods of the `Meter` in `go.opentelemetry.io/otel/sdk/metric` instead. (#3530)
- The `Counter` method is replaced by `Meter.Int64ObservableCounter`
Expand Down
96 changes: 96 additions & 0 deletions metric/instrument/asyncfloat64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// 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 instrument // import "go.opentelemetry.io/otel/metric/instrument"

import (
"context"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/unit"
)

// Float64Observer is a recorder of float64 measurement values.
// Warning: methods may be added to this interface in minor releases.
type Float64Observer interface {
Asynchronous

// Observe records the measurement value for a set of attributes.
//
// It is only valid to call this within a callback. If called outside of
// the registered callback it should have no effect on the instrument, and
// an error will be reported via the error handler.
Observe(ctx context.Context, value float64, attributes ...attribute.KeyValue)
}

// Float64Callback is a function registered with a Meter that makes
// observations for a Float64Observer it is registered with.
//
// The function needs to complete in a finite amount of time and the deadline
// of the passed context is expected to be honored.
MrAlias marked this conversation as resolved.
Show resolved Hide resolved
//
// The function needs to be concurrent safe.
type Float64Callback func(context.Context, Float64Observer) error

// Float64ObserverConfig contains options for Asynchronous instruments that
// observe float64 values.
type Float64ObserverConfig struct {
description string
unit unit.Unit
callbacks []Float64Callback
}

// NewFloat64ObserverConfig returns a new Float64ObserverConfig with all opts
// applied.
func NewFloat64ObserverConfig(opts ...Float64ObserverOption) Float64ObserverConfig {
var config Float64ObserverConfig
for _, o := range opts {
config = o.applyFloat64Observer(config)
}
return config
}

// Description returns the Config description.
func (c Float64ObserverConfig) Description() string {
return c.description
}

// Unit returns the Config unit.
func (c Float64ObserverConfig) Unit() unit.Unit {
return c.unit
}

// Callbacks returns the Config callbacks.
func (c Float64ObserverConfig) Callbacks() []Float64Callback {
return c.callbacks
}

// Float64ObserverOption applies options to float64 Observer instruments.
type Float64ObserverOption interface {
applyFloat64Observer(Float64ObserverConfig) Float64ObserverConfig
}

type float64ObserverOptionFunc func(Float64ObserverConfig) Float64ObserverConfig

func (fn float64ObserverOptionFunc) applyFloat64Observer(cfg Float64ObserverConfig) Float64ObserverConfig {
return fn(cfg)
}

// WithFloat64Callback adds callback to be called for an instrument.
func WithFloat64Callback(callback Float64Callback) Float64ObserverOption {
return float64ObserverOptionFunc(func(cfg Float64ObserverConfig) Float64ObserverConfig {
cfg.callbacks = append(cfg.callbacks, callback)
return cfg
})
}
57 changes: 16 additions & 41 deletions metric/instrument/asyncfloat64/asyncfloat64.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,53 +14,28 @@

package asyncfloat64 // import "go.opentelemetry.io/otel/metric/instrument/asyncfloat64"

import (
"context"
import "go.opentelemetry.io/otel/metric/instrument"

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

// Counter is an instrument that records increasing values.
// Counter is an instrument used to asynchronously record increasing float64
// measurements once per a measurement collection cycle. The Observe method is
// used to record the measured state of the instrument when it is called.
// Implementations will assume the observed value to be the cumulative sum of
// the count.
//
// Warning: methods may be added to this interface in minor releases.
type Counter interface {
// Observe records the state of the instrument to be x. Implementations
// will assume x to be the cumulative sum of the count.
//
// It is only valid to call this within a callback. If called outside of the
// registered callback it should have no effect on the instrument, and an
// error will be reported via the error handler.
Observe(ctx context.Context, x float64, attrs ...attribute.KeyValue)

instrument.Asynchronous
}
type Counter interface{ instrument.Float64Observer }

// UpDownCounter is an instrument that records increasing or decreasing values.
// UpDownCounter is an instrument used to asynchronously record float64
// measurements once per a measurement collection cycle. The Observe method is
// used to record the measured state of the instrument when it is called.
// Implementations will assume the observed value to be the cumulative sum of
// the count.
//
// Warning: methods may be added to this interface in minor releases.
type UpDownCounter interface {
// Observe records the state of the instrument to be x. Implementations
// will assume x to be the cumulative sum of the count.
//
// It is only valid to call this within a callback. If called outside of the
// registered callback it should have no effect on the instrument, and an
// error will be reported via the error handler.
Observe(ctx context.Context, x float64, attrs ...attribute.KeyValue)
type UpDownCounter interface{ instrument.Float64Observer }

instrument.Asynchronous
}

// Gauge is an instrument that records independent readings.
// Gauge is an instrument used to asynchronously record instantaneous float64
// measurements once per a measurement collection cycle.
//
// Warning: methods may be added to this interface in minor releases.
type Gauge interface {
// Observe records the state of the instrument to be x.
//
// It is only valid to call this within a callback. If called outside of the
// registered callback it should have no effect on the instrument, and an
// error will be reported via the error handler.
Observe(ctx context.Context, x float64, attrs ...attribute.KeyValue)

instrument.Asynchronous
}
type Gauge interface{ instrument.Float64Observer }
62 changes: 62 additions & 0 deletions metric/instrument/asyncfloat64_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// 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 instrument // import "go.opentelemetry.io/otel/metric/instrument"

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/unit"
)

func TestFloat64ObserverOptions(t *testing.T) {
const (
token float64 = 43
desc = "Instrument description."
uBytes = unit.Bytes
)

got := NewFloat64ObserverConfig(
WithDescription(desc),
WithUnit(uBytes),
WithFloat64Callback(func(ctx context.Context, o Float64Observer) error {
o.Observe(ctx, token)
return nil
}),
)
assert.Equal(t, desc, got.Description(), "description")
assert.Equal(t, uBytes, got.Unit(), "unit")

// Functions are not comparable.
cBacks := got.Callbacks()
require.Len(t, cBacks, 1, "callbacks")
o := &float64Observer{}
err := cBacks[0](context.Background(), o)
require.NoError(t, err)
assert.Equal(t, token, o.got, "callback not set")
}

type float64Observer struct {
Asynchronous
got float64
}

func (o *float64Observer) Observe(_ context.Context, v float64, _ ...attribute.KeyValue) {
o.got = v
}
97 changes: 97 additions & 0 deletions metric/instrument/asyncint64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// 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 instrument // import "go.opentelemetry.io/otel/metric/instrument"

import (
"context"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/unit"
)

// Int64Observer is a recorder of int64 measurement values.
//
// Warning: methods may be added to this interface in minor releases.
type Int64Observer interface {
Asynchronous

// Observe records the measurement value for a set of attributes.
//
// It is only valid to call this within a callback. If called outside of
// the registered callback it should have no effect on the instrument, and
// an error will be reported via the error handler.
Observe(ctx context.Context, value int64, attributes ...attribute.KeyValue)
}

// Int64Callback is a function registered with a Meter that makes
// observations for an Int64Observer it is registered with.
//
// The function needs to complete in a finite amount of time and the deadline
// of the passed context is expected to be honored.
//
MrAlias marked this conversation as resolved.
Show resolved Hide resolved
// The function needs to be concurrent safe.
type Int64Callback func(context.Context, Int64Observer) error

// Int64ObserverConfig contains options for Asynchronous instruments that
// observe int64 values.
type Int64ObserverConfig struct {
description string
unit unit.Unit
callbacks []Int64Callback
}

// NewInt64ObserverConfig returns a new Int64ObserverConfig with all opts
// applied.
func NewInt64ObserverConfig(opts ...Int64ObserverOption) Int64ObserverConfig {
var config Int64ObserverConfig
for _, o := range opts {
config = o.applyInt64Observer(config)
}
return config
}

// Description returns the Config description.
func (c Int64ObserverConfig) Description() string {
return c.description
}

// Unit returns the Config unit.
func (c Int64ObserverConfig) Unit() unit.Unit {
return c.unit
}

// Callbacks returns the Config callbacks.
func (c Int64ObserverConfig) Callbacks() []Int64Callback {
return c.callbacks
}

// Int64ObserverOption applies options to int64 Observer instruments.
type Int64ObserverOption interface {
applyInt64Observer(Int64ObserverConfig) Int64ObserverConfig
}

type int64ObserverOptionFunc func(Int64ObserverConfig) Int64ObserverConfig

func (fn int64ObserverOptionFunc) applyInt64Observer(cfg Int64ObserverConfig) Int64ObserverConfig {
return fn(cfg)
}

// WithInt64Callback adds callback to be called for an instrument.
func WithInt64Callback(callback Int64Callback) Int64ObserverOption {
return int64ObserverOptionFunc(func(cfg Int64ObserverConfig) Int64ObserverConfig {
cfg.callbacks = append(cfg.callbacks, callback)
return cfg
})
}
Loading