Add gzip support.
Change-Id: I6ea6e0dcbe7234ad143403d262da6cb40e7d3b50
This commit is contained in:
parent
457bc47eac
commit
23e5e5fefd
|
@ -28,10 +28,12 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"compress/gzip"
|
||||||
"code.google.com/p/goprotobuf/proto"
|
"code.google.com/p/goprotobuf/proto"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/_vendor/goautoneg"
|
"github.com/prometheus/client_golang/_vendor/goautoneg"
|
||||||
|
@ -74,8 +76,12 @@ const (
|
||||||
capMetricChan = 1000
|
capMetricChan = 1000
|
||||||
capDescChan = 10
|
capDescChan = 10
|
||||||
|
|
||||||
contentTypeHeader = "Content-Type"
|
contentTypeHeader = "Content-Type"
|
||||||
contentLengthHeader = "Content-Length"
|
contentLengthHeader = "Content-Length"
|
||||||
|
contentEncodingHeader = "Content-Encoding"
|
||||||
|
|
||||||
|
acceptEncodingHeader = "Accept-Encoding"
|
||||||
|
acceptHeader = "Accept"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler returns the HTTP handler for the global Prometheus registry. It is
|
// Handler returns the HTTP handler for the global Prometheus registry. It is
|
||||||
|
@ -370,16 +376,23 @@ func (r *registry) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
enc, contentType := chooseEncoder(req)
|
enc, contentType := chooseEncoder(req)
|
||||||
buf := r.getBuf()
|
buf := r.getBuf()
|
||||||
defer r.giveBuf(buf)
|
defer r.giveBuf(buf)
|
||||||
if _, err := r.writePB(buf, enc); err != nil {
|
writer, encoding := decorateWriter(req, buf)
|
||||||
|
if _, err := r.writePB(writer, enc); err != nil {
|
||||||
if r.panicOnCollectError {
|
if r.panicOnCollectError {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
http.Error(w, "An error has occurred:\n\n"+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "An error has occurred:\n\n"+err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if closer, ok := writer.(io.Closer); ok {
|
||||||
|
closer.Close()
|
||||||
|
}
|
||||||
header := w.Header()
|
header := w.Header()
|
||||||
header.Set(contentTypeHeader, contentType)
|
header.Set(contentTypeHeader, contentType)
|
||||||
header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
|
header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
|
||||||
|
if encoding != "" {
|
||||||
|
header.Set(contentEncodingHeader, encoding)
|
||||||
|
}
|
||||||
w.Write(buf.Bytes())
|
w.Write(buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +635,7 @@ func newRegistry() *registry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func chooseEncoder(req *http.Request) (encoder, string) {
|
func chooseEncoder(req *http.Request) (encoder, string) {
|
||||||
accepts := goautoneg.ParseAccept(req.Header.Get("Accept"))
|
accepts := goautoneg.ParseAccept(req.Header.Get(acceptHeader))
|
||||||
for _, accept := range accepts {
|
for _, accept := range accepts {
|
||||||
switch {
|
switch {
|
||||||
case accept.Type == "application" &&
|
case accept.Type == "application" &&
|
||||||
|
@ -649,6 +662,21 @@ func chooseEncoder(req *http.Request) (encoder, string) {
|
||||||
return text.MetricFamilyToText, TextTelemetryContentType
|
return text.MetricFamilyToText, TextTelemetryContentType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decorateWriter wraps a writer to handle gzip compression if requested. It
|
||||||
|
// returns the decorated writer and the appropriate "Content-Encoding" header
|
||||||
|
// (which is empty if no compression is enabled).
|
||||||
|
func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string) {
|
||||||
|
header := request.Header.Get(acceptEncodingHeader)
|
||||||
|
parts := strings.Split(header, ",")
|
||||||
|
for _, part := range parts {
|
||||||
|
part := strings.TrimSpace(part)
|
||||||
|
if part == "gzip" || strings.HasPrefix(part, "gzip;") {
|
||||||
|
return gzip.NewWriter(writer), "gzip"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return writer, ""
|
||||||
|
}
|
||||||
|
|
||||||
type metricSorter []*dto.Metric
|
type metricSorter []*dto.Metric
|
||||||
|
|
||||||
func (s metricSorter) Len() int {
|
func (s metricSorter) Len() int {
|
||||||
|
|
Loading…
Reference in New Issue