promhttp

package
v0.9.0-pre1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2017 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package promhttp provides tooling around HTTP servers and clients.

First, the package allows the creation of http.Handler instances to expose Prometheus metrics via HTTP. promhttp.Handler acts on the prometheus.DefaultGatherer. With HandlerFor, you can create a handler for a custom registry or anything that implements the Gatherer interface. It also allows the creation of handlers that act differently on errors or allow to log errors.

Second, the package provides tooling to instrument instances of http.Handler via middleware. Middleware wrappers follow the naming scheme InstrumentHandlerX, where X describes the intended use of the middleware. See each function's doc comment for specific details.

Finally, the package allows for an http.RoundTripper to be instrumented via middleware. Middleware wrappers follow the naming scheme InstrumentRoundTripperX, where X describes the intended use of the middleware. See each function's doc comment for specific details.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Handler

func Handler() http.Handler

Handler returns an HTTP handler for the prometheus.DefaultGatherer. The Handler uses the default HandlerOpts, i.e. report the first error as an HTTP error, no error logging, and compression if requested by the client.

If you want to create a Handler for the DefaultGatherer with different HandlerOpts, create it with HandlerFor with prometheus.DefaultGatherer and your desired HandlerOpts.

func HandlerFor

func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler

HandlerFor returns an http.Handler for the provided Gatherer. The behavior of the Handler is defined by the provided HandlerOpts.

func InstrumentHandlerCounter

func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc

InstrumentHandlerCounter is a middleware that wraps the provided http.Handler to observe the request result with the provided CounterVec. The CounterVec must have zero, one, or two labels. The only allowed label names are "code" and "method". The function panics if any other instance labels are provided. Partitioning of the CounterVec happens by HTTP status code and/or HTTP method if the respective instance label names are present in the CounterVec. For unpartitioned counting, use a CounterVec with zero labels.

If the wrapped Handler does not set a status code, a status code of 200 is assumed.

If the wrapped Handler panics, the Counter is not incremented.

See the example for InstrumentHandlerDuration for example usage.

func InstrumentHandlerDuration

func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc

InstrumentHandlerDuration is a middleware that wraps the provided http.Handler to observe the request duration with the provided ObserverVec. The ObserverVec must have zero, one, or two labels. The only allowed label names are "code" and "method". The function panics if any other instance labels are provided. The Observe method of the Observer in the ObserverVec is called with the request duration in seconds. Partitioning happens by HTTP status code and/or HTTP method if the respective instance label names are present in the ObserverVec. For unpartitioned observations, use an ObserverVec with zero labels. Note that partitioning of Histograms is expensive and should be used judiciously.

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+.

Example
inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{
	Name: "in_flight_requests",
	Help: "A gauge of requests currently being served by the wrapped handler.",
})

counter := prometheus.NewCounterVec(
	prometheus.CounterOpts{
		Name: "api_requests_total",
		Help: "A counter for requests to the wrapped handler.",
	},
	[]string{"code", "method"},
)

// pushVec and pullVec are partitioned by the HTTP method and use custom
// buckets based on the expected request duration. ConstLabels are used
// to set a handler label to mark pushVec as tracking the durations for
// pushes and pullVec as tracking the durations for pulls. Note that
// Name, Help, and Buckets need to be the same for consistency, so we
// use the same HistogramOpts after just modifying the ConstLabels.
histogramOpts := prometheus.HistogramOpts{
	Name:        "request_duration_seconds",
	Help:        "A histogram of latencies for requests.",
	Buckets:     []float64{.25, .5, 1, 2.5, 5, 10},
	ConstLabels: prometheus.Labels{"handler": "push"},
}
pushVec := prometheus.NewHistogramVec(
	histogramOpts,
	[]string{"method"},
)
histogramOpts.ConstLabels = prometheus.Labels{"handler": "pull"}
pullVec := prometheus.NewHistogramVec(
	histogramOpts,
	[]string{"method"},
)

// responseSize has no labels, making it a zero-dimensional
// ObserverVec.
responseSize := prometheus.NewHistogramVec(
	prometheus.HistogramOpts{
		Name:    "response_size_bytes",
		Help:    "A histogram of response sizes for requests.",
		Buckets: []float64{200, 500, 900, 1500},
	},
	[]string{},
)

// Create the handlers that will be wrapped by the middleware.
pushHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Push"))
})
pullHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Pull"))
})

// Register all of the metrics in the standard registry.
prometheus.MustRegister(inFlightGauge, counter, pullVec, pushVec, responseSize)

// Wrap the pushHandler with our shared middleware, but use the
// endpoint-specific pushVec with InstrumentHandlerDuration.
pushChain := InstrumentHandlerInFlight(inFlightGauge,
	InstrumentHandlerCounter(counter,
		InstrumentHandlerDuration(pushVec,
			InstrumentHandlerResponseSize(responseSize, pushHandler),
		),
	),
)

// Wrap the pushHandler with the shared middleware, but use the
// endpoint-specific pullVec with InstrumentHandlerDuration.
pullChain := InstrumentHandlerInFlight(inFlightGauge,
	InstrumentHandlerCounter(counter,
		InstrumentHandlerDuration(pullVec,
			InstrumentHandlerResponseSize(responseSize, pullHandler),
		),
	),
)

http.Handle("/metrics", Handler())
http.Handle("/push", pushChain)
http.Handle("/pull", pullChain)

if err := http.ListenAndServe(":3000", nil); err != nil {
	log.Fatal(err)
}
Output:

func InstrumentHandlerInFlight

func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handler

InstrumentHandlerInFlight is a middleware that wraps the provided http.Handler. It sets the provided prometheus.Gauge to the number of requests currently handled by the wrapped http.Handler.

See the example for InstrumentHandlerDuration for example usage.

func InstrumentHandlerRequestSize

func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc

InstrumentHandlerRequestSize is a middleware that wraps the provided http.Handler to observe the request size with the provided ObserverVec. The ObserverVec must have zero, one, or two labels. The only allowed label names are "code" and "method". The function panics if any other instance labels are provided. The Observe method of the Observer in the ObserverVec is called with the request size in bytes. Partitioning happens by HTTP status code and/or HTTP method if the respective instance label names are present in the ObserverVec. For unpartitioned observations, use an ObserverVec with zero labels. Note that partitioning of Histograms is expensive and should be used judiciously.

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.

See the example for InstrumentHandlerDuration for example usage.

func InstrumentHandlerResponseSize

func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler

InstrumentHandlerResponseSize is a middleware that wraps the provided http.Handler to observe the response size with the provided ObserverVec. The ObserverVec must have zero, one, or two labels. The only allowed label names are "code" and "method". The function panics if any other instance labels are provided. The Observe method of the Observer in the ObserverVec is called with the response size in bytes. Partitioning happens by HTTP status code and/or HTTP method if the respective instance label names are present in the ObserverVec. For unpartitioned observations, use an ObserverVec with zero labels. Note that partitioning of Histograms is expensive and should be used judiciously.

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.

See the example for InstrumentHandlerDuration for example usage.

func InstrumentHandlerTimeToWriteHeader

func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc

InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided http.Handler to observe with the provided ObserverVec the request duration until the response headers are written. The ObserverVec must have zero, one, or two labels. The only allowed label names are "code" and "method". The function panics if any other instance labels are provided. The Observe method of the Observer in the ObserverVec is called with the request duration in seconds. Partitioning happens by HTTP status code and/or HTTP method if the respective instance label names are present in the ObserverVec. For unpartitioned observations, use an ObserverVec with zero labels. Note that partitioning of Histograms is expensive and should be used judiciously.

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.

Types

type HandlerErrorHandling

type HandlerErrorHandling int

HandlerErrorHandling defines how a Handler serving metrics will handle errors.

const (
	// Serve an HTTP status code 500 upon the first error
	// encountered. Report the error message in the body.
	HTTPErrorOnError HandlerErrorHandling = iota
	// Ignore errors and try to serve as many metrics as possible.  However,
	// if no metrics can be served, serve an HTTP status code 500 and the
	// last error message in the body. Only use this in deliberate "best
	// effort" metrics collection scenarios. It is recommended to at least
	// log errors (by providing an ErrorLog in HandlerOpts) to not mask
	// errors completely.
	ContinueOnError
	// Panic upon the first error encountered (useful for "crash only" apps).
	PanicOnError
)

These constants cause handlers serving metrics to behave as described if errors are encountered.

type HandlerOpts

type HandlerOpts struct {
	// ErrorLog specifies an optional logger for errors collecting and
	// serving metrics. If nil, errors are not logged at all.
	ErrorLog Logger
	// ErrorHandling defines how errors are handled. Note that errors are
	// logged regardless of the configured ErrorHandling provided ErrorLog
	// is not nil.
	ErrorHandling HandlerErrorHandling
	// If DisableCompression is true, the handler will never compress the
	// response, even if requested by the client.
	DisableCompression bool
}

HandlerOpts specifies options how to serve metrics via an http.Handler. The zero value of HandlerOpts is a reasonable default.

type InstrumentTrace

type InstrumentTrace struct {
	GotConn              func(float64)
	PutIdleConn          func(float64)
	GotFirstResponseByte func(float64)
	Got100Continue       func(float64)
	DNSStart             func(float64)
	DNSDone              func(float64)
	ConnectStart         func(float64)
	ConnectDone          func(float64)
	TLSHandshakeStart    func(float64)
	TLSHandshakeDone     func(float64)
	WroteHeaders         func(float64)
	Wait100Continue      func(float64)
	WroteRequest         func(float64)
}

InstrumentTrace is used to offer flexibility in instrumenting the available httptrace.ClientTrace hook functions. Each function is passed a float64 representing the time in seconds since the start of the http request. A user may choose to use separately buckets Histograms, or implement custom instance labels on a per function basis.

type Logger

type Logger interface {
	Println(v ...interface{})
}

Logger is the minimal interface HandlerOpts needs for logging. Note that log.Logger from the standard library implements this interface, and it is easy to implement by custom loggers, if they don't do so already anyway.

type RoundTripperFunc

type RoundTripperFunc func(req *http.Request) (*http.Response, error)

The RoundTripperFunc type is an adapter to allow the use of ordinary functions as RoundTrippers. If f is a function with the appropriate signature, RountTripperFunc(f) is a RoundTripper that calls f.

func InstrumentRoundTripperCounter

func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc

InstrumentRoundTripperCounter is a middleware that wraps the provided http.RoundTripper to observe the request result with the provided CounterVec. The CounterVec must have zero, one, or two labels. The only allowed label names are "code" and "method". The function panics if any other instance labels are provided. Partitioning of the CounterVec happens by HTTP status code and/or HTTP method if the respective instance label names are present in the CounterVec. For unpartitioned counting, use a CounterVec with zero labels.

If the wrapped RoundTripper panics or returns a non-nil error, the Counter is not incremented.

See the example for ExampleInstrumentRoundTripperDuration for example usage.

func InstrumentRoundTripperDuration

func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc

InstrumentRoundTripperDuration is a middleware that wraps the provided http.RoundTripper to observe the request duration with the provided ObserverVec. The ObserverVec must have zero, one, or two labels. The only allowed label names are "code" and "method". The function panics if any other instance labels are provided. The Observe method of the Observer in the ObserverVec is called with the request duration in seconds. Partitioning happens by HTTP status code and/or HTTP method if the respective instance label names are present in the ObserverVec. For unpartitioned observations, use an ObserverVec with zero labels. Note that partitioning of Histograms is expensive and should be used judiciously.

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+.

Example
client := http.DefaultClient
client.Timeout = 1 * time.Second

inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{
	Name: "client_in_flight_requests",
	Help: "A gauge of in-flight requests for the wrapped client.",
})

counter := prometheus.NewCounterVec(
	prometheus.CounterOpts{
		Name: "client_api_requests_total",
		Help: "A counter for requests from the wrapped client.",
	},
	[]string{"code", "method"},
)

// dnsLatencyVec uses custom buckets based on expected dns durations.
// It has an instance label "event", which is set in the
// DNSStart and DNSDonehook functions defined in the
// InstrumentTrace struct below.
dnsLatencyVec := prometheus.NewHistogramVec(
	prometheus.HistogramOpts{
		Name:    "dns_duration_seconds",
		Help:    "Trace dns latency histogram.",
		Buckets: []float64{.005, .01, .025, .05},
	},
	[]string{"event"},
)

// tlsLatencyVec uses custom buckets based on expected tls durations.
// It has an instance label "event", which is set in the
// TLSHandshakeStart and TLSHandshakeDone hook functions defined in the
// InstrumentTrace struct below.
tlsLatencyVec := prometheus.NewHistogramVec(
	prometheus.HistogramOpts{
		Name:    "tls_duration_seconds",
		Help:    "Trace tls latency histogram.",
		Buckets: []float64{.05, .1, .25, .5},
	},
	[]string{"event"},
)

// histVec has no labels, making it a zero-dimensional ObserverVec.
histVec := prometheus.NewHistogramVec(
	prometheus.HistogramOpts{
		Name:    "request_duration_seconds",
		Help:    "A histogram of request latencies.",
		Buckets: prometheus.DefBuckets,
	},
	[]string{},
)

// Register all of the metrics in the standard registry.
prometheus.MustRegister(counter, tlsLatencyVec, dnsLatencyVec, histVec, inFlightGauge)

// Define functions for the available httptrace.ClientTrace hook
// functions that we want to instrument.
trace := &InstrumentTrace{
	DNSStart: func(t float64) {
		dnsLatencyVec.WithLabelValues("dns_start")
	},
	DNSDone: func(t float64) {
		dnsLatencyVec.WithLabelValues("dns_done")
	},
	TLSHandshakeStart: func(t float64) {
		tlsLatencyVec.WithLabelValues("tls_handshake_start")
	},
	TLSHandshakeDone: func(t float64) {
		tlsLatencyVec.WithLabelValues("tls_handshake_done")
	},
}

// Wrap the default RoundTripper with middleware.
roundTripper := InstrumentRoundTripperInFlight(inFlightGauge,
	InstrumentRoundTripperCounter(counter,
		InstrumentRoundTripperTrace(trace,
			InstrumentRoundTripperDuration(histVec, http.DefaultTransport),
		),
	),
)

// Set the RoundTripper on our client.
client.Transport = roundTripper

resp, err := client.Get("http://google.com")
if err != nil {
	log.Printf("error: %v", err)
}
defer resp.Body.Close()
Output:

func InstrumentRoundTripperInFlight

func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc

InstrumentRoundTripperInFlight is a middleware that wraps the provided http.RoundTripper. It sets the provided prometheus.Gauge to the number of requests currently handled by the wrapped http.RoundTripper.

See the example for ExampleInstrumentRoundTripperDuration for example usage.

func InstrumentRoundTripperTrace

func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc

InstrumentRoundTripperTrace is a middleware that wraps the provided 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. 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.

See the example for ExampleInstrumentRoundTripperDuration for example usage.

func (RoundTripperFunc) RoundTrip

func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip implements the RoundTripper interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL