github.com/thanos-io/thanos@v0.32.5/pkg/extprom/http/instrument_client.go (about) 1 // Copyright (c) The Thanos Authors. 2 // Licensed under the Apache License 2.0. 3 4 package http 5 6 import ( 7 "net/http" 8 9 "github.com/prometheus/client_golang/prometheus" 10 "github.com/prometheus/client_golang/prometheus/promauto" 11 "github.com/prometheus/client_golang/prometheus/promhttp" 12 ) 13 14 // ClientMetrics holds a collection of metrics that can be used to instrument a http client. 15 // By setting this field in HTTPClientConfig, NewHTTPClient will create an instrumented client. 16 type ClientMetrics struct { 17 inFlightGauge prometheus.Gauge 18 requestTotalCount *prometheus.CounterVec 19 dnsLatencyHistogram *prometheus.HistogramVec 20 tlsLatencyHistogram *prometheus.HistogramVec 21 requestDurationHistogram *prometheus.HistogramVec 22 } 23 24 // NewClientMetrics creates a new instance of ClientMetrics. 25 // It will also register the metrics with the included register. 26 // This ClientMetrics should be re-used for diff clients with the same purpose. 27 // e.g. 1 ClientMetrics should be used for all the clients that talk to Alertmanager. 28 func NewClientMetrics(reg prometheus.Registerer) *ClientMetrics { 29 var m ClientMetrics 30 31 m.inFlightGauge = promauto.With(reg).NewGauge(prometheus.GaugeOpts{ 32 Subsystem: "http_client", 33 Name: "in_flight_requests", 34 Help: "A gauge of in-flight requests.", 35 }) 36 37 m.requestTotalCount = promauto.With(reg).NewCounterVec(prometheus.CounterOpts{ 38 Subsystem: "http_client", 39 Name: "request_total", 40 Help: "Total http client request by code and method.", 41 }, []string{"code", "method"}) 42 43 m.dnsLatencyHistogram = promauto.With(reg).NewHistogramVec( 44 prometheus.HistogramOpts{ 45 Subsystem: "http_client", 46 Name: "dns_duration_seconds", 47 Help: "Trace dns latency histogram.", 48 Buckets: []float64{0.025, .05, .1, .5, 1, 5, 10}, 49 }, 50 []string{"event"}, 51 ) 52 53 m.tlsLatencyHistogram = promauto.With(reg).NewHistogramVec( 54 prometheus.HistogramOpts{ 55 Subsystem: "http_client", 56 Name: "tls_duration_seconds", 57 Help: "Trace tls latency histogram.", 58 Buckets: []float64{0.025, .05, .1, .5, 1, 5, 10}, 59 }, 60 []string{"event"}, 61 ) 62 63 m.requestDurationHistogram = promauto.With(reg).NewHistogramVec( 64 prometheus.HistogramOpts{ 65 Subsystem: "http_client", 66 Name: "request_duration_seconds", 67 Help: "A histogram of request latencies.", 68 Buckets: []float64{0.025, .05, .1, .5, 1, 5, 10}, 69 }, 70 []string{"code", "method"}, 71 ) 72 73 return &m 74 } 75 76 // InstrumentedRoundTripper instruments the given roundtripper with metrics that are 77 // registered in the provided ClientMetrics. 78 func InstrumentedRoundTripper(tripper http.RoundTripper, m *ClientMetrics) http.RoundTripper { 79 if m == nil { 80 return tripper 81 } 82 83 trace := &promhttp.InstrumentTrace{ 84 DNSStart: func(t float64) { 85 m.dnsLatencyHistogram.WithLabelValues("dns_start").Observe(t) 86 }, 87 DNSDone: func(t float64) { 88 m.dnsLatencyHistogram.WithLabelValues("dns_done").Observe(t) 89 }, 90 TLSHandshakeStart: func(t float64) { 91 m.tlsLatencyHistogram.WithLabelValues("tls_handshake_start").Observe(t) 92 }, 93 TLSHandshakeDone: func(t float64) { 94 m.tlsLatencyHistogram.WithLabelValues("tls_handshake_done").Observe(t) 95 }, 96 } 97 98 return promhttp.InstrumentRoundTripperInFlight( 99 m.inFlightGauge, 100 promhttp.InstrumentRoundTripperCounter( 101 m.requestTotalCount, 102 promhttp.InstrumentRoundTripperTrace( 103 trace, 104 promhttp.InstrumentRoundTripperDuration( 105 m.requestDurationHistogram, 106 tripper, 107 ), 108 ), 109 ), 110 ) 111 }