You've already forked opentelemetry-go
							
							
				mirror of
				https://github.com/open-telemetry/opentelemetry-go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	Observer metric has not been specified (#222)
This commit is contained in:
		| @@ -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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user