instrument_client.go 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2017 The Prometheus Authors
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package promhttp
  14. import (
  15. "net/http"
  16. "time"
  17. "github.com/prometheus/client_golang/prometheus"
  18. )
  19. // The RoundTripperFunc type is an adapter to allow the use of ordinary
  20. // functions as RoundTrippers. If f is a function with the appropriate
  21. // signature, RountTripperFunc(f) is a RoundTripper that calls f.
  22. type RoundTripperFunc func(req *http.Request) (*http.Response, error)
  23. // RoundTrip implements the RoundTripper interface.
  24. func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) {
  25. return rt(r)
  26. }
  27. // InstrumentRoundTripperInFlight is a middleware that wraps the provided
  28. // http.RoundTripper. It sets the provided prometheus.Gauge to the number of
  29. // requests currently handled by the wrapped http.RoundTripper.
  30. //
  31. // See the example for ExampleInstrumentRoundTripperDuration for example usage.
  32. func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc {
  33. return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
  34. gauge.Inc()
  35. defer gauge.Dec()
  36. return next.RoundTrip(r)
  37. })
  38. }
  39. // InstrumentRoundTripperCounter is a middleware that wraps the provided
  40. // http.RoundTripper to observe the request result with the provided CounterVec.
  41. // The CounterVec must have zero, one, or two non-const non-curried labels. For
  42. // those, the only allowed label names are "code" and "method". The function
  43. // panics otherwise. Partitioning of the CounterVec happens by HTTP status code
  44. // and/or HTTP method if the respective instance label names are present in the
  45. // CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
  46. //
  47. // If the wrapped RoundTripper panics or returns a non-nil error, the Counter
  48. // is not incremented.
  49. //
  50. // See the example for ExampleInstrumentRoundTripperDuration for example usage.
  51. func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc {
  52. code, method := checkLabels(counter)
  53. return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
  54. resp, err := next.RoundTrip(r)
  55. if err == nil {
  56. counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc()
  57. }
  58. return resp, err
  59. })
  60. }
  61. // InstrumentRoundTripperDuration is a middleware that wraps the provided
  62. // http.RoundTripper to observe the request duration with the provided
  63. // ObserverVec. The ObserverVec must have zero, one, or two non-const
  64. // non-curried labels. For those, the only allowed label names are "code" and
  65. // "method". The function panics otherwise. The Observe method of the Observer
  66. // in the ObserverVec is called with the request duration in
  67. // seconds. Partitioning happens by HTTP status code and/or HTTP method if the
  68. // respective instance label names are present in the ObserverVec. For
  69. // unpartitioned observations, use an ObserverVec with zero labels. Note that
  70. // partitioning of Histograms is expensive and should be used judiciously.
  71. //
  72. // If the wrapped RoundTripper panics or returns a non-nil error, no values are
  73. // reported.
  74. //
  75. // Note that this method is only guaranteed to never observe negative durations
  76. // if used with Go1.9+.
  77. func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc {
  78. code, method := checkLabels(obs)
  79. return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
  80. start := time.Now()
  81. resp, err := next.RoundTrip(r)
  82. if err == nil {
  83. obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds())
  84. }
  85. return resp, err
  86. })
  87. }