-
Notifications
You must be signed in to change notification settings - Fork 32
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 functions that instruments http handler using promhttp #15
Conversation
@stevvooe cc @manishtomar |
cc @nandhini915 |
handler.go
Outdated
|
||
// InstrumentHandlerFuncWithOpts instruments http handler with in-flight gauge, | ||
// request count, handle duration, request size, and response size | ||
func InstrumentHandlerFuncWithOpts(opts HttpHandlerOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should take the handler type, not the function type. Also, it should return a handler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stevvooe The deprecated functions uses http.HandlerFunc. I can added another wrapper that uses/returns a handler type. Do we need that ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. http.HandlerFunc
is an implementation of http.Handler
. I would generally only deal in http.Handler
for exported types, but I can see this is a specific function. Doing it the other way around would be better, since it is odd to take a method value:
func InstrumentHandlerWithOpts(ops HTTPHandlerOpts, handler http.Handler) http.Handler {
// body of this function.
}
func InstrumentHandlerFuncWithOpts(opts HttpHandlerOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.Handler {
return InstrumentHandlerWithOpts(opts, http.HandlerFunc(handlerFunc))
}
handler.go
Outdated
inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ | ||
Namespace: opts.Namespace, | ||
Subsystem: opts.Subsystem, | ||
Name: fmt.Sprintf("%s_in_flight_requests", opts.HandlerName), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't handler names be labels?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that using it is better to use labels. However the promhttp
API only allows "code" and "method" as labels:
https://godoc.org/github.com/prometheus/client_golang/prometheus/promhttp#InstrumentHandlerCounter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Label the counter before you pass it to that function. Is that possible?
The issue here is there is nothing to enforce naming standard on the handler name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can give a try to see if we can label the counter. Well, not only counter, but almost all the APIs only accept "code" and "method" as labels.
If the handler name is not standard, say use "blob-upload" instead of "blob_upload" the API will panic at run time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, these are fine then. It would be a lot easier to service-wide rollups if these are labels, but you'd have to rewrite all of these.
Looks like this is copy pasted from https://github.com/prometheus/client_golang/blob/master/prometheus/http.go#L232. Why not use the standard layout? |
Answered my own question in godoc: "- It uses Summaries rather than Histograms. Summaries are not useful if aggregation across multiple instances is required.". |
handler.go
Outdated
} | ||
responseSizeHistogram := prometheus.NewHistogramVec(responseSizeHistogramOpts, []string{}) | ||
|
||
prometheus.MustRegister(inFlightGauge, requestTotal, requestDurationHistogram, requestSizeHistogram, responseSizeHistogram) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should register with the go-metrics registry.
handler.go
Outdated
if len(responseSizeHistogramOpts.Buckets) == 0 { | ||
responseSizeHistogramOpts.Buckets = defaultResponseSizeBucket | ||
} | ||
responseSizeHistogram := prometheus.NewHistogramVec(responseSizeHistogramOpts, []string{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these need to define the buckets?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The buckets can be defined in HttpHandlerOpts. If not provided, it uses the default bucket: defaultResponseSizeBucket = prometheus.ExponentialBuckets(1024, 2, 22) //1K to 4G
handler.go
Outdated
} | ||
|
||
// HttpHandlerOpts describes a set of configurable options of http metrics | ||
type HttpHandlerOpts struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please follow Go style guidelines: HTTPHandlerOpts
.
timer.go
Outdated
@@ -36,7 +36,7 @@ type labeledTimer struct { | |||
} | |||
|
|||
func (lt *labeledTimer) WithValues(labels ...string) Timer { | |||
return &timer{m: lt.m.WithLabelValues(labels...)} | |||
return &timer{m: lt.m.WithLabelValues(labels...).(prometheus.Histogram)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is going on here? Was there a problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, due to the api change, it cannot compile against prom master now:
#12
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please send a separate PR. We may need to change the field type instead of adding a type assertion.
Ok, this generally looks okay. @cpuguy83 Did we instrument the moby api in prometheus yet? We should probably use this functions, if we can. |
.gitignore
Outdated
@@ -0,0 +1 @@ | |||
.idea/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this go into ~/.gitconfig?
I'm not crazy about the API here. Should this panic if name is empty? |
I have pushed another commit with the following changes:
|
@tifayuki I really meant that it would be good to bind the HTTP instrumentation helpers to the |
c6e608f
to
bb4f080
Compare
@stevvooe |
namespace.go
Outdated
|
||
func (n *Namespace) NewHttpMetricsWithOpts(opts HttpHandlerOpts) []*HttpMetric { | ||
if _, ok := n.labels["handler"]; !ok { | ||
panic("label \"handler\" must be provided in the namespace") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this part of the original interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so it looks like we need a specialized constructor that creates this for the particular handler. Looking at the example, it should not be required to construct the namespace with a specific label. That should be part of creating the handler metric.
namespace.go
Outdated
|
||
func (n *Namespace) NewResponseSizeMetric(buckets []float64) *HttpMetric { | ||
if len(buckets) == 0 { | ||
panic("ResponseSizeBuckets must be provided") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not provided, use a default.
handler.go
Outdated
InstrumentHandlerInFlight | ||
) | ||
|
||
type HttpMetric struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HTTPMetric
Signed-off-by: tifayuki <tifayuki@gmail.com>
Signed-off-by: tifayuki <tifayuki@gmail.com>
namespace.go
Outdated
}, | ||
[]string{"code", "method"}, | ||
) | ||
httpMetric := &HTTPMetric{metric, InstrumentHandlerCounter} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to specify the fields that these are getting set to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to fix this one.
namespace.go
Outdated
ConstLabels: prometheus.Labels(labels), | ||
} | ||
metric := prometheus.NewHistogramVec(opts, []string{"method"}) | ||
httpMetric := &HTTPMetric{metric, InstrumentHandlerDuration} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to fix this one.
namespace.go
Outdated
ConstLabels: prometheus.Labels(labels), | ||
} | ||
metric := prometheus.NewHistogramVec(opts, []string{}) | ||
httpMetric := &HTTPMetric{metric, InstrumentHandlerRequestSize} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix this one.
Signed-off-by: tifayuki <tifayuki@gmail.com>
handler.go
Outdated
} | ||
|
||
var ( | ||
defaultDurationBuckets = []float64{0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1., 2., 5., 10., 20., 30., 40., 50.} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[]float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 25, 60}
Note that I went with 60, instead of 50 at the top end.
Signed-off-by: tifayuki <tifayuki@gmail.com>
LGTM |
full diff: docker/go-metrics@4ea375f...v0.0.1 - docker/go-metrics#15 Add functions that instruments http handler using promhttp - docker/go-metrics#20 Rename LICENSE.code → LICENSE - docker/go-metrics#22 Support Go Modules Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
bump docker/go-metrics v0.0.1: full diff: docker/go-metrics@d466d4f...v0.0.1 - docker/go-metrics#16 fix the compilation error against prometheus/client-golang master - fixes docker/go-metrics#12 No longer builds against Prom master - docker/go-metrics#18 metrics: address compile error correctly - fixes docker/go-metrics#12 No longer builds against Prom master - docker/go-metrics#15 Add functions that instruments http handler using promhttp - docker/go-metrics#20 Rename LICENSE.code → LICENSE - docker/go-metrics#22 Support Go Modules bump prometheus/client_golang v0.9.4: full diff: prometheus/client_golang@c5b7fcc...v0.9.4 version v0.9.0 is the minimum required version to work with go-metrics v0.0.1, as it depends on `prometheus.Observer`: vendor/github.com/docker/go-metrics/timer.go:39:4: undefined: prometheus.Observer Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
bump docker/go-metrics v0.0.1: full diff: docker/go-metrics@d466d4f...v0.0.1 - docker/go-metrics#16 fix the compilation error against prometheus/client-golang master - fixes docker/go-metrics#12 No longer builds against Prom master - docker/go-metrics#18 metrics: address compile error correctly - fixes docker/go-metrics#12 No longer builds against Prom master - docker/go-metrics#15 Add functions that instruments http handler using promhttp - docker/go-metrics#20 Rename LICENSE.code → LICENSE - docker/go-metrics#22 Support Go Modules bump prometheus/client_golang v0.9.4: full diff: prometheus/client_golang@c5b7fcc...v0.9.4 version v0.9.0 is the minimum required version to work with go-metrics v0.0.1, as it depends on `prometheus.Observer`: vendor/github.com/docker/go-metrics/timer.go:39:4: undefined: prometheus.Observer Signed-off-by: Sebastiaan van Stijn <github@gone.nl> Upstream-commit: b2db7c8bc967b52609877f5d856c338ea51e4c46 Component: engine
full diff: docker/go-metrics@4ea375f...v0.0.1 - docker/go-metrics#15 Add functions that instruments http handler using promhttp - docker/go-metrics#20 Rename LICENSE.code → LICENSE - docker/go-metrics#22 Support Go Modules Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
In the latest prometheus go client, handlers provided before in
prometheus
package are deprecated. Instead,promhttp
package is recommended.This PR implements functions that wraps original methods in
promhttp
.It also fix the compilation error, when building against
prometheus/client-golang
master.