[VOL-4291] Rw-core updates for gRPC migration
Change-Id: I8d5a554409115b29318089671ca4e1ab3fa98810
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/build_info.go b/vendor/github.com/prometheus/client_golang/prometheus/build_info.go
deleted file mode 100644
index 288f0e8..0000000
--- a/vendor/github.com/prometheus/client_golang/prometheus/build_info.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The Prometheus Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// +build go1.12
-
-package prometheus
-
-import "runtime/debug"
-
-// readBuildInfo is a wrapper around debug.ReadBuildInfo for Go 1.12+.
-func readBuildInfo() (path, version, sum string) {
- path, version, sum = "unknown", "unknown", "unknown"
- if bi, ok := debug.ReadBuildInfo(); ok {
- path = bi.Main.Path
- version = bi.Main.Version
- sum = bi.Main.Sum
- }
- return
-}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/build_info_pre_1.12.go b/vendor/github.com/prometheus/client_golang/prometheus/build_info_pre_1.12.go
deleted file mode 100644
index 6609e28..0000000
--- a/vendor/github.com/prometheus/client_golang/prometheus/build_info_pre_1.12.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 The Prometheus Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// +build !go1.12
-
-package prometheus
-
-// readBuildInfo is a wrapper around debug.ReadBuildInfo for Go versions before
-// 1.12. Remove this whole file once the minimum supported Go version is 1.12.
-func readBuildInfo() (path, version, sum string) {
- return "unknown", "unknown", "unknown"
-}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter.go b/vendor/github.com/prometheus/client_golang/prometheus/counter.go
index d463e36..3f8fd79 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/counter.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/counter.go
@@ -17,6 +17,7 @@
"errors"
"math"
"sync/atomic"
+ "time"
dto "github.com/prometheus/client_model/go"
)
@@ -42,11 +43,27 @@
Add(float64)
}
+// ExemplarAdder is implemented by Counters that offer the option of adding a
+// value to the Counter together with an exemplar. Its AddWithExemplar method
+// works like the Add method of the Counter interface but also replaces the
+// currently saved exemplar (if any) with a new one, created from the provided
+// value, the current time as timestamp, and the provided labels. Empty Labels
+// will lead to a valid (label-less) exemplar. But if Labels is nil, the current
+// exemplar is left in place. AddWithExemplar panics if the value is < 0, if any
+// of the provided labels are invalid, or if the provided labels contain more
+// than 64 runes in total.
+type ExemplarAdder interface {
+ AddWithExemplar(value float64, exemplar Labels)
+}
+
// CounterOpts is an alias for Opts. See there for doc comments.
type CounterOpts Opts
// NewCounter creates a new Counter based on the provided CounterOpts.
//
+// The returned implementation also implements ExemplarAdder. It is safe to
+// perform the corresponding type assertion.
+//
// The returned implementation tracks the counter value in two separate
// variables, a float64 and a uint64. The latter is used to track calls of the
// Inc method and calls of the Add method with a value that can be represented
@@ -61,7 +78,7 @@
nil,
opts.ConstLabels,
)
- result := &counter{desc: desc, labelPairs: desc.constLabelPairs}
+ result := &counter{desc: desc, labelPairs: desc.constLabelPairs, now: time.Now}
result.init(result) // Init self-collection.
return result
}
@@ -78,6 +95,9 @@
desc *Desc
labelPairs []*dto.LabelPair
+ exemplar atomic.Value // Containing nil or a *dto.Exemplar.
+
+ now func() time.Time // To mock out time.Now() for testing.
}
func (c *counter) Desc() *Desc {
@@ -88,6 +108,7 @@
if v < 0 {
panic(errors.New("counter cannot decrease in value"))
}
+
ival := uint64(v)
if float64(ival) == v {
atomic.AddUint64(&c.valInt, ival)
@@ -103,6 +124,11 @@
}
}
+func (c *counter) AddWithExemplar(v float64, e Labels) {
+ c.Add(v)
+ c.updateExemplar(v, e)
+}
+
func (c *counter) Inc() {
atomic.AddUint64(&c.valInt, 1)
}
@@ -112,7 +138,23 @@
ival := atomic.LoadUint64(&c.valInt)
val := fval + float64(ival)
- return populateMetric(CounterValue, val, c.labelPairs, out)
+ var exemplar *dto.Exemplar
+ if e := c.exemplar.Load(); e != nil {
+ exemplar = e.(*dto.Exemplar)
+ }
+
+ return populateMetric(CounterValue, val, c.labelPairs, exemplar, out)
+}
+
+func (c *counter) updateExemplar(v float64, l Labels) {
+ if l == nil {
+ return
+ }
+ e, err := newExemplar(v, c.now(), l)
+ if err != nil {
+ panic(err)
+ }
+ c.exemplar.Store(e)
}
// CounterVec is a Collector that bundles a set of Counters that all share the
@@ -121,7 +163,7 @@
// (e.g. number of HTTP requests, partitioned by response code and
// method). Create instances with NewCounterVec.
type CounterVec struct {
- *metricVec
+ *MetricVec
}
// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
@@ -134,11 +176,11 @@
opts.ConstLabels,
)
return &CounterVec{
- metricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
}
- result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
+ result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: time.Now}
result.init(result) // Init self-collection.
return result
}),
@@ -146,7 +188,7 @@
}
// GetMetricWithLabelValues returns the Counter for the given slice of label
-// values (same order as the VariableLabels in Desc). If that combination of
+// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Counter is created.
//
// It is possible to call this method without using the returned Counter to only
@@ -160,7 +202,7 @@
// Counter with the same label values is created later.
//
// An error is returned if the number of label values is not the same as the
-// number of VariableLabels in Desc (minus any curried labels).
+// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@@ -169,7 +211,7 @@
// with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example.
func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
- metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
+ metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Counter), err
}
@@ -177,19 +219,19 @@
}
// GetMetricWith returns the Counter for the given Labels map (the label names
-// must match those of the VariableLabels in Desc). If that label map is
+// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Counter is created. Implications of
// creating a Counter without using it and keeping the Counter for later use are
// the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
-// with those of the VariableLabels in Desc (minus any curried labels).
+// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
- metric, err := v.metricVec.getMetricWith(labels)
+ metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Counter), err
}
@@ -233,7 +275,7 @@
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) {
- vec, err := v.curryWith(labels)
+ vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &CounterVec{vec}, err
}
@@ -267,6 +309,8 @@
// provided function must be concurrency-safe. The function should also honor
// the contract for a Counter (values only go up, not down), but compliance will
// not be checked.
+//
+// Check out the ExampleGaugeFunc examples for the similar GaugeFunc.
func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc {
return newValueFunc(NewDesc(
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc.go b/vendor/github.com/prometheus/client_golang/prometheus/desc.go
index 1d034f8..4bb816a 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/desc.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/desc.go
@@ -19,6 +19,8 @@
"sort"
"strings"
+ "github.com/cespare/xxhash/v2"
+ //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/model"
@@ -49,7 +51,7 @@
// constLabelPairs contains precalculated DTO label pairs based on
// the constant labels.
constLabelPairs []*dto.LabelPair
- // VariableLabels contains names of labels for which the metric
+ // variableLabels contains names of labels for which the metric
// maintains variable values.
variableLabels []string
// id is a hash of the values of the ConstLabels and fqName. This
@@ -126,24 +128,24 @@
return d
}
- vh := hashNew()
+ xxh := xxhash.New()
for _, val := range labelValues {
- vh = hashAdd(vh, val)
- vh = hashAddByte(vh, separatorByte)
+ xxh.WriteString(val)
+ xxh.Write(separatorByteSlice)
}
- d.id = vh
+ d.id = xxh.Sum64()
// Sort labelNames so that order doesn't matter for the hash.
sort.Strings(labelNames)
// Now hash together (in this order) the help string and the sorted
// label names.
- lh := hashNew()
- lh = hashAdd(lh, help)
- lh = hashAddByte(lh, separatorByte)
+ xxh.Reset()
+ xxh.WriteString(help)
+ xxh.Write(separatorByteSlice)
for _, labelName := range labelNames {
- lh = hashAdd(lh, labelName)
- lh = hashAddByte(lh, separatorByte)
+ xxh.WriteString(labelName)
+ xxh.Write(separatorByteSlice)
}
- d.dimHash = lh
+ d.dimHash = xxh.Sum64()
d.constLabelPairs = make([]*dto.LabelPair, 0, len(constLabels))
for n, v := range constLabels {
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/doc.go b/vendor/github.com/prometheus/client_golang/prometheus/doc.go
index 01977de..9845012 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/doc.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/doc.go
@@ -84,25 +84,21 @@
// of those four metric types can be found in the Prometheus docs:
// https://prometheus.io/docs/concepts/metric_types/
//
-// A fifth "type" of metric is Untyped. It behaves like a Gauge, but signals the
-// Prometheus server not to assume anything about its type.
-//
-// In addition to the fundamental metric types Gauge, Counter, Summary,
-// Histogram, and Untyped, a very important part of the Prometheus data model is
-// the partitioning of samples along dimensions called labels, which results in
+// In addition to the fundamental metric types Gauge, Counter, Summary, and
+// Histogram, a very important part of the Prometheus data model is the
+// partitioning of samples along dimensions called labels, which results in
// metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec,
-// HistogramVec, and UntypedVec.
+// and HistogramVec.
//
// While only the fundamental metric types implement the Metric interface, both
// the metrics and their vector versions implement the Collector interface. A
// Collector manages the collection of a number of Metrics, but for convenience,
-// a Metric can also “collect itself”. Note that Gauge, Counter, Summary,
-// Histogram, and Untyped are interfaces themselves while GaugeVec, CounterVec,
-// SummaryVec, HistogramVec, and UntypedVec are not.
+// a Metric can also “collect itself”. Note that Gauge, Counter, Summary, and
+// Histogram are interfaces themselves while GaugeVec, CounterVec, SummaryVec,
+// and HistogramVec are not.
//
// To create instances of Metrics and their vector versions, you need a suitable
-// …Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts, HistogramOpts, or
-// UntypedOpts.
+// …Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts, or HistogramOpts.
//
// Custom Collectors and constant Metrics
//
@@ -118,13 +114,16 @@
// existing numbers into Prometheus Metrics during collection. An own
// implementation of the Collector interface is perfect for that. You can create
// Metric instances “on the fly” using NewConstMetric, NewConstHistogram, and
-// NewConstSummary (and their respective Must… versions). That will happen in
-// the Collect method. The Describe method has to return separate Desc
-// instances, representative of the “throw-away” metrics to be created later.
-// NewDesc comes in handy to create those Desc instances. Alternatively, you
-// could return no Desc at all, which will mark the Collector “unchecked”. No
-// checks are performed at registration time, but metric consistency will still
-// be ensured at scrape time, i.e. any inconsistencies will lead to scrape
+// NewConstSummary (and their respective Must… versions). NewConstMetric is used
+// for all metric types with just a float64 as their value: Counter, Gauge, and
+// a special “type” called Untyped. Use the latter if you are not sure if the
+// mirrored metric is a Counter or a Gauge. Creation of the Metric instance
+// happens in the Collect method. The Describe method has to return separate
+// Desc instances, representative of the “throw-away” metrics to be created
+// later. NewDesc comes in handy to create those Desc instances. Alternatively,
+// you could return no Desc at all, which will mark the Collector “unchecked”.
+// No checks are performed at registration time, but metric consistency will
+// still be ensured at scrape time, i.e. any inconsistencies will lead to scrape
// errors. Thus, with unchecked Collectors, the responsibility to not collect
// metrics that lead to inconsistencies in the total scrape result lies with the
// implementer of the Collector. While this is not a desirable state, it is
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go
index 18a99d5..c41ab37 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go
@@ -22,43 +22,10 @@
exports map[string]*Desc
}
-// NewExpvarCollector returns a newly allocated expvar Collector that still has
-// to be registered with a Prometheus registry.
+// NewExpvarCollector is the obsolete version of collectors.NewExpvarCollector.
+// See there for documentation.
//
-// An expvar Collector collects metrics from the expvar interface. It provides a
-// quick way to expose numeric values that are already exported via expvar as
-// Prometheus metrics. Note that the data models of expvar and Prometheus are
-// fundamentally different, and that the expvar Collector is inherently slower
-// than native Prometheus metrics. Thus, the expvar Collector is probably great
-// for experiments and prototying, but you should seriously consider a more
-// direct implementation of Prometheus metrics for monitoring production
-// systems.
-//
-// The exports map has the following meaning:
-//
-// The keys in the map correspond to expvar keys, i.e. for every expvar key you
-// want to export as Prometheus metric, you need an entry in the exports
-// map. The descriptor mapped to each key describes how to export the expvar
-// value. It defines the name and the help string of the Prometheus metric
-// proxying the expvar value. The type will always be Untyped.
-//
-// For descriptors without variable labels, the expvar value must be a number or
-// a bool. The number is then directly exported as the Prometheus sample
-// value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values
-// that are not numbers or bools are silently ignored.
-//
-// If the descriptor has one variable label, the expvar value must be an expvar
-// map. The keys in the expvar map become the various values of the one
-// Prometheus label. The values in the expvar map must be numbers or bools again
-// as above.
-//
-// For descriptors with more than one variable label, the expvar must be a
-// nested expvar map, i.e. where the values of the topmost map are maps again
-// etc. until a depth is reached that corresponds to the number of labels. The
-// leaves of that structure must be numbers or bools as above to serve as the
-// sample values.
-//
-// Anything that does not fit into the scheme above is silently ignored.
+// Deprecated: Use collectors.NewExpvarCollector instead.
func NewExpvarCollector(exports map[string]*Desc) Collector {
return &expvarCollector{
exports: exports,
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go
index 71d406b..bd0733d 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go
@@ -123,7 +123,7 @@
func (g *gauge) Write(out *dto.Metric) error {
val := math.Float64frombits(atomic.LoadUint64(&g.valBits))
- return populateMetric(GaugeValue, val, g.labelPairs, out)
+ return populateMetric(GaugeValue, val, g.labelPairs, nil, out)
}
// GaugeVec is a Collector that bundles a set of Gauges that all share the same
@@ -132,7 +132,7 @@
// (e.g. number of operations queued, partitioned by user and operation
// type). Create instances with NewGaugeVec.
type GaugeVec struct {
- *metricVec
+ *MetricVec
}
// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
@@ -145,11 +145,11 @@
opts.ConstLabels,
)
return &GaugeVec{
- metricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
}
- result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
+ result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)}
result.init(result) // Init self-collection.
return result
}),
@@ -157,7 +157,7 @@
}
// GetMetricWithLabelValues returns the Gauge for the given slice of label
-// values (same order as the VariableLabels in Desc). If that combination of
+// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Gauge is created.
//
// It is possible to call this method without using the returned Gauge to only
@@ -172,7 +172,7 @@
// example.
//
// An error is returned if the number of label values is not the same as the
-// number of VariableLabels in Desc (minus any curried labels).
+// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@@ -180,7 +180,7 @@
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
- metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
+ metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Gauge), err
}
@@ -188,19 +188,19 @@
}
// GetMetricWith returns the Gauge for the given Labels map (the label names
-// must match those of the VariableLabels in Desc). If that label map is
+// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Gauge is created. Implications of
// creating a Gauge without using it and keeping the Gauge for later use are
// the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
-// with those of the VariableLabels in Desc (minus any curried labels).
+// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
- metric, err := v.metricVec.getMetricWith(labels)
+ metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Gauge), err
}
@@ -244,7 +244,7 @@
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
- vec, err := v.curryWith(labels)
+ vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &GaugeVec{vec}, err
}
@@ -273,9 +273,12 @@
// NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The
// value reported is determined by calling the given function from within the
// Write method. Take into account that metric collection may happen
-// concurrently. If that results in concurrent calls to Write, like in the case
-// where a GaugeFunc is directly registered with Prometheus, the provided
-// function must be concurrency-safe.
+// concurrently. Therefore, it must be safe to call the provided function
+// concurrently.
+//
+// NewGaugeFunc is a good way to create an “info” style metric with a constant
+// value of 1. Example:
+// https://github.com/prometheus/common/blob/8558a5b7db3c84fa38b4766966059a7bd5bfa2ee/version/info.go#L36-L56
func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc {
return newValueFunc(NewDesc(
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
index dc9247f..a96ed1c 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
@@ -36,31 +36,10 @@
msMaxAge time.Duration // Maximum allowed age of old memstats.
}
-// NewGoCollector returns a collector that exports metrics about the current Go
-// process. This includes memory stats. To collect those, runtime.ReadMemStats
-// is called. This requires to “stop the world”, which usually only happens for
-// garbage collection (GC). Take the following implications into account when
-// deciding whether to use the Go collector:
+// NewGoCollector is the obsolete version of collectors.NewGoCollector.
+// See there for documentation.
//
-// 1. The performance impact of stopping the world is the more relevant the more
-// frequently metrics are collected. However, with Go1.9 or later the
-// stop-the-world time per metrics collection is very short (~25µs) so that the
-// performance impact will only matter in rare cases. However, with older Go
-// versions, the stop-the-world duration depends on the heap size and can be
-// quite significant (~1.7 ms/GiB as per
-// https://go-review.googlesource.com/c/go/+/34937).
-//
-// 2. During an ongoing GC, nothing else can stop the world. Therefore, if the
-// metrics collection happens to coincide with GC, it will only complete after
-// GC has finished. Usually, GC is fast enough to not cause problems. However,
-// with a very large heap, GC might take multiple seconds, which is enough to
-// cause scrape timeouts in common setups. To avoid this problem, the Go
-// collector will use the memstats from a previous collection if
-// runtime.ReadMemStats takes more than 1s. However, if there are no previously
-// collected memstats, or their collection is more than 5m ago, the collection
-// will block until runtime.ReadMemStats succeeds. (The problem might be solved
-// in Go1.13, see https://github.com/golang/go/issues/19812 for the related Go
-// issue.)
+// Deprecated: Use collectors.NewGoCollector instead.
func NewGoCollector() Collector {
return &goCollector{
goroutinesDesc: NewDesc(
@@ -73,7 +52,7 @@
nil, nil),
gcDesc: NewDesc(
"go_gc_duration_seconds",
- "A summary of the GC invocation durations.",
+ "A summary of the pause duration of garbage collection cycles.",
nil, nil),
goInfoDesc: NewDesc(
"go_info",
@@ -365,25 +344,17 @@
valType ValueType
}
-// NewBuildInfoCollector returns a collector collecting a single metric
-// "go_build_info" with the constant value 1 and three labels "path", "version",
-// and "checksum". Their label values contain the main module path, version, and
-// checksum, respectively. The labels will only have meaningful values if the
-// binary is built with Go module support and from source code retrieved from
-// the source repository (rather than the local file system). This is usually
-// accomplished by building from outside of GOPATH, specifying the full address
-// of the main package, e.g. "GO111MODULE=on go run
-// github.com/prometheus/client_golang/examples/random". If built without Go
-// module support, all label values will be "unknown". If built with Go module
-// support but using the source code from the local file system, the "path" will
-// be set appropriately, but "checksum" will be empty and "version" will be
-// "(devel)".
+// NewBuildInfoCollector is the obsolete version of collectors.NewBuildInfoCollector.
+// See there for documentation.
//
-// This collector uses only the build information for the main module. See
-// https://github.com/povilasv/prommod for an example of a collector for the
-// module dependencies.
+// Deprecated: Use collectors.NewBuildInfoCollector instead.
func NewBuildInfoCollector() Collector {
- path, version, sum := readBuildInfo()
+ path, version, sum := "unknown", "unknown", "unknown"
+ if bi, ok := debug.ReadBuildInfo(); ok {
+ path = bi.Main.Path
+ version = bi.Main.Version
+ sum = bi.Main.Sum
+ }
c := &selfCollector{MustNewConstMetric(
NewDesc(
"go_build_info",
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go
index d7ea67b..8425640 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go
@@ -20,7 +20,9 @@
"sort"
"sync"
"sync/atomic"
+ "time"
+ //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
@@ -45,7 +47,12 @@
Metric
Collector
- // Observe adds a single observation to the histogram.
+ // Observe adds a single observation to the histogram. Observations are
+ // usually positive or zero. Negative observations are accepted but
+ // prevent current versions of Prometheus from properly detecting
+ // counter resets in the sum of observations. See
+ // https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
+ // for details.
Observe(float64)
}
@@ -138,7 +145,7 @@
// better covered by target labels set by the scraping Prometheus
// server, or by one specific metric (e.g. a build_info or a
// machine_role metric). See also
- // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
+ // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
ConstLabels Labels
// Buckets defines the buckets into which observations are counted. Each
@@ -151,6 +158,10 @@
// NewHistogram creates a new Histogram based on the provided HistogramOpts. It
// panics if the buckets in HistogramOpts are not in strictly increasing order.
+//
+// The returned implementation also implements ExemplarObserver. It is safe to
+// perform the corresponding type assertion. Exemplars are tracked separately
+// for each bucket.
func NewHistogram(opts HistogramOpts) Histogram {
return newHistogram(
NewDesc(
@@ -186,8 +197,9 @@
h := &histogram{
desc: desc,
upperBounds: opts.Buckets,
- labelPairs: makeLabelPairs(desc, labelValues),
- counts: [2]*histogramCounts{&histogramCounts{}, &histogramCounts{}},
+ labelPairs: MakeLabelPairs(desc, labelValues),
+ counts: [2]*histogramCounts{{}, {}},
+ now: time.Now,
}
for i, upperBound := range h.upperBounds {
if i < len(h.upperBounds)-1 {
@@ -205,9 +217,10 @@
}
}
// Finally we know the final length of h.upperBounds and can make buckets
- // for both counts:
+ // for both counts as well as exemplars:
h.counts[0].buckets = make([]uint64, len(h.upperBounds))
h.counts[1].buckets = make([]uint64, len(h.upperBounds))
+ h.exemplars = make([]atomic.Value, len(h.upperBounds)+1)
h.init(h) // Init self-collection.
return h
@@ -254,6 +267,9 @@
upperBounds []float64
labelPairs []*dto.LabelPair
+ exemplars []atomic.Value // One more than buckets (to include +Inf), each a *dto.Exemplar.
+
+ now func() time.Time // To mock out time.Now() for testing.
}
func (h *histogram) Desc() *Desc {
@@ -261,36 +277,13 @@
}
func (h *histogram) Observe(v float64) {
- // TODO(beorn7): For small numbers of buckets (<30), a linear search is
- // slightly faster than the binary search. If we really care, we could
- // switch from one search strategy to the other depending on the number
- // of buckets.
- //
- // Microbenchmarks (BenchmarkHistogramNoLabels):
- // 11 buckets: 38.3 ns/op linear - binary 48.7 ns/op
- // 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op
- // 300 buckets: 154 ns/op linear - binary 61.6 ns/op
- i := sort.SearchFloat64s(h.upperBounds, v)
+ h.observe(v, h.findBucket(v))
+}
- // We increment h.countAndHotIdx so that the counter in the lower
- // 63 bits gets incremented. At the same time, we get the new value
- // back, which we can use to find the currently-hot counts.
- n := atomic.AddUint64(&h.countAndHotIdx, 1)
- hotCounts := h.counts[n>>63]
-
- if i < len(h.upperBounds) {
- atomic.AddUint64(&hotCounts.buckets[i], 1)
- }
- for {
- oldBits := atomic.LoadUint64(&hotCounts.sumBits)
- newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
- if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) {
- break
- }
- }
- // Increment count last as we take it as a signal that the observation
- // is complete.
- atomic.AddUint64(&hotCounts.count, 1)
+func (h *histogram) ObserveWithExemplar(v float64, e Labels) {
+ i := h.findBucket(v)
+ h.observe(v, i)
+ h.updateExemplar(v, i, e)
}
func (h *histogram) Write(out *dto.Metric) error {
@@ -329,6 +322,18 @@
CumulativeCount: proto.Uint64(cumCount),
UpperBound: proto.Float64(upperBound),
}
+ if e := h.exemplars[i].Load(); e != nil {
+ his.Bucket[i].Exemplar = e.(*dto.Exemplar)
+ }
+ }
+ // If there is an exemplar for the +Inf bucket, we have to add that bucket explicitly.
+ if e := h.exemplars[len(h.upperBounds)].Load(); e != nil {
+ b := &dto.Bucket{
+ CumulativeCount: proto.Uint64(count),
+ UpperBound: proto.Float64(math.Inf(1)),
+ Exemplar: e.(*dto.Exemplar),
+ }
+ his.Bucket = append(his.Bucket, b)
}
out.Histogram = his
@@ -352,13 +357,64 @@
return nil
}
+// findBucket returns the index of the bucket for the provided value, or
+// len(h.upperBounds) for the +Inf bucket.
+func (h *histogram) findBucket(v float64) int {
+ // TODO(beorn7): For small numbers of buckets (<30), a linear search is
+ // slightly faster than the binary search. If we really care, we could
+ // switch from one search strategy to the other depending on the number
+ // of buckets.
+ //
+ // Microbenchmarks (BenchmarkHistogramNoLabels):
+ // 11 buckets: 38.3 ns/op linear - binary 48.7 ns/op
+ // 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op
+ // 300 buckets: 154 ns/op linear - binary 61.6 ns/op
+ return sort.SearchFloat64s(h.upperBounds, v)
+}
+
+// observe is the implementation for Observe without the findBucket part.
+func (h *histogram) observe(v float64, bucket int) {
+ // We increment h.countAndHotIdx so that the counter in the lower
+ // 63 bits gets incremented. At the same time, we get the new value
+ // back, which we can use to find the currently-hot counts.
+ n := atomic.AddUint64(&h.countAndHotIdx, 1)
+ hotCounts := h.counts[n>>63]
+
+ if bucket < len(h.upperBounds) {
+ atomic.AddUint64(&hotCounts.buckets[bucket], 1)
+ }
+ for {
+ oldBits := atomic.LoadUint64(&hotCounts.sumBits)
+ newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
+ if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) {
+ break
+ }
+ }
+ // Increment count last as we take it as a signal that the observation
+ // is complete.
+ atomic.AddUint64(&hotCounts.count, 1)
+}
+
+// updateExemplar replaces the exemplar for the provided bucket. With empty
+// labels, it's a no-op. It panics if any of the labels is invalid.
+func (h *histogram) updateExemplar(v float64, bucket int, l Labels) {
+ if l == nil {
+ return
+ }
+ e, err := newExemplar(v, h.now(), l)
+ if err != nil {
+ panic(err)
+ }
+ h.exemplars[bucket].Store(e)
+}
+
// HistogramVec is a Collector that bundles a set of Histograms that all share the
// same Desc, but have different values for their variable labels. This is used
// if you want to count the same thing partitioned by various dimensions
// (e.g. HTTP request latencies, partitioned by status code and method). Create
// instances with NewHistogramVec.
type HistogramVec struct {
- *metricVec
+ *MetricVec
}
// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
@@ -371,14 +427,14 @@
opts.ConstLabels,
)
return &HistogramVec{
- metricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
return newHistogram(desc, opts, lvs...)
}),
}
}
// GetMetricWithLabelValues returns the Histogram for the given slice of label
-// values (same order as the VariableLabels in Desc). If that combination of
+// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Histogram is created.
//
// It is possible to call this method without using the returned Histogram to only
@@ -393,7 +449,7 @@
// example.
//
// An error is returned if the number of label values is not the same as the
-// number of VariableLabels in Desc (minus any curried labels).
+// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@@ -402,7 +458,7 @@
// with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example.
func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
- metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
+ metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Observer), err
}
@@ -410,19 +466,19 @@
}
// GetMetricWith returns the Histogram for the given Labels map (the label names
-// must match those of the VariableLabels in Desc). If that label map is
+// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Histogram is created. Implications of
// creating a Histogram without using it and keeping the Histogram for later use
// are the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
-// with those of the VariableLabels in Desc (minus any curried labels).
+// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
- metric, err := v.metricVec.getMetricWith(labels)
+ metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Observer), err
}
@@ -466,7 +522,7 @@
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) {
- vec, err := v.curryWith(labels)
+ vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &HistogramVec{vec}, err
}
@@ -551,12 +607,12 @@
count: count,
sum: sum,
buckets: buckets,
- labelPairs: makeLabelPairs(desc, labelValues),
+ labelPairs: MakeLabelPairs(desc, labelValues),
}, nil
}
// MustNewConstHistogram is a version of NewConstHistogram that panics where
-// NewConstMetric would have returned an error.
+// NewConstHistogram would have returned an error.
func MustNewConstHistogram(
desc *Desc,
count uint64,
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go
index 55e6d86..dc12191 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go
@@ -17,12 +17,14 @@
"strings"
"time"
+ //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
+ "github.com/prometheus/common/model"
dto "github.com/prometheus/client_model/go"
)
-const separatorByte byte = 255
+var separatorByteSlice = []byte{model.SeparatorByte} // For convenient use with xxhash.
// A Metric models a single sample value with its meta data being exported to
// Prometheus. Implementations of Metric in this package are Gauge, Counter,
@@ -56,7 +58,7 @@
}
// Opts bundles the options for creating most Metric types. Each metric
-// implementation XXX has its own XXXOpts type, but in most cases, it is just be
+// implementation XXX has its own XXXOpts type, but in most cases, it is just
// an alias of this type (which might change when the requirement arises.)
//
// It is mandatory to set Name to a non-empty string. All other fields are
@@ -87,7 +89,7 @@
// better covered by target labels set by the scraping Prometheus
// server, or by one specific metric (e.g. a build_info or a
// machine_role metric). See also
- // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
+ // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
ConstLabels Labels
}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/observer.go b/vendor/github.com/prometheus/client_golang/prometheus/observer.go
index 5806cd0..4412801 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/observer.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/observer.go
@@ -50,3 +50,15 @@
Collector
}
+
+// ExemplarObserver is implemented by Observers that offer the option of
+// observing a value together with an exemplar. Its ObserveWithExemplar method
+// works like the Observe method of an Observer but also replaces the currently
+// saved exemplar (if any) with a new one, created from the provided value, the
+// current time as timestamp, and the provided Labels. Empty Labels will lead to
+// a valid (label-less) exemplar. But if Labels is nil, the current exemplar is
+// left in place. ObserveWithExemplar panics if any of the provided labels are
+// invalid or if the provided labels contain more than 64 runes in total.
+type ExemplarObserver interface {
+ ObserveWithExemplar(value float64, exemplar Labels)
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
index 9b80979..5bfe0ff 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
@@ -15,7 +15,11 @@
import (
"errors"
+ "fmt"
+ "io/ioutil"
"os"
+ "strconv"
+ "strings"
)
type processCollector struct {
@@ -50,16 +54,10 @@
ReportErrors bool
}
-// NewProcessCollector returns a collector which exports the current state of
-// process metrics including CPU, memory and file descriptor usage as well as
-// the process start time. The detailed behavior is defined by the provided
-// ProcessCollectorOpts. The zero value of ProcessCollectorOpts creates a
-// collector for the current process with an empty namespace string and no error
-// reporting.
+// NewProcessCollector is the obsolete version of collectors.NewProcessCollector.
+// See there for documentation.
//
-// The collector only works on operating systems with a Linux-style proc
-// filesystem and on Microsoft Windows. On other operating systems, it will not
-// collect any metrics.
+// Deprecated: Use collectors.NewProcessCollector instead.
func NewProcessCollector(opts ProcessCollectorOpts) Collector {
ns := ""
if len(opts.Namespace) > 0 {
@@ -149,3 +147,20 @@
}
ch <- NewInvalidMetric(desc, err)
}
+
+// NewPidFileFn returns a function that retrieves a pid from the specified file.
+// It is meant to be used for the PidFn field in ProcessCollectorOpts.
+func NewPidFileFn(pidFilePath string) func() (int, error) {
+ return func() (int, error) {
+ content, err := ioutil.ReadFile(pidFilePath)
+ if err != nil {
+ return 0, fmt.Errorf("can't read pid file %q: %+v", pidFilePath, err)
+ }
+ pid, err := strconv.Atoi(strings.TrimSpace(string(content)))
+ if err != nil {
+ return 0, fmt.Errorf("can't parse pid file %q: %+v", pidFilePath, err)
+ }
+
+ return pid, nil
+ }
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
index e0b935d..f973398 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
@@ -33,18 +33,22 @@
)
type processMemoryCounters struct {
- // https://docs.microsoft.com/en-us/windows/desktop/api/psapi/ns-psapi-_process_memory_counters_ex
+ // System interface description
+ // https://docs.microsoft.com/en-us/windows/desktop/api/psapi/ns-psapi-process_memory_counters_ex
+
+ // Refer to the Golang internal implementation
+ // https://golang.org/src/internal/syscall/windows/psapi_windows.go
_ uint32
PageFaultCount uint32
- PeakWorkingSetSize uint64
- WorkingSetSize uint64
- QuotaPeakPagedPoolUsage uint64
- QuotaPagedPoolUsage uint64
- QuotaPeakNonPagedPoolUsage uint64
- QuotaNonPagedPoolUsage uint64
- PagefileUsage uint64
- PeakPagefileUsage uint64
- PrivateUsage uint64
+ PeakWorkingSetSize uintptr
+ WorkingSetSize uintptr
+ QuotaPeakPagedPoolUsage uintptr
+ QuotaPagedPoolUsage uintptr
+ QuotaPeakNonPagedPoolUsage uintptr
+ QuotaNonPagedPoolUsage uintptr
+ PagefileUsage uintptr
+ PeakPagefileUsage uintptr
+ PrivateUsage uintptr
}
func getProcessMemoryInfo(handle windows.Handle) (processMemoryCounters, error) {
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go
index fa53568..e7c0d05 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go
@@ -53,15 +53,21 @@
}
func (r *responseWriterDelegator) WriteHeader(code int) {
+ if r.observeWriteHeader != nil && !r.wroteHeader {
+ // Only call observeWriteHeader for the 1st time. It's a bug if
+ // WriteHeader is called more than once, but we want to protect
+ // against it here. Note that we still delegate the WriteHeader
+ // to the original ResponseWriter to not mask the bug from it.
+ r.observeWriteHeader(code)
+ }
r.status = code
r.wroteHeader = true
r.ResponseWriter.WriteHeader(code)
- if r.observeWriteHeader != nil {
- r.observeWriteHeader(code)
- }
}
func (r *responseWriterDelegator) Write(b []byte) (int, error) {
+ // If applicable, call WriteHeader here so that observeWriteHeader is
+ // handled appropriately.
if !r.wroteHeader {
r.WriteHeader(http.StatusOK)
}
@@ -77,17 +83,23 @@
type pusherDelegator struct{ *responseWriterDelegator }
func (d closeNotifierDelegator) CloseNotify() <-chan bool {
- //lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to
- //remove support from client_golang yet.
+ //nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
return d.ResponseWriter.(http.CloseNotifier).CloseNotify()
}
func (d flusherDelegator) Flush() {
+ // If applicable, call WriteHeader here so that observeWriteHeader is
+ // handled appropriately.
+ if !d.wroteHeader {
+ d.WriteHeader(http.StatusOK)
+ }
d.ResponseWriter.(http.Flusher).Flush()
}
func (d hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return d.ResponseWriter.(http.Hijacker).Hijack()
}
func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) {
+ // If applicable, call WriteHeader here so that observeWriteHeader is
+ // handled appropriately.
if !d.wroteHeader {
d.WriteHeader(http.StatusOK)
}
@@ -335,8 +347,7 @@
}
id := 0
- //lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to
- //remove support from client_golang yet.
+ //nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
if _, ok := w.(http.CloseNotifier); ok {
id += closeNotifier
}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
index cea5a90..d86d0cf 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
@@ -99,7 +99,7 @@
inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight)
}
if opts.Registry != nil {
- // Initialize all possibilites that can occur below.
+ // Initialize all possibilities that can occur below.
errCnt.WithLabelValues("gathering")
errCnt.WithLabelValues("encoding")
if err := opts.Registry.Register(errCnt); err != nil {
@@ -144,7 +144,12 @@
}
}
- contentType := expfmt.Negotiate(req.Header)
+ var contentType expfmt.Format
+ if opts.EnableOpenMetrics {
+ contentType = expfmt.NegotiateIncludingOpenMetrics(req.Header)
+ } else {
+ contentType = expfmt.Negotiate(req.Header)
+ }
header := rsp.Header()
header.Set(contentTypeHeader, string(contentType))
@@ -162,28 +167,40 @@
enc := expfmt.NewEncoder(w, contentType)
- var lastErr error
- for _, mf := range mfs {
- if err := enc.Encode(mf); err != nil {
- lastErr = err
- if opts.ErrorLog != nil {
- opts.ErrorLog.Println("error encoding and sending metric family:", err)
- }
- errCnt.WithLabelValues("encoding").Inc()
- switch opts.ErrorHandling {
- case PanicOnError:
- panic(err)
- case ContinueOnError:
- // Handled later.
- case HTTPErrorOnError:
- httpError(rsp, err)
- return
- }
+ // handleError handles the error according to opts.ErrorHandling
+ // and returns true if we have to abort after the handling.
+ handleError := func(err error) bool {
+ if err == nil {
+ return false
}
+ if opts.ErrorLog != nil {
+ opts.ErrorLog.Println("error encoding and sending metric family:", err)
+ }
+ errCnt.WithLabelValues("encoding").Inc()
+ switch opts.ErrorHandling {
+ case PanicOnError:
+ panic(err)
+ case HTTPErrorOnError:
+ // We cannot really send an HTTP error at this
+ // point because we most likely have written
+ // something to rsp already. But at least we can
+ // stop sending.
+ return true
+ }
+ // Do nothing in all other cases, including ContinueOnError.
+ return false
}
- if lastErr != nil {
- httpError(rsp, lastErr)
+ for _, mf := range mfs {
+ if handleError(enc.Encode(mf)) {
+ return
+ }
+ }
+ if closer, ok := enc.(expfmt.Closer); ok {
+ // This in particular takes care of the final "# EOF\n" line for OpenMetrics.
+ if handleError(closer.Close()) {
+ return
+ }
}
})
@@ -255,7 +272,12 @@
// errors are encountered.
const (
// Serve an HTTP status code 500 upon the first error
- // encountered. Report the error message in the body.
+ // encountered. Report the error message in the body. Note that HTTP
+ // errors cannot be served anymore once the beginning of a regular
+ // payload has been sent. Thus, in the (unlikely) case that encoding the
+ // payload into the negotiated wire format fails, serving the response
+ // will simply be aborted. Set an ErrorLog in HandlerOpts to detect
+ // those errors.
HTTPErrorOnError HandlerErrorHandling = iota
// Ignore errors and try to serve as many metrics as possible. However,
// if no metrics can be served, serve an HTTP status code 500 and the
@@ -281,8 +303,12 @@
// HandlerOpts specifies options how to serve metrics via an http.Handler. The
// zero value of HandlerOpts is a reasonable default.
type HandlerOpts struct {
- // ErrorLog specifies an optional logger for errors collecting and
- // serving metrics. If nil, errors are not logged at all.
+ // ErrorLog specifies an optional Logger for errors collecting and
+ // serving metrics. If nil, errors are not logged at all. Note that the
+ // type of a reported error is often prometheus.MultiError, which
+ // formats into a multi-line error string. If you want to avoid the
+ // latter, create a Logger implementation that detects a
+ // prometheus.MultiError and formats the contained errors into one line.
ErrorLog Logger
// ErrorHandling defines how errors are handled. Note that errors are
// logged regardless of the configured ErrorHandling provided ErrorLog
@@ -318,6 +344,16 @@
// away). Until the implementation is improved, it is recommended to
// implement a separate timeout in potentially slow Collectors.
Timeout time.Duration
+ // If true, the experimental OpenMetrics encoding is added to the
+ // possible options during content negotiation. Note that Prometheus
+ // 2.5.0+ will negotiate OpenMetrics as first priority. OpenMetrics is
+ // the only way to transmit exemplars. However, the move to OpenMetrics
+ // is not completely transparent. Most notably, the values of "quantile"
+ // labels of Summaries and "le" labels of Histograms are formatted with
+ // a trailing ".0" if they would otherwise look like integer numbers
+ // (which changes the identity of the resulting series on the Prometheus
+ // server).
+ EnableOpenMetrics bool
}
// gzipAccepted returns whether the client will accept gzip-encoded content.
@@ -334,11 +370,9 @@
}
// httpError removes any content-encoding header and then calls http.Error with
-// the provided error and http.StatusInternalServerErrer. Error contents is
-// supposed to be uncompressed plain text. However, same as with a plain
-// http.Error, any header settings will be void if the header has already been
-// sent. The error message will still be written to the writer, but it will
-// probably be of limited use.
+// the provided error and http.StatusInternalServerError. Error contents is
+// supposed to be uncompressed plain text. Same as with a plain http.Error, this
+// must not be called if the header or any payload has already been sent.
func httpError(rsp http.ResponseWriter, err error) {
rsp.Header().Del(contentEncodingHeader)
http.Error(
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
index 9db2438..ab037db 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
@@ -43,14 +43,14 @@
// InstrumentHandlerDuration is a middleware that wraps the provided
// http.Handler to observe the request duration with the provided ObserverVec.
-// The ObserverVec must have zero, one, or two non-const non-curried labels. For
-// those, the only allowed label names are "code" and "method". The function
-// panics otherwise. The Observe method of the Observer in the ObserverVec is
-// called with the request duration in seconds. Partitioning happens by HTTP
-// status code and/or HTTP method if the respective instance label names are
-// present in the ObserverVec. For unpartitioned observations, use an
-// ObserverVec with zero labels. Note that partitioning of Histograms is
-// expensive and should be used judiciously.
+// The ObserverVec must have valid metric and label names and must have zero,
+// one, or two non-const non-curried labels. For those, the only allowed label
+// names are "code" and "method". The function panics otherwise. The Observe
+// method of the Observer in the ObserverVec is called with the request duration
+// in seconds. Partitioning happens by HTTP status code and/or HTTP method if
+// the respective instance label names are present in the ObserverVec. For
+// unpartitioned observations, use an ObserverVec with zero labels. Note that
+// partitioning of Histograms is expensive and should be used judiciously.
//
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
//
@@ -79,12 +79,13 @@
}
// InstrumentHandlerCounter is a middleware that wraps the provided http.Handler
-// to observe the request result with the provided CounterVec. The CounterVec
-// must have zero, one, or two non-const non-curried labels. For those, the only
-// allowed label names are "code" and "method". The function panics
-// otherwise. Partitioning of the CounterVec happens by HTTP status code and/or
-// HTTP method if the respective instance label names are present in the
-// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
+// to observe the request result with the provided CounterVec. The CounterVec
+// must have valid metric and label names and must have zero, one, or two
+// non-const non-curried labels. For those, the only allowed label names are
+// "code" and "method". The function panics otherwise. Partitioning of the
+// CounterVec happens by HTTP status code and/or HTTP method if the respective
+// instance label names are present in the CounterVec. For unpartitioned
+// counting, use a CounterVec with zero labels.
//
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
//
@@ -110,14 +111,15 @@
// InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided
// http.Handler to observe with the provided ObserverVec the request duration
-// until the response headers are written. The ObserverVec must have zero, one,
-// or two non-const non-curried labels. For those, the only allowed label names
-// are "code" and "method". The function panics otherwise. The Observe method of
-// the Observer in the ObserverVec is called with the request duration in
-// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
-// respective instance label names are present in the ObserverVec. For
-// unpartitioned observations, use an ObserverVec with zero labels. Note that
-// partitioning of Histograms is expensive and should be used judiciously.
+// until the response headers are written. The ObserverVec must have valid
+// metric and label names and must have zero, one, or two non-const non-curried
+// labels. For those, the only allowed label names are "code" and "method". The
+// function panics otherwise. The Observe method of the Observer in the
+// ObserverVec is called with the request duration in seconds. Partitioning
+// happens by HTTP status code and/or HTTP method if the respective instance
+// label names are present in the ObserverVec. For unpartitioned observations,
+// use an ObserverVec with zero labels. Note that partitioning of Histograms is
+// expensive and should be used judiciously.
//
// If the wrapped Handler panics before calling WriteHeader, no value is
// reported.
@@ -139,15 +141,15 @@
}
// InstrumentHandlerRequestSize is a middleware that wraps the provided
-// http.Handler to observe the request size with the provided ObserverVec. The
-// ObserverVec must have zero, one, or two non-const non-curried labels. For
-// those, the only allowed label names are "code" and "method". The function
-// panics otherwise. The Observe method of the Observer in the ObserverVec is
-// called with the request size in bytes. Partitioning happens by HTTP status
-// code and/or HTTP method if the respective instance label names are present in
-// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
-// labels. Note that partitioning of Histograms is expensive and should be used
-// judiciously.
+// http.Handler to observe the request size with the provided ObserverVec. The
+// ObserverVec must have valid metric and label names and must have zero, one,
+// or two non-const non-curried labels. For those, the only allowed label names
+// are "code" and "method". The function panics otherwise. The Observe method of
+// the Observer in the ObserverVec is called with the request size in
+// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
+// respective instance label names are present in the ObserverVec. For
+// unpartitioned observations, use an ObserverVec with zero labels. Note that
+// partitioning of Histograms is expensive and should be used judiciously.
//
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
//
@@ -174,15 +176,15 @@
}
// InstrumentHandlerResponseSize is a middleware that wraps the provided
-// http.Handler to observe the response size with the provided ObserverVec. The
-// ObserverVec must have zero, one, or two non-const non-curried labels. For
-// those, the only allowed label names are "code" and "method". The function
-// panics otherwise. The Observe method of the Observer in the ObserverVec is
-// called with the response size in bytes. Partitioning happens by HTTP status
-// code and/or HTTP method if the respective instance label names are present in
-// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
-// labels. Note that partitioning of Histograms is expensive and should be used
-// judiciously.
+// http.Handler to observe the response size with the provided ObserverVec. The
+// ObserverVec must have valid metric and label names and must have zero, one,
+// or two non-const non-curried labels. For those, the only allowed label names
+// are "code" and "method". The function panics otherwise. The Observe method of
+// the Observer in the ObserverVec is called with the response size in
+// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
+// respective instance label names are present in the ObserverVec. For
+// unpartitioned observations, use an ObserverVec with zero labels. Note that
+// partitioning of Histograms is expensive and should be used judiciously.
//
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
//
@@ -198,6 +200,11 @@
})
}
+// checkLabels returns whether the provided Collector has a non-const,
+// non-curried label named "code" and/or "method". It panics if the provided
+// Collector does not have a Desc or has more than one Desc or its Desc is
+// invalid. It also panics if the Collector has any non-const, non-curried
+// labels that are not named "code" or "method".
func checkLabels(c prometheus.Collector) (code bool, method bool) {
// TODO(beorn7): Remove this hacky way to check for instance labels
// once Descriptors can have their dimensionality queried.
@@ -225,6 +232,10 @@
close(descc)
+ // Make sure the Collector has a valid Desc by registering it with a
+ // temporary registry.
+ prometheus.NewRegistry().MustRegister(c)
+
// Create a ConstMetric with the Desc. Since we don't know how many
// variable labels there are, try for as long as it needs.
for err := errors.New("dummy"); err != nil; lvs = append(lvs, magicString) {
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go
index 6c32516..383a7f5 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go
@@ -25,6 +25,8 @@
"sync"
"unicode/utf8"
+ "github.com/cespare/xxhash/v2"
+ //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/expfmt"
@@ -74,7 +76,7 @@
// NewPedanticRegistry returns a registry that checks during collection if each
// collected Metric is consistent with its reported Desc, and if the Desc has
// actually been registered with the registry. Unchecked Collectors (those whose
-// Describe methed does not yield any descriptors) are excluded from the check.
+// Describe method does not yield any descriptors) are excluded from the check.
//
// Usually, a Registry will be happy as long as the union of all collected
// Metrics is consistent and valid even if some metrics are not consistent with
@@ -213,6 +215,8 @@
// by a Gatherer to report multiple errors during MetricFamily gathering.
type MultiError []error
+// Error formats the contained errors as a bullet point list, preceded by the
+// total number of errors. Note that this results in a multi-line string.
func (errs MultiError) Error() string {
if len(errs) == 0 {
return ""
@@ -266,7 +270,7 @@
descChan = make(chan *Desc, capDescChan)
newDescIDs = map[uint64]struct{}{}
newDimHashesByName = map[string]uint64{}
- collectorID uint64 // Just a sum of all desc IDs.
+ collectorID uint64 // All desc IDs XOR'd together.
duplicateDescErr error
)
go func() {
@@ -293,12 +297,12 @@
if _, exists := r.descIDs[desc.id]; exists {
duplicateDescErr = fmt.Errorf("descriptor %s already exists with the same fully-qualified name and const label values", desc)
}
- // If it is not a duplicate desc in this collector, add it to
+ // If it is not a duplicate desc in this collector, XOR it to
// the collectorID. (We allow duplicate descs within the same
// collector, but their existence must be a no-op.)
if _, exists := newDescIDs[desc.id]; !exists {
newDescIDs[desc.id] = struct{}{}
- collectorID += desc.id
+ collectorID ^= desc.id
}
// Are all the label names and the help string consistent with
@@ -360,7 +364,7 @@
var (
descChan = make(chan *Desc, capDescChan)
descIDs = map[uint64]struct{}{}
- collectorID uint64 // Just a sum of the desc IDs.
+ collectorID uint64 // All desc IDs XOR'd together.
)
go func() {
c.Describe(descChan)
@@ -368,7 +372,7 @@
}()
for desc := range descChan {
if _, exists := descIDs[desc.id]; !exists {
- collectorID += desc.id
+ collectorID ^= desc.id
descIDs[desc.id] = struct{}{}
}
}
@@ -875,9 +879,9 @@
}
// Is the metric unique (i.e. no other metric with the same name and the same labels)?
- h := hashNew()
- h = hashAdd(h, name)
- h = hashAddByte(h, separatorByte)
+ h := xxhash.New()
+ h.WriteString(name)
+ h.Write(separatorByteSlice)
// Make sure label pairs are sorted. We depend on it for the consistency
// check.
if !sort.IsSorted(labelPairSorter(dtoMetric.Label)) {
@@ -888,18 +892,19 @@
dtoMetric.Label = copiedLabels
}
for _, lp := range dtoMetric.Label {
- h = hashAdd(h, lp.GetName())
- h = hashAddByte(h, separatorByte)
- h = hashAdd(h, lp.GetValue())
- h = hashAddByte(h, separatorByte)
+ h.WriteString(lp.GetName())
+ h.Write(separatorByteSlice)
+ h.WriteString(lp.GetValue())
+ h.Write(separatorByteSlice)
}
- if _, exists := metricHashes[h]; exists {
+ hSum := h.Sum64()
+ if _, exists := metricHashes[hSum]; exists {
return fmt.Errorf(
"collected metric %q { %s} was collected before with the same name and label values",
name, dtoMetric,
)
}
- metricHashes[h] = struct{}{}
+ metricHashes[hSum] = struct{}{}
return nil
}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go
index c970fde..c5fa8ed 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go
@@ -23,6 +23,7 @@
"time"
"github.com/beorn7/perks/quantile"
+ //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
@@ -54,7 +55,12 @@
Metric
Collector
- // Observe adds a single observation to the summary.
+ // Observe adds a single observation to the summary. Observations are
+ // usually positive or zero. Negative observations are accepted but
+ // prevent current versions of Prometheus from properly detecting
+ // counter resets in the sum of observations. See
+ // https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
+ // for details.
Observe(float64)
}
@@ -109,7 +115,7 @@
// better covered by target labels set by the scraping Prometheus
// server, or by one specific metric (e.g. a build_info or a
// machine_role metric). See also
- // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
+ // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
ConstLabels Labels
// Objectives defines the quantile rank estimates with their respective
@@ -120,7 +126,9 @@
Objectives map[float64]float64
// MaxAge defines the duration for which an observation stays relevant
- // for the summary. Must be positive. The default value is DefMaxAge.
+ // for the summary. Only applies to pre-calculated quantiles, does not
+ // apply to _sum and _count. Must be positive. The default value is
+ // DefMaxAge.
MaxAge time.Duration
// AgeBuckets is the number of buckets used to exclude observations that
@@ -207,8 +215,8 @@
// Use the lock-free implementation of a Summary without objectives.
s := &noObjectivesSummary{
desc: desc,
- labelPairs: makeLabelPairs(desc, labelValues),
- counts: [2]*summaryCounts{&summaryCounts{}, &summaryCounts{}},
+ labelPairs: MakeLabelPairs(desc, labelValues),
+ counts: [2]*summaryCounts{{}, {}},
}
s.init(s) // Init self-collection.
return s
@@ -220,7 +228,7 @@
objectives: opts.Objectives,
sortedObjectives: make([]float64, 0, len(opts.Objectives)),
- labelPairs: makeLabelPairs(desc, labelValues),
+ labelPairs: MakeLabelPairs(desc, labelValues),
hotBuf: make([]float64, 0, opts.BufCap),
coldBuf: make([]float64, 0, opts.BufCap),
@@ -512,7 +520,7 @@
// (e.g. HTTP request latencies, partitioned by status code and method). Create
// instances with NewSummaryVec.
type SummaryVec struct {
- *metricVec
+ *MetricVec
}
// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
@@ -534,14 +542,14 @@
opts.ConstLabels,
)
return &SummaryVec{
- metricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
return newSummary(desc, opts, lvs...)
}),
}
}
// GetMetricWithLabelValues returns the Summary for the given slice of label
-// values (same order as the VariableLabels in Desc). If that combination of
+// values (same order as the variable labels in Desc). If that combination of
// label values is accessed for the first time, a new Summary is created.
//
// It is possible to call this method without using the returned Summary to only
@@ -556,7 +564,7 @@
// example.
//
// An error is returned if the number of label values is not the same as the
-// number of VariableLabels in Desc (minus any curried labels).
+// number of variable labels in Desc (minus any curried labels).
//
// Note that for more than one label value, this method is prone to mistakes
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
@@ -565,7 +573,7 @@
// with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example.
func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
- metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
+ metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Observer), err
}
@@ -573,19 +581,19 @@
}
// GetMetricWith returns the Summary for the given Labels map (the label names
-// must match those of the VariableLabels in Desc). If that label map is
+// must match those of the variable labels in Desc). If that label map is
// accessed for the first time, a new Summary is created. Implications of
// creating a Summary without using it and keeping the Summary for later use are
// the same as for GetMetricWithLabelValues.
//
// An error is returned if the number and names of the Labels are inconsistent
-// with those of the VariableLabels in Desc (minus any curried labels).
+// with those of the variable labels in Desc (minus any curried labels).
//
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) {
- metric, err := v.metricVec.getMetricWith(labels)
+ metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Observer), err
}
@@ -629,7 +637,7 @@
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) {
- vec, err := v.curryWith(labels)
+ vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &SummaryVec{vec}, err
}
@@ -715,7 +723,7 @@
count: count,
sum: sum,
quantiles: quantiles,
- labelPairs: makeLabelPairs(desc, labelValues),
+ labelPairs: MakeLabelPairs(desc, labelValues),
}, nil
}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/value.go b/vendor/github.com/prometheus/client_golang/prometheus/value.go
index eb248f1..c778711 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/value.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/value.go
@@ -16,8 +16,12 @@
import (
"fmt"
"sort"
+ "time"
+ "unicode/utf8"
+ //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/ptypes"
dto "github.com/prometheus/client_model/go"
)
@@ -25,7 +29,8 @@
// ValueType is an enumeration of metric types that represent a simple value.
type ValueType int
-// Possible values for the ValueType enum.
+// Possible values for the ValueType enum. Use UntypedValue to mark a metric
+// with an unknown type.
const (
_ ValueType = iota
CounterValue
@@ -58,7 +63,7 @@
desc: desc,
valType: valueType,
function: function,
- labelPairs: makeLabelPairs(desc, nil),
+ labelPairs: MakeLabelPairs(desc, nil),
}
result.init(result)
return result
@@ -69,7 +74,7 @@
}
func (v *valueFunc) Write(out *dto.Metric) error {
- return populateMetric(v.valType, v.function(), v.labelPairs, out)
+ return populateMetric(v.valType, v.function(), v.labelPairs, nil, out)
}
// NewConstMetric returns a metric with one fixed value that cannot be
@@ -90,7 +95,7 @@
desc: desc,
valType: valueType,
val: value,
- labelPairs: makeLabelPairs(desc, labelValues),
+ labelPairs: MakeLabelPairs(desc, labelValues),
}, nil
}
@@ -116,19 +121,20 @@
}
func (m *constMetric) Write(out *dto.Metric) error {
- return populateMetric(m.valType, m.val, m.labelPairs, out)
+ return populateMetric(m.valType, m.val, m.labelPairs, nil, out)
}
func populateMetric(
t ValueType,
v float64,
labelPairs []*dto.LabelPair,
+ e *dto.Exemplar,
m *dto.Metric,
) error {
m.Label = labelPairs
switch t {
case CounterValue:
- m.Counter = &dto.Counter{Value: proto.Float64(v)}
+ m.Counter = &dto.Counter{Value: proto.Float64(v), Exemplar: e}
case GaugeValue:
m.Gauge = &dto.Gauge{Value: proto.Float64(v)}
case UntypedValue:
@@ -139,7 +145,14 @@
return nil
}
-func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
+// MakeLabelPairs is a helper function to create protobuf LabelPairs from the
+// variable and constant labels in the provided Desc. The values for the
+// variable labels are defined by the labelValues slice, which must be in the
+// same order as the corresponding variable labels in the Desc.
+//
+// This function is only needed for custom Metric implementations. See MetricVec
+// example.
+func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
if totalLen == 0 {
// Super fast path.
@@ -160,3 +173,40 @@
sort.Sort(labelPairSorter(labelPairs))
return labelPairs
}
+
+// ExemplarMaxRunes is the max total number of runes allowed in exemplar labels.
+const ExemplarMaxRunes = 64
+
+// newExemplar creates a new dto.Exemplar from the provided values. An error is
+// returned if any of the label names or values are invalid or if the total
+// number of runes in the label names and values exceeds ExemplarMaxRunes.
+func newExemplar(value float64, ts time.Time, l Labels) (*dto.Exemplar, error) {
+ e := &dto.Exemplar{}
+ e.Value = proto.Float64(value)
+ tsProto, err := ptypes.TimestampProto(ts)
+ if err != nil {
+ return nil, err
+ }
+ e.Timestamp = tsProto
+ labelPairs := make([]*dto.LabelPair, 0, len(l))
+ var runes int
+ for name, value := range l {
+ if !checkLabelName(name) {
+ return nil, fmt.Errorf("exemplar label name %q is invalid", name)
+ }
+ runes += utf8.RuneCountInString(name)
+ if !utf8.ValidString(value) {
+ return nil, fmt.Errorf("exemplar label value %q is not valid UTF-8", value)
+ }
+ runes += utf8.RuneCountInString(value)
+ labelPairs = append(labelPairs, &dto.LabelPair{
+ Name: proto.String(name),
+ Value: proto.String(value),
+ })
+ }
+ if runes > ExemplarMaxRunes {
+ return nil, fmt.Errorf("exemplar labels have %d runes, exceeding the limit of %d", runes, ExemplarMaxRunes)
+ }
+ e.Label = labelPairs
+ return e, nil
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go
index 14ed9e8..4ababe6 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/vec.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/vec.go
@@ -20,12 +20,20 @@
"github.com/prometheus/common/model"
)
-// metricVec is a Collector to bundle metrics of the same name that differ in
-// their label values. metricVec is not used directly (and therefore
-// unexported). It is used as a building block for implementations of vectors of
-// a given metric type, like GaugeVec, CounterVec, SummaryVec, and HistogramVec.
-// It also handles label currying. It uses basicMetricVec internally.
-type metricVec struct {
+// MetricVec is a Collector to bundle metrics of the same name that differ in
+// their label values. MetricVec is not used directly but as a building block
+// for implementations of vectors of a given metric type, like GaugeVec,
+// CounterVec, SummaryVec, and HistogramVec. It is exported so that it can be
+// used for custom Metric implementations.
+//
+// To create a FooVec for custom Metric Foo, embed a pointer to MetricVec in
+// FooVec and initialize it with NewMetricVec. Implement wrappers for
+// GetMetricWithLabelValues and GetMetricWith that return (Foo, error) rather
+// than (Metric, error). Similarly, create a wrapper for CurryWith that returns
+// (*FooVec, error) rather than (*MetricVec, error). It is recommended to also
+// add the convenience methods WithLabelValues, With, and MustCurryWith, which
+// panic instead of returning errors. See also the MetricVec example.
+type MetricVec struct {
*metricMap
curry []curriedLabelValue
@@ -35,9 +43,9 @@
hashAddByte func(h uint64, b byte) uint64
}
-// newMetricVec returns an initialized metricVec.
-func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
- return &metricVec{
+// NewMetricVec returns an initialized metricVec.
+func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec {
+ return &MetricVec{
metricMap: &metricMap{
metrics: map[uint64][]metricWithLabelValues{},
desc: desc,
@@ -63,7 +71,7 @@
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
// See also the CounterVec example.
-func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
+func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
h, err := m.hashLabelValues(lvs)
if err != nil {
return false
@@ -82,7 +90,7 @@
//
// This method is used for the same purpose as DeleteLabelValues(...string). See
// there for pros and cons of the two methods.
-func (m *metricVec) Delete(labels Labels) bool {
+func (m *MetricVec) Delete(labels Labels) bool {
h, err := m.hashLabels(labels)
if err != nil {
return false
@@ -91,7 +99,36 @@
return m.metricMap.deleteByHashWithLabels(h, labels, m.curry)
}
-func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
+// Without explicit forwarding of Describe, Collect, Reset, those methods won't
+// show up in GoDoc.
+
+// Describe implements Collector.
+func (m *MetricVec) Describe(ch chan<- *Desc) { m.metricMap.Describe(ch) }
+
+// Collect implements Collector.
+func (m *MetricVec) Collect(ch chan<- Metric) { m.metricMap.Collect(ch) }
+
+// Reset deletes all metrics in this vector.
+func (m *MetricVec) Reset() { m.metricMap.Reset() }
+
+// CurryWith returns a vector curried with the provided labels, i.e. the
+// returned vector has those labels pre-set for all labeled operations performed
+// on it. The cardinality of the curried vector is reduced accordingly. The
+// order of the remaining labels stays the same (just with the curried labels
+// taken out of the sequence – which is relevant for the
+// (GetMetric)WithLabelValues methods). It is possible to curry a curried
+// vector, but only with labels not yet used for currying before.
+//
+// The metrics contained in the MetricVec are shared between the curried and
+// uncurried vectors. They are just accessed differently. Curried and uncurried
+// vectors behave identically in terms of collection. Only one must be
+// registered with a given registry (usually the uncurried version). The Reset
+// method deletes all metrics, even if called on a curried vector.
+//
+// Note that CurryWith is usually not called directly but through a wrapper
+// around MetricVec, implementing a vector for a specific Metric
+// implementation, for example GaugeVec.
+func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
var (
newCurry []curriedLabelValue
oldCurry = m.curry
@@ -116,7 +153,7 @@
return nil, fmt.Errorf("%d unknown label(s) found during currying", l)
}
- return &metricVec{
+ return &MetricVec{
metricMap: m.metricMap,
curry: newCurry,
hashAdd: m.hashAdd,
@@ -124,7 +161,34 @@
}, nil
}
-func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
+// GetMetricWithLabelValues returns the Metric for the given slice of label
+// values (same order as the variable labels in Desc). If that combination of
+// label values is accessed for the first time, a new Metric is created (by
+// calling the newMetric function provided during construction of the
+// MetricVec).
+//
+// It is possible to call this method without using the returned Metric to only
+// create the new Metric but leave it in its initial state.
+//
+// Keeping the Metric for later use is possible (and should be considered if
+// performance is critical), but keep in mind that Reset, DeleteLabelValues and
+// Delete can be used to delete the Metric from the MetricVec. In that case, the
+// Metric will still exist, but it will not be exported anymore, even if a
+// Metric with the same label values is created later.
+//
+// An error is returned if the number of label values is not the same as the
+// number of variable labels in Desc (minus any curried labels).
+//
+// Note that for more than one label value, this method is prone to mistakes
+// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
+// an alternative to avoid that type of mistake. For higher label numbers, the
+// latter has a much more readable (albeit more verbose) syntax, but it comes
+// with a performance overhead (for creating and processing the Labels map).
+//
+// Note that GetMetricWithLabelValues is usually not called directly but through
+// a wrapper around MetricVec, implementing a vector for a specific Metric
+// implementation, for example GaugeVec.
+func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
h, err := m.hashLabelValues(lvs)
if err != nil {
return nil, err
@@ -133,7 +197,23 @@
return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil
}
-func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
+// GetMetricWith returns the Metric for the given Labels map (the label names
+// must match those of the variable labels in Desc). If that label map is
+// accessed for the first time, a new Metric is created. Implications of
+// creating a Metric without using it and keeping the Metric for later use
+// are the same as for GetMetricWithLabelValues.
+//
+// An error is returned if the number and names of the Labels are inconsistent
+// with those of the variable labels in Desc (minus any curried labels).
+//
+// This method is used for the same purpose as
+// GetMetricWithLabelValues(...string). See there for pros and cons of the two
+// methods.
+//
+// Note that GetMetricWith is usually not called directly but through a wrapper
+// around MetricVec, implementing a vector for a specific Metric implementation,
+// for example GaugeVec.
+func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
h, err := m.hashLabels(labels)
if err != nil {
return nil, err
@@ -142,7 +222,7 @@
return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil
}
-func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
+func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil {
return 0, err
}
@@ -165,7 +245,7 @@
return h, nil
}
-func (m *metricVec) hashLabels(labels Labels) (uint64, error) {
+func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil {
return 0, err
}
@@ -264,7 +344,9 @@
}
if len(metrics) > 1 {
+ old := metrics
m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
+ old[len(old)-1] = metricWithLabelValues{}
} else {
delete(m.metrics, h)
}
@@ -290,7 +372,9 @@
}
if len(metrics) > 1 {
+ old := metrics
m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
+ old[len(old)-1] = metricWithLabelValues{}
} else {
delete(m.metrics, h)
}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go
index e303eef..74ee932 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go
@@ -17,6 +17,7 @@
"fmt"
"sort"
+ //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
@@ -27,10 +28,13 @@
// registered with the wrapped Registerer in a modified way. The modified
// Collector adds the provided Labels to all Metrics it collects (as
// ConstLabels). The Metrics collected by the unmodified Collector must not
-// duplicate any of those labels.
+// duplicate any of those labels. Wrapping a nil value is valid, resulting
+// in a no-op Registerer.
//
// WrapRegistererWith provides a way to add fixed labels to a subset of
-// Collectors. It should not be used to add fixed labels to all metrics exposed.
+// Collectors. It should not be used to add fixed labels to all metrics
+// exposed. See also
+// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
//
// Conflicts between Collectors registered through the original Registerer with
// Collectors registered through the wrapping Registerer will still be
@@ -50,6 +54,7 @@
// Registerer. Collectors registered with the returned Registerer will be
// registered with the wrapped Registerer in a modified way. The modified
// Collector adds the provided prefix to the name of all Metrics it collects.
+// Wrapping a nil value is valid, resulting in a no-op Registerer.
//
// WrapRegistererWithPrefix is useful to have one place to prefix all metrics of
// a sub-system. To make this work, register metrics of the sub-system with the
@@ -80,6 +85,9 @@
}
func (r *wrappingRegisterer) Register(c Collector) error {
+ if r.wrappedRegisterer == nil {
+ return nil
+ }
return r.wrappedRegisterer.Register(&wrappingCollector{
wrappedCollector: c,
prefix: r.prefix,
@@ -88,6 +96,9 @@
}
func (r *wrappingRegisterer) MustRegister(cs ...Collector) {
+ if r.wrappedRegisterer == nil {
+ return
+ }
for _, c := range cs {
if err := r.Register(c); err != nil {
panic(err)
@@ -96,6 +107,9 @@
}
func (r *wrappingRegisterer) Unregister(c Collector) bool {
+ if r.wrappedRegisterer == nil {
+ return false
+ }
return r.wrappedRegisterer.Unregister(&wrappingCollector{
wrappedCollector: c,
prefix: r.prefix,