timer: Added support for exemplars. (#1233)
Signed-off-by: bwplotka <bwplotka@gmail.com>
This commit is contained in:
parent
232b949d1f
commit
e79d7e71ce
|
@ -23,7 +23,9 @@ type Timer struct {
|
|||
}
|
||||
|
||||
// NewTimer creates a new Timer. The provided Observer is used to observe a
|
||||
// duration in seconds. Timer is usually used to time a function call in the
|
||||
// duration in seconds. If the Observer implements ExemplarObserver, passing exemplar
|
||||
// later on will be also supported.
|
||||
// Timer is usually used to time a function call in the
|
||||
// following way:
|
||||
//
|
||||
// func TimeMe() {
|
||||
|
@ -31,6 +33,14 @@ type Timer struct {
|
|||
// defer timer.ObserveDuration()
|
||||
// // Do actual work.
|
||||
// }
|
||||
//
|
||||
// or
|
||||
//
|
||||
// func TimeMeWithExemplar() {
|
||||
// timer := NewTimer(myHistogram)
|
||||
// defer timer.ObserveDurationWithExemplar(exemplar)
|
||||
// // Do actual work.
|
||||
// }
|
||||
func NewTimer(o Observer) *Timer {
|
||||
return &Timer{
|
||||
begin: time.Now(),
|
||||
|
@ -53,3 +63,19 @@ func (t *Timer) ObserveDuration() time.Duration {
|
|||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// ObserveDurationWithExemplar is like ObserveDuration, but it will also
|
||||
// observe exemplar with the duration unless exemplar is nil or provided Observer can't
|
||||
// be casted to ExemplarObserver.
|
||||
func (t *Timer) ObserveDurationWithExemplar(exemplar Labels) time.Duration {
|
||||
d := time.Since(t.begin)
|
||||
eo, ok := t.observer.(ExemplarObserver)
|
||||
if ok && exemplar != nil {
|
||||
eo.ObserveWithExemplar(d.Seconds(), exemplar)
|
||||
return d
|
||||
}
|
||||
if t.observer != nil {
|
||||
t.observer.Observe(d.Seconds())
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
|
|
@ -14,8 +14,11 @@
|
|||
package prometheus
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
|
@ -52,6 +55,54 @@ func TestTimerObserve(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTimerObserveWithExemplar(t *testing.T) {
|
||||
var (
|
||||
exemplar = Labels{"foo": "bar"}
|
||||
his = NewHistogram(HistogramOpts{Name: "test_histogram"})
|
||||
sum = NewSummary(SummaryOpts{Name: "test_summary"})
|
||||
gauge = NewGauge(GaugeOpts{Name: "test_gauge"})
|
||||
)
|
||||
|
||||
func() {
|
||||
hisTimer := NewTimer(his)
|
||||
sumTimer := NewTimer(sum)
|
||||
gaugeTimer := NewTimer(ObserverFunc(gauge.Set))
|
||||
defer hisTimer.ObserveDurationWithExemplar(exemplar)
|
||||
// Gauges and summaries does not implement ExemplarObserver, so we expect them to ignore exemplar.
|
||||
defer sumTimer.ObserveDurationWithExemplar(exemplar)
|
||||
defer gaugeTimer.ObserveDurationWithExemplar(exemplar)
|
||||
}()
|
||||
|
||||
m := &dto.Metric{}
|
||||
his.Write(m)
|
||||
if want, got := uint64(1), m.GetHistogram().GetSampleCount(); want != got {
|
||||
t.Errorf("want %d observations for histogram, got %d", want, got)
|
||||
}
|
||||
var got []*dto.LabelPair
|
||||
for _, b := range m.GetHistogram().GetBucket() {
|
||||
if b.Exemplar != nil {
|
||||
got = b.Exemplar.GetLabel()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
want := []*dto.LabelPair{{Name: proto.String("foo"), Value: proto.String("bar")}}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("expected %v exemplar labels, got %v", want, got)
|
||||
}
|
||||
|
||||
m.Reset()
|
||||
sum.Write(m)
|
||||
if want, got := uint64(1), m.GetSummary().GetSampleCount(); want != got {
|
||||
t.Errorf("want %d observations for summary, got %d", want, got)
|
||||
}
|
||||
m.Reset()
|
||||
gauge.Write(m)
|
||||
if got := m.GetGauge().GetValue(); got <= 0 {
|
||||
t.Errorf("want value > 0 for gauge, got %f", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimerEmpty(t *testing.T) {
|
||||
emptyTimer := NewTimer(nil)
|
||||
emptyTimer.ObserveDuration()
|
||||
|
|
Loading…
Reference in New Issue