aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/prometheus/common/expfmt/encode.go
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2022-09-05 14:27:54 +0200
committerGitHub <noreply@github.com>2022-09-05 12:27:54 +0000
commitb2f2446b46bf02821d90ebedadae2bf7ae0e880e (patch)
tree923cf42842918d6bebca1d6bbdc08abed54d274d /vendor/github.com/prometheus/common/expfmt/encode.go
parente6654faff4bcca4be92e9a8596fd4b77f747c39e (diff)
go.mod, vendor: update (#3358)
* go.mod, vendor: remove unnecessary dependencies Commands: 1. go mod tidy 2. go mod vendor * go.mod, vendor: update cloud.google.com/go Commands: 1. go get -u cloud.google.com/go 2. go mod tidy 3. go mod vendor * go.mod, vendor: update cloud.google.com/* Commands: 1. go get -u cloud.google.com/storage cloud.google.com/logging 2. go mod tidy 3. go mod vendor * go.mod, .golangci.yml, vendor: update *lint* Commands: 1. go get -u golang.org/x/tools github.com/golangci/golangci-lint@v1.47.0 2. go mod tidy 3. go mod vendor 4. edit .golangci.yml to suppress new errors (resolved in the same PR later) * all: fix lint errors hash.go: copy() recommended by gosimple parse.go: ent is never nil verifier.go: signal.Notify() with unbuffered channel is bad. Have no idea why. * .golangci.yml: adjust godot rules check-all is deprecated, but still work if you're hesitating too - I'll remove this commit
Diffstat (limited to 'vendor/github.com/prometheus/common/expfmt/encode.go')
-rw-r--r--vendor/github.com/prometheus/common/expfmt/encode.go126
1 files changed, 100 insertions, 26 deletions
diff --git a/vendor/github.com/prometheus/common/expfmt/encode.go b/vendor/github.com/prometheus/common/expfmt/encode.go
index 11839ed65..64dc0eb40 100644
--- a/vendor/github.com/prometheus/common/expfmt/encode.go
+++ b/vendor/github.com/prometheus/common/expfmt/encode.go
@@ -18,7 +18,7 @@ import (
"io"
"net/http"
- "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/proto" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/matttproud/golang_protobuf_extensions/pbutil"
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
@@ -30,17 +30,38 @@ type Encoder interface {
Encode(*dto.MetricFamily) error
}
-type encoder func(*dto.MetricFamily) error
+// Closer is implemented by Encoders that need to be closed to finalize
+// encoding. (For example, OpenMetrics needs a final `# EOF` line.)
+//
+// Note that all Encoder implementations returned from this package implement
+// Closer, too, even if the Close call is a no-op. This happens in preparation
+// for adding a Close method to the Encoder interface directly in a (mildly
+// breaking) release in the future.
+type Closer interface {
+ Close() error
+}
+
+type encoderCloser struct {
+ encode func(*dto.MetricFamily) error
+ close func() error
+}
-func (e encoder) Encode(v *dto.MetricFamily) error {
- return e(v)
+func (ec encoderCloser) Encode(v *dto.MetricFamily) error {
+ return ec.encode(v)
}
-// Negotiate returns the Content-Type based on the given Accept header.
-// If no appropriate accepted type is found, FmtText is returned.
+func (ec encoderCloser) Close() error {
+ return ec.close()
+}
+
+// Negotiate returns the Content-Type based on the given Accept header. If no
+// appropriate accepted type is found, FmtText is returned (which is the
+// Prometheus text format). This function will never negotiate FmtOpenMetrics,
+// as the support is still experimental. To include the option to negotiate
+// FmtOpenMetrics, use NegotiateOpenMetrics.
func Negotiate(h http.Header) Format {
for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
- // Check for protocol buffer
+ ver := ac.Params["version"]
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
switch ac.Params["encoding"] {
case "delimited":
@@ -51,38 +72,91 @@ func Negotiate(h http.Header) Format {
return FmtProtoCompact
}
}
- // Check for text format.
+ if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
+ return FmtText
+ }
+ }
+ return FmtText
+}
+
+// NegotiateIncludingOpenMetrics works like Negotiate but includes
+// FmtOpenMetrics as an option for the result. Note that this function is
+// temporary and will disappear once FmtOpenMetrics is fully supported and as
+// such may be negotiated by the normal Negotiate function.
+func NegotiateIncludingOpenMetrics(h http.Header) Format {
+ for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
ver := ac.Params["version"]
+ if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
+ switch ac.Params["encoding"] {
+ case "delimited":
+ return FmtProtoDelim
+ case "text":
+ return FmtProtoText
+ case "compact-text":
+ return FmtProtoCompact
+ }
+ }
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
return FmtText
}
+ if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion || ver == "") {
+ return FmtOpenMetrics
+ }
}
return FmtText
}
-// NewEncoder returns a new encoder based on content type negotiation.
+// NewEncoder returns a new encoder based on content type negotiation. All
+// Encoder implementations returned by NewEncoder also implement Closer, and
+// callers should always call the Close method. It is currently only required
+// for FmtOpenMetrics, but a future (breaking) release will add the Close method
+// to the Encoder interface directly. The current version of the Encoder
+// interface is kept for backwards compatibility.
func NewEncoder(w io.Writer, format Format) Encoder {
switch format {
case FmtProtoDelim:
- return encoder(func(v *dto.MetricFamily) error {
- _, err := pbutil.WriteDelimited(w, v)
- return err
- })
+ return encoderCloser{
+ encode: func(v *dto.MetricFamily) error {
+ _, err := pbutil.WriteDelimited(w, v)
+ return err
+ },
+ close: func() error { return nil },
+ }
case FmtProtoCompact:
- return encoder(func(v *dto.MetricFamily) error {
- _, err := fmt.Fprintln(w, v.String())
- return err
- })
+ return encoderCloser{
+ encode: func(v *dto.MetricFamily) error {
+ _, err := fmt.Fprintln(w, v.String())
+ return err
+ },
+ close: func() error { return nil },
+ }
case FmtProtoText:
- return encoder(func(v *dto.MetricFamily) error {
- _, err := fmt.Fprintln(w, proto.MarshalTextString(v))
- return err
- })
+ return encoderCloser{
+ encode: func(v *dto.MetricFamily) error {
+ _, err := fmt.Fprintln(w, proto.MarshalTextString(v))
+ return err
+ },
+ close: func() error { return nil },
+ }
case FmtText:
- return encoder(func(v *dto.MetricFamily) error {
- _, err := MetricFamilyToText(w, v)
- return err
- })
+ return encoderCloser{
+ encode: func(v *dto.MetricFamily) error {
+ _, err := MetricFamilyToText(w, v)
+ return err
+ },
+ close: func() error { return nil },
+ }
+ case FmtOpenMetrics:
+ return encoderCloser{
+ encode: func(v *dto.MetricFamily) error {
+ _, err := MetricFamilyToOpenMetrics(w, v)
+ return err
+ },
+ close: func() error {
+ _, err := FinalizeOpenMetrics(w)
+ return err
+ },
+ }
}
- panic("expfmt.NewEncoder: unknown format")
+ panic(fmt.Errorf("expfmt.NewEncoder: unknown format %q", format))
}