@@ -108,6 +108,40 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler)
108108 })
109109}
110110
111+ // InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided
112+ // http.Handler to observe with the provided ObserverVec the request duration
113+ // until the response headers are written. The ObserverVec must have zero, one,
114+ // or two labels. The only allowed label names are "code" and "method". The
115+ // function panics if any other instance labels are provided. The Observe
116+ // method of the Observer in the ObserverVec is called with the request
117+ // duration in seconds. Partitioning happens by HTTP status code and/or HTTP
118+ // method if the respective instance label names are present in the
119+ // ObserverVec. For unpartitioned observations, use an ObserverVec with zero
120+ // labels. Note that partitioning of Histograms is expensive and should be used
121+ // judiciously.
122+ //
123+ // If the wrapped Handler does not set a status code via WriteHeader, no value
124+ // is reported.
125+ //
126+ // If the wrapped Handler panics before calling WriteHeader, no value is
127+ // reported.
128+ //
129+ // See the example for InstrumentHandlerDuration for example usage.
130+ func InstrumentHandlerTimeToWriteHeader (obs prometheus.ObserverVec , next http.Handler ) http.HandlerFunc {
131+ code , method := checkLabels (obs )
132+
133+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
134+ now := time .Now ()
135+ d := & wroteHeaderDelegator {
136+ delegator : newDelegator (w ),
137+ observeWriteHeader : func (status int ) {
138+ obs .With (labels (code , method , r .Method , status )).Observe (time .Since (now ).Seconds ())
139+ },
140+ }
141+ next .ServeHTTP (d , r )
142+ })
143+ }
144+
111145// InstrumentHandlerRequestSize is a middleware that wraps the provided
112146// http.Handler to observe the request size with the provided ObserverVec.
113147// The ObserverVec must have zero, one, or two labels. The only allowed label
@@ -415,6 +449,19 @@ type delegator interface {
415449 http.ResponseWriter
416450}
417451
452+ type wroteHeaderDelegator struct {
453+ observeWriteHeader func (int )
454+
455+ delegator
456+ }
457+
458+ func (r * wroteHeaderDelegator ) WriteHeader (code int ) {
459+ r .delegator .WriteHeader (code )
460+ if r .observeWriteHeader != nil {
461+ r .observeWriteHeader (code )
462+ }
463+ }
464+
418465type responseWriterDelegator struct {
419466 http.ResponseWriter
420467
0 commit comments