mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-01-01 22:09:57 +02:00
Observer metric has not been specified (#222)
This commit is contained in:
parent
e11b90cab2
commit
1191a07836
@ -35,9 +35,6 @@ const (
|
||||
GaugeKind
|
||||
// MeasureKind describes a metric that supports Record().
|
||||
MeasureKind
|
||||
// ObserverKind describes a metric that reports measurement on
|
||||
// demand.
|
||||
ObserverKind
|
||||
)
|
||||
|
||||
// Handle is the implementation-level interface to Set/Add/Record
|
||||
@ -58,14 +55,6 @@ type LabelSet interface {
|
||||
Meter() Meter
|
||||
}
|
||||
|
||||
// ObservationCallback defines a type of the callback the observer
|
||||
// will use to report the measurement
|
||||
type ObservationCallback func(LabelSet, MeasurementValue)
|
||||
|
||||
// ObserverCallback defines a type of the callback SDK will call for
|
||||
// the registered observers.
|
||||
type ObserverCallback func(Meter, Observer, ObservationCallback)
|
||||
|
||||
// WithDescriptor is an interface that all metric implement.
|
||||
type WithDescriptor interface {
|
||||
// Descriptor returns a descriptor of this metric.
|
||||
@ -99,19 +88,6 @@ type Meter interface {
|
||||
// DeleteHandle destroys the Handle and does a cleanup of the
|
||||
// underlying resources.
|
||||
DeleteHandle(Handle)
|
||||
|
||||
// RegisterObserver registers the observer with callback
|
||||
// returning a measurement. When and how often the callback
|
||||
// will be called is defined by SDK. This should not be used
|
||||
// directly - prefer either RegisterInt64Observer or
|
||||
// RegisterFloat64Observer, depending on the type of the
|
||||
// observer to be registered.
|
||||
RegisterObserver(Observer, ObserverCallback)
|
||||
// UnregisterObserver removes the observer from registered
|
||||
// observers. This should not be used directly - prefer either
|
||||
// UnregisterInt64Observer or UnregisterFloat64Observer,
|
||||
// depending on the type of the observer to be registered.
|
||||
UnregisterObserver(Observer)
|
||||
}
|
||||
|
||||
// DescriptorID is a unique identifier of a metric.
|
||||
@ -185,8 +161,8 @@ func (d *Descriptor) ValueKind() ValueKind {
|
||||
//
|
||||
// - for Counter, true implies that the metric is an up-down Counter
|
||||
//
|
||||
// - for Gauge/Observer, true implies that the metric is a
|
||||
// non-descending Gauge/Observer
|
||||
// - for Gauge, true implies that the metric is a
|
||||
// non-descending Gauge
|
||||
//
|
||||
// - for Measure, true implies that the metric supports positive and
|
||||
// negative values
|
||||
@ -300,57 +276,3 @@ func (d Descriptor) Defined() bool {
|
||||
func RecordBatch(ctx context.Context, labels LabelSet, batch ...Measurement) {
|
||||
GlobalMeter().RecordBatch(ctx, labels, batch...)
|
||||
}
|
||||
|
||||
// Int64ObservationCallback defines a type of the callback the
|
||||
// observer will use to report the int64 measurement.
|
||||
type Int64ObservationCallback func(LabelSet, int64)
|
||||
|
||||
// Int64ObserverCallback defines a type of the callback SDK will call
|
||||
// for the registered int64 observers.
|
||||
type Int64ObserverCallback func(Meter, Int64Observer, Int64ObservationCallback)
|
||||
|
||||
// RegisterInt64Observer is a convenience wrapper around
|
||||
// Meter.RegisterObserver that provides a type-safe callback for
|
||||
// Int64Observer.
|
||||
func RegisterInt64Observer(meter Meter, observer Int64Observer, callback Int64ObserverCallback) {
|
||||
cb := func(m Meter, o Observer, ocb ObservationCallback) {
|
||||
iocb := func(l LabelSet, i int64) {
|
||||
ocb(l, NewInt64MeasurementValue(i))
|
||||
}
|
||||
callback(m, Int64Observer{o}, iocb)
|
||||
}
|
||||
meter.RegisterObserver(observer.Observer, cb)
|
||||
}
|
||||
|
||||
// UnregisterInt64Observer is a convenience wrapper around
|
||||
// Meter.UnregisterObserver for Int64Observer.
|
||||
func UnregisterInt64Observer(meter Meter, observer Int64Observer) {
|
||||
meter.UnregisterObserver(observer.Observer)
|
||||
}
|
||||
|
||||
// Float64ObservationCallback defines a type of the callback the
|
||||
// observer will use to report the float64 measurement.
|
||||
type Float64ObservationCallback func(LabelSet, float64)
|
||||
|
||||
// Float64ObserverCallback defines a type of the callback SDK will
|
||||
// call for the registered float64 observers.
|
||||
type Float64ObserverCallback func(Meter, Float64Observer, Float64ObservationCallback)
|
||||
|
||||
// RegisterFloat64Observer is a convenience wrapper around
|
||||
// Meter.RegisterObserver that provides a type-safe callback for
|
||||
// Float64Observer.
|
||||
func RegisterFloat64Observer(meter Meter, observer Float64Observer, callback Float64ObserverCallback) {
|
||||
cb := func(m Meter, o Observer, ocb ObservationCallback) {
|
||||
focb := func(l LabelSet, f float64) {
|
||||
ocb(l, NewFloat64MeasurementValue(f))
|
||||
}
|
||||
callback(m, Float64Observer{o}, focb)
|
||||
}
|
||||
meter.RegisterObserver(observer.Observer, cb)
|
||||
}
|
||||
|
||||
// UnregisterFloat64Observer is a convenience wrapper around
|
||||
// Meter.UnregisterObserver for Float64Observer.
|
||||
func UnregisterFloat64Observer(meter Meter, observer Float64Observer) {
|
||||
meter.UnregisterObserver(observer.Observer)
|
||||
}
|
||||
|
@ -381,125 +381,6 @@ func TestMeasureOptions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestObserverOptions(t *testing.T) {
|
||||
type testcase struct {
|
||||
name string
|
||||
opts []GaugeOptionApplier
|
||||
keys []core.Key
|
||||
desc string
|
||||
unit unit.Unit
|
||||
alt bool
|
||||
}
|
||||
testcases := []testcase{
|
||||
{
|
||||
name: "no opts",
|
||||
opts: nil,
|
||||
keys: nil,
|
||||
desc: "",
|
||||
unit: "",
|
||||
alt: false,
|
||||
},
|
||||
{
|
||||
name: "keys keys keys",
|
||||
opts: []GaugeOptionApplier{
|
||||
WithKeys(key.New("foo"), key.New("foo2")),
|
||||
WithKeys(key.New("bar"), key.New("bar2")),
|
||||
WithKeys(key.New("baz"), key.New("baz2")),
|
||||
},
|
||||
keys: []core.Key{
|
||||
key.New("foo"), key.New("foo2"),
|
||||
key.New("bar"), key.New("bar2"),
|
||||
key.New("baz"), key.New("baz2"),
|
||||
},
|
||||
desc: "",
|
||||
unit: "",
|
||||
alt: false,
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
opts: []GaugeOptionApplier{
|
||||
WithDescription("stuff"),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "stuff",
|
||||
unit: "",
|
||||
alt: false,
|
||||
},
|
||||
{
|
||||
name: "description override",
|
||||
opts: []GaugeOptionApplier{
|
||||
WithDescription("stuff"),
|
||||
WithDescription("things"),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "things",
|
||||
unit: "",
|
||||
alt: false,
|
||||
},
|
||||
{
|
||||
name: "unit",
|
||||
opts: []GaugeOptionApplier{
|
||||
WithUnit("s"),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "",
|
||||
unit: "s",
|
||||
alt: false,
|
||||
},
|
||||
{
|
||||
name: "unit override",
|
||||
opts: []GaugeOptionApplier{
|
||||
WithUnit("s"),
|
||||
WithUnit("h"),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "",
|
||||
unit: "h",
|
||||
alt: false,
|
||||
},
|
||||
{
|
||||
name: "monotonic",
|
||||
opts: []GaugeOptionApplier{
|
||||
WithMonotonic(true),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "",
|
||||
unit: "",
|
||||
alt: true,
|
||||
},
|
||||
{
|
||||
name: "monotonic, but not really",
|
||||
opts: []GaugeOptionApplier{
|
||||
WithMonotonic(true),
|
||||
WithMonotonic(false),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "",
|
||||
unit: "",
|
||||
alt: false,
|
||||
},
|
||||
}
|
||||
checkObserverDescriptor := func(tt testcase, vk ValueKind, d *Descriptor) {
|
||||
e := descriptor{
|
||||
name: tt.name,
|
||||
keys: tt.keys,
|
||||
desc: tt.desc,
|
||||
unit: tt.unit,
|
||||
alt: tt.alt,
|
||||
kind: ObserverKind,
|
||||
vk: vk,
|
||||
}
|
||||
checkDescriptor(t, e, d)
|
||||
}
|
||||
for idx, tt := range testcases {
|
||||
t.Logf("Testing observer case %s (%d)", tt.name, idx)
|
||||
f := NewFloat64Observer(tt.name, tt.opts...)
|
||||
checkObserverDescriptor(tt, Float64ValueKind, f.Descriptor())
|
||||
i := NewInt64Observer(tt.name, tt.opts...)
|
||||
checkObserverDescriptor(tt, Int64ValueKind, i.Descriptor())
|
||||
}
|
||||
}
|
||||
|
||||
type descriptor struct {
|
||||
name string
|
||||
keys []core.Key
|
||||
@ -624,37 +505,6 @@ func TestMeasure(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestObserver(t *testing.T) {
|
||||
{
|
||||
o := NewFloat64Observer("ajwaj")
|
||||
meter := newMockMeter()
|
||||
ctx := context.Background()
|
||||
labels := meter.DefineLabels(ctx)
|
||||
RegisterFloat64Observer(meter, o, func(meter Meter, o Float64Observer, cb Float64ObservationCallback) {
|
||||
cb(labels, 42)
|
||||
cb(labels, 42)
|
||||
cb(labels, 42)
|
||||
})
|
||||
meter.PerformObservations()
|
||||
t.Log("Testing float observer")
|
||||
checkBatches(t, ctx, labels, meter, o.Descriptor())
|
||||
}
|
||||
{
|
||||
o := NewInt64Observer("ajwaj")
|
||||
ctx := context.Background()
|
||||
meter := newMockMeter()
|
||||
labels := meter.DefineLabels(ctx)
|
||||
RegisterInt64Observer(meter, o, func(meter Meter, o Int64Observer, cb Int64ObservationCallback) {
|
||||
cb(labels, 42)
|
||||
cb(labels, 42)
|
||||
cb(labels, 42)
|
||||
})
|
||||
meter.PerformObservations()
|
||||
t.Log("Testing int observer")
|
||||
checkBatches(t, ctx, labels, meter, o.Descriptor())
|
||||
}
|
||||
}
|
||||
|
||||
func checkBatches(t *testing.T, ctx context.Context, labels LabelSet, meter *mockMeter, descriptor *Descriptor) {
|
||||
t.Helper()
|
||||
if len(meter.measurementBatches) != 3 {
|
||||
|
@ -22,9 +22,6 @@
|
||||
// - gauges
|
||||
// - measures
|
||||
//
|
||||
// There is also a special case of a gauge instrument called
|
||||
// observer. It will be discussed later.
|
||||
//
|
||||
// All instruments report either float64 or int64 values.
|
||||
//
|
||||
// The primary object that handles metrics is Meter. The
|
||||
@ -62,18 +59,9 @@
|
||||
// allows reporting negative values too. To report a new value, use
|
||||
// the Record function.
|
||||
//
|
||||
// A special case of a gauge is observer. It has the same role as
|
||||
// gauge, but reports values in a different way. The observer can be
|
||||
// created with NewFloat64Observer or NewInt64Observer and then
|
||||
// registered within a Meter with either RegisterInt64Observer or
|
||||
// RegisterFloat64Observer functions. These take a callback for
|
||||
// reporting the values. The callback will be called by the Meter when
|
||||
// it deems it necessary.
|
||||
//
|
||||
// All the basic kinds of instruments (so, not observers) also support
|
||||
// creating handles for a potentially more efficient reporting. The
|
||||
// handles have the same function names as the instruments (so counter
|
||||
// handle has Add, gauge handle has Set and measure handle has
|
||||
// Record). Handles can be created with the GetHandle function of the
|
||||
// respective instrument.
|
||||
// All the basic kinds of instruments also support creating handles
|
||||
// for a potentially more efficient reporting. The handles have the
|
||||
// same function names as the instruments (so counter handle has Add,
|
||||
// gauge handle has Set and measure handle has Record). Handles can be
|
||||
// created with the GetHandle function of the respective instrument.
|
||||
package metric // import "go.opentelemetry.io/api/metric"
|
||||
|
@ -12,12 +12,11 @@ func _() {
|
||||
_ = x[CounterKind-1]
|
||||
_ = x[GaugeKind-2]
|
||||
_ = x[MeasureKind-3]
|
||||
_ = x[ObserverKind-4]
|
||||
}
|
||||
|
||||
const _Kind_name = "InvalidCounterKindGaugeKindMeasureKindObserverKind"
|
||||
const _Kind_name = "InvalidCounterKindGaugeKindMeasureKind"
|
||||
|
||||
var _Kind_index = [...]uint8{0, 7, 18, 27, 38, 50}
|
||||
var _Kind_index = [...]uint8{0, 7, 18, 27, 38}
|
||||
|
||||
func (i Kind) String() string {
|
||||
if i < 0 || i >= Kind(len(_Kind_index)-1) {
|
||||
|
@ -37,16 +37,8 @@ type (
|
||||
measurements []Measurement
|
||||
}
|
||||
|
||||
observerData struct {
|
||||
observer Observer
|
||||
callback ObserverCallback
|
||||
}
|
||||
|
||||
observerMap map[DescriptorID]observerData
|
||||
|
||||
mockMeter struct {
|
||||
measurementBatches []batch
|
||||
observers observerMap
|
||||
}
|
||||
)
|
||||
|
||||
@ -103,39 +95,3 @@ func (m *mockMeter) NewHandle(erm ExplicitReportingMetric, labels LabelSet) Hand
|
||||
|
||||
func (m *mockMeter) DeleteHandle(Handle) {
|
||||
}
|
||||
|
||||
func (m *mockMeter) RegisterObserver(o Observer, cb ObserverCallback) {
|
||||
id := o.Descriptor().ID()
|
||||
if _, ok := m.observers[id]; ok {
|
||||
return
|
||||
}
|
||||
data := observerData{
|
||||
observer: o,
|
||||
callback: cb,
|
||||
}
|
||||
if m.observers == nil {
|
||||
m.observers = observerMap{
|
||||
id: data,
|
||||
}
|
||||
} else {
|
||||
m.observers[id] = data
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockMeter) UnregisterObserver(o Observer) {
|
||||
delete(m.observers, o.Descriptor().ID())
|
||||
}
|
||||
|
||||
func (m *mockMeter) PerformObservations() {
|
||||
for _, data := range m.observers {
|
||||
o := data.observer
|
||||
descriptor := o.Descriptor()
|
||||
ocb := func(l LabelSet, v MeasurementValue) {
|
||||
m.RecordBatch(context.Background(), l, Measurement{
|
||||
Descriptor: descriptor,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
data.callback(m, o, ocb)
|
||||
}
|
||||
}
|
||||
|
@ -34,9 +34,3 @@ func (noopMeter) DeleteHandle(Handle) {
|
||||
|
||||
func (noopMeter) RecordBatch(context.Context, LabelSet, ...Measurement) {
|
||||
}
|
||||
|
||||
func (noopMeter) RegisterObserver(Observer, ObserverCallback) {
|
||||
}
|
||||
|
||||
func (noopMeter) UnregisterObserver(Observer) {
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
// Copyright 2019, 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
|
||||
|
||||
// Observer is a base of typed-observers. Shouldn't be used directly.
|
||||
type Observer struct {
|
||||
d *Descriptor
|
||||
}
|
||||
|
||||
// Float64Observer is an observer that reports float64 values.
|
||||
type Float64Observer struct {
|
||||
Observer
|
||||
}
|
||||
|
||||
// Int64Observer is an observer that reports int64 values.
|
||||
type Int64Observer struct {
|
||||
Observer
|
||||
}
|
||||
|
||||
func newObserver(name string, valueKind ValueKind, mos ...GaugeOptionApplier) (o Observer) {
|
||||
o.d = registerDescriptor(name, ObserverKind, valueKind)
|
||||
for _, opt := range mos {
|
||||
opt.ApplyGaugeOption(o.d)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewFloat64Observer creates a new observer for float64.
|
||||
func NewFloat64Observer(name string, mos ...GaugeOptionApplier) (o Float64Observer) {
|
||||
o.Observer = newObserver(name, Float64ValueKind, mos...)
|
||||
return
|
||||
}
|
||||
|
||||
// NewInt64Observer creates a new observer for int64.
|
||||
func NewInt64Observer(name string, mos ...GaugeOptionApplier) (o Int64Observer) {
|
||||
o.Observer = newObserver(name, Int64ValueKind, mos...)
|
||||
return
|
||||
}
|
||||
|
||||
func (o Observer) Descriptor() *Descriptor {
|
||||
return o.d
|
||||
}
|
Loading…
Reference in New Issue
Block a user