2013-04-03 20:33:32 +04:00
// Copyright (c) 2013, Prometheus Team
2013-03-29 00:03:01 +04:00
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
package exp
import (
"fmt"
2013-04-03 20:33:32 +04:00
"github.com/prometheus/client_golang/prometheus"
2013-03-29 00:03:01 +04:00
"net/http"
"strings"
"time"
)
const (
handler = "handler"
code = "code"
method = "method"
)
type (
coarseMux struct {
* http . ServeMux
}
handlerDelegator struct {
delegate http . Handler
pattern string
}
)
var (
2013-04-03 20:33:32 +04:00
requestCounts = prometheus . NewCounter ( )
requestDuration = prometheus . NewCounter ( )
requestDurations = prometheus . NewDefaultHistogram ( )
requestBytes = prometheus . NewCounter ( )
responseBytes = prometheus . NewCounter ( )
2013-03-29 00:03:01 +04:00
// DefaultCoarseMux is a drop-in replacement for http.DefaultServeMux that
// provides standardized telemetry for Go's standard HTTP handler registration
// and dispatch API.
//
// The name is due to the coarse grouping of telemetry by (HTTP Method, HTTP Response Code,
// and handler match pattern) triples.
DefaultCoarseMux = newCoarseMux ( )
)
func ( h handlerDelegator ) ServeHTTP ( w http . ResponseWriter , r * http . Request ) {
start := time . Now ( )
rwd := NewResponseWriterDelegator ( w )
defer func ( ) {
duration := float64 ( time . Since ( start ) / time . Microsecond )
status := rwd . Status ( )
labels := map [ string ] string { handler : h . pattern , code : status , method : strings . ToLower ( r . Method ) }
requestCounts . Increment ( labels )
requestDuration . IncrementBy ( labels , duration )
requestDurations . Add ( labels , duration )
requestBytes . IncrementBy ( labels , float64 ( computeApproximateRequestSize ( * r ) ) )
responseBytes . IncrementBy ( labels , float64 ( rwd . BytesWritten ) )
} ( )
h . delegate . ServeHTTP ( rwd , r )
}
func ( h handlerDelegator ) String ( ) string {
return fmt . Sprintf ( "handlerDelegator wrapping %s for %s" , h . delegate , h . pattern )
}
// Handle registers a http.Handler to this CoarseMux. See http.ServeMux.Handle.
func ( m * coarseMux ) handle ( pattern string , handler http . Handler ) {
m . ServeMux . Handle ( pattern , handlerDelegator {
delegate : handler ,
pattern : pattern ,
} )
}
// Handle registers a handler to this CoarseMux. See http.ServeMux.HandleFunc.
func ( m * coarseMux ) handleFunc ( pattern string , handler http . HandlerFunc ) {
m . ServeMux . Handle ( pattern , handlerDelegator {
delegate : handler ,
pattern : pattern ,
} )
}
func newCoarseMux ( ) * coarseMux {
return & coarseMux {
ServeMux : http . NewServeMux ( ) ,
}
}
// Handle registers a http.Handler to DefaultCoarseMux. See http.Handle.
func Handle ( pattern string , handler http . Handler ) {
DefaultCoarseMux . handle ( pattern , handler )
}
// HandleFunc registers a handler to DefaultCoarseMux. See http.HandleFunc.
func HandleFunc ( pattern string , handler http . HandlerFunc ) {
DefaultCoarseMux . handleFunc ( pattern , handler )
}
func init ( ) {
2013-04-03 20:33:32 +04:00
prometheus . Register ( "http_requests_total" , "A counter of the total number of HTTP requests made against the default multiplexor." , prometheus . NilLabels , requestCounts )
prometheus . Register ( "http_request_durations_total_microseconds" , "The total amount of time the default multiplexor has spent answering HTTP requests (microseconds)." , prometheus . NilLabels , requestDuration )
prometheus . Register ( "http_request_durations_microseconds" , "The amounts of time the default multiplexor has spent answering HTTP requests (microseconds)." , prometheus . NilLabels , requestDurations )
prometheus . Register ( "http_request_bytes_total" , "The total volume of content body sizes received (bytes)." , prometheus . NilLabels , requestBytes )
prometheus . Register ( "http_response_bytes_total" , "The total volume of response payloads emitted (bytes)." , prometheus . NilLabels , responseBytes )
2013-03-29 00:03:01 +04:00
}