Update metric dependencies (#5023)
This commit is contained in:
parent
4befa8cc8a
commit
9278f0cad2
128 changed files with 3873 additions and 2729 deletions
46
vendor/github.com/prometheus/client_golang/prometheus/counter.go
generated
vendored
46
vendor/github.com/prometheus/client_golang/prometheus/counter.go
generated
vendored
|
|
@ -17,6 +17,7 @@ import (
|
|||
"errors"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
|
@ -42,11 +43,27 @@ type Counter interface {
|
|||
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 @@ func NewCounter(opts CounterOpts) Counter {
|
|||
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 @@ type counter struct {
|
|||
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 @@ func (c *counter) Add(v float64) {
|
|||
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) Add(v float64) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ func (c *counter) Write(out *dto.Metric) error {
|
|||
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
|
||||
|
|
|
|||
2
vendor/github.com/prometheus/client_golang/prometheus/gauge.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/gauge.go
generated
vendored
|
|
@ -123,7 +123,7 @@ func (g *gauge) Sub(val float64) {
|
|||
|
||||
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
|
||||
|
|
|
|||
2
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
|
|
@ -73,7 +73,7 @@ func NewGoCollector() Collector {
|
|||
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",
|
||||
|
|
|
|||
110
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
110
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
|
|
@ -20,6 +20,7 @@ import (
|
|||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
|
|
@ -151,6 +152,10 @@ type HistogramOpts struct {
|
|||
|
||||
// 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(
|
||||
|
|
@ -188,6 +193,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
|||
upperBounds: opts.Buckets,
|
||||
labelPairs: makeLabelPairs(desc, labelValues),
|
||||
counts: [2]*histogramCounts{{}, {}},
|
||||
now: time.Now,
|
||||
}
|
||||
for i, upperBound := range h.upperBounds {
|
||||
if i < len(h.upperBounds)-1 {
|
||||
|
|
@ -205,9 +211,10 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
|||
}
|
||||
}
|
||||
// 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 +261,9 @@ type histogram struct {
|
|||
|
||||
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 +271,13 @@ func (h *histogram) Desc() *Desc {
|
|||
}
|
||||
|
||||
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 +316,18 @@ func (h *histogram) Write(out *dto.Metric) error {
|
|||
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,6 +351,57 @@ func (h *histogram) Write(out *dto.Metric) error {
|
|||
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
|
||||
|
|
|
|||
12
vendor/github.com/prometheus/client_golang/prometheus/observer.go
generated
vendored
12
vendor/github.com/prometheus/client_golang/prometheus/observer.go
generated
vendored
|
|
@ -50,3 +50,15 @@ type ObserverVec interface {
|
|||
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
63
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
generated
vendored
63
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
generated
vendored
|
|
@ -144,7 +144,12 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
|||
}
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
|
|
@ -163,22 +168,38 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
|||
enc := expfmt.NewEncoder(w, contentType)
|
||||
|
||||
var lastErr error
|
||||
|
||||
// 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
|
||||
}
|
||||
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 HTTPErrorOnError:
|
||||
httpError(rsp, err)
|
||||
return true
|
||||
}
|
||||
// Do nothing in all other cases, including ContinueOnError.
|
||||
return false
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -318,6 +339,16 @@ type HandlerOpts struct {
|
|||
// 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.
|
||||
|
|
|
|||
47
vendor/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
47
vendor/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
|
|
@ -16,8 +16,11 @@ package prometheus
|
|||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
|
@ -69,7 +72,7 @@ func (v *valueFunc) Desc() *Desc {
|
|||
}
|
||||
|
||||
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
|
||||
|
|
@ -116,19 +119,20 @@ func (m *constMetric) Desc() *Desc {
|
|||
}
|
||||
|
||||
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:
|
||||
|
|
@ -160,3 +164,40 @@ func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
|
|||
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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue