diff --git a/prometheus/promhttp/instrument_client.go b/prometheus/promhttp/instrument_client.go index 1cf21f2..65f9425 100644 --- a/prometheus/promhttp/instrument_client.go +++ b/prometheus/promhttp/instrument_client.go @@ -81,6 +81,9 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou // // If the wrapped RoundTripper panics or returns a non-nil error, no values are // reported. +// +// Note that this method is only guaranteed to never observe negative durations +// if used with Go1.9+. func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc { code, method := checkLabels(obs) diff --git a/prometheus/promhttp/instrument_client_1_8.go b/prometheus/promhttp/instrument_client_1_8.go index b51d910..0bd80c3 100644 --- a/prometheus/promhttp/instrument_client_1_8.go +++ b/prometheus/promhttp/instrument_client_1_8.go @@ -48,8 +48,10 @@ type InstrumentTrace struct { // RoundTripper and reports times to hook functions provided in the // InstrumentTrace struct. Hook functions that are not present in the provided // InstrumentTrace struct are ignored. Times reported to the hook functions are -// time since the start of the request. Note that partitioning of Histograms -// is expensive and should be used judiciously. +// time since the start of the request. Only with Go1.9+, those times are +// guaranteed to never be negative. (Earlier Go versions are not using a +// monotonic clock.) Note that partitioning of Histograms is expensive and +// should be used judiciously. // // For hook functions that receive an error as an argument, no observations are // made in the event of a non-nil error value. diff --git a/prometheus/promhttp/instrument_server.go b/prometheus/promhttp/instrument_server.go index a9b9649..3d145ad 100644 --- a/prometheus/promhttp/instrument_server.go +++ b/prometheus/promhttp/instrument_server.go @@ -54,6 +54,9 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // If the wrapped Handler does not set a status code, a status code of 200 is assumed. // // If the wrapped Handler panics, no values are reported. +// +// Note that this method is only guaranteed to never observe negative durations +// if used with Go1.9+. func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { code, method := checkLabels(obs) @@ -120,6 +123,9 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) // If the wrapped Handler panics before calling WriteHeader, no value is // reported. // +// Note that this method is only guaranteed to never observe negative durations +// if used with Go1.9+. +// // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { code, method := checkLabels(obs) diff --git a/prometheus/push/example_add_from_gatherer_test.go b/prometheus/push/example_add_from_gatherer_test.go index dd5c10a..5180c07 100644 --- a/prometheus/push/example_add_from_gatherer_test.go +++ b/prometheus/push/example_add_from_gatherer_test.go @@ -61,6 +61,7 @@ func ExampleAddFromGatherer() { start := time.Now() n, err := performBackup() records.Set(float64(n)) + // Note that time.Since only uses a monotonic clock in Go1.9+. duration.Set(time.Since(start).Seconds()) completionTime.SetToCurrentTime() if err != nil { diff --git a/prometheus/timer.go b/prometheus/timer.go index 12b6569..b8fc5f1 100644 --- a/prometheus/timer.go +++ b/prometheus/timer.go @@ -41,6 +41,9 @@ func NewTimer(o Observer) *Timer { // NewTimer. It calls the Observe method of the Observer provided during // construction with the duration in seconds as an argument. ObserveDuration is // usually called with a defer statement. +// +// Note that this method is only guaranteed to never observe negative durations +// if used with Go1.9+. func (t *Timer) ObserveDuration() { if t.observer != nil { t.observer.Observe(time.Since(t.begin).Seconds())