1
0
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:
Joshua MacDonald 2019-10-17 15:35:42 -07:00 committed by GitHub
parent e11b90cab2
commit 1191a07836
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 9 additions and 354 deletions

View File

@ -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)
}

View File

@ -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 {

View File

@ -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"

View File

@ -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) {

View File

@ -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)
}
}

View File

@ -34,9 +34,3 @@ func (noopMeter) DeleteHandle(Handle) {
func (noopMeter) RecordBatch(context.Context, LabelSet, ...Measurement) {
}
func (noopMeter) RegisterObserver(Observer, ObserverCallback) {
}
func (noopMeter) UnregisterObserver(Observer) {
}

View File

@ -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
}