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 first class support for Histograms #63

Merged
merged 6 commits into from
Dec 13, 2018

Conversation

objectiser
Copy link
Contributor

Resolves #62

Signed-off-by: Gary Brown gary@brownuk.com

Signed-off-by: Gary Brown <gary@brownuk.com>
@objectiser objectiser changed the title Add first class support for Histograms WIP: Add first class support for Histograms Dec 5, 2018
@objectiser objectiser requested a review from yurishkuro December 5, 2018 16:42
@codecov
Copy link

codecov bot commented Dec 5, 2018

Codecov Report

Merging #63 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff           @@
##           master    #63    +/-   ##
======================================
  Coverage     100%   100%            
======================================
  Files          25     26     +1     
  Lines         711    890   +179     
======================================
+ Hits          711    890   +179
Impacted Files Coverage Δ
metrics/factory.go 100% <100%> (ø) ⬆️
metrics/adapters/tagless.go 100% <100%> (ø) ⬆️
metrics/go-kit/factory.go 100% <100%> (ø) ⬆️
metrics/prometheus/factory.go 100% <100%> (ø) ⬆️
metrics/go-kit/metrics.go 100% <100%> (ø) ⬆️
metrics/tally/metrics.go 100% <100%> (ø) ⬆️
metrics/adapters/cache.go 100% <100%> (ø) ⬆️
metrics/histogram.go 100% <100%> (ø)
metrics/adapters/factory.go 100% <100%> (ø) ⬆️
metrics/expvar/factory.go 100% <100%> (ø) ⬆️
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3fa9aa0...7b4ca24. Read the comment docs.

@objectiser
Copy link
Contributor Author

@yurishkuro Currently just adds Histogram alongside Timer - although your suggestion in #62 to replace Timer, was wondering whether would be better to leave Timer as-is - to minimise breaking changes, but also because the Timer reports durations, whereas the histogram reports floats.

Help string
Buckets []float64
}

// Factory creates new metrics
type Factory interface {
Counter(metric Options) Counter
Timer(metric Options) Timer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my main question is: do we want to keep the Timer() as a function in the interface, or move it to a static helper function that will be based on the histogram?

Pros: This is what already happens in most implementations, so we could just do it once.
Cons: in some metrics backends timers are 1st class citizens

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your call 😄

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the only change I would propose is having the Timer() function take options struct that includes buckets (probably expressed as []time.Duration rather than []float64).

@yurishkuro
Copy link
Member

I am ok with leaving times in the interface.

@objectiser
Copy link
Contributor Author

@yurishkuro Ok will work on the test coverage and fixing the failing test. Let me know if there are other areas that need addressing.

Signed-off-by: Gary Brown <gary@brownuk.com>
Signed-off-by: Gary Brown <gary@brownuk.com>
Signed-off-by: Gary Brown <gary@brownuk.com>
@objectiser objectiser changed the title WIP: Add first class support for Histograms Add first class support for Histograms Dec 5, 2018
@objectiser
Copy link
Contributor Author

@yurishkuro Updated to use TimerOptions and fixed coverage. Let me know if there is anything else.

metrics/adapters/tagless.go Show resolved Hide resolved
return xkit.NewTimer(f.factory.Histogram(name))
}

func (f *factory) Histogram(name string, help string, buckets []float64) metrics.Histogram {
return xkit.NewHistogram(f.factory.Histogram(name))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a TODO to respect the buckets? Doesn't gokit allow buckets for histograms?

Copy link
Contributor Author

@objectiser objectiser Dec 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. #66

import (
"time"
)

// NSOptions defines the name and tags map associated with a metric
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/with a metric/with a factory namespace/ ?

@@ -0,0 +1,28 @@
// Copyright (c) 2018 Uber Technologies, Inc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Jaeger Authors


package metrics

// Histogram represents a histogram metric types.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that keeps track of a distribution of values.

@@ -47,6 +48,7 @@ func InitOrError(m interface{}, factory Factory, globalTags map[string]string) e
counterPtrType := reflect.TypeOf((*Counter)(nil)).Elem()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should fix #64 while at it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think InitOrError should be renamed to Init()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

metrics/metrics.go Show resolved Hide resolved
metrics/metrics.go Show resolved Hide resolved
func asFloatBuckets(buckets []time.Duration) []float64 {
data := make([]float64, len(buckets))
for i := range data {
data[i] = float64(buckets[i])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't Prometheus client expects double(1.0) == 1sec? Do we need:

data[i] =  float64(buckets[i]) / float64(time.Second)

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly for Timer (duration) buckets - but for Histogram this is just a list of floats,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but this function is used for Timer buckets, is it not? Since it accepts []time.Duration. I think you need to divide this by time.Second, since this is what the Record function of the timer does:

func (t *timer) Record(v time.Duration) {
t.histogram.Observe(float64(v.Nanoseconds()) / float64(time.Second/time.Nanosecond))
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep sorry - not sure what I was thinking.

@@ -48,14 +48,22 @@ func (f *factory) Gauge(options metrics.Options) metrics.Gauge {
return NewGauge(scope.Gauge(options.Name))
}

func (f *factory) Timer(options metrics.Options) metrics.Timer {
func (f *factory) Timer(options metrics.TimerOptions) metrics.Timer {
scope := f.tally
if len(options.Tags) > 0 {
scope = scope.Tagged(options.Tags)
}
return NewTimer(scope.Timer(options.Name))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, I thought tally supported buckets for timers. At least let's have a TODO, since we're dropping the buckets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, Timer doesn't, but the tally.Histogram suports a DurationBucket - so depends if we want to switch underlying representation? Will mark as TODO for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#67

Signed-off-by: Gary Brown <gary@brownuk.com>
@objectiser
Copy link
Contributor Author

objectiser commented Dec 7, 2018

Updated.
Resolves #64

@objectiser
Copy link
Contributor Author

@yurishkuro Ready for another review.

@objectiser
Copy link
Contributor Author

@yurishkuro Anything further required on this one?

b, err := strconv.ParseFloat(bucket, 64)
if err != nil {
return fmt.Errorf(
"Field [%s]: Bucket [%s] could not be converted to float64 in 'buckets' stirng [%s]",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: stirng

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Signed-off-by: Gary Brown <gary@brownuk.com>
@objectiser
Copy link
Contributor Author

@yurishkuro updated.

@yurishkuro
Copy link
Member

🎉

@yurishkuro yurishkuro merged commit c323da6 into jaegertracing:master Dec 13, 2018
@objectiser objectiser deleted the histo branch December 13, 2018 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants