Merge pull request #172 from prometheus/move-to-common

Move from client_golang/text to common/expfmt
This commit is contained in:
Björn Rabenstein 2015-09-17 14:37:51 +02:00
commit 13985ab413
1 changed files with 14 additions and 47 deletions

View File

@ -33,12 +33,10 @@ import (
"strings" "strings"
"sync" "sync"
"bitbucket.org/ww/goautoneg"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/prometheus/common/expfmt"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
"github.com/prometheus/client_golang/text"
) )
var ( var (
@ -345,7 +343,7 @@ func (r *registry) Push(job, instance, pushURL, method string) error {
} }
buf := r.getBuf() buf := r.getBuf()
defer r.giveBuf(buf) defer r.giveBuf(buf)
if _, err := r.writePB(buf, text.WriteProtoDelimited); err != nil { if err := r.writePB(expfmt.NewEncoder(buf, expfmt.FmtProtoDelim)); err != nil {
if r.panicOnCollectError { if r.panicOnCollectError {
panic(err) panic(err)
} }
@ -368,11 +366,11 @@ func (r *registry) Push(job, instance, pushURL, method string) error {
} }
func (r *registry) ServeHTTP(w http.ResponseWriter, req *http.Request) { func (r *registry) ServeHTTP(w http.ResponseWriter, req *http.Request) {
enc, contentType := chooseEncoder(req) contentType := expfmt.Negotiate(req.Header)
buf := r.getBuf() buf := r.getBuf()
defer r.giveBuf(buf) defer r.giveBuf(buf)
writer, encoding := decorateWriter(req, buf) writer, encoding := decorateWriter(req, buf)
if _, err := r.writePB(writer, enc); err != nil { if err := r.writePB(expfmt.NewEncoder(writer, contentType)); err != nil {
if r.panicOnCollectError { if r.panicOnCollectError {
panic(err) panic(err)
} }
@ -383,7 +381,7 @@ func (r *registry) ServeHTTP(w http.ResponseWriter, req *http.Request) {
closer.Close() closer.Close()
} }
header := w.Header() header := w.Header()
header.Set(contentTypeHeader, contentType) header.Set(contentTypeHeader, string(contentType))
header.Set(contentLengthHeader, fmt.Sprint(buf.Len())) header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
if encoding != "" { if encoding != "" {
header.Set(contentEncodingHeader, encoding) header.Set(contentEncodingHeader, encoding)
@ -391,7 +389,7 @@ func (r *registry) ServeHTTP(w http.ResponseWriter, req *http.Request) {
w.Write(buf.Bytes()) w.Write(buf.Bytes())
} }
func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) { func (r *registry) writePB(encoder expfmt.Encoder) error {
var metricHashes map[uint64]struct{} var metricHashes map[uint64]struct{}
if r.collectChecksEnabled { if r.collectChecksEnabled {
metricHashes = make(map[uint64]struct{}) metricHashes = make(map[uint64]struct{})
@ -443,7 +441,7 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
// TODO: Consider different means of error reporting so // TODO: Consider different means of error reporting so
// that a single erroneous metric could be skipped // that a single erroneous metric could be skipped
// instead of blowing up the whole collection. // instead of blowing up the whole collection.
return 0, fmt.Errorf("error collecting metric %v: %s", desc, err) return fmt.Errorf("error collecting metric %v: %s", desc, err)
} }
switch { switch {
case metricFamily.Type != nil: case metricFamily.Type != nil:
@ -459,11 +457,11 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
case dtoMetric.Histogram != nil: case dtoMetric.Histogram != nil:
metricFamily.Type = dto.MetricType_HISTOGRAM.Enum() metricFamily.Type = dto.MetricType_HISTOGRAM.Enum()
default: default:
return 0, fmt.Errorf("empty metric collected: %s", dtoMetric) return fmt.Errorf("empty metric collected: %s", dtoMetric)
} }
if r.collectChecksEnabled { if r.collectChecksEnabled {
if err := r.checkConsistency(metricFamily, dtoMetric, desc, metricHashes); err != nil { if err := r.checkConsistency(metricFamily, dtoMetric, desc, metricHashes); err != nil {
return 0, err return err
} }
} }
metricFamily.Metric = append(metricFamily.Metric, dtoMetric) metricFamily.Metric = append(metricFamily.Metric, dtoMetric)
@ -477,7 +475,7 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
if r.collectChecksEnabled { if r.collectChecksEnabled {
for _, m := range mf.Metric { for _, m := range mf.Metric {
if err := r.checkConsistency(mf, m, nil, metricHashes); err != nil { if err := r.checkConsistency(mf, m, nil, metricHashes); err != nil {
return 0, err return err
} }
} }
} }
@ -486,7 +484,7 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
for _, m := range mf.Metric { for _, m := range mf.Metric {
if r.collectChecksEnabled { if r.collectChecksEnabled {
if err := r.checkConsistency(existingMF, m, nil, metricHashes); err != nil { if err := r.checkConsistency(existingMF, m, nil, metricHashes); err != nil {
return 0, err return err
} }
} }
existingMF.Metric = append(existingMF.Metric, m) existingMF.Metric = append(existingMF.Metric, m)
@ -507,15 +505,12 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
} }
sort.Strings(names) sort.Strings(names)
var written int
for _, name := range names { for _, name := range names {
w, err := writeEncoded(w, metricFamiliesByName[name]) if err := encoder.Encode(metricFamiliesByName[name]); err != nil {
written += w return err
if err != nil {
return written, err
} }
} }
return written, nil return nil
} }
func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *dto.Metric, desc *Desc, metricHashes map[uint64]struct{}) error { func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *dto.Metric, desc *Desc, metricHashes map[uint64]struct{}) error {
@ -685,34 +680,6 @@ func newDefaultRegistry() *registry {
return r return r
} }
func chooseEncoder(req *http.Request) (encoder, string) {
accepts := goautoneg.ParseAccept(req.Header.Get(acceptHeader))
for _, accept := range accepts {
switch {
case accept.Type == "application" &&
accept.SubType == "vnd.google.protobuf" &&
accept.Params["proto"] == "io.prometheus.client.MetricFamily":
switch accept.Params["encoding"] {
case "delimited":
return text.WriteProtoDelimited, DelimitedTelemetryContentType
case "text":
return text.WriteProtoText, ProtoTextTelemetryContentType
case "compact-text":
return text.WriteProtoCompactText, ProtoCompactTextTelemetryContentType
default:
continue
}
case accept.Type == "text" &&
accept.SubType == "plain" &&
(accept.Params["version"] == "0.0.4" || accept.Params["version"] == ""):
return text.MetricFamilyToText, TextTelemetryContentType
default:
continue
}
}
return text.MetricFamilyToText, TextTelemetryContentType
}
// decorateWriter wraps a writer to handle gzip compression if requested. It // decorateWriter wraps a writer to handle gzip compression if requested. It
// returns the decorated writer and the appropriate "Content-Encoding" header // returns the decorated writer and the appropriate "Content-Encoding" header
// (which is empty if no compression is enabled). // (which is empty if no compression is enabled).