diff --git a/expfmt/encode.go b/expfmt/encode.go index ba55fba4..76a812a7 100644 --- a/expfmt/encode.go +++ b/expfmt/encode.go @@ -27,6 +27,24 @@ import ( "github.com/prometheus/common/model" ) +var formatToAccept = map[Format]goautoneg.Accept{} + +func init() { + for _, f := range []Format{ + FmtText, + FmtProtoDelim, + FmtProtoText, + FmtProtoCompact, + FmtOpenMetrics_1_0_0, + fmtOpenMetrics_2_0_0, + FmtOpenMetrics_0_0_1, + } { + if parsed := goautoneg.ParseAccept(string(f)); len(parsed) > 0 { + formatToAccept[f] = parsed[0] + } + } +} + // Encoder types encode metric families into an underlying wire protocol. type Encoder interface { Encode(*dto.MetricFamily) error @@ -81,7 +99,7 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format { // format if present in the accepted list, or the first accepted format (or FmtText // if accepted is empty). func NegotiateAccept(h http.Header, accepted ...Format) Format { - escapingScheme := Format(fmt.Sprintf("; escaping=%s", Format(model.NameEscapingScheme.String()))) + escapingScheme := Format("; escaping=" + model.NameEscapingScheme.String()) for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" { switch Format(escapeParam) { @@ -111,11 +129,14 @@ func NegotiateAccept(h http.Header, accepted ...Format) Format { // matchFormat checks if a parsed accept clause matches a given Format. func matchFormat(ac goautoneg.Accept, f Format) bool { - parsed := goautoneg.ParseAccept(string(f)) - if len(parsed) == 0 { - return false + target, ok := formatToAccept[f] + if !ok { + parsed := goautoneg.ParseAccept(string(f)) + if len(parsed) == 0 { + return false + } + target = parsed[0] } - target := parsed[0] if ac.Type != "*" && ac.Type != target.Type { return false diff --git a/expfmt/encode_test.go b/expfmt/encode_test.go index c5c30cd4..43150f4e 100644 --- a/expfmt/encode_test.go +++ b/expfmt/encode_test.go @@ -547,3 +547,34 @@ func TestDottedEncode(t *testing.T) { } } } + +func BenchmarkNegotiate(b *testing.B) { + h := http.Header{} + h.Set(hdrAccept, "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.7,text/plain;version=0.0.4;q=0.3,application/json;q=0.1,*/*;q=0.01") + b.ReportAllocs() + b.ResetTimer() + for b.Loop() { + _ = Negotiate(h) + } +} + +func BenchmarkNegotiateIncludingOpenMetrics(b *testing.B) { + h := http.Header{} + h.Set(hdrAccept, "application/openmetrics-text;version=1.0.0;q=0.8,application/openmetrics-text;version=0.0.1;q=0.5,text/plain;version=0.0.4;q=0.3,*/*;q=0.1") + b.ReportAllocs() + b.ResetTimer() + for b.Loop() { + _ = NegotiateIncludingOpenMetrics(h) + } +} + +func BenchmarkNegotiateAccept(b *testing.B) { + h := http.Header{} + h.Set(hdrAccept, "application/openmetrics-text;version=1.0.0;q=0.8,text/plain;version=0.0.4;q=0.3,*/*;q=0.1") + accepted := []Format{FmtOpenMetrics_1_0_0, FmtOpenMetrics_0_0_1, FmtProtoDelim, FmtProtoText, FmtProtoCompact, FmtText} + b.ReportAllocs() + b.ResetTimer() + for b.Loop() { + _ = NegotiateAccept(h, accepted...) + } +}