Merge pull request #1025 from kubernetes-csi/dependabot/go_modules/github.com/prometheus/client_golang-1.19.0
Bump github.com/prometheus/client_golang from 1.18.0 to 1.19.0
This commit is contained in:
4
go.mod
4
go.mod
@@ -11,9 +11,9 @@ require (
|
|||||||
github.com/kubernetes-csi/csi-lib-utils v0.17.0
|
github.com/kubernetes-csi/csi-lib-utils v0.17.0
|
||||||
github.com/kubernetes-csi/csi-test/v5 v5.2.0
|
github.com/kubernetes-csi/csi-test/v5 v5.2.0
|
||||||
github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0
|
github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.19.0
|
||||||
github.com/prometheus/client_model v0.6.0
|
github.com/prometheus/client_model v0.6.0
|
||||||
github.com/prometheus/common v0.46.0
|
github.com/prometheus/common v0.48.0
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.0
|
||||||
google.golang.org/grpc v1.62.1
|
google.golang.org/grpc v1.62.1
|
||||||
google.golang.org/protobuf v1.32.0
|
google.golang.org/protobuf v1.32.0
|
||||||
|
8
go.sum
8
go.sum
@@ -99,12 +99,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||||
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
||||||
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
||||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
|
||||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
|
18
vendor/github.com/prometheus/common/expfmt/decode.go
generated
vendored
18
vendor/github.com/prometheus/common/expfmt/decode.go
generated
vendored
@@ -45,7 +45,7 @@ func ResponseFormat(h http.Header) Format {
|
|||||||
|
|
||||||
mediatype, params, err := mime.ParseMediaType(ct)
|
mediatype, params, err := mime.ParseMediaType(ct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return FmtUnknown
|
return fmtUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
const textType = "text/plain"
|
const textType = "text/plain"
|
||||||
@@ -53,28 +53,28 @@ func ResponseFormat(h http.Header) Format {
|
|||||||
switch mediatype {
|
switch mediatype {
|
||||||
case ProtoType:
|
case ProtoType:
|
||||||
if p, ok := params["proto"]; ok && p != ProtoProtocol {
|
if p, ok := params["proto"]; ok && p != ProtoProtocol {
|
||||||
return FmtUnknown
|
return fmtUnknown
|
||||||
}
|
}
|
||||||
if e, ok := params["encoding"]; ok && e != "delimited" {
|
if e, ok := params["encoding"]; ok && e != "delimited" {
|
||||||
return FmtUnknown
|
return fmtUnknown
|
||||||
}
|
}
|
||||||
return FmtProtoDelim
|
return fmtProtoDelim
|
||||||
|
|
||||||
case textType:
|
case textType:
|
||||||
if v, ok := params["version"]; ok && v != TextVersion {
|
if v, ok := params["version"]; ok && v != TextVersion {
|
||||||
return FmtUnknown
|
return fmtUnknown
|
||||||
}
|
}
|
||||||
return FmtText
|
return fmtText
|
||||||
}
|
}
|
||||||
|
|
||||||
return FmtUnknown
|
return fmtUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDecoder returns a new decoder based on the given input format.
|
// NewDecoder returns a new decoder based on the given input format.
|
||||||
// If the input format does not imply otherwise, a text format decoder is returned.
|
// If the input format does not imply otherwise, a text format decoder is returned.
|
||||||
func NewDecoder(r io.Reader, format Format) Decoder {
|
func NewDecoder(r io.Reader, format Format) Decoder {
|
||||||
switch format {
|
switch format.FormatType() {
|
||||||
case FmtProtoDelim:
|
case TypeProtoDelim:
|
||||||
return &protoDecoder{r: r}
|
return &protoDecoder{r: r}
|
||||||
}
|
}
|
||||||
return &textDecoder{r: r}
|
return &textDecoder{r: r}
|
||||||
|
73
vendor/github.com/prometheus/common/expfmt/encode.go
generated
vendored
73
vendor/github.com/prometheus/common/expfmt/encode.go
generated
vendored
@@ -22,6 +22,7 @@ import (
|
|||||||
"google.golang.org/protobuf/encoding/prototext"
|
"google.golang.org/protobuf/encoding/prototext"
|
||||||
|
|
||||||
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
|
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
|
||||||
|
"github.com/prometheus/common/model"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
@@ -61,23 +62,32 @@ func (ec encoderCloser) Close() error {
|
|||||||
// as the support is still experimental. To include the option to negotiate
|
// as the support is still experimental. To include the option to negotiate
|
||||||
// FmtOpenMetrics, use NegotiateOpenMetrics.
|
// FmtOpenMetrics, use NegotiateOpenMetrics.
|
||||||
func Negotiate(h http.Header) Format {
|
func Negotiate(h http.Header) Format {
|
||||||
|
escapingScheme := Format(fmt.Sprintf("; escaping=%s", Format(model.NameEscapingScheme.String())))
|
||||||
for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
|
for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
|
||||||
|
if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" {
|
||||||
|
switch Format(escapeParam) {
|
||||||
|
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
|
||||||
|
escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam))
|
||||||
|
default:
|
||||||
|
// If the escaping parameter is unknown, ignore it.
|
||||||
|
}
|
||||||
|
}
|
||||||
ver := ac.Params["version"]
|
ver := ac.Params["version"]
|
||||||
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
|
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
|
||||||
switch ac.Params["encoding"] {
|
switch ac.Params["encoding"] {
|
||||||
case "delimited":
|
case "delimited":
|
||||||
return FmtProtoDelim
|
return fmtProtoDelim + escapingScheme
|
||||||
case "text":
|
case "text":
|
||||||
return FmtProtoText
|
return fmtProtoText + escapingScheme
|
||||||
case "compact-text":
|
case "compact-text":
|
||||||
return FmtProtoCompact
|
return fmtProtoCompact + escapingScheme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
|
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
|
||||||
return FmtText
|
return fmtText + escapingScheme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FmtText
|
return fmtText + escapingScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
// NegotiateIncludingOpenMetrics works like Negotiate but includes
|
// NegotiateIncludingOpenMetrics works like Negotiate but includes
|
||||||
@@ -85,29 +95,40 @@ func Negotiate(h http.Header) Format {
|
|||||||
// temporary and will disappear once FmtOpenMetrics is fully supported and as
|
// temporary and will disappear once FmtOpenMetrics is fully supported and as
|
||||||
// such may be negotiated by the normal Negotiate function.
|
// such may be negotiated by the normal Negotiate function.
|
||||||
func NegotiateIncludingOpenMetrics(h http.Header) Format {
|
func NegotiateIncludingOpenMetrics(h http.Header) Format {
|
||||||
|
escapingScheme := Format(fmt.Sprintf("; escaping=%s", Format(model.NameEscapingScheme.String())))
|
||||||
for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
|
for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
|
||||||
|
if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" {
|
||||||
|
switch Format(escapeParam) {
|
||||||
|
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
|
||||||
|
escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam))
|
||||||
|
default:
|
||||||
|
// If the escaping parameter is unknown, ignore it.
|
||||||
|
}
|
||||||
|
}
|
||||||
ver := ac.Params["version"]
|
ver := ac.Params["version"]
|
||||||
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
|
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
|
||||||
switch ac.Params["encoding"] {
|
switch ac.Params["encoding"] {
|
||||||
case "delimited":
|
case "delimited":
|
||||||
return FmtProtoDelim
|
return fmtProtoDelim + escapingScheme
|
||||||
case "text":
|
case "text":
|
||||||
return FmtProtoText
|
return fmtProtoText + escapingScheme
|
||||||
case "compact-text":
|
case "compact-text":
|
||||||
return FmtProtoCompact
|
return fmtProtoCompact + escapingScheme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
|
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
|
||||||
return FmtText
|
return fmtText + escapingScheme
|
||||||
}
|
}
|
||||||
if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") {
|
if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") {
|
||||||
if ver == OpenMetricsVersion_1_0_0 {
|
switch ver {
|
||||||
return FmtOpenMetrics_1_0_0
|
case OpenMetricsVersion_1_0_0:
|
||||||
}
|
return fmtOpenMetrics_1_0_0 + escapingScheme
|
||||||
return FmtOpenMetrics_0_0_1
|
default:
|
||||||
|
return fmtOpenMetrics_0_0_1 + escapingScheme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FmtText
|
}
|
||||||
|
return fmtText + escapingScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncoder returns a new encoder based on content type negotiation. All
|
// NewEncoder returns a new encoder based on content type negotiation. All
|
||||||
@@ -116,9 +137,13 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
|
|||||||
// for FmtOpenMetrics, but a future (breaking) release will add the Close method
|
// for FmtOpenMetrics, but a future (breaking) release will add the Close method
|
||||||
// to the Encoder interface directly. The current version of the Encoder
|
// to the Encoder interface directly. The current version of the Encoder
|
||||||
// interface is kept for backwards compatibility.
|
// interface is kept for backwards compatibility.
|
||||||
|
// In cases where the Format does not allow for UTF-8 names, the global
|
||||||
|
// NameEscapingScheme will be applied.
|
||||||
func NewEncoder(w io.Writer, format Format) Encoder {
|
func NewEncoder(w io.Writer, format Format) Encoder {
|
||||||
switch format {
|
escapingScheme := format.ToEscapingScheme()
|
||||||
case FmtProtoDelim:
|
|
||||||
|
switch format.FormatType() {
|
||||||
|
case TypeProtoDelim:
|
||||||
return encoderCloser{
|
return encoderCloser{
|
||||||
encode: func(v *dto.MetricFamily) error {
|
encode: func(v *dto.MetricFamily) error {
|
||||||
_, err := protodelim.MarshalTo(w, v)
|
_, err := protodelim.MarshalTo(w, v)
|
||||||
@@ -126,34 +151,34 @@ func NewEncoder(w io.Writer, format Format) Encoder {
|
|||||||
},
|
},
|
||||||
close: func() error { return nil },
|
close: func() error { return nil },
|
||||||
}
|
}
|
||||||
case FmtProtoCompact:
|
case TypeProtoCompact:
|
||||||
return encoderCloser{
|
return encoderCloser{
|
||||||
encode: func(v *dto.MetricFamily) error {
|
encode: func(v *dto.MetricFamily) error {
|
||||||
_, err := fmt.Fprintln(w, v.String())
|
_, err := fmt.Fprintln(w, model.EscapeMetricFamily(v, escapingScheme).String())
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
close: func() error { return nil },
|
close: func() error { return nil },
|
||||||
}
|
}
|
||||||
case FmtProtoText:
|
case TypeProtoText:
|
||||||
return encoderCloser{
|
return encoderCloser{
|
||||||
encode: func(v *dto.MetricFamily) error {
|
encode: func(v *dto.MetricFamily) error {
|
||||||
_, err := fmt.Fprintln(w, prototext.Format(v))
|
_, err := fmt.Fprintln(w, prototext.Format(model.EscapeMetricFamily(v, escapingScheme)))
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
close: func() error { return nil },
|
close: func() error { return nil },
|
||||||
}
|
}
|
||||||
case FmtText:
|
case TypeTextPlain:
|
||||||
return encoderCloser{
|
return encoderCloser{
|
||||||
encode: func(v *dto.MetricFamily) error {
|
encode: func(v *dto.MetricFamily) error {
|
||||||
_, err := MetricFamilyToText(w, v)
|
_, err := MetricFamilyToText(w, model.EscapeMetricFamily(v, escapingScheme))
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
close: func() error { return nil },
|
close: func() error { return nil },
|
||||||
}
|
}
|
||||||
case FmtOpenMetrics_0_0_1, FmtOpenMetrics_1_0_0:
|
case TypeOpenMetrics:
|
||||||
return encoderCloser{
|
return encoderCloser{
|
||||||
encode: func(v *dto.MetricFamily) error {
|
encode: func(v *dto.MetricFamily) error {
|
||||||
_, err := MetricFamilyToOpenMetrics(w, v)
|
_, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme))
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
close: func() error {
|
close: func() error {
|
||||||
|
144
vendor/github.com/prometheus/common/expfmt/expfmt.go
generated
vendored
144
vendor/github.com/prometheus/common/expfmt/expfmt.go
generated
vendored
@@ -14,30 +14,154 @@
|
|||||||
// Package expfmt contains tools for reading and writing Prometheus metrics.
|
// Package expfmt contains tools for reading and writing Prometheus metrics.
|
||||||
package expfmt
|
package expfmt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/common/model"
|
||||||
|
)
|
||||||
|
|
||||||
// Format specifies the HTTP content type of the different wire protocols.
|
// Format specifies the HTTP content type of the different wire protocols.
|
||||||
type Format string
|
type Format string
|
||||||
|
|
||||||
// Constants to assemble the Content-Type values for the different wire protocols.
|
// Constants to assemble the Content-Type values for the different wire
|
||||||
|
// protocols. The Content-Type strings here are all for the legacy exposition
|
||||||
|
// formats, where valid characters for metric names and label names are limited.
|
||||||
|
// Support for arbitrary UTF-8 characters in those names is already partially
|
||||||
|
// implemented in this module (see model.ValidationScheme), but to actually use
|
||||||
|
// it on the wire, new content-type strings will have to be agreed upon and
|
||||||
|
// added here.
|
||||||
const (
|
const (
|
||||||
TextVersion = "0.0.4"
|
TextVersion = "0.0.4"
|
||||||
ProtoType = `application/vnd.google.protobuf`
|
ProtoType = `application/vnd.google.protobuf`
|
||||||
ProtoProtocol = `io.prometheus.client.MetricFamily`
|
ProtoProtocol = `io.prometheus.client.MetricFamily`
|
||||||
ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
|
protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
|
||||||
OpenMetricsType = `application/openmetrics-text`
|
OpenMetricsType = `application/openmetrics-text`
|
||||||
OpenMetricsVersion_0_0_1 = "0.0.1"
|
OpenMetricsVersion_0_0_1 = "0.0.1"
|
||||||
OpenMetricsVersion_1_0_0 = "1.0.0"
|
OpenMetricsVersion_1_0_0 = "1.0.0"
|
||||||
|
|
||||||
// The Content-Type values for the different wire protocols.
|
// The Content-Type values for the different wire protocols. Note that these
|
||||||
FmtUnknown Format = `<unknown>`
|
// values are now unexported. If code was relying on comparisons to these
|
||||||
FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
|
// constants, instead use FormatType().
|
||||||
FmtProtoDelim Format = ProtoFmt + ` encoding=delimited`
|
fmtUnknown Format = `<unknown>`
|
||||||
FmtProtoText Format = ProtoFmt + ` encoding=text`
|
fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
|
||||||
FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
|
fmtProtoDelim Format = protoFmt + ` encoding=delimited`
|
||||||
FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
|
fmtProtoText Format = protoFmt + ` encoding=text`
|
||||||
FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
|
fmtProtoCompact Format = protoFmt + ` encoding=compact-text`
|
||||||
|
fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
|
||||||
|
fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
hdrContentType = "Content-Type"
|
hdrContentType = "Content-Type"
|
||||||
hdrAccept = "Accept"
|
hdrAccept = "Accept"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FormatType is a Go enum representing the overall category for the given
|
||||||
|
// Format. As the number of Format permutations increases, doing basic string
|
||||||
|
// comparisons are not feasible, so this enum captures the most useful
|
||||||
|
// high-level attribute of the Format string.
|
||||||
|
type FormatType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
TypeUnknown = iota
|
||||||
|
TypeProtoCompact
|
||||||
|
TypeProtoDelim
|
||||||
|
TypeProtoText
|
||||||
|
TypeTextPlain
|
||||||
|
TypeOpenMetrics
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewFormat generates a new Format from the type provided. Mostly used for
|
||||||
|
// tests, most Formats should be generated as part of content negotiation in
|
||||||
|
// encode.go.
|
||||||
|
func NewFormat(t FormatType) Format {
|
||||||
|
switch t {
|
||||||
|
case TypeProtoCompact:
|
||||||
|
return fmtProtoCompact
|
||||||
|
case TypeProtoDelim:
|
||||||
|
return fmtProtoDelim
|
||||||
|
case TypeProtoText:
|
||||||
|
return fmtProtoText
|
||||||
|
case TypeTextPlain:
|
||||||
|
return fmtText
|
||||||
|
case TypeOpenMetrics:
|
||||||
|
return fmtOpenMetrics_1_0_0
|
||||||
|
default:
|
||||||
|
return fmtUnknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatType deduces an overall FormatType for the given format.
|
||||||
|
func (f Format) FormatType() FormatType {
|
||||||
|
toks := strings.Split(string(f), ";")
|
||||||
|
if len(toks) < 2 {
|
||||||
|
return TypeUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
params := make(map[string]string)
|
||||||
|
for i, t := range toks {
|
||||||
|
if i == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
args := strings.Split(t, "=")
|
||||||
|
if len(args) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
params[strings.TrimSpace(args[0])] = strings.TrimSpace(args[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
switch strings.TrimSpace(toks[0]) {
|
||||||
|
case ProtoType:
|
||||||
|
if params["proto"] != ProtoProtocol {
|
||||||
|
return TypeUnknown
|
||||||
|
}
|
||||||
|
switch params["encoding"] {
|
||||||
|
case "delimited":
|
||||||
|
return TypeProtoDelim
|
||||||
|
case "text":
|
||||||
|
return TypeProtoText
|
||||||
|
case "compact-text":
|
||||||
|
return TypeProtoCompact
|
||||||
|
default:
|
||||||
|
return TypeUnknown
|
||||||
|
}
|
||||||
|
case OpenMetricsType:
|
||||||
|
if params["charset"] != "utf-8" {
|
||||||
|
return TypeUnknown
|
||||||
|
}
|
||||||
|
return TypeOpenMetrics
|
||||||
|
case "text/plain":
|
||||||
|
v, ok := params["version"]
|
||||||
|
if !ok {
|
||||||
|
return TypeTextPlain
|
||||||
|
}
|
||||||
|
if v == TextVersion {
|
||||||
|
return TypeTextPlain
|
||||||
|
}
|
||||||
|
return TypeUnknown
|
||||||
|
default:
|
||||||
|
return TypeUnknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToEscapingScheme returns an EscapingScheme depending on the Format. Iff the
|
||||||
|
// Format contains a escaping=allow-utf-8 term, it will select NoEscaping. If a valid
|
||||||
|
// "escaping" term exists, that will be used. Otherwise, the global default will
|
||||||
|
// be returned.
|
||||||
|
func (format Format) ToEscapingScheme() model.EscapingScheme {
|
||||||
|
for _, p := range strings.Split(string(format), ";") {
|
||||||
|
toks := strings.Split(p, "=")
|
||||||
|
if len(toks) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key, value := strings.TrimSpace(toks[0]), strings.TrimSpace(toks[1])
|
||||||
|
if key == model.EscapingKey {
|
||||||
|
scheme, err := model.ToEscapingScheme(value)
|
||||||
|
if err != nil {
|
||||||
|
return model.NameEscapingScheme
|
||||||
|
}
|
||||||
|
return scheme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return model.NameEscapingScheme
|
||||||
|
}
|
||||||
|
81
vendor/github.com/prometheus/common/expfmt/openmetrics_create.go
generated
vendored
81
vendor/github.com/prometheus/common/expfmt/openmetrics_create.go
generated
vendored
@@ -35,6 +35,18 @@ import (
|
|||||||
// sanity checks. If the input contains duplicate metrics or invalid metric or
|
// sanity checks. If the input contains duplicate metrics or invalid metric or
|
||||||
// label names, the conversion will result in invalid text format output.
|
// label names, the conversion will result in invalid text format output.
|
||||||
//
|
//
|
||||||
|
// If metric names conform to the legacy validation pattern, they will be placed
|
||||||
|
// outside the brackets in the traditional way, like `foo{}`. If the metric name
|
||||||
|
// fails the legacy validation check, it will be placed quoted inside the
|
||||||
|
// brackets: `{"foo"}`. As stated above, the input is assumed to be santized and
|
||||||
|
// no error will be thrown in this case.
|
||||||
|
//
|
||||||
|
// Similar to metric names, if label names conform to the legacy validation
|
||||||
|
// pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label
|
||||||
|
// name fails the legacy validation check, it will be quoted:
|
||||||
|
// `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and
|
||||||
|
// no error will be thrown in this case.
|
||||||
|
//
|
||||||
// This function fulfills the type 'expfmt.encoder'.
|
// This function fulfills the type 'expfmt.encoder'.
|
||||||
//
|
//
|
||||||
// Note that OpenMetrics requires a final `# EOF` line. Since this function acts
|
// Note that OpenMetrics requires a final `# EOF` line. Since this function acts
|
||||||
@@ -98,7 +110,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, err = w.WriteString(shortName)
|
n, err = writeName(w, shortName)
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -124,7 +136,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, err = w.WriteString(shortName)
|
n, err = writeName(w, shortName)
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -303,21 +315,9 @@ func writeOpenMetricsSample(
|
|||||||
floatValue float64, intValue uint64, useIntValue bool,
|
floatValue float64, intValue uint64, useIntValue bool,
|
||||||
exemplar *dto.Exemplar,
|
exemplar *dto.Exemplar,
|
||||||
) (int, error) {
|
) (int, error) {
|
||||||
var written int
|
written := 0
|
||||||
n, err := w.WriteString(name)
|
n, err := writeOpenMetricsNameAndLabelPairs(
|
||||||
written += n
|
w, name+suffix, metric.Label, additionalLabelName, additionalLabelValue,
|
||||||
if err != nil {
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
if suffix != "" {
|
|
||||||
n, err = w.WriteString(suffix)
|
|
||||||
written += n
|
|
||||||
if err != nil {
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n, err = writeOpenMetricsLabelPairs(
|
|
||||||
w, metric.Label, additionalLabelName, additionalLabelValue,
|
|
||||||
)
|
)
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -365,27 +365,58 @@ func writeOpenMetricsSample(
|
|||||||
return written, nil
|
return written, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeOpenMetricsLabelPairs works like writeOpenMetrics but formats the float
|
// writeOpenMetricsNameAndLabelPairs works like writeOpenMetricsSample but
|
||||||
// in OpenMetrics style.
|
// formats the float in OpenMetrics style.
|
||||||
func writeOpenMetricsLabelPairs(
|
func writeOpenMetricsNameAndLabelPairs(
|
||||||
w enhancedWriter,
|
w enhancedWriter,
|
||||||
|
name string,
|
||||||
in []*dto.LabelPair,
|
in []*dto.LabelPair,
|
||||||
additionalLabelName string, additionalLabelValue float64,
|
additionalLabelName string, additionalLabelValue float64,
|
||||||
) (int, error) {
|
) (int, error) {
|
||||||
if len(in) == 0 && additionalLabelName == "" {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
var (
|
var (
|
||||||
written int
|
written int
|
||||||
separator byte = '{'
|
separator byte = '{'
|
||||||
|
metricInsideBraces = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if name != "" {
|
||||||
|
// If the name does not pass the legacy validity check, we must put the
|
||||||
|
// metric name inside the braces, quoted.
|
||||||
|
if !model.IsValidLegacyMetricName(model.LabelValue(name)) {
|
||||||
|
metricInsideBraces = true
|
||||||
|
err := w.WriteByte(separator)
|
||||||
|
written++
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
separator = ','
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := writeName(w, name)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(in) == 0 && additionalLabelName == "" {
|
||||||
|
if metricInsideBraces {
|
||||||
|
err := w.WriteByte('}')
|
||||||
|
written++
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return written, nil
|
||||||
|
}
|
||||||
|
|
||||||
for _, lp := range in {
|
for _, lp := range in {
|
||||||
err := w.WriteByte(separator)
|
err := w.WriteByte(separator)
|
||||||
written++
|
written++
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return written, err
|
return written, err
|
||||||
}
|
}
|
||||||
n, err := w.WriteString(lp.GetName())
|
n, err := writeName(w, lp.GetName())
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return written, err
|
return written, err
|
||||||
@@ -451,7 +482,7 @@ func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return written, err
|
return written, err
|
||||||
}
|
}
|
||||||
n, err = writeOpenMetricsLabelPairs(w, e.Label, "", 0)
|
n, err = writeOpenMetricsNameAndLabelPairs(w, "", e.Label, "", 0)
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return written, err
|
return written, err
|
||||||
|
114
vendor/github.com/prometheus/common/expfmt/text_create.go
generated
vendored
114
vendor/github.com/prometheus/common/expfmt/text_create.go
generated
vendored
@@ -62,6 +62,18 @@ var (
|
|||||||
// contains duplicate metrics or invalid metric or label names, the conversion
|
// contains duplicate metrics or invalid metric or label names, the conversion
|
||||||
// will result in invalid text format output.
|
// will result in invalid text format output.
|
||||||
//
|
//
|
||||||
|
// If metric names conform to the legacy validation pattern, they will be placed
|
||||||
|
// outside the brackets in the traditional way, like `foo{}`. If the metric name
|
||||||
|
// fails the legacy validation check, it will be placed quoted inside the
|
||||||
|
// brackets: `{"foo"}`. As stated above, the input is assumed to be santized and
|
||||||
|
// no error will be thrown in this case.
|
||||||
|
//
|
||||||
|
// Similar to metric names, if label names conform to the legacy validation
|
||||||
|
// pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label
|
||||||
|
// name fails the legacy validation check, it will be quoted:
|
||||||
|
// `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and
|
||||||
|
// no error will be thrown in this case.
|
||||||
|
//
|
||||||
// This method fulfills the type 'prometheus.encoder'.
|
// This method fulfills the type 'prometheus.encoder'.
|
||||||
func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err error) {
|
func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err error) {
|
||||||
// Fail-fast checks.
|
// Fail-fast checks.
|
||||||
@@ -98,7 +110,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, err = w.WriteString(name)
|
n, err = writeName(w, name)
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -124,7 +136,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, err = w.WriteString(name)
|
n, err = writeName(w, name)
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -280,21 +292,9 @@ func writeSample(
|
|||||||
additionalLabelName string, additionalLabelValue float64,
|
additionalLabelName string, additionalLabelValue float64,
|
||||||
value float64,
|
value float64,
|
||||||
) (int, error) {
|
) (int, error) {
|
||||||
var written int
|
written := 0
|
||||||
n, err := w.WriteString(name)
|
n, err := writeNameAndLabelPairs(
|
||||||
written += n
|
w, name+suffix, metric.Label, additionalLabelName, additionalLabelValue,
|
||||||
if err != nil {
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
if suffix != "" {
|
|
||||||
n, err = w.WriteString(suffix)
|
|
||||||
written += n
|
|
||||||
if err != nil {
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n, err = writeLabelPairs(
|
|
||||||
w, metric.Label, additionalLabelName, additionalLabelValue,
|
|
||||||
)
|
)
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -330,32 +330,64 @@ func writeSample(
|
|||||||
return written, nil
|
return written, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeLabelPairs converts a slice of LabelPair proto messages plus the
|
// writeNameAndLabelPairs converts a slice of LabelPair proto messages plus the
|
||||||
// explicitly given additional label pair into text formatted as required by the
|
// explicitly given metric name and additional label pair into text formatted as
|
||||||
// text format and writes it to 'w'. An empty slice in combination with an empty
|
// required by the text format and writes it to 'w'. An empty slice in
|
||||||
// string 'additionalLabelName' results in nothing being written. Otherwise, the
|
// combination with an empty string 'additionalLabelName' results in nothing
|
||||||
// label pairs are written, escaped as required by the text format, and enclosed
|
// being written. Otherwise, the label pairs are written, escaped as required by
|
||||||
// in '{...}'. The function returns the number of bytes written and any error
|
// the text format, and enclosed in '{...}'. The function returns the number of
|
||||||
// encountered.
|
// bytes written and any error encountered. If the metric name is not
|
||||||
func writeLabelPairs(
|
// legacy-valid, it will be put inside the brackets as well. Legacy-invalid
|
||||||
|
// label names will also be quoted.
|
||||||
|
func writeNameAndLabelPairs(
|
||||||
w enhancedWriter,
|
w enhancedWriter,
|
||||||
|
name string,
|
||||||
in []*dto.LabelPair,
|
in []*dto.LabelPair,
|
||||||
additionalLabelName string, additionalLabelValue float64,
|
additionalLabelName string, additionalLabelValue float64,
|
||||||
) (int, error) {
|
) (int, error) {
|
||||||
if len(in) == 0 && additionalLabelName == "" {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
var (
|
var (
|
||||||
written int
|
written int
|
||||||
separator byte = '{'
|
separator byte = '{'
|
||||||
|
metricInsideBraces = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if name != "" {
|
||||||
|
// If the name does not pass the legacy validity check, we must put the
|
||||||
|
// metric name inside the braces.
|
||||||
|
if !model.IsValidLegacyMetricName(model.LabelValue(name)) {
|
||||||
|
metricInsideBraces = true
|
||||||
|
err := w.WriteByte(separator)
|
||||||
|
written++
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
separator = ','
|
||||||
|
}
|
||||||
|
n, err := writeName(w, name)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(in) == 0 && additionalLabelName == "" {
|
||||||
|
if metricInsideBraces {
|
||||||
|
err := w.WriteByte('}')
|
||||||
|
written++
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return written, nil
|
||||||
|
}
|
||||||
|
|
||||||
for _, lp := range in {
|
for _, lp := range in {
|
||||||
err := w.WriteByte(separator)
|
err := w.WriteByte(separator)
|
||||||
written++
|
written++
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return written, err
|
return written, err
|
||||||
}
|
}
|
||||||
n, err := w.WriteString(lp.GetName())
|
n, err := writeName(w, lp.GetName())
|
||||||
written += n
|
written += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return written, err
|
return written, err
|
||||||
@@ -462,3 +494,27 @@ func writeInt(w enhancedWriter, i int64) (int, error) {
|
|||||||
numBufPool.Put(bp)
|
numBufPool.Put(bp)
|
||||||
return written, err
|
return written, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeName writes a string as-is if it complies with the legacy naming
|
||||||
|
// scheme, or escapes it in double quotes if not.
|
||||||
|
func writeName(w enhancedWriter, name string) (int, error) {
|
||||||
|
if model.IsValidLegacyMetricName(model.LabelValue(name)) {
|
||||||
|
return w.WriteString(name)
|
||||||
|
}
|
||||||
|
var written int
|
||||||
|
var err error
|
||||||
|
err = w.WriteByte('"')
|
||||||
|
written++
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
var n int
|
||||||
|
n, err = writeEscapedString(w, name, true)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
err = w.WriteByte('"')
|
||||||
|
written++
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
16
vendor/github.com/prometheus/common/model/labels.go
generated
vendored
16
vendor/github.com/prometheus/common/model/labels.go
generated
vendored
@@ -97,18 +97,26 @@ var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
|
|||||||
// therewith.
|
// therewith.
|
||||||
type LabelName string
|
type LabelName string
|
||||||
|
|
||||||
// IsValid is true iff the label name matches the pattern of LabelNameRE. This
|
// IsValid returns true iff name matches the pattern of LabelNameRE for legacy
|
||||||
// method, however, does not use LabelNameRE for the check but a much faster
|
// names, and iff it's valid UTF-8 if NameValidationScheme is set to
|
||||||
// hardcoded implementation.
|
// UTF8Validation. For the legacy matching, it does not use LabelNameRE for the
|
||||||
|
// check but a much faster hardcoded implementation.
|
||||||
func (ln LabelName) IsValid() bool {
|
func (ln LabelName) IsValid() bool {
|
||||||
if len(ln) == 0 {
|
if len(ln) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
switch NameValidationScheme {
|
||||||
|
case LegacyValidation:
|
||||||
for i, b := range ln {
|
for i, b := range ln {
|
||||||
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
|
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case UTF8Validation:
|
||||||
|
return utf8.ValidString(string(ln))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Invalid name validation scheme requested: %d", NameValidationScheme))
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +172,7 @@ func (l LabelNames) String() string {
|
|||||||
// A LabelValue is an associated value for a LabelName.
|
// A LabelValue is an associated value for a LabelName.
|
||||||
type LabelValue string
|
type LabelValue string
|
||||||
|
|
||||||
// IsValid returns true iff the string is a valid UTF8.
|
// IsValid returns true iff the string is a valid UTF-8.
|
||||||
func (lv LabelValue) IsValid() bool {
|
func (lv LabelValue) IsValid() bool {
|
||||||
return utf8.ValidString(string(lv))
|
return utf8.ValidString(string(lv))
|
||||||
}
|
}
|
||||||
|
362
vendor/github.com/prometheus/common/model/metric.go
generated
vendored
362
vendor/github.com/prometheus/common/model/metric.go
generated
vendored
@@ -18,6 +18,77 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// NameValidationScheme determines the method of name validation to be used by
|
||||||
|
// all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 mode
|
||||||
|
// in isolation from other components that don't support UTF-8 may result in
|
||||||
|
// bugs or other undefined behavior. This value is intended to be set by
|
||||||
|
// UTF-8-aware binaries as part of their startup. To avoid need for locking,
|
||||||
|
// this value should be set once, ideally in an init(), before multiple
|
||||||
|
// goroutines are started.
|
||||||
|
NameValidationScheme = LegacyValidation
|
||||||
|
|
||||||
|
// NameEscapingScheme defines the default way that names will be
|
||||||
|
// escaped when presented to systems that do not support UTF-8 names. If the
|
||||||
|
// Content-Type "escaping" term is specified, that will override this value.
|
||||||
|
NameEscapingScheme = ValueEncodingEscaping
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidationScheme is a Go enum for determining how metric and label names will
|
||||||
|
// be validated by this library.
|
||||||
|
type ValidationScheme int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// LegacyValidation is a setting that requirets that metric and label names
|
||||||
|
// conform to the original Prometheus character requirements described by
|
||||||
|
// MetricNameRE and LabelNameRE.
|
||||||
|
LegacyValidation ValidationScheme = iota
|
||||||
|
|
||||||
|
// UTF8Validation only requires that metric and label names be valid UTF-8
|
||||||
|
// strings.
|
||||||
|
UTF8Validation
|
||||||
|
)
|
||||||
|
|
||||||
|
type EscapingScheme int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NoEscaping indicates that a name will not be escaped. Unescaped names that
|
||||||
|
// do not conform to the legacy validity check will use a new exposition
|
||||||
|
// format syntax that will be officially standardized in future versions.
|
||||||
|
NoEscaping EscapingScheme = iota
|
||||||
|
|
||||||
|
// UnderscoreEscaping replaces all legacy-invalid characters with underscores.
|
||||||
|
UnderscoreEscaping
|
||||||
|
|
||||||
|
// DotsEscaping is similar to UnderscoreEscaping, except that dots are
|
||||||
|
// converted to `_dot_` and pre-existing underscores are converted to `__`.
|
||||||
|
DotsEscaping
|
||||||
|
|
||||||
|
// ValueEncodingEscaping prepends the name with `U__` and replaces all invalid
|
||||||
|
// characters with the unicode value, surrounded by underscores. Single
|
||||||
|
// underscores are replaced with double underscores.
|
||||||
|
ValueEncodingEscaping
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// EscapingKey is the key in an Accept or Content-Type header that defines how
|
||||||
|
// metric and label names that do not conform to the legacy character
|
||||||
|
// requirements should be escaped when being scraped by a legacy prometheus
|
||||||
|
// system. If a system does not explicitly pass an escaping parameter in the
|
||||||
|
// Accept header, the default NameEscapingScheme will be used.
|
||||||
|
EscapingKey = "escaping"
|
||||||
|
|
||||||
|
// Possible values for Escaping Key:
|
||||||
|
AllowUTF8 = "allow-utf-8" // No escaping required.
|
||||||
|
EscapeUnderscores = "underscores"
|
||||||
|
EscapeDots = "dots"
|
||||||
|
EscapeValues = "values"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MetricNameRE is a regular expression matching valid metric
|
// MetricNameRE is a regular expression matching valid metric
|
||||||
@@ -84,17 +155,302 @@ func (m Metric) FastFingerprint() Fingerprint {
|
|||||||
return LabelSet(m).FastFingerprint()
|
return LabelSet(m).FastFingerprint()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValidMetricName returns true iff name matches the pattern of MetricNameRE.
|
// IsValidMetricName returns true iff name matches the pattern of MetricNameRE
|
||||||
|
// for legacy names, and iff it's valid UTF-8 if the UTF8Validation scheme is
|
||||||
|
// selected.
|
||||||
|
func IsValidMetricName(n LabelValue) bool {
|
||||||
|
switch NameValidationScheme {
|
||||||
|
case LegacyValidation:
|
||||||
|
return IsValidLegacyMetricName(n)
|
||||||
|
case UTF8Validation:
|
||||||
|
if len(n) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return utf8.ValidString(string(n))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Invalid name validation scheme requested: %d", NameValidationScheme))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidLegacyMetricName is similar to IsValidMetricName but always uses the
|
||||||
|
// legacy validation scheme regardless of the value of NameValidationScheme.
|
||||||
// This function, however, does not use MetricNameRE for the check but a much
|
// This function, however, does not use MetricNameRE for the check but a much
|
||||||
// faster hardcoded implementation.
|
// faster hardcoded implementation.
|
||||||
func IsValidMetricName(n LabelValue) bool {
|
func IsValidLegacyMetricName(n LabelValue) bool {
|
||||||
if len(n) == 0 {
|
if len(n) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i, b := range n {
|
for i, b := range n {
|
||||||
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) {
|
if !isValidLegacyRune(b, i) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EscapeMetricFamily escapes the given metric names and labels with the given
|
||||||
|
// escaping scheme. Returns a new object that uses the same pointers to fields
|
||||||
|
// when possible and creates new escaped versions so as not to mutate the
|
||||||
|
// input.
|
||||||
|
func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricFamily {
|
||||||
|
if v == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if scheme == NoEscaping {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
out := &dto.MetricFamily{
|
||||||
|
Help: v.Help,
|
||||||
|
Type: v.Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the name is nil, copy as-is, don't try to escape.
|
||||||
|
if v.Name == nil || IsValidLegacyMetricName(LabelValue(v.GetName())) {
|
||||||
|
out.Name = v.Name
|
||||||
|
} else {
|
||||||
|
out.Name = proto.String(EscapeName(v.GetName(), scheme))
|
||||||
|
}
|
||||||
|
for _, m := range v.Metric {
|
||||||
|
if !metricNeedsEscaping(m) {
|
||||||
|
out.Metric = append(out.Metric, m)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
escaped := &dto.Metric{
|
||||||
|
Gauge: m.Gauge,
|
||||||
|
Counter: m.Counter,
|
||||||
|
Summary: m.Summary,
|
||||||
|
Untyped: m.Untyped,
|
||||||
|
Histogram: m.Histogram,
|
||||||
|
TimestampMs: m.TimestampMs,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, l := range m.Label {
|
||||||
|
if l.GetName() == MetricNameLabel {
|
||||||
|
if l.Value == nil || IsValidLegacyMetricName(LabelValue(l.GetValue())) {
|
||||||
|
escaped.Label = append(escaped.Label, l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
escaped.Label = append(escaped.Label, &dto.LabelPair{
|
||||||
|
Name: proto.String(MetricNameLabel),
|
||||||
|
Value: proto.String(EscapeName(l.GetValue(), scheme)),
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if l.Name == nil || IsValidLegacyMetricName(LabelValue(l.GetName())) {
|
||||||
|
escaped.Label = append(escaped.Label, l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
escaped.Label = append(escaped.Label, &dto.LabelPair{
|
||||||
|
Name: proto.String(EscapeName(l.GetName(), scheme)),
|
||||||
|
Value: l.Value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
out.Metric = append(out.Metric, escaped)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func metricNeedsEscaping(m *dto.Metric) bool {
|
||||||
|
for _, l := range m.Label {
|
||||||
|
if l.GetName() == MetricNameLabel && !IsValidLegacyMetricName(LabelValue(l.GetValue())) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if !IsValidLegacyMetricName(LabelValue(l.GetName())) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
lowerhex = "0123456789abcdef"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EscapeName escapes the incoming name according to the provided escaping
|
||||||
|
// scheme. Depending on the rules of escaping, this may cause no change in the
|
||||||
|
// string that is returned. (Especially NoEscaping, which by definition is a
|
||||||
|
// noop). This function does not do any validation of the name.
|
||||||
|
func EscapeName(name string, scheme EscapingScheme) string {
|
||||||
|
if len(name) == 0 {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
var escaped strings.Builder
|
||||||
|
switch scheme {
|
||||||
|
case NoEscaping:
|
||||||
|
return name
|
||||||
|
case UnderscoreEscaping:
|
||||||
|
if IsValidLegacyMetricName(LabelValue(name)) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
for i, b := range name {
|
||||||
|
if isValidLegacyRune(b, i) {
|
||||||
|
escaped.WriteRune(b)
|
||||||
|
} else {
|
||||||
|
escaped.WriteRune('_')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return escaped.String()
|
||||||
|
case DotsEscaping:
|
||||||
|
// Do not early return for legacy valid names, we still escape underscores.
|
||||||
|
for i, b := range name {
|
||||||
|
if b == '_' {
|
||||||
|
escaped.WriteString("__")
|
||||||
|
} else if b == '.' {
|
||||||
|
escaped.WriteString("_dot_")
|
||||||
|
} else if isValidLegacyRune(b, i) {
|
||||||
|
escaped.WriteRune(b)
|
||||||
|
} else {
|
||||||
|
escaped.WriteRune('_')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return escaped.String()
|
||||||
|
case ValueEncodingEscaping:
|
||||||
|
if IsValidLegacyMetricName(LabelValue(name)) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
escaped.WriteString("U__")
|
||||||
|
for i, b := range name {
|
||||||
|
if isValidLegacyRune(b, i) {
|
||||||
|
escaped.WriteRune(b)
|
||||||
|
} else if !utf8.ValidRune(b) {
|
||||||
|
escaped.WriteString("_FFFD_")
|
||||||
|
} else if b < 0x100 {
|
||||||
|
escaped.WriteRune('_')
|
||||||
|
for s := 4; s >= 0; s -= 4 {
|
||||||
|
escaped.WriteByte(lowerhex[b>>uint(s)&0xF])
|
||||||
|
}
|
||||||
|
escaped.WriteRune('_')
|
||||||
|
} else if b < 0x10000 {
|
||||||
|
escaped.WriteRune('_')
|
||||||
|
for s := 12; s >= 0; s -= 4 {
|
||||||
|
escaped.WriteByte(lowerhex[b>>uint(s)&0xF])
|
||||||
|
}
|
||||||
|
escaped.WriteRune('_')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return escaped.String()
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid escaping scheme %d", scheme))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// lower function taken from strconv.atoi
|
||||||
|
func lower(c byte) byte {
|
||||||
|
return c | ('x' - 'X')
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnescapeName unescapes the incoming name according to the provided escaping
|
||||||
|
// scheme if possible. Some schemes are partially or totally non-roundtripable.
|
||||||
|
// If any error is enountered, returns the original input.
|
||||||
|
func UnescapeName(name string, scheme EscapingScheme) string {
|
||||||
|
if len(name) == 0 {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
switch scheme {
|
||||||
|
case NoEscaping:
|
||||||
|
return name
|
||||||
|
case UnderscoreEscaping:
|
||||||
|
// It is not possible to unescape from underscore replacement.
|
||||||
|
return name
|
||||||
|
case DotsEscaping:
|
||||||
|
name = strings.ReplaceAll(name, "_dot_", ".")
|
||||||
|
name = strings.ReplaceAll(name, "__", "_")
|
||||||
|
return name
|
||||||
|
case ValueEncodingEscaping:
|
||||||
|
escapedName, found := strings.CutPrefix(name, "U__")
|
||||||
|
if !found {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
var unescaped strings.Builder
|
||||||
|
TOP:
|
||||||
|
for i := 0; i < len(escapedName); i++ {
|
||||||
|
// All non-underscores are treated normally.
|
||||||
|
if escapedName[i] != '_' {
|
||||||
|
unescaped.WriteByte(escapedName[i])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
if i >= len(escapedName) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
// A double underscore is a single underscore.
|
||||||
|
if escapedName[i] == '_' {
|
||||||
|
unescaped.WriteByte('_')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// We think we are in a UTF-8 code, process it.
|
||||||
|
var utf8Val uint
|
||||||
|
for j := 0; i < len(escapedName); j++ {
|
||||||
|
// This is too many characters for a utf8 value.
|
||||||
|
if j > 4 {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
// Found a closing underscore, convert to a rune, check validity, and append.
|
||||||
|
if escapedName[i] == '_' {
|
||||||
|
utf8Rune := rune(utf8Val)
|
||||||
|
if !utf8.ValidRune(utf8Rune) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
unescaped.WriteRune(utf8Rune)
|
||||||
|
continue TOP
|
||||||
|
}
|
||||||
|
r := lower(escapedName[i])
|
||||||
|
utf8Val *= 16
|
||||||
|
if r >= '0' && r <= '9' {
|
||||||
|
utf8Val += uint(r) - '0'
|
||||||
|
} else if r >= 'a' && r <= 'f' {
|
||||||
|
utf8Val += uint(r) - 'a' + 10
|
||||||
|
} else {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
// Didn't find closing underscore, invalid.
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return unescaped.String()
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid escaping scheme %d", scheme))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidLegacyRune(b rune, i int) bool {
|
||||||
|
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EscapingScheme) String() string {
|
||||||
|
switch e {
|
||||||
|
case NoEscaping:
|
||||||
|
return AllowUTF8
|
||||||
|
case UnderscoreEscaping:
|
||||||
|
return EscapeUnderscores
|
||||||
|
case DotsEscaping:
|
||||||
|
return EscapeDots
|
||||||
|
case ValueEncodingEscaping:
|
||||||
|
return EscapeValues
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown format scheme %d", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToEscapingScheme(s string) (EscapingScheme, error) {
|
||||||
|
if s == "" {
|
||||||
|
return NoEscaping, fmt.Errorf("got empty string instead of escaping scheme")
|
||||||
|
}
|
||||||
|
switch s {
|
||||||
|
case AllowUTF8:
|
||||||
|
return NoEscaping, nil
|
||||||
|
case EscapeUnderscores:
|
||||||
|
return UnderscoreEscaping, nil
|
||||||
|
case EscapeDots:
|
||||||
|
return DotsEscaping, nil
|
||||||
|
case EscapeValues:
|
||||||
|
return ValueEncodingEscaping, nil
|
||||||
|
default:
|
||||||
|
return NoEscaping, fmt.Errorf("unknown format scheme " + s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
@@ -141,15 +141,15 @@ github.com/munnerz/goautoneg
|
|||||||
# github.com/pkg/errors v0.9.1
|
# github.com/pkg/errors v0.9.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/pkg/errors
|
github.com/pkg/errors
|
||||||
# github.com/prometheus/client_golang v1.18.0
|
# github.com/prometheus/client_golang v1.19.0
|
||||||
## explicit; go 1.19
|
## explicit; go 1.20
|
||||||
github.com/prometheus/client_golang/prometheus
|
github.com/prometheus/client_golang/prometheus
|
||||||
github.com/prometheus/client_golang/prometheus/internal
|
github.com/prometheus/client_golang/prometheus/internal
|
||||||
github.com/prometheus/client_golang/prometheus/promhttp
|
github.com/prometheus/client_golang/prometheus/promhttp
|
||||||
# github.com/prometheus/client_model v0.6.0
|
# github.com/prometheus/client_model v0.6.0
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
github.com/prometheus/client_model/go
|
github.com/prometheus/client_model/go
|
||||||
# github.com/prometheus/common v0.46.0
|
# github.com/prometheus/common v0.48.0
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
github.com/prometheus/common/expfmt
|
github.com/prometheus/common/expfmt
|
||||||
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
|
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
|
||||||
|
Reference in New Issue
Block a user