gбновление зависимостей, рефакторинг кода, чтобы он выглядел как гошный проект
This commit is contained in:
5
vendor/github.com/prometheus/client_golang/NOTICE
generated
vendored
5
vendor/github.com/prometheus/client_golang/NOTICE
generated
vendored
@@ -16,8 +16,3 @@ Go support for Protocol Buffers - Google's data interchange format
|
||||
http://github.com/golang/protobuf/
|
||||
Copyright 2010 The Go Authors
|
||||
See source code for license details.
|
||||
|
||||
Support for streaming Protocol Buffer messages for the Go language (golang).
|
||||
https://github.com/matttproud/golang_protobuf_extensions
|
||||
Copyright 2013 Matt T. Proud
|
||||
Licensed under the Apache License, Version 2.0
|
||||
|
||||
15
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
15
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
@@ -189,12 +189,15 @@ func (d *Desc) String() string {
|
||||
fmt.Sprintf("%s=%q", lp.GetName(), lp.GetValue()),
|
||||
)
|
||||
}
|
||||
vlStrings := make([]string, 0, len(d.variableLabels.names))
|
||||
for _, vl := range d.variableLabels.names {
|
||||
if fn, ok := d.variableLabels.labelConstraints[vl]; ok && fn != nil {
|
||||
vlStrings = append(vlStrings, fmt.Sprintf("c(%s)", vl))
|
||||
} else {
|
||||
vlStrings = append(vlStrings, vl)
|
||||
vlStrings := []string{}
|
||||
if d.variableLabels != nil {
|
||||
vlStrings = make([]string, 0, len(d.variableLabels.names))
|
||||
for _, vl := range d.variableLabels.names {
|
||||
if fn, ok := d.variableLabels.labelConstraints[vl]; ok && fn != nil {
|
||||
vlStrings = append(vlStrings, fmt.Sprintf("c(%s)", vl))
|
||||
} else {
|
||||
vlStrings = append(vlStrings, vl)
|
||||
}
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
|
||||
55
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
55
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
@@ -22,13 +22,13 @@ import (
|
||||
// goRuntimeMemStats provides the metrics initially provided by runtime.ReadMemStats.
|
||||
// From Go 1.17 those similar (and better) statistics are provided by runtime/metrics, so
|
||||
// while eval closure works on runtime.MemStats, the struct from Go 1.17+ is
|
||||
// populated using runtime/metrics.
|
||||
// populated using runtime/metrics. Those are the defaults we can't alter.
|
||||
func goRuntimeMemStats() memStatsMetrics {
|
||||
return memStatsMetrics{
|
||||
{
|
||||
desc: NewDesc(
|
||||
memstatNamespace("alloc_bytes"),
|
||||
"Number of bytes allocated and still in use.",
|
||||
"Number of bytes allocated in heap and currently in use. Equals to /memory/classes/heap/objects:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) },
|
||||
@@ -36,7 +36,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("alloc_bytes_total"),
|
||||
"Total number of bytes allocated, even if freed.",
|
||||
"Total number of bytes allocated in heap until now, even if released already. Equals to /gc/heap/allocs:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) },
|
||||
@@ -44,23 +44,16 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("sys_bytes"),
|
||||
"Number of bytes obtained from system.",
|
||||
"Number of bytes obtained from system. Equals to /memory/classes/total:byte.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) },
|
||||
valType: GaugeValue,
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("lookups_total"),
|
||||
"Total number of pointer lookups.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) },
|
||||
valType: CounterValue,
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("mallocs_total"),
|
||||
"Total number of mallocs.",
|
||||
// TODO(bwplotka): We could add go_memstats_heap_objects, probably useful for discovery. Let's gather more feedback, kind of a waste of bytes for everybody for compatibility reasons to keep both, and we can't really rename/remove useful metric.
|
||||
"Total number of heap objects allocated, both live and gc-ed. Semantically a counter version for go_memstats_heap_objects gauge. Equals to /gc/heap/allocs:objects + /gc/heap/tiny/allocs:objects.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) },
|
||||
@@ -68,7 +61,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("frees_total"),
|
||||
"Total number of frees.",
|
||||
"Total number of heap objects frees. Equals to /gc/heap/frees:objects + /gc/heap/tiny/allocs:objects.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) },
|
||||
@@ -76,7 +69,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("heap_alloc_bytes"),
|
||||
"Number of heap bytes allocated and still in use.",
|
||||
"Number of heap bytes allocated and currently in use, same as go_memstats_alloc_bytes. Equals to /memory/classes/heap/objects:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) },
|
||||
@@ -84,7 +77,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("heap_sys_bytes"),
|
||||
"Number of heap bytes obtained from system.",
|
||||
"Number of heap bytes obtained from system. Equals to /memory/classes/heap/objects:bytes + /memory/classes/heap/unused:bytes + /memory/classes/heap/released:bytes + /memory/classes/heap/free:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) },
|
||||
@@ -92,7 +85,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("heap_idle_bytes"),
|
||||
"Number of heap bytes waiting to be used.",
|
||||
"Number of heap bytes waiting to be used. Equals to /memory/classes/heap/released:bytes + /memory/classes/heap/free:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) },
|
||||
@@ -100,7 +93,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("heap_inuse_bytes"),
|
||||
"Number of heap bytes that are in use.",
|
||||
"Number of heap bytes that are in use. Equals to /memory/classes/heap/objects:bytes + /memory/classes/heap/unused:bytes",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) },
|
||||
@@ -108,7 +101,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("heap_released_bytes"),
|
||||
"Number of heap bytes released to OS.",
|
||||
"Number of heap bytes released to OS. Equals to /memory/classes/heap/released:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) },
|
||||
@@ -116,7 +109,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("heap_objects"),
|
||||
"Number of allocated objects.",
|
||||
"Number of currently allocated objects. Equals to /gc/heap/objects:objects.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) },
|
||||
@@ -124,7 +117,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("stack_inuse_bytes"),
|
||||
"Number of bytes in use by the stack allocator.",
|
||||
"Number of bytes obtained from system for stack allocator in non-CGO environments. Equals to /memory/classes/heap/stacks:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) },
|
||||
@@ -132,7 +125,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("stack_sys_bytes"),
|
||||
"Number of bytes obtained from system for stack allocator.",
|
||||
"Number of bytes obtained from system for stack allocator. Equals to /memory/classes/heap/stacks:bytes + /memory/classes/os-stacks:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) },
|
||||
@@ -140,7 +133,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("mspan_inuse_bytes"),
|
||||
"Number of bytes in use by mspan structures.",
|
||||
"Number of bytes in use by mspan structures. Equals to /memory/classes/metadata/mspan/inuse:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) },
|
||||
@@ -148,7 +141,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("mspan_sys_bytes"),
|
||||
"Number of bytes used for mspan structures obtained from system.",
|
||||
"Number of bytes used for mspan structures obtained from system. Equals to /memory/classes/metadata/mspan/inuse:bytes + /memory/classes/metadata/mspan/free:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) },
|
||||
@@ -156,7 +149,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("mcache_inuse_bytes"),
|
||||
"Number of bytes in use by mcache structures.",
|
||||
"Number of bytes in use by mcache structures. Equals to /memory/classes/metadata/mcache/inuse:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) },
|
||||
@@ -164,7 +157,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("mcache_sys_bytes"),
|
||||
"Number of bytes used for mcache structures obtained from system.",
|
||||
"Number of bytes used for mcache structures obtained from system. Equals to /memory/classes/metadata/mcache/inuse:bytes + /memory/classes/metadata/mcache/free:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) },
|
||||
@@ -172,7 +165,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("buck_hash_sys_bytes"),
|
||||
"Number of bytes used by the profiling bucket hash table.",
|
||||
"Number of bytes used by the profiling bucket hash table. Equals to /memory/classes/profiling/buckets:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) },
|
||||
@@ -180,7 +173,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("gc_sys_bytes"),
|
||||
"Number of bytes used for garbage collection system metadata.",
|
||||
"Number of bytes used for garbage collection system metadata. Equals to /memory/classes/metadata/other:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) },
|
||||
@@ -188,7 +181,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("other_sys_bytes"),
|
||||
"Number of bytes used for other system allocations.",
|
||||
"Number of bytes used for other system allocations. Equals to /memory/classes/other:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) },
|
||||
@@ -196,7 +189,7 @@ func goRuntimeMemStats() memStatsMetrics {
|
||||
}, {
|
||||
desc: NewDesc(
|
||||
memstatNamespace("next_gc_bytes"),
|
||||
"Number of heap bytes when next garbage collection will take place.",
|
||||
"Number of heap bytes when next garbage collection will take place. Equals to /gc/heap/goal:bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
|
||||
@@ -225,7 +218,7 @@ func newBaseGoCollector() baseGoCollector {
|
||||
nil, nil),
|
||||
gcDesc: NewDesc(
|
||||
"go_gc_duration_seconds",
|
||||
"A summary of the pause duration of garbage collection cycles.",
|
||||
"A summary of the wall-time pause (stop-the-world) duration in garbage collection cycles.",
|
||||
nil, nil),
|
||||
gcLastTimeDesc: NewDesc(
|
||||
"go_memstats_last_gc_time_seconds",
|
||||
|
||||
19
vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go
generated
vendored
19
vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go
generated
vendored
@@ -17,6 +17,7 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
"runtime/metrics"
|
||||
@@ -153,7 +154,8 @@ func defaultGoCollectorOptions() internal.GoCollectorOptions {
|
||||
"/gc/heap/frees-by-size:bytes": goGCHeapFreesBytes,
|
||||
},
|
||||
RuntimeMetricRules: []internal.GoCollectorRule{
|
||||
//{Matcher: regexp.MustCompile("")},
|
||||
// Recommended metrics we want by default from runtime/metrics.
|
||||
{Matcher: internal.GoCollectorDefaultRuntimeMetrics},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -203,6 +205,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
|
||||
// to fail here. This condition is tested in TestExpectedRuntimeMetrics.
|
||||
continue
|
||||
}
|
||||
help := attachOriginalName(d.Description.Description, d.Name)
|
||||
|
||||
sampleBuf = append(sampleBuf, metrics.Sample{Name: d.Name})
|
||||
sampleMap[d.Name] = &sampleBuf[len(sampleBuf)-1]
|
||||
@@ -214,7 +217,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
|
||||
m = newBatchHistogram(
|
||||
NewDesc(
|
||||
BuildFQName(namespace, subsystem, name),
|
||||
d.Description.Description,
|
||||
help,
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
@@ -226,7 +229,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: name,
|
||||
Help: d.Description.Description,
|
||||
Help: help,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
@@ -234,7 +237,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: name,
|
||||
Help: d.Description.Description,
|
||||
Help: help,
|
||||
})
|
||||
}
|
||||
metricSet = append(metricSet, m)
|
||||
@@ -284,6 +287,10 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
|
||||
}
|
||||
}
|
||||
|
||||
func attachOriginalName(desc, origName string) string {
|
||||
return fmt.Sprintf("%s Sourced from %s.", desc, origName)
|
||||
}
|
||||
|
||||
// Describe returns all descriptions of the collector.
|
||||
func (c *goCollector) Describe(ch chan<- *Desc) {
|
||||
c.base.Describe(ch)
|
||||
@@ -376,13 +383,13 @@ func unwrapScalarRMValue(v metrics.Value) float64 {
|
||||
//
|
||||
// This should never happen because we always populate our metric
|
||||
// set from the runtime/metrics package.
|
||||
panic("unexpected unsupported metric")
|
||||
panic("unexpected bad kind metric")
|
||||
default:
|
||||
// Unsupported metric kind.
|
||||
//
|
||||
// This should never happen because we check for this during initialization
|
||||
// and flag and filter metrics whose kinds we don't understand.
|
||||
panic("unexpected unsupported metric kind")
|
||||
panic(fmt.Sprintf("unexpected unsupported metric: %v", v.Kind()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
517
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
517
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
@@ -14,6 +14,7 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
@@ -28,6 +29,11 @@ import (
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
const (
|
||||
nativeHistogramSchemaMaximum = 8
|
||||
nativeHistogramSchemaMinimum = -4
|
||||
)
|
||||
|
||||
// nativeHistogramBounds for the frac of observed values. Only relevant for
|
||||
// schema > 0. The position in the slice is the schema. (0 is never used, just
|
||||
// here for convenience of using the schema directly as the index.)
|
||||
@@ -330,11 +336,11 @@ func ExponentialBuckets(start, factor float64, count int) []float64 {
|
||||
// used for the Buckets field of HistogramOpts.
|
||||
//
|
||||
// The function panics if 'count' is 0 or negative, if 'min' is 0 or negative.
|
||||
func ExponentialBucketsRange(min, max float64, count int) []float64 {
|
||||
func ExponentialBucketsRange(minBucket, maxBucket float64, count int) []float64 {
|
||||
if count < 1 {
|
||||
panic("ExponentialBucketsRange count needs a positive count")
|
||||
}
|
||||
if min <= 0 {
|
||||
if minBucket <= 0 {
|
||||
panic("ExponentialBucketsRange min needs to be greater than 0")
|
||||
}
|
||||
|
||||
@@ -342,12 +348,12 @@ func ExponentialBucketsRange(min, max float64, count int) []float64 {
|
||||
// max = min*growthFactor^(bucketCount-1)
|
||||
|
||||
// We know max/min and highest bucket. Solve for growthFactor.
|
||||
growthFactor := math.Pow(max/min, 1.0/float64(count-1))
|
||||
growthFactor := math.Pow(maxBucket/minBucket, 1.0/float64(count-1))
|
||||
|
||||
// Now that we know growthFactor, solve for each bucket.
|
||||
buckets := make([]float64, count)
|
||||
for i := 1; i <= count; i++ {
|
||||
buckets[i-1] = min * math.Pow(growthFactor, float64(i-1))
|
||||
buckets[i-1] = minBucket * math.Pow(growthFactor, float64(i-1))
|
||||
}
|
||||
return buckets
|
||||
}
|
||||
@@ -440,7 +446,7 @@ type HistogramOpts struct {
|
||||
// constant (or any negative float value).
|
||||
NativeHistogramZeroThreshold float64
|
||||
|
||||
// The remaining fields define a strategy to limit the number of
|
||||
// The next three fields define a strategy to limit the number of
|
||||
// populated sparse buckets. If NativeHistogramMaxBucketNumber is left
|
||||
// at zero, the number of buckets is not limited. (Note that this might
|
||||
// lead to unbounded memory consumption if the values observed by the
|
||||
@@ -473,6 +479,22 @@ type HistogramOpts struct {
|
||||
NativeHistogramMinResetDuration time.Duration
|
||||
NativeHistogramMaxZeroThreshold float64
|
||||
|
||||
// NativeHistogramMaxExemplars limits the number of exemplars
|
||||
// that are kept in memory for each native histogram. If you leave it at
|
||||
// zero, a default value of 10 is used. If no exemplars should be kept specifically
|
||||
// for native histograms, set it to a negative value. (Scrapers can
|
||||
// still use the exemplars exposed for classic buckets, which are managed
|
||||
// independently.)
|
||||
NativeHistogramMaxExemplars int
|
||||
// NativeHistogramExemplarTTL is only checked once
|
||||
// NativeHistogramMaxExemplars is exceeded. In that case, the
|
||||
// oldest exemplar is removed if it is older than NativeHistogramExemplarTTL.
|
||||
// Otherwise, the older exemplar in the pair of exemplars that are closest
|
||||
// together (on an exponential scale) is removed.
|
||||
// If NativeHistogramExemplarTTL is left at its zero value, a default value of
|
||||
// 5m is used. To always delete the oldest exemplar, set it to a negative value.
|
||||
NativeHistogramExemplarTTL time.Duration
|
||||
|
||||
// now is for testing purposes, by default it's time.Now.
|
||||
now func() time.Time
|
||||
|
||||
@@ -532,6 +554,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
||||
if opts.afterFunc == nil {
|
||||
opts.afterFunc = time.AfterFunc
|
||||
}
|
||||
|
||||
h := &histogram{
|
||||
desc: desc,
|
||||
upperBounds: opts.Buckets,
|
||||
@@ -556,6 +579,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
||||
h.nativeHistogramZeroThreshold = DefNativeHistogramZeroThreshold
|
||||
} // Leave h.nativeHistogramZeroThreshold at 0 otherwise.
|
||||
h.nativeHistogramSchema = pickSchema(opts.NativeHistogramBucketFactor)
|
||||
h.nativeExemplars = makeNativeExemplars(opts.NativeHistogramExemplarTTL, opts.NativeHistogramMaxExemplars)
|
||||
}
|
||||
for i, upperBound := range h.upperBounds {
|
||||
if i < len(h.upperBounds)-1 {
|
||||
@@ -725,7 +749,8 @@ type histogram struct {
|
||||
// resetScheduled is protected by mtx. It is true if a reset is
|
||||
// scheduled for a later time (when nativeHistogramMinResetDuration has
|
||||
// passed).
|
||||
resetScheduled bool
|
||||
resetScheduled bool
|
||||
nativeExemplars nativeExemplars
|
||||
|
||||
// now is for testing purposes, by default it's time.Now.
|
||||
now func() time.Time
|
||||
@@ -742,6 +767,9 @@ func (h *histogram) Observe(v float64) {
|
||||
h.observe(v, h.findBucket(v))
|
||||
}
|
||||
|
||||
// ObserveWithExemplar should not be called in a high-frequency setting
|
||||
// for a native histogram with configured exemplars. For this case,
|
||||
// the implementation isn't lock-free and might suffer from lock contention.
|
||||
func (h *histogram) ObserveWithExemplar(v float64, e Labels) {
|
||||
i := h.findBucket(v)
|
||||
h.observe(v, i)
|
||||
@@ -821,6 +849,13 @@ func (h *histogram) Write(out *dto.Metric) error {
|
||||
Length: proto.Uint32(0),
|
||||
}}
|
||||
}
|
||||
|
||||
if h.nativeExemplars.isEnabled() {
|
||||
h.nativeExemplars.Lock()
|
||||
his.Exemplars = append(his.Exemplars, h.nativeExemplars.exemplars...)
|
||||
h.nativeExemplars.Unlock()
|
||||
}
|
||||
|
||||
}
|
||||
addAndResetCounts(hotCounts, coldCounts)
|
||||
return nil
|
||||
@@ -829,15 +864,35 @@ func (h *histogram) Write(out *dto.Metric) error {
|
||||
// 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
|
||||
n := len(h.upperBounds)
|
||||
if n == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Early exit: if v is less than or equal to the first upper bound, return 0
|
||||
if v <= h.upperBounds[0] {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Early exit: if v is greater than the last upper bound, return len(h.upperBounds)
|
||||
if v > h.upperBounds[n-1] {
|
||||
return n
|
||||
}
|
||||
|
||||
// For small arrays, use simple linear search
|
||||
// "magic number" 35 is result of tests on couple different (AWS and baremetal) servers
|
||||
// see more details here: https://github.com/prometheus/client_golang/pull/1662
|
||||
if n < 35 {
|
||||
for i, bound := range h.upperBounds {
|
||||
if v <= bound {
|
||||
return i
|
||||
}
|
||||
}
|
||||
// If v is greater than all upper bounds, return len(h.upperBounds)
|
||||
return n
|
||||
}
|
||||
|
||||
// For larger arrays, use stdlib's binary search
|
||||
return sort.SearchFloat64s(h.upperBounds, v)
|
||||
}
|
||||
|
||||
@@ -1091,8 +1146,10 @@ func (h *histogram) resetCounts(counts *histogramCounts) {
|
||||
deleteSyncMap(&counts.nativeHistogramBucketsPositive)
|
||||
}
|
||||
|
||||
// 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.
|
||||
// updateExemplar replaces the exemplar for the provided classic bucket.
|
||||
// With empty labels, it's a no-op. It panics if any of the labels is invalid.
|
||||
// If histogram is native, the exemplar will be cached into nativeExemplars,
|
||||
// which has a limit, and will remove one exemplar when limit is reached.
|
||||
func (h *histogram) updateExemplar(v float64, bucket int, l Labels) {
|
||||
if l == nil {
|
||||
return
|
||||
@@ -1102,6 +1159,10 @@ func (h *histogram) updateExemplar(v float64, bucket int, l Labels) {
|
||||
panic(err)
|
||||
}
|
||||
h.exemplars[bucket].Store(e)
|
||||
doSparse := h.nativeHistogramSchema > math.MinInt32 && !math.IsNaN(v)
|
||||
if doSparse {
|
||||
h.nativeExemplars.addExemplar(e)
|
||||
}
|
||||
}
|
||||
|
||||
// HistogramVec is a Collector that bundles a set of Histograms that all share the
|
||||
@@ -1336,6 +1397,48 @@ func MustNewConstHistogram(
|
||||
return m
|
||||
}
|
||||
|
||||
// NewConstHistogramWithCreatedTimestamp does the same thing as NewConstHistogram but sets the created timestamp.
|
||||
func NewConstHistogramWithCreatedTimestamp(
|
||||
desc *Desc,
|
||||
count uint64,
|
||||
sum float64,
|
||||
buckets map[float64]uint64,
|
||||
ct time.Time,
|
||||
labelValues ...string,
|
||||
) (Metric, error) {
|
||||
if desc.err != nil {
|
||||
return nil, desc.err
|
||||
}
|
||||
if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &constHistogram{
|
||||
desc: desc,
|
||||
count: count,
|
||||
sum: sum,
|
||||
buckets: buckets,
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
createdTs: timestamppb.New(ct),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MustNewConstHistogramWithCreatedTimestamp is a version of NewConstHistogramWithCreatedTimestamp that panics where
|
||||
// NewConstHistogramWithCreatedTimestamp would have returned an error.
|
||||
func MustNewConstHistogramWithCreatedTimestamp(
|
||||
desc *Desc,
|
||||
count uint64,
|
||||
sum float64,
|
||||
buckets map[float64]uint64,
|
||||
ct time.Time,
|
||||
labelValues ...string,
|
||||
) Metric {
|
||||
m, err := NewConstHistogramWithCreatedTimestamp(desc, count, sum, buckets, ct, labelValues...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
type buckSort []*dto.Bucket
|
||||
|
||||
func (s buckSort) Len() int {
|
||||
@@ -1363,9 +1466,9 @@ func pickSchema(bucketFactor float64) int32 {
|
||||
floor := math.Floor(math.Log2(math.Log2(bucketFactor)))
|
||||
switch {
|
||||
case floor <= -8:
|
||||
return 8
|
||||
return nativeHistogramSchemaMaximum
|
||||
case floor >= 4:
|
||||
return -4
|
||||
return nativeHistogramSchemaMinimum
|
||||
default:
|
||||
return -int32(floor)
|
||||
}
|
||||
@@ -1575,3 +1678,379 @@ func addAndResetCounts(hot, cold *histogramCounts) {
|
||||
atomic.AddUint64(&hot.nativeHistogramZeroBucket, atomic.LoadUint64(&cold.nativeHistogramZeroBucket))
|
||||
atomic.StoreUint64(&cold.nativeHistogramZeroBucket, 0)
|
||||
}
|
||||
|
||||
type nativeExemplars struct {
|
||||
sync.Mutex
|
||||
|
||||
// Time-to-live for exemplars, it is set to -1 if exemplars are disabled, that is NativeHistogramMaxExemplars is below 0.
|
||||
// The ttl is used on insertion to remove an exemplar that is older than ttl, if present.
|
||||
ttl time.Duration
|
||||
|
||||
exemplars []*dto.Exemplar
|
||||
}
|
||||
|
||||
func (n *nativeExemplars) isEnabled() bool {
|
||||
return n.ttl != -1
|
||||
}
|
||||
|
||||
func makeNativeExemplars(ttl time.Duration, maxCount int) nativeExemplars {
|
||||
if ttl == 0 {
|
||||
ttl = 5 * time.Minute
|
||||
}
|
||||
|
||||
if maxCount == 0 {
|
||||
maxCount = 10
|
||||
}
|
||||
|
||||
if maxCount < 0 {
|
||||
maxCount = 0
|
||||
ttl = -1
|
||||
}
|
||||
|
||||
return nativeExemplars{
|
||||
ttl: ttl,
|
||||
exemplars: make([]*dto.Exemplar, 0, maxCount),
|
||||
}
|
||||
}
|
||||
|
||||
func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
|
||||
if !n.isEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
// When the number of exemplars has not yet exceeded or
|
||||
// is equal to cap(n.exemplars), then
|
||||
// insert the new exemplar directly.
|
||||
if len(n.exemplars) < cap(n.exemplars) {
|
||||
var nIdx int
|
||||
for nIdx = 0; nIdx < len(n.exemplars); nIdx++ {
|
||||
if *e.Value < *n.exemplars[nIdx].Value {
|
||||
break
|
||||
}
|
||||
}
|
||||
n.exemplars = append(n.exemplars[:nIdx], append([]*dto.Exemplar{e}, n.exemplars[nIdx:]...)...)
|
||||
return
|
||||
}
|
||||
|
||||
if len(n.exemplars) == 1 {
|
||||
// When the number of exemplars is 1, then
|
||||
// replace the existing exemplar with the new exemplar.
|
||||
n.exemplars[0] = e
|
||||
return
|
||||
}
|
||||
// From this point on, the number of exemplars is greater than 1.
|
||||
|
||||
// When the number of exemplars exceeds the limit, remove one exemplar.
|
||||
var (
|
||||
ot = time.Time{} // Oldest timestamp seen. Initial value doesn't matter as we replace it due to otIdx == -1 in the loop.
|
||||
otIdx = -1 // Index of the exemplar with the oldest timestamp.
|
||||
|
||||
md = -1.0 // Logarithm of the delta of the closest pair of exemplars.
|
||||
|
||||
// The insertion point of the new exemplar in the exemplars slice after insertion.
|
||||
// This is calculated purely based on the order of the exemplars by value.
|
||||
// nIdx == len(n.exemplars) means the new exemplar is to be inserted after the end.
|
||||
nIdx = -1
|
||||
|
||||
// rIdx is ultimately the index for the exemplar that we are replacing with the new exemplar.
|
||||
// The aim is to keep a good spread of exemplars by value and not let them bunch up too much.
|
||||
// It is calculated in 3 steps:
|
||||
// 1. First we set rIdx to the index of the older exemplar within the closest pair by value.
|
||||
// That is the following will be true (on log scale):
|
||||
// either the exemplar pair on index (rIdx-1, rIdx) or (rIdx, rIdx+1) will have
|
||||
// the closest values to each other from all pairs.
|
||||
// For example, suppose the values are distributed like this:
|
||||
// |-----------x-------------x----------------x----x-----|
|
||||
// ^--rIdx as this is older.
|
||||
// Or like this:
|
||||
// |-----------x-------------x----------------x----x-----|
|
||||
// ^--rIdx as this is older.
|
||||
// 2. If there is an exemplar that expired, then we simple reset rIdx to that index.
|
||||
// 3. We check if by inserting the new exemplar we would create a closer pair at
|
||||
// (nIdx-1, nIdx) or (nIdx, nIdx+1) and set rIdx to nIdx-1 or nIdx accordingly to
|
||||
// keep the spread of exemplars by value; otherwise we keep rIdx as it is.
|
||||
rIdx = -1
|
||||
cLog float64 // Logarithm of the current exemplar.
|
||||
pLog float64 // Logarithm of the previous exemplar.
|
||||
)
|
||||
|
||||
for i, exemplar := range n.exemplars {
|
||||
// Find the exemplar with the oldest timestamp.
|
||||
if otIdx == -1 || exemplar.Timestamp.AsTime().Before(ot) {
|
||||
ot = exemplar.Timestamp.AsTime()
|
||||
otIdx = i
|
||||
}
|
||||
|
||||
// Find the index at which to insert new the exemplar.
|
||||
if nIdx == -1 && *e.Value <= *exemplar.Value {
|
||||
nIdx = i
|
||||
}
|
||||
|
||||
// Find the two closest exemplars and pick the one the with older timestamp.
|
||||
pLog = cLog
|
||||
cLog = math.Log(exemplar.GetValue())
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
diff := math.Abs(cLog - pLog)
|
||||
if md == -1 || diff < md {
|
||||
// The closest exemplar pair is at index: i-1, i.
|
||||
// Choose the exemplar with the older timestamp for replacement.
|
||||
md = diff
|
||||
if n.exemplars[i].Timestamp.AsTime().Before(n.exemplars[i-1].Timestamp.AsTime()) {
|
||||
rIdx = i
|
||||
} else {
|
||||
rIdx = i - 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If all existing exemplar are smaller than new exemplar,
|
||||
// then the exemplar should be inserted at the end.
|
||||
if nIdx == -1 {
|
||||
nIdx = len(n.exemplars)
|
||||
}
|
||||
// Here, we have the following relationships:
|
||||
// n.exemplars[nIdx-1].Value < e.Value (if nIdx > 0)
|
||||
// e.Value <= n.exemplars[nIdx].Value (if nIdx < len(n.exemplars))
|
||||
|
||||
if otIdx != -1 && e.Timestamp.AsTime().Sub(ot) > n.ttl {
|
||||
// If the oldest exemplar has expired, then replace it with the new exemplar.
|
||||
rIdx = otIdx
|
||||
} else {
|
||||
// In the previous for loop, when calculating the closest pair of exemplars,
|
||||
// we did not take into account the newly inserted exemplar.
|
||||
// So we need to calculate with the newly inserted exemplar again.
|
||||
elog := math.Log(e.GetValue())
|
||||
if nIdx > 0 {
|
||||
diff := math.Abs(elog - math.Log(n.exemplars[nIdx-1].GetValue()))
|
||||
if diff < md {
|
||||
// The value we are about to insert is closer to the previous exemplar at the insertion point than what we calculated before in rIdx.
|
||||
// v--rIdx
|
||||
// |-----------x-n-----------x----------------x----x-----|
|
||||
// nIdx-1--^ ^--new exemplar value
|
||||
// Do not make the spread worse, replace nIdx-1 and not rIdx.
|
||||
md = diff
|
||||
rIdx = nIdx - 1
|
||||
}
|
||||
}
|
||||
if nIdx < len(n.exemplars) {
|
||||
diff := math.Abs(math.Log(n.exemplars[nIdx].GetValue()) - elog)
|
||||
if diff < md {
|
||||
// The value we are about to insert is closer to the next exemplar at the insertion point than what we calculated before in rIdx.
|
||||
// v--rIdx
|
||||
// |-----------x-----------n-x----------------x----x-----|
|
||||
// new exemplar value--^ ^--nIdx
|
||||
// Do not make the spread worse, replace nIdx-1 and not rIdx.
|
||||
rIdx = nIdx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust the slice according to rIdx and nIdx.
|
||||
switch {
|
||||
case rIdx == nIdx:
|
||||
n.exemplars[nIdx] = e
|
||||
case rIdx < nIdx:
|
||||
n.exemplars = append(n.exemplars[:rIdx], append(n.exemplars[rIdx+1:nIdx], append([]*dto.Exemplar{e}, n.exemplars[nIdx:]...)...)...)
|
||||
case rIdx > nIdx:
|
||||
n.exemplars = append(n.exemplars[:nIdx], append([]*dto.Exemplar{e}, append(n.exemplars[nIdx:rIdx], n.exemplars[rIdx+1:]...)...)...)
|
||||
}
|
||||
}
|
||||
|
||||
type constNativeHistogram struct {
|
||||
desc *Desc
|
||||
dto.Histogram
|
||||
labelPairs []*dto.LabelPair
|
||||
}
|
||||
|
||||
func validateCount(sum float64, count uint64, negativeBuckets, positiveBuckets map[int]int64, zeroBucket uint64) error {
|
||||
var bucketPopulationSum int64
|
||||
for _, v := range positiveBuckets {
|
||||
bucketPopulationSum += v
|
||||
}
|
||||
for _, v := range negativeBuckets {
|
||||
bucketPopulationSum += v
|
||||
}
|
||||
bucketPopulationSum += int64(zeroBucket)
|
||||
|
||||
// If the sum of observations is NaN, the number of observations must be greater or equal to the sum of all bucket counts.
|
||||
// Otherwise, the number of observations must be equal to the sum of all bucket counts .
|
||||
|
||||
if math.IsNaN(sum) && bucketPopulationSum > int64(count) ||
|
||||
!math.IsNaN(sum) && bucketPopulationSum != int64(count) {
|
||||
return errors.New("the sum of all bucket populations exceeds the count of observations")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewConstNativeHistogram returns a metric representing a Prometheus native histogram with
|
||||
// fixed values for the count, sum, and positive/negative/zero bucket counts. As those parameters
|
||||
// cannot be changed, the returned value does not implement the Histogram
|
||||
// interface (but only the Metric interface). Users of this package will not
|
||||
// have much use for it in regular operations. However, when implementing custom
|
||||
// OpenTelemetry Collectors, it is useful as a throw-away metric that is generated on the fly
|
||||
// to send it to Prometheus in the Collect method.
|
||||
//
|
||||
// zeroBucket counts all (positive and negative)
|
||||
// observations in the zero bucket (with an absolute value less or equal
|
||||
// the current threshold).
|
||||
// positiveBuckets and negativeBuckets are separate maps for negative and positive
|
||||
// observations. The map's value is an int64, counting observations in
|
||||
// that bucket. The map's key is the
|
||||
// index of the bucket according to the used
|
||||
// Schema. Index 0 is for an upper bound of 1 in positive buckets and for a lower bound of -1 in negative buckets.
|
||||
// NewConstNativeHistogram returns an error if
|
||||
// - the length of labelValues is not consistent with the variable labels in Desc or if Desc is invalid.
|
||||
// - the schema passed is not between 8 and -4
|
||||
// - the sum of counts in all buckets including the zero bucket does not equal the count if sum is not NaN (or exceeds the count if sum is NaN)
|
||||
//
|
||||
// See https://opentelemetry.io/docs/specs/otel/compatibility/prometheus_and_openmetrics/#exponential-histograms for more details about the conversion from OTel to Prometheus.
|
||||
func NewConstNativeHistogram(
|
||||
desc *Desc,
|
||||
count uint64,
|
||||
sum float64,
|
||||
positiveBuckets, negativeBuckets map[int]int64,
|
||||
zeroBucket uint64,
|
||||
schema int32,
|
||||
zeroThreshold float64,
|
||||
createdTimestamp time.Time,
|
||||
labelValues ...string,
|
||||
) (Metric, error) {
|
||||
if desc.err != nil {
|
||||
return nil, desc.err
|
||||
}
|
||||
if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if schema > nativeHistogramSchemaMaximum || schema < nativeHistogramSchemaMinimum {
|
||||
return nil, errors.New("invalid native histogram schema")
|
||||
}
|
||||
if err := validateCount(sum, count, negativeBuckets, positiveBuckets, zeroBucket); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
NegativeSpan, NegativeDelta := makeBucketsFromMap(negativeBuckets)
|
||||
PositiveSpan, PositiveDelta := makeBucketsFromMap(positiveBuckets)
|
||||
ret := &constNativeHistogram{
|
||||
desc: desc,
|
||||
Histogram: dto.Histogram{
|
||||
CreatedTimestamp: timestamppb.New(createdTimestamp),
|
||||
Schema: &schema,
|
||||
ZeroThreshold: &zeroThreshold,
|
||||
SampleCount: &count,
|
||||
SampleSum: &sum,
|
||||
|
||||
NegativeSpan: NegativeSpan,
|
||||
NegativeDelta: NegativeDelta,
|
||||
|
||||
PositiveSpan: PositiveSpan,
|
||||
PositiveDelta: PositiveDelta,
|
||||
|
||||
ZeroCount: proto.Uint64(zeroBucket),
|
||||
},
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
}
|
||||
if *ret.ZeroThreshold == 0 && *ret.ZeroCount == 0 && len(ret.PositiveSpan) == 0 && len(ret.NegativeSpan) == 0 {
|
||||
ret.PositiveSpan = []*dto.BucketSpan{{
|
||||
Offset: proto.Int32(0),
|
||||
Length: proto.Uint32(0),
|
||||
}}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// MustNewConstNativeHistogram is a version of NewConstNativeHistogram that panics where
|
||||
// NewConstNativeHistogram would have returned an error.
|
||||
func MustNewConstNativeHistogram(
|
||||
desc *Desc,
|
||||
count uint64,
|
||||
sum float64,
|
||||
positiveBuckets, negativeBuckets map[int]int64,
|
||||
zeroBucket uint64,
|
||||
nativeHistogramSchema int32,
|
||||
nativeHistogramZeroThreshold float64,
|
||||
createdTimestamp time.Time,
|
||||
labelValues ...string,
|
||||
) Metric {
|
||||
nativehistogram, err := NewConstNativeHistogram(desc,
|
||||
count,
|
||||
sum,
|
||||
positiveBuckets,
|
||||
negativeBuckets,
|
||||
zeroBucket,
|
||||
nativeHistogramSchema,
|
||||
nativeHistogramZeroThreshold,
|
||||
createdTimestamp,
|
||||
labelValues...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nativehistogram
|
||||
}
|
||||
|
||||
func (h *constNativeHistogram) Desc() *Desc {
|
||||
return h.desc
|
||||
}
|
||||
|
||||
func (h *constNativeHistogram) Write(out *dto.Metric) error {
|
||||
out.Histogram = &h.Histogram
|
||||
out.Label = h.labelPairs
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeBucketsFromMap(buckets map[int]int64) ([]*dto.BucketSpan, []int64) {
|
||||
if len(buckets) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var ii []int
|
||||
for k := range buckets {
|
||||
ii = append(ii, k)
|
||||
}
|
||||
sort.Ints(ii)
|
||||
|
||||
var (
|
||||
spans []*dto.BucketSpan
|
||||
deltas []int64
|
||||
prevCount int64
|
||||
nextI int
|
||||
)
|
||||
|
||||
appendDelta := func(count int64) {
|
||||
*spans[len(spans)-1].Length++
|
||||
deltas = append(deltas, count-prevCount)
|
||||
prevCount = count
|
||||
}
|
||||
|
||||
for n, i := range ii {
|
||||
count := buckets[i]
|
||||
// Multiple spans with only small gaps in between are probably
|
||||
// encoded more efficiently as one larger span with a few empty
|
||||
// buckets. Needs some research to find the sweet spot. For now,
|
||||
// we assume that gaps of one or two buckets should not create
|
||||
// a new span.
|
||||
iDelta := int32(i - nextI)
|
||||
if n == 0 || iDelta > 2 {
|
||||
// We have to create a new span, either because we are
|
||||
// at the very beginning, or because we have found a gap
|
||||
// of more than two buckets.
|
||||
spans = append(spans, &dto.BucketSpan{
|
||||
Offset: proto.Int32(iDelta),
|
||||
Length: proto.Uint32(0),
|
||||
})
|
||||
} else {
|
||||
// We have found a small gap (or no gap at all).
|
||||
// Insert empty buckets as needed.
|
||||
for j := int32(0); j < iDelta; j++ {
|
||||
appendDelta(0)
|
||||
}
|
||||
}
|
||||
appendDelta(count)
|
||||
nextI = i + 1
|
||||
}
|
||||
return spans, deltas
|
||||
}
|
||||
|
||||
19
vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go
generated
vendored
19
vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go
generated
vendored
@@ -22,17 +22,18 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func min(a, b int) int {
|
||||
func minInt(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
func maxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
@@ -427,12 +428,12 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
|
||||
if codes[0].Tag == 'e' {
|
||||
c := codes[0]
|
||||
i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
|
||||
codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2}
|
||||
codes[0] = OpCode{c.Tag, maxInt(i1, i2-n), i2, maxInt(j1, j2-n), j2}
|
||||
}
|
||||
if codes[len(codes)-1].Tag == 'e' {
|
||||
c := codes[len(codes)-1]
|
||||
i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
|
||||
codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}
|
||||
codes[len(codes)-1] = OpCode{c.Tag, i1, minInt(i2, i1+n), j1, minInt(j2, j1+n)}
|
||||
}
|
||||
nn := n + n
|
||||
groups := [][]OpCode{}
|
||||
@@ -443,12 +444,12 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
|
||||
// there is a large range with no changes.
|
||||
if c.Tag == 'e' && i2-i1 > nn {
|
||||
group = append(group, OpCode{
|
||||
c.Tag, i1, min(i2, i1+n),
|
||||
j1, min(j2, j1+n),
|
||||
c.Tag, i1, minInt(i2, i1+n),
|
||||
j1, minInt(j2, j1+n),
|
||||
})
|
||||
groups = append(groups, group)
|
||||
group = []OpCode{}
|
||||
i1, j1 = max(i1, i2-n), max(j1, j2-n)
|
||||
i1, j1 = maxInt(i1, i2-n), maxInt(j1, j2-n)
|
||||
}
|
||||
group = append(group, OpCode{c.Tag, i1, i2, j1, j2})
|
||||
}
|
||||
@@ -515,7 +516,7 @@ func (m *SequenceMatcher) QuickRatio() float64 {
|
||||
// is faster to compute than either .Ratio() or .QuickRatio().
|
||||
func (m *SequenceMatcher) RealQuickRatio() float64 {
|
||||
la, lb := len(m.a), len(m.b)
|
||||
return calculateRatio(min(la, lb), la+lb)
|
||||
return calculateRatio(minInt(la, lb), la+lb)
|
||||
}
|
||||
|
||||
// Convert range to the "ed" format
|
||||
@@ -524,7 +525,7 @@ func formatRangeUnified(start, stop int) string {
|
||||
beginning := start + 1 // lines start numbering with one
|
||||
length := stop - start
|
||||
if length == 1 {
|
||||
return fmt.Sprintf("%d", beginning)
|
||||
return strconv.Itoa(beginning)
|
||||
}
|
||||
if length == 0 {
|
||||
beginning-- // empty ranges begin at line just before the range
|
||||
|
||||
@@ -30,3 +30,5 @@ type GoCollectorOptions struct {
|
||||
RuntimeMetricSumForHist map[string]string
|
||||
RuntimeMetricRules []GoCollectorRule
|
||||
}
|
||||
|
||||
var GoCollectorDefaultRuntimeMetrics = regexp.MustCompile(`/gc/gogc:percent|/gc/gomemlimit:bytes|/sched/gomaxprocs:threads`)
|
||||
|
||||
3
vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go
generated
vendored
3
vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go
generated
vendored
@@ -66,7 +66,8 @@ func RuntimeMetricsToProm(d *metrics.Description) (string, string, string, bool)
|
||||
name += "_total"
|
||||
}
|
||||
|
||||
valid := model.IsValidMetricName(model.LabelValue(namespace + "_" + subsystem + "_" + name))
|
||||
// Our current conversion moves to legacy naming, so use legacy validation.
|
||||
valid := model.IsValidLegacyMetricName(namespace + "_" + subsystem + "_" + name)
|
||||
switch d.Kind {
|
||||
case metrics.KindUint64:
|
||||
case metrics.KindFloat64:
|
||||
|
||||
26
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
26
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
@@ -108,15 +108,23 @@ func BuildFQName(namespace, subsystem, name string) string {
|
||||
if name == "" {
|
||||
return ""
|
||||
}
|
||||
switch {
|
||||
case namespace != "" && subsystem != "":
|
||||
return strings.Join([]string{namespace, subsystem, name}, "_")
|
||||
case namespace != "":
|
||||
return strings.Join([]string{namespace, name}, "_")
|
||||
case subsystem != "":
|
||||
return strings.Join([]string{subsystem, name}, "_")
|
||||
|
||||
sb := strings.Builder{}
|
||||
sb.Grow(len(namespace) + len(subsystem) + len(name) + 2)
|
||||
|
||||
if namespace != "" {
|
||||
sb.WriteString(namespace)
|
||||
sb.WriteString("_")
|
||||
}
|
||||
return name
|
||||
|
||||
if subsystem != "" {
|
||||
sb.WriteString(subsystem)
|
||||
sb.WriteString("_")
|
||||
}
|
||||
|
||||
sb.WriteString(name)
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
type invalidMetric struct {
|
||||
@@ -234,7 +242,7 @@ func NewMetricWithExemplars(m Metric, exemplars ...Exemplar) (Metric, error) {
|
||||
)
|
||||
for i, e := range exemplars {
|
||||
ts := e.Timestamp
|
||||
if ts == (time.Time{}) {
|
||||
if ts.IsZero() {
|
||||
ts = now
|
||||
}
|
||||
exs[i], err = newExemplar(e.Value, ts, e.Labels)
|
||||
|
||||
56
vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
generated
vendored
56
vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
generated
vendored
@@ -22,14 +22,16 @@ import (
|
||||
)
|
||||
|
||||
type processCollector struct {
|
||||
collectFn func(chan<- Metric)
|
||||
pidFn func() (int, error)
|
||||
reportErrors bool
|
||||
cpuTotal *Desc
|
||||
openFDs, maxFDs *Desc
|
||||
vsize, maxVsize *Desc
|
||||
rss *Desc
|
||||
startTime *Desc
|
||||
collectFn func(chan<- Metric)
|
||||
describeFn func(chan<- *Desc)
|
||||
pidFn func() (int, error)
|
||||
reportErrors bool
|
||||
cpuTotal *Desc
|
||||
openFDs, maxFDs *Desc
|
||||
vsize, maxVsize *Desc
|
||||
rss *Desc
|
||||
startTime *Desc
|
||||
inBytes, outBytes *Desc
|
||||
}
|
||||
|
||||
// ProcessCollectorOpts defines the behavior of a process metrics collector
|
||||
@@ -100,6 +102,16 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector {
|
||||
"Start time of the process since unix epoch in seconds.",
|
||||
nil, nil,
|
||||
),
|
||||
inBytes: NewDesc(
|
||||
ns+"process_network_receive_bytes_total",
|
||||
"Number of bytes received by the process over the network.",
|
||||
nil, nil,
|
||||
),
|
||||
outBytes: NewDesc(
|
||||
ns+"process_network_transmit_bytes_total",
|
||||
"Number of bytes sent by the process over the network.",
|
||||
nil, nil,
|
||||
),
|
||||
}
|
||||
|
||||
if opts.PidFn == nil {
|
||||
@@ -111,24 +123,23 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector {
|
||||
// Set up process metric collection if supported by the runtime.
|
||||
if canCollectProcess() {
|
||||
c.collectFn = c.processCollect
|
||||
c.describeFn = c.describe
|
||||
} else {
|
||||
c.collectFn = func(ch chan<- Metric) {
|
||||
c.reportError(ch, nil, errors.New("process metrics not supported on this platform"))
|
||||
}
|
||||
c.collectFn = c.errorCollectFn
|
||||
c.describeFn = c.errorDescribeFn
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// Describe returns all descriptions of the collector.
|
||||
func (c *processCollector) Describe(ch chan<- *Desc) {
|
||||
ch <- c.cpuTotal
|
||||
ch <- c.openFDs
|
||||
ch <- c.maxFDs
|
||||
ch <- c.vsize
|
||||
ch <- c.maxVsize
|
||||
ch <- c.rss
|
||||
ch <- c.startTime
|
||||
func (c *processCollector) errorCollectFn(ch chan<- Metric) {
|
||||
c.reportError(ch, nil, errors.New("process metrics not supported on this platform"))
|
||||
}
|
||||
|
||||
func (c *processCollector) errorDescribeFn(ch chan<- *Desc) {
|
||||
if c.reportErrors {
|
||||
ch <- NewInvalidDesc(errors.New("process metrics not supported on this platform"))
|
||||
}
|
||||
}
|
||||
|
||||
// Collect returns the current state of all metrics of the collector.
|
||||
@@ -136,6 +147,11 @@ func (c *processCollector) Collect(ch chan<- Metric) {
|
||||
c.collectFn(ch)
|
||||
}
|
||||
|
||||
// Describe returns all descriptions of the collector.
|
||||
func (c *processCollector) Describe(ch chan<- *Desc) {
|
||||
c.describeFn(ch)
|
||||
}
|
||||
|
||||
func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) {
|
||||
if !c.reportErrors {
|
||||
return
|
||||
|
||||
130
vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go
generated
vendored
Normal file
130
vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright 2024 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.
|
||||
|
||||
//go:build darwin && !ios
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// notImplementedErr is returned by stub functions that replace cgo functions, when cgo
|
||||
// isn't available.
|
||||
var notImplementedErr = errors.New("not implemented")
|
||||
|
||||
type memoryInfo struct {
|
||||
vsize uint64 // Virtual memory size in bytes
|
||||
rss uint64 // Resident memory size in bytes
|
||||
}
|
||||
|
||||
func canCollectProcess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func getSoftLimit(which int) (uint64, error) {
|
||||
rlimit := syscall.Rlimit{}
|
||||
|
||||
if err := syscall.Getrlimit(which, &rlimit); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return rlimit.Cur, nil
|
||||
}
|
||||
|
||||
func getOpenFileCount() (float64, error) {
|
||||
// Alternately, the undocumented proc_pidinfo(PROC_PIDLISTFDS) can be used to
|
||||
// return a list of open fds, but that requires a way to call C APIs. The
|
||||
// benefits, however, include fewer system calls and not failing when at the
|
||||
// open file soft limit.
|
||||
|
||||
if dir, err := os.Open("/dev/fd"); err != nil {
|
||||
return 0.0, err
|
||||
} else {
|
||||
defer dir.Close()
|
||||
|
||||
// Avoid ReadDir(), as it calls stat(2) on each descriptor. Not only is
|
||||
// that info not used, but KQUEUE descriptors fail stat(2), which causes
|
||||
// the whole method to fail.
|
||||
if names, err := dir.Readdirnames(0); err != nil {
|
||||
return 0.0, err
|
||||
} else {
|
||||
// Subtract 1 to ignore the open /dev/fd descriptor above.
|
||||
return float64(len(names) - 1), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
if procs, err := unix.SysctlKinfoProcSlice("kern.proc.pid", os.Getpid()); err == nil {
|
||||
if len(procs) == 1 {
|
||||
startTime := float64(procs[0].Proc.P_starttime.Nano() / 1e9)
|
||||
ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime)
|
||||
} else {
|
||||
err = fmt.Errorf("sysctl() returned %d proc structs (expected 1)", len(procs))
|
||||
c.reportError(ch, c.startTime, err)
|
||||
}
|
||||
} else {
|
||||
c.reportError(ch, c.startTime, err)
|
||||
}
|
||||
|
||||
// The proc structure returned by kern.proc.pid above has an Rusage member,
|
||||
// but it is not filled in, so it needs to be fetched by getrusage(2). For
|
||||
// that call, the UTime, STime, and Maxrss members are filled out, but not
|
||||
// Ixrss, Idrss, or Isrss for the memory usage. Memory stats will require
|
||||
// access to the C API to call task_info(TASK_BASIC_INFO).
|
||||
rusage := unix.Rusage{}
|
||||
|
||||
if err := unix.Getrusage(syscall.RUSAGE_SELF, &rusage); err == nil {
|
||||
cpuTime := time.Duration(rusage.Stime.Nano() + rusage.Utime.Nano()).Seconds()
|
||||
ch <- MustNewConstMetric(c.cpuTotal, CounterValue, cpuTime)
|
||||
} else {
|
||||
c.reportError(ch, c.cpuTotal, err)
|
||||
}
|
||||
|
||||
if memInfo, err := getMemory(); err == nil {
|
||||
ch <- MustNewConstMetric(c.rss, GaugeValue, float64(memInfo.rss))
|
||||
ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(memInfo.vsize))
|
||||
} else if !errors.Is(err, notImplementedErr) {
|
||||
// Don't report an error when support is not compiled in.
|
||||
c.reportError(ch, c.rss, err)
|
||||
c.reportError(ch, c.vsize, err)
|
||||
}
|
||||
|
||||
if fds, err := getOpenFileCount(); err == nil {
|
||||
ch <- MustNewConstMetric(c.openFDs, GaugeValue, fds)
|
||||
} else {
|
||||
c.reportError(ch, c.openFDs, err)
|
||||
}
|
||||
|
||||
if openFiles, err := getSoftLimit(syscall.RLIMIT_NOFILE); err == nil {
|
||||
ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(openFiles))
|
||||
} else {
|
||||
c.reportError(ch, c.maxFDs, err)
|
||||
}
|
||||
|
||||
if addressSpace, err := getSoftLimit(syscall.RLIMIT_AS); err == nil {
|
||||
ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(addressSpace))
|
||||
} else {
|
||||
c.reportError(ch, c.maxVsize, err)
|
||||
}
|
||||
|
||||
// TODO: socket(PF_SYSTEM) to fetch "com.apple.network.statistics" might
|
||||
// be able to get the per-process network send/receive counts.
|
||||
}
|
||||
84
vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.c
generated
vendored
Normal file
84
vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.c
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright 2024 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.
|
||||
|
||||
//go:build darwin && !ios && cgo
|
||||
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach/mach_vm.h>
|
||||
|
||||
// The compiler warns that mach/shared_memory_server.h is deprecated, and to use
|
||||
// mach/shared_region.h instead. But that doesn't define
|
||||
// SHARED_DATA_REGION_SIZE or SHARED_TEXT_REGION_SIZE, so redefine them here and
|
||||
// avoid a warning message when running tests.
|
||||
#define GLOBAL_SHARED_TEXT_SEGMENT 0x90000000U
|
||||
#define SHARED_DATA_REGION_SIZE 0x10000000
|
||||
#define SHARED_TEXT_REGION_SIZE 0x10000000
|
||||
|
||||
|
||||
int get_memory_info(unsigned long long *rss, unsigned long long *vsize)
|
||||
{
|
||||
// This is lightly adapted from how ps(1) obtains its memory info.
|
||||
// https://github.com/apple-oss-distributions/adv_cmds/blob/8744084ea0ff41ca4bb96b0f9c22407d0e48e9b7/ps/tasks.c#L109
|
||||
|
||||
kern_return_t error;
|
||||
task_t task = MACH_PORT_NULL;
|
||||
mach_task_basic_info_data_t info;
|
||||
mach_msg_type_number_t info_count = MACH_TASK_BASIC_INFO_COUNT;
|
||||
|
||||
error = task_info(
|
||||
mach_task_self(),
|
||||
MACH_TASK_BASIC_INFO,
|
||||
(task_info_t) &info,
|
||||
&info_count );
|
||||
|
||||
if( error != KERN_SUCCESS )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
*rss = info.resident_size;
|
||||
*vsize = info.virtual_size;
|
||||
|
||||
{
|
||||
vm_region_basic_info_data_64_t b_info;
|
||||
mach_vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT;
|
||||
mach_vm_size_t size;
|
||||
mach_port_t object_name;
|
||||
|
||||
/*
|
||||
* try to determine if this task has the split libraries
|
||||
* mapped in... if so, adjust its virtual size down by
|
||||
* the 2 segments that are used for split libraries
|
||||
*/
|
||||
info_count = VM_REGION_BASIC_INFO_COUNT_64;
|
||||
|
||||
error = mach_vm_region(
|
||||
mach_task_self(),
|
||||
&address,
|
||||
&size,
|
||||
VM_REGION_BASIC_INFO_64,
|
||||
(vm_region_info_t) &b_info,
|
||||
&info_count,
|
||||
&object_name);
|
||||
|
||||
if (error == KERN_SUCCESS) {
|
||||
if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) &&
|
||||
*vsize > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE)) {
|
||||
*vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
51
vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.go
generated
vendored
Normal file
51
vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2024 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.
|
||||
|
||||
//go:build darwin && !ios && cgo
|
||||
|
||||
package prometheus
|
||||
|
||||
/*
|
||||
int get_memory_info(unsigned long long *rss, unsigned long long *vs);
|
||||
*/
|
||||
import "C"
|
||||
import "fmt"
|
||||
|
||||
func getMemory() (*memoryInfo, error) {
|
||||
var rss, vsize C.ulonglong
|
||||
|
||||
if err := C.get_memory_info(&rss, &vsize); err != 0 {
|
||||
return nil, fmt.Errorf("task_info() failed with 0x%x", int(err))
|
||||
}
|
||||
|
||||
return &memoryInfo{vsize: uint64(vsize), rss: uint64(rss)}, nil
|
||||
}
|
||||
|
||||
// describe returns all descriptions of the collector for Darwin.
|
||||
// Ensure that this list of descriptors is kept in sync with the metrics collected
|
||||
// in the processCollect method. Any changes to the metrics in processCollect
|
||||
// (such as adding or removing metrics) should be reflected in this list of descriptors.
|
||||
func (c *processCollector) describe(ch chan<- *Desc) {
|
||||
ch <- c.cpuTotal
|
||||
ch <- c.openFDs
|
||||
ch <- c.maxFDs
|
||||
ch <- c.maxVsize
|
||||
ch <- c.startTime
|
||||
ch <- c.rss
|
||||
ch <- c.vsize
|
||||
|
||||
/* the process could be collected but not implemented yet
|
||||
ch <- c.inBytes
|
||||
ch <- c.outBytes
|
||||
*/
|
||||
}
|
||||
39
vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go
generated
vendored
Normal file
39
vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2024 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.
|
||||
|
||||
//go:build darwin && !ios && !cgo
|
||||
|
||||
package prometheus
|
||||
|
||||
func getMemory() (*memoryInfo, error) {
|
||||
return nil, notImplementedErr
|
||||
}
|
||||
|
||||
// describe returns all descriptions of the collector for Darwin.
|
||||
// Ensure that this list of descriptors is kept in sync with the metrics collected
|
||||
// in the processCollect method. Any changes to the metrics in processCollect
|
||||
// (such as adding or removing metrics) should be reflected in this list of descriptors.
|
||||
func (c *processCollector) describe(ch chan<- *Desc) {
|
||||
ch <- c.cpuTotal
|
||||
ch <- c.openFDs
|
||||
ch <- c.maxFDs
|
||||
ch <- c.maxVsize
|
||||
ch <- c.startTime
|
||||
|
||||
/* the process could be collected but not implemented yet
|
||||
ch <- c.rss
|
||||
ch <- c.vsize
|
||||
ch <- c.inBytes
|
||||
ch <- c.outBytes
|
||||
*/
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 The Prometheus Authors
|
||||
// Copyright 2023 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
|
||||
@@ -11,8 +11,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build js
|
||||
// +build js
|
||||
//go:build wasip1 || js || ios
|
||||
// +build wasip1 js ios
|
||||
|
||||
package prometheus
|
||||
|
||||
@@ -21,6 +21,13 @@ func canCollectProcess() bool {
|
||||
}
|
||||
|
||||
func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
// noop on this platform
|
||||
return
|
||||
c.errorCollectFn(ch)
|
||||
}
|
||||
|
||||
// describe returns all descriptions of the collector for wasip1 and js.
|
||||
// Ensure that this list of descriptors is kept in sync with the metrics collected
|
||||
// in the processCollect method. Any changes to the metrics in processCollect
|
||||
// (such as adding or removing metrics) should be reflected in this list of descriptors.
|
||||
func (c *processCollector) describe(ch chan<- *Desc) {
|
||||
c.errorDescribeFn(ch)
|
||||
}
|
||||
@@ -11,8 +11,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !windows && !js && !wasip1
|
||||
// +build !windows,!js,!wasip1
|
||||
//go:build !windows && !js && !wasip1 && !darwin
|
||||
// +build !windows,!js,!wasip1,!darwin
|
||||
|
||||
package prometheus
|
||||
|
||||
@@ -63,4 +63,34 @@ func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
} else {
|
||||
c.reportError(ch, nil, err)
|
||||
}
|
||||
|
||||
if netstat, err := p.Netstat(); err == nil {
|
||||
var inOctets, outOctets float64
|
||||
if netstat.IpExt.InOctets != nil {
|
||||
inOctets = *netstat.IpExt.InOctets
|
||||
}
|
||||
if netstat.IpExt.OutOctets != nil {
|
||||
outOctets = *netstat.IpExt.OutOctets
|
||||
}
|
||||
ch <- MustNewConstMetric(c.inBytes, CounterValue, inOctets)
|
||||
ch <- MustNewConstMetric(c.outBytes, CounterValue, outOctets)
|
||||
} else {
|
||||
c.reportError(ch, nil, err)
|
||||
}
|
||||
}
|
||||
|
||||
// describe returns all descriptions of the collector for others than windows, js, wasip1 and darwin.
|
||||
// Ensure that this list of descriptors is kept in sync with the metrics collected
|
||||
// in the processCollect method. Any changes to the metrics in processCollect
|
||||
// (such as adding or removing metrics) should be reflected in this list of descriptors.
|
||||
func (c *processCollector) describe(ch chan<- *Desc) {
|
||||
ch <- c.cpuTotal
|
||||
ch <- c.openFDs
|
||||
ch <- c.maxFDs
|
||||
ch <- c.vsize
|
||||
ch <- c.maxVsize
|
||||
ch <- c.rss
|
||||
ch <- c.startTime
|
||||
ch <- c.inBytes
|
||||
ch <- c.outBytes
|
||||
}
|
||||
26
vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go
generated
vendored
26
vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
// Copyright 2023 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.
|
||||
|
||||
//go:build wasip1
|
||||
// +build wasip1
|
||||
|
||||
package prometheus
|
||||
|
||||
func canCollectProcess() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (*processCollector) processCollect(chan<- Metric) {
|
||||
// noop on this platform
|
||||
return
|
||||
}
|
||||
21
vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
generated
vendored
21
vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
generated
vendored
@@ -79,14 +79,10 @@ func getProcessHandleCount(handle windows.Handle) (uint32, error) {
|
||||
}
|
||||
|
||||
func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
h, err := windows.GetCurrentProcess()
|
||||
if err != nil {
|
||||
c.reportError(ch, nil, err)
|
||||
return
|
||||
}
|
||||
h := windows.CurrentProcess()
|
||||
|
||||
var startTime, exitTime, kernelTime, userTime windows.Filetime
|
||||
err = windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime)
|
||||
err := windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime)
|
||||
if err != nil {
|
||||
c.reportError(ch, nil, err)
|
||||
return
|
||||
@@ -111,6 +107,19 @@ func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(16*1024*1024)) // Windows has a hard-coded max limit, not per-process.
|
||||
}
|
||||
|
||||
// describe returns all descriptions of the collector for windows.
|
||||
// Ensure that this list of descriptors is kept in sync with the metrics collected
|
||||
// in the processCollect method. Any changes to the metrics in processCollect
|
||||
// (such as adding or removing metrics) should be reflected in this list of descriptors.
|
||||
func (c *processCollector) describe(ch chan<- *Desc) {
|
||||
ch <- c.cpuTotal
|
||||
ch <- c.openFDs
|
||||
ch <- c.maxFDs
|
||||
ch <- c.vsize
|
||||
ch <- c.rss
|
||||
ch <- c.startTime
|
||||
}
|
||||
|
||||
func fileTimeToSeconds(ft windows.Filetime) float64 {
|
||||
return float64(uint64(ft.HighDateTime)<<32+uint64(ft.LowDateTime)) / 1e7
|
||||
}
|
||||
|
||||
19
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
19
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
@@ -314,16 +314,17 @@ func (r *Registry) Register(c Collector) error {
|
||||
if dimHash != desc.dimHash {
|
||||
return fmt.Errorf("a previously registered descriptor with the same fully-qualified name as %s has different label names or a different help string", desc)
|
||||
}
|
||||
} else {
|
||||
// ...then check the new descriptors already seen.
|
||||
if dimHash, exists := newDimHashesByName[desc.fqName]; exists {
|
||||
if dimHash != desc.dimHash {
|
||||
return fmt.Errorf("descriptors reported by collector have inconsistent label names or help strings for the same fully-qualified name, offender is %s", desc)
|
||||
}
|
||||
} else {
|
||||
newDimHashesByName[desc.fqName] = desc.dimHash
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// ...then check the new descriptors already seen.
|
||||
if dimHash, exists := newDimHashesByName[desc.fqName]; exists {
|
||||
if dimHash != desc.dimHash {
|
||||
return fmt.Errorf("descriptors reported by collector have inconsistent label names or help strings for the same fully-qualified name, offender is %s", desc)
|
||||
}
|
||||
continue
|
||||
}
|
||||
newDimHashesByName[desc.fqName] = desc.dimHash
|
||||
}
|
||||
// A Collector yielding no Desc at all is considered unchecked.
|
||||
if len(newDescIDs) == 0 {
|
||||
|
||||
49
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
49
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
@@ -243,6 +243,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
||||
|
||||
s := &summary{
|
||||
desc: desc,
|
||||
now: opts.now,
|
||||
|
||||
objectives: opts.Objectives,
|
||||
sortedObjectives: make([]float64, 0, len(opts.Objectives)),
|
||||
@@ -280,6 +281,8 @@ type summary struct {
|
||||
|
||||
desc *Desc
|
||||
|
||||
now func() time.Time
|
||||
|
||||
objectives map[float64]float64
|
||||
sortedObjectives []float64
|
||||
|
||||
@@ -307,7 +310,7 @@ func (s *summary) Observe(v float64) {
|
||||
s.bufMtx.Lock()
|
||||
defer s.bufMtx.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
now := s.now()
|
||||
if now.After(s.hotBufExpTime) {
|
||||
s.asyncFlush(now)
|
||||
}
|
||||
@@ -326,7 +329,7 @@ func (s *summary) Write(out *dto.Metric) error {
|
||||
s.bufMtx.Lock()
|
||||
s.mtx.Lock()
|
||||
// Swap bufs even if hotBuf is empty to set new hotBufExpTime.
|
||||
s.swapBufs(time.Now())
|
||||
s.swapBufs(s.now())
|
||||
s.bufMtx.Unlock()
|
||||
|
||||
s.flushColdBuf()
|
||||
@@ -783,3 +786,45 @@ func MustNewConstSummary(
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// NewConstSummaryWithCreatedTimestamp does the same thing as NewConstSummary but sets the created timestamp.
|
||||
func NewConstSummaryWithCreatedTimestamp(
|
||||
desc *Desc,
|
||||
count uint64,
|
||||
sum float64,
|
||||
quantiles map[float64]float64,
|
||||
ct time.Time,
|
||||
labelValues ...string,
|
||||
) (Metric, error) {
|
||||
if desc.err != nil {
|
||||
return nil, desc.err
|
||||
}
|
||||
if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &constSummary{
|
||||
desc: desc,
|
||||
count: count,
|
||||
sum: sum,
|
||||
quantiles: quantiles,
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
createdTs: timestamppb.New(ct),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MustNewConstSummaryWithCreatedTimestamp is a version of NewConstSummaryWithCreatedTimestamp that panics where
|
||||
// NewConstSummaryWithCreatedTimestamp would have returned an error.
|
||||
func MustNewConstSummaryWithCreatedTimestamp(
|
||||
desc *Desc,
|
||||
count uint64,
|
||||
sum float64,
|
||||
quantiles map[float64]float64,
|
||||
ct time.Time,
|
||||
labelValues ...string,
|
||||
) Metric {
|
||||
m, err := NewConstSummaryWithCreatedTimestamp(desc, count, sum, quantiles, ct, labelValues...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
2
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
@@ -507,7 +507,7 @@ func (m *metricMap) getOrCreateMetricWithLabelValues(
|
||||
return metric
|
||||
}
|
||||
|
||||
// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
|
||||
// getOrCreateMetricWithLabels retrieves the metric by hash and label value
|
||||
// or creates it and returns the new one.
|
||||
//
|
||||
// This function holds the mutex.
|
||||
|
||||
14
vendor/github.com/prometheus/common/expfmt/decode.go
generated
vendored
14
vendor/github.com/prometheus/common/expfmt/decode.go
generated
vendored
@@ -45,7 +45,7 @@ func ResponseFormat(h http.Header) Format {
|
||||
|
||||
mediatype, params, err := mime.ParseMediaType(ct)
|
||||
if err != nil {
|
||||
return fmtUnknown
|
||||
return FmtUnknown
|
||||
}
|
||||
|
||||
const textType = "text/plain"
|
||||
@@ -53,21 +53,21 @@ func ResponseFormat(h http.Header) Format {
|
||||
switch mediatype {
|
||||
case ProtoType:
|
||||
if p, ok := params["proto"]; ok && p != ProtoProtocol {
|
||||
return fmtUnknown
|
||||
return FmtUnknown
|
||||
}
|
||||
if e, ok := params["encoding"]; ok && e != "delimited" {
|
||||
return fmtUnknown
|
||||
return FmtUnknown
|
||||
}
|
||||
return fmtProtoDelim
|
||||
return FmtProtoDelim
|
||||
|
||||
case textType:
|
||||
if v, ok := params["version"]; ok && v != TextVersion {
|
||||
return fmtUnknown
|
||||
return FmtUnknown
|
||||
}
|
||||
return fmtText
|
||||
return FmtText
|
||||
}
|
||||
|
||||
return fmtUnknown
|
||||
return FmtUnknown
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder based on the given input format.
|
||||
|
||||
28
vendor/github.com/prometheus/common/expfmt/encode.go
generated
vendored
28
vendor/github.com/prometheus/common/expfmt/encode.go
generated
vendored
@@ -68,7 +68,7 @@ func Negotiate(h http.Header) Format {
|
||||
if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" {
|
||||
switch Format(escapeParam) {
|
||||
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
|
||||
escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam))
|
||||
escapingScheme = Format("; escaping=" + escapeParam)
|
||||
default:
|
||||
// If the escaping parameter is unknown, ignore it.
|
||||
}
|
||||
@@ -77,18 +77,18 @@ func Negotiate(h http.Header) Format {
|
||||
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
|
||||
switch ac.Params["encoding"] {
|
||||
case "delimited":
|
||||
return fmtProtoDelim + escapingScheme
|
||||
return FmtProtoDelim + escapingScheme
|
||||
case "text":
|
||||
return fmtProtoText + escapingScheme
|
||||
return FmtProtoText + escapingScheme
|
||||
case "compact-text":
|
||||
return fmtProtoCompact + escapingScheme
|
||||
return FmtProtoCompact + escapingScheme
|
||||
}
|
||||
}
|
||||
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
|
||||
return fmtText + escapingScheme
|
||||
return FmtText + escapingScheme
|
||||
}
|
||||
}
|
||||
return fmtText + escapingScheme
|
||||
return FmtText + escapingScheme
|
||||
}
|
||||
|
||||
// NegotiateIncludingOpenMetrics works like Negotiate but includes
|
||||
@@ -101,7 +101,7 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
|
||||
if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" {
|
||||
switch Format(escapeParam) {
|
||||
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
|
||||
escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam))
|
||||
escapingScheme = Format("; escaping=" + escapeParam)
|
||||
default:
|
||||
// If the escaping parameter is unknown, ignore it.
|
||||
}
|
||||
@@ -110,26 +110,26 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
|
||||
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
|
||||
switch ac.Params["encoding"] {
|
||||
case "delimited":
|
||||
return fmtProtoDelim + escapingScheme
|
||||
return FmtProtoDelim + escapingScheme
|
||||
case "text":
|
||||
return fmtProtoText + escapingScheme
|
||||
return FmtProtoText + escapingScheme
|
||||
case "compact-text":
|
||||
return fmtProtoCompact + escapingScheme
|
||||
return FmtProtoCompact + escapingScheme
|
||||
}
|
||||
}
|
||||
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
|
||||
return fmtText + escapingScheme
|
||||
return FmtText + escapingScheme
|
||||
}
|
||||
if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") {
|
||||
switch ver {
|
||||
case OpenMetricsVersion_1_0_0:
|
||||
return fmtOpenMetrics_1_0_0 + escapingScheme
|
||||
return FmtOpenMetrics_1_0_0 + escapingScheme
|
||||
default:
|
||||
return fmtOpenMetrics_0_0_1 + escapingScheme
|
||||
return FmtOpenMetrics_0_0_1 + escapingScheme
|
||||
}
|
||||
}
|
||||
}
|
||||
return fmtText + escapingScheme
|
||||
return FmtText + escapingScheme
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder based on content type negotiation. All
|
||||
|
||||
78
vendor/github.com/prometheus/common/expfmt/expfmt.go
generated
vendored
78
vendor/github.com/prometheus/common/expfmt/expfmt.go
generated
vendored
@@ -15,7 +15,7 @@
|
||||
package expfmt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -32,24 +32,31 @@ type Format string
|
||||
// it on the wire, new content-type strings will have to be agreed upon and
|
||||
// added here.
|
||||
const (
|
||||
TextVersion = "0.0.4"
|
||||
ProtoType = `application/vnd.google.protobuf`
|
||||
ProtoProtocol = `io.prometheus.client.MetricFamily`
|
||||
protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
|
||||
TextVersion = "0.0.4"
|
||||
ProtoType = `application/vnd.google.protobuf`
|
||||
ProtoProtocol = `io.prometheus.client.MetricFamily`
|
||||
// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoCompact) instead.
|
||||
ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
|
||||
OpenMetricsType = `application/openmetrics-text`
|
||||
OpenMetricsVersion_0_0_1 = "0.0.1"
|
||||
OpenMetricsVersion_1_0_0 = "1.0.0"
|
||||
|
||||
// The Content-Type values for the different wire protocols. Note that these
|
||||
// values are now unexported. If code was relying on comparisons to these
|
||||
// constants, instead use FormatType().
|
||||
fmtUnknown Format = `<unknown>`
|
||||
fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
|
||||
fmtProtoDelim Format = protoFmt + ` encoding=delimited`
|
||||
fmtProtoText Format = protoFmt + ` encoding=text`
|
||||
fmtProtoCompact Format = protoFmt + ` encoding=compact-text`
|
||||
fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
|
||||
fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
|
||||
// The Content-Type values for the different wire protocols. Do not do direct
|
||||
// comparisons to these constants, instead use the comparison functions.
|
||||
// Deprecated: Use expfmt.NewFormat(expfmt.TypeUnknown) instead.
|
||||
FmtUnknown Format = `<unknown>`
|
||||
// Deprecated: Use expfmt.NewFormat(expfmt.TypeTextPlain) instead.
|
||||
FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
|
||||
// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoDelim) instead.
|
||||
FmtProtoDelim Format = ProtoFmt + ` encoding=delimited`
|
||||
// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoText) instead.
|
||||
FmtProtoText Format = ProtoFmt + ` encoding=text`
|
||||
// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoCompact) instead.
|
||||
FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
|
||||
// Deprecated: Use expfmt.NewFormat(expfmt.TypeOpenMetrics) instead.
|
||||
FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
|
||||
// Deprecated: Use expfmt.NewFormat(expfmt.TypeOpenMetrics) instead.
|
||||
FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -79,17 +86,17 @@ const (
|
||||
func NewFormat(t FormatType) Format {
|
||||
switch t {
|
||||
case TypeProtoCompact:
|
||||
return fmtProtoCompact
|
||||
return FmtProtoCompact
|
||||
case TypeProtoDelim:
|
||||
return fmtProtoDelim
|
||||
return FmtProtoDelim
|
||||
case TypeProtoText:
|
||||
return fmtProtoText
|
||||
return FmtProtoText
|
||||
case TypeTextPlain:
|
||||
return fmtText
|
||||
return FmtText
|
||||
case TypeOpenMetrics:
|
||||
return fmtOpenMetrics_1_0_0
|
||||
return FmtOpenMetrics_1_0_0
|
||||
default:
|
||||
return fmtUnknown
|
||||
return FmtUnknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,12 +104,35 @@ func NewFormat(t FormatType) Format {
|
||||
// specified version number.
|
||||
func NewOpenMetricsFormat(version string) (Format, error) {
|
||||
if version == OpenMetricsVersion_0_0_1 {
|
||||
return fmtOpenMetrics_0_0_1, nil
|
||||
return FmtOpenMetrics_0_0_1, nil
|
||||
}
|
||||
if version == OpenMetricsVersion_1_0_0 {
|
||||
return fmtOpenMetrics_1_0_0, nil
|
||||
return FmtOpenMetrics_1_0_0, nil
|
||||
}
|
||||
return fmtUnknown, fmt.Errorf("unknown open metrics version string")
|
||||
return FmtUnknown, errors.New("unknown open metrics version string")
|
||||
}
|
||||
|
||||
// WithEscapingScheme returns a copy of Format with the specified escaping
|
||||
// scheme appended to the end. If an escaping scheme already exists it is
|
||||
// removed.
|
||||
func (f Format) WithEscapingScheme(s model.EscapingScheme) Format {
|
||||
var terms []string
|
||||
for _, p := range strings.Split(string(f), ";") {
|
||||
toks := strings.Split(p, "=")
|
||||
if len(toks) != 2 {
|
||||
trimmed := strings.TrimSpace(p)
|
||||
if len(trimmed) > 0 {
|
||||
terms = append(terms, trimmed)
|
||||
}
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(toks[0])
|
||||
if key != model.EscapingKey {
|
||||
terms = append(terms, strings.TrimSpace(p))
|
||||
}
|
||||
}
|
||||
terms = append(terms, model.EscapingKey+"="+s.String())
|
||||
return Format(strings.Join(terms, "; "))
|
||||
}
|
||||
|
||||
// FormatType deduces an overall FormatType for the given format.
|
||||
|
||||
10
vendor/github.com/prometheus/common/expfmt/openmetrics_create.go
generated
vendored
10
vendor/github.com/prometheus/common/expfmt/openmetrics_create.go
generated
vendored
@@ -38,7 +38,7 @@ type EncoderOption func(*encoderOption)
|
||||
|
||||
// WithCreatedLines is an EncoderOption that configures the OpenMetrics encoder
|
||||
// to include _created lines (See
|
||||
// https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#counter-1).
|
||||
// https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#counter-1).
|
||||
// Created timestamps can improve the accuracy of series reset detection, but
|
||||
// come with a bandwidth cost.
|
||||
//
|
||||
@@ -102,7 +102,7 @@ func WithUnit() EncoderOption {
|
||||
//
|
||||
// - According to the OM specs, the `# UNIT` line is optional, but if populated,
|
||||
// the unit has to be present in the metric name as its suffix:
|
||||
// (see https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#unit).
|
||||
// (see https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#unit).
|
||||
// However, in order to accommodate any potential scenario where such a change in the
|
||||
// metric name is not desirable, the users are here given the choice of either explicitly
|
||||
// opt in, in case they wish for the unit to be included in the output AND in the metric name
|
||||
@@ -152,8 +152,8 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
|
||||
if metricType == dto.MetricType_COUNTER && strings.HasSuffix(compliantName, "_total") {
|
||||
compliantName = name[:len(name)-6]
|
||||
}
|
||||
if toOM.withUnit && in.Unit != nil && !strings.HasSuffix(compliantName, fmt.Sprintf("_%s", *in.Unit)) {
|
||||
compliantName = compliantName + fmt.Sprintf("_%s", *in.Unit)
|
||||
if toOM.withUnit && in.Unit != nil && !strings.HasSuffix(compliantName, "_"+*in.Unit) {
|
||||
compliantName = compliantName + "_" + *in.Unit
|
||||
}
|
||||
|
||||
// Comments, first HELP, then TYPE.
|
||||
@@ -477,7 +477,7 @@ func writeOpenMetricsNameAndLabelPairs(
|
||||
if name != "" {
|
||||
// If the name does not pass the legacy validity check, we must put the
|
||||
// metric name inside the braces, quoted.
|
||||
if !model.IsValidLegacyMetricName(model.LabelValue(name)) {
|
||||
if !model.IsValidLegacyMetricName(name) {
|
||||
metricInsideBraces = true
|
||||
err := w.WriteByte(separator)
|
||||
written++
|
||||
|
||||
4
vendor/github.com/prometheus/common/expfmt/text_create.go
generated
vendored
4
vendor/github.com/prometheus/common/expfmt/text_create.go
generated
vendored
@@ -354,7 +354,7 @@ func writeNameAndLabelPairs(
|
||||
if name != "" {
|
||||
// If the name does not pass the legacy validity check, we must put the
|
||||
// metric name inside the braces.
|
||||
if !model.IsValidLegacyMetricName(model.LabelValue(name)) {
|
||||
if !model.IsValidLegacyMetricName(name) {
|
||||
metricInsideBraces = true
|
||||
err := w.WriteByte(separator)
|
||||
written++
|
||||
@@ -498,7 +498,7 @@ func writeInt(w enhancedWriter, i int64) (int, error) {
|
||||
// writeName writes a string as-is if it complies with the legacy naming
|
||||
// scheme, or escapes it in double quotes if not.
|
||||
func writeName(w enhancedWriter, name string) (int, error) {
|
||||
if model.IsValidLegacyMetricName(model.LabelValue(name)) {
|
||||
if model.IsValidLegacyMetricName(name) {
|
||||
return w.WriteString(name)
|
||||
}
|
||||
var written int
|
||||
|
||||
164
vendor/github.com/prometheus/common/expfmt/text_parse.go
generated
vendored
164
vendor/github.com/prometheus/common/expfmt/text_parse.go
generated
vendored
@@ -22,9 +22,9 @@ import (
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -60,6 +60,7 @@ type TextParser struct {
|
||||
currentMF *dto.MetricFamily
|
||||
currentMetric *dto.Metric
|
||||
currentLabelPair *dto.LabelPair
|
||||
currentLabelPairs []*dto.LabelPair // Temporarily stores label pairs while parsing a metric line.
|
||||
|
||||
// The remaining member variables are only used for summaries/histograms.
|
||||
currentLabels map[string]string // All labels including '__name__' but excluding 'quantile'/'le'
|
||||
@@ -74,6 +75,9 @@ type TextParser struct {
|
||||
// count and sum of that summary/histogram.
|
||||
currentIsSummaryCount, currentIsSummarySum bool
|
||||
currentIsHistogramCount, currentIsHistogramSum bool
|
||||
// These indicate if the metric name from the current line being parsed is inside
|
||||
// braces and if that metric name was found respectively.
|
||||
currentMetricIsInsideBraces, currentMetricInsideBracesIsPresent bool
|
||||
}
|
||||
|
||||
// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange
|
||||
@@ -137,12 +141,15 @@ func (p *TextParser) reset(in io.Reader) {
|
||||
}
|
||||
p.currentQuantile = math.NaN()
|
||||
p.currentBucket = math.NaN()
|
||||
p.currentMF = nil
|
||||
}
|
||||
|
||||
// startOfLine represents the state where the next byte read from p.buf is the
|
||||
// start of a line (or whitespace leading up to it).
|
||||
func (p *TextParser) startOfLine() stateFn {
|
||||
p.lineCount++
|
||||
p.currentMetricIsInsideBraces = false
|
||||
p.currentMetricInsideBracesIsPresent = false
|
||||
if p.skipBlankTab(); p.err != nil {
|
||||
// This is the only place that we expect to see io.EOF,
|
||||
// which is not an error but the signal that we are done.
|
||||
@@ -158,6 +165,9 @@ func (p *TextParser) startOfLine() stateFn {
|
||||
return p.startComment
|
||||
case '\n':
|
||||
return p.startOfLine // Empty line, start the next one.
|
||||
case '{':
|
||||
p.currentMetricIsInsideBraces = true
|
||||
return p.readingLabels
|
||||
}
|
||||
return p.readingMetricName
|
||||
}
|
||||
@@ -275,6 +285,8 @@ func (p *TextParser) startLabelName() stateFn {
|
||||
return nil // Unexpected end of input.
|
||||
}
|
||||
if p.currentByte == '}' {
|
||||
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...)
|
||||
p.currentLabelPairs = nil
|
||||
if p.skipBlankTab(); p.err != nil {
|
||||
return nil // Unexpected end of input.
|
||||
}
|
||||
@@ -287,6 +299,45 @@ func (p *TextParser) startLabelName() stateFn {
|
||||
p.parseError(fmt.Sprintf("invalid label name for metric %q", p.currentMF.GetName()))
|
||||
return nil
|
||||
}
|
||||
if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
|
||||
return nil // Unexpected end of input.
|
||||
}
|
||||
if p.currentByte != '=' {
|
||||
if p.currentMetricIsInsideBraces {
|
||||
if p.currentMetricInsideBracesIsPresent {
|
||||
p.parseError(fmt.Sprintf("multiple metric names for metric %q", p.currentMF.GetName()))
|
||||
return nil
|
||||
}
|
||||
switch p.currentByte {
|
||||
case ',':
|
||||
p.setOrCreateCurrentMF()
|
||||
if p.currentMF.Type == nil {
|
||||
p.currentMF.Type = dto.MetricType_UNTYPED.Enum()
|
||||
}
|
||||
p.currentMetric = &dto.Metric{}
|
||||
p.currentMetricInsideBracesIsPresent = true
|
||||
return p.startLabelName
|
||||
case '}':
|
||||
p.setOrCreateCurrentMF()
|
||||
if p.currentMF.Type == nil {
|
||||
p.currentMF.Type = dto.MetricType_UNTYPED.Enum()
|
||||
}
|
||||
p.currentMetric = &dto.Metric{}
|
||||
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...)
|
||||
p.currentLabelPairs = nil
|
||||
if p.skipBlankTab(); p.err != nil {
|
||||
return nil // Unexpected end of input.
|
||||
}
|
||||
return p.readingValue
|
||||
default:
|
||||
p.parseError(fmt.Sprintf("unexpected end of metric name %q", p.currentByte))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
|
||||
p.currentLabelPairs = nil
|
||||
return nil
|
||||
}
|
||||
p.currentLabelPair = &dto.LabelPair{Name: proto.String(p.currentToken.String())}
|
||||
if p.currentLabelPair.GetName() == string(model.MetricNameLabel) {
|
||||
p.parseError(fmt.Sprintf("label name %q is reserved", model.MetricNameLabel))
|
||||
@@ -296,23 +347,17 @@ func (p *TextParser) startLabelName() stateFn {
|
||||
// labels to 'real' labels.
|
||||
if !(p.currentMF.GetType() == dto.MetricType_SUMMARY && p.currentLabelPair.GetName() == model.QuantileLabel) &&
|
||||
!(p.currentMF.GetType() == dto.MetricType_HISTOGRAM && p.currentLabelPair.GetName() == model.BucketLabel) {
|
||||
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPair)
|
||||
}
|
||||
if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
|
||||
return nil // Unexpected end of input.
|
||||
}
|
||||
if p.currentByte != '=' {
|
||||
p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
|
||||
return nil
|
||||
p.currentLabelPairs = append(p.currentLabelPairs, p.currentLabelPair)
|
||||
}
|
||||
// Check for duplicate label names.
|
||||
labels := make(map[string]struct{})
|
||||
for _, l := range p.currentMetric.Label {
|
||||
for _, l := range p.currentLabelPairs {
|
||||
lName := l.GetName()
|
||||
if _, exists := labels[lName]; !exists {
|
||||
labels[lName] = struct{}{}
|
||||
} else {
|
||||
p.parseError(fmt.Sprintf("duplicate label names for metric %q", p.currentMF.GetName()))
|
||||
p.currentLabelPairs = nil
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -345,6 +390,7 @@ func (p *TextParser) startLabelValue() stateFn {
|
||||
if p.currentQuantile, p.err = parseFloat(p.currentLabelPair.GetValue()); p.err != nil {
|
||||
// Create a more helpful error message.
|
||||
p.parseError(fmt.Sprintf("expected float as value for 'quantile' label, got %q", p.currentLabelPair.GetValue()))
|
||||
p.currentLabelPairs = nil
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
@@ -371,12 +417,19 @@ func (p *TextParser) startLabelValue() stateFn {
|
||||
return p.startLabelName
|
||||
|
||||
case '}':
|
||||
if p.currentMF == nil {
|
||||
p.parseError("invalid metric name")
|
||||
return nil
|
||||
}
|
||||
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...)
|
||||
p.currentLabelPairs = nil
|
||||
if p.skipBlankTab(); p.err != nil {
|
||||
return nil // Unexpected end of input.
|
||||
}
|
||||
return p.readingValue
|
||||
default:
|
||||
p.parseError(fmt.Sprintf("unexpected end of label value %q", p.currentLabelPair.GetValue()))
|
||||
p.currentLabelPairs = nil
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -585,6 +638,8 @@ func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) {
|
||||
p.currentToken.WriteByte(p.currentByte)
|
||||
case 'n':
|
||||
p.currentToken.WriteByte('\n')
|
||||
case '"':
|
||||
p.currentToken.WriteByte('"')
|
||||
default:
|
||||
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
|
||||
return
|
||||
@@ -610,13 +665,45 @@ func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) {
|
||||
// but not into p.currentToken.
|
||||
func (p *TextParser) readTokenAsMetricName() {
|
||||
p.currentToken.Reset()
|
||||
// A UTF-8 metric name must be quoted and may have escaped characters.
|
||||
quoted := false
|
||||
escaped := false
|
||||
if !isValidMetricNameStart(p.currentByte) {
|
||||
return
|
||||
}
|
||||
for {
|
||||
p.currentToken.WriteByte(p.currentByte)
|
||||
for p.err == nil {
|
||||
if escaped {
|
||||
switch p.currentByte {
|
||||
case '\\':
|
||||
p.currentToken.WriteByte(p.currentByte)
|
||||
case 'n':
|
||||
p.currentToken.WriteByte('\n')
|
||||
case '"':
|
||||
p.currentToken.WriteByte('"')
|
||||
default:
|
||||
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
|
||||
return
|
||||
}
|
||||
escaped = false
|
||||
} else {
|
||||
switch p.currentByte {
|
||||
case '"':
|
||||
quoted = !quoted
|
||||
if !quoted {
|
||||
p.currentByte, p.err = p.buf.ReadByte()
|
||||
return
|
||||
}
|
||||
case '\n':
|
||||
p.parseError(fmt.Sprintf("metric name %q contains unescaped new-line", p.currentToken.String()))
|
||||
return
|
||||
case '\\':
|
||||
escaped = true
|
||||
default:
|
||||
p.currentToken.WriteByte(p.currentByte)
|
||||
}
|
||||
}
|
||||
p.currentByte, p.err = p.buf.ReadByte()
|
||||
if p.err != nil || !isValidMetricNameContinuation(p.currentByte) {
|
||||
if !isValidMetricNameContinuation(p.currentByte, quoted) || (!quoted && p.currentByte == ' ') {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -628,13 +715,45 @@ func (p *TextParser) readTokenAsMetricName() {
|
||||
// but not into p.currentToken.
|
||||
func (p *TextParser) readTokenAsLabelName() {
|
||||
p.currentToken.Reset()
|
||||
// A UTF-8 label name must be quoted and may have escaped characters.
|
||||
quoted := false
|
||||
escaped := false
|
||||
if !isValidLabelNameStart(p.currentByte) {
|
||||
return
|
||||
}
|
||||
for {
|
||||
p.currentToken.WriteByte(p.currentByte)
|
||||
for p.err == nil {
|
||||
if escaped {
|
||||
switch p.currentByte {
|
||||
case '\\':
|
||||
p.currentToken.WriteByte(p.currentByte)
|
||||
case 'n':
|
||||
p.currentToken.WriteByte('\n')
|
||||
case '"':
|
||||
p.currentToken.WriteByte('"')
|
||||
default:
|
||||
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
|
||||
return
|
||||
}
|
||||
escaped = false
|
||||
} else {
|
||||
switch p.currentByte {
|
||||
case '"':
|
||||
quoted = !quoted
|
||||
if !quoted {
|
||||
p.currentByte, p.err = p.buf.ReadByte()
|
||||
return
|
||||
}
|
||||
case '\n':
|
||||
p.parseError(fmt.Sprintf("label name %q contains unescaped new-line", p.currentToken.String()))
|
||||
return
|
||||
case '\\':
|
||||
escaped = true
|
||||
default:
|
||||
p.currentToken.WriteByte(p.currentByte)
|
||||
}
|
||||
}
|
||||
p.currentByte, p.err = p.buf.ReadByte()
|
||||
if p.err != nil || !isValidLabelNameContinuation(p.currentByte) {
|
||||
if !isValidLabelNameContinuation(p.currentByte, quoted) || (!quoted && p.currentByte == '=') {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -660,6 +779,7 @@ func (p *TextParser) readTokenAsLabelValue() {
|
||||
p.currentToken.WriteByte('\n')
|
||||
default:
|
||||
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
|
||||
p.currentLabelPairs = nil
|
||||
return
|
||||
}
|
||||
escaped = false
|
||||
@@ -718,19 +838,19 @@ func (p *TextParser) setOrCreateCurrentMF() {
|
||||
}
|
||||
|
||||
func isValidLabelNameStart(b byte) bool {
|
||||
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_'
|
||||
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == '"'
|
||||
}
|
||||
|
||||
func isValidLabelNameContinuation(b byte) bool {
|
||||
return isValidLabelNameStart(b) || (b >= '0' && b <= '9')
|
||||
func isValidLabelNameContinuation(b byte, quoted bool) bool {
|
||||
return isValidLabelNameStart(b) || (b >= '0' && b <= '9') || (quoted && utf8.ValidString(string(b)))
|
||||
}
|
||||
|
||||
func isValidMetricNameStart(b byte) bool {
|
||||
return isValidLabelNameStart(b) || b == ':'
|
||||
}
|
||||
|
||||
func isValidMetricNameContinuation(b byte) bool {
|
||||
return isValidLabelNameContinuation(b) || b == ':'
|
||||
func isValidMetricNameContinuation(b byte, quoted bool) bool {
|
||||
return isValidLabelNameContinuation(b, quoted) || b == ':'
|
||||
}
|
||||
|
||||
func isBlankOrTab(b byte) bool {
|
||||
@@ -775,7 +895,7 @@ func histogramMetricName(name string) string {
|
||||
|
||||
func parseFloat(s string) (float64, error) {
|
||||
if strings.ContainsAny(s, "pP_") {
|
||||
return 0, fmt.Errorf("unsupported character in float")
|
||||
return 0, errors.New("unsupported character in float")
|
||||
}
|
||||
return strconv.ParseFloat(s, 64)
|
||||
}
|
||||
|
||||
9
vendor/github.com/prometheus/common/model/alert.go
generated
vendored
9
vendor/github.com/prometheus/common/model/alert.go
generated
vendored
@@ -14,6 +14,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
@@ -64,7 +65,7 @@ func (a *Alert) Resolved() bool {
|
||||
return a.ResolvedAt(time.Now())
|
||||
}
|
||||
|
||||
// ResolvedAt returns true off the activity interval ended before
|
||||
// ResolvedAt returns true iff the activity interval ended before
|
||||
// the given timestamp.
|
||||
func (a *Alert) ResolvedAt(ts time.Time) bool {
|
||||
if a.EndsAt.IsZero() {
|
||||
@@ -89,16 +90,16 @@ func (a *Alert) StatusAt(ts time.Time) AlertStatus {
|
||||
// Validate checks whether the alert data is inconsistent.
|
||||
func (a *Alert) Validate() error {
|
||||
if a.StartsAt.IsZero() {
|
||||
return fmt.Errorf("start time missing")
|
||||
return errors.New("start time missing")
|
||||
}
|
||||
if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) {
|
||||
return fmt.Errorf("start time must be before end time")
|
||||
return errors.New("start time must be before end time")
|
||||
}
|
||||
if err := a.Labels.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid label set: %w", err)
|
||||
}
|
||||
if len(a.Labels) == 0 {
|
||||
return fmt.Errorf("at least one label pair required")
|
||||
return errors.New("at least one label pair required")
|
||||
}
|
||||
if err := a.Annotations.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid annotations: %w", err)
|
||||
|
||||
29
vendor/github.com/prometheus/common/model/labels.go
generated
vendored
29
vendor/github.com/prometheus/common/model/labels.go
generated
vendored
@@ -22,7 +22,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// AlertNameLabel is the name of the label containing the an alert's name.
|
||||
// AlertNameLabel is the name of the label containing the alert's name.
|
||||
AlertNameLabel = "alertname"
|
||||
|
||||
// ExportedLabelPrefix is the prefix to prepend to the label names present in
|
||||
@@ -97,26 +97,35 @@ var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
|
||||
// therewith.
|
||||
type LabelName string
|
||||
|
||||
// IsValid returns true iff name matches the pattern of LabelNameRE for legacy
|
||||
// names, and iff it's valid UTF-8 if NameValidationScheme is set to
|
||||
// UTF8Validation. For the legacy matching, it does not use LabelNameRE for the
|
||||
// check but a much faster hardcoded implementation.
|
||||
// IsValid returns true iff the name matches the pattern of LabelNameRE when
|
||||
// NameValidationScheme is set to LegacyValidation, or valid UTF-8 if
|
||||
// NameValidationScheme is set to UTF8Validation.
|
||||
func (ln LabelName) IsValid() bool {
|
||||
if len(ln) == 0 {
|
||||
return false
|
||||
}
|
||||
switch NameValidationScheme {
|
||||
case LegacyValidation:
|
||||
for i, b := range ln {
|
||||
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return ln.IsValidLegacy()
|
||||
case UTF8Validation:
|
||||
return utf8.ValidString(string(ln))
|
||||
default:
|
||||
panic(fmt.Sprintf("Invalid name validation scheme requested: %d", NameValidationScheme))
|
||||
}
|
||||
}
|
||||
|
||||
// IsValidLegacy returns true iff name matches the pattern of LabelNameRE for
|
||||
// legacy names. It does not use LabelNameRE for the check but a much faster
|
||||
// hardcoded implementation.
|
||||
func (ln LabelName) IsValidLegacy() bool {
|
||||
if len(ln) == 0 {
|
||||
return false
|
||||
}
|
||||
for i, b := range ln {
|
||||
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/prometheus/common/model/labelset_string.go
generated
vendored
2
vendor/github.com/prometheus/common/model/labelset_string.go
generated
vendored
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build go1.21
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
|
||||
39
vendor/github.com/prometheus/common/model/labelset_string_go120.go
generated
vendored
39
vendor/github.com/prometheus/common/model/labelset_string_go120.go
generated
vendored
@@ -1,39 +0,0 @@
|
||||
// Copyright 2024 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.
|
||||
|
||||
//go:build !go1.21
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// String was optimized using functions not available for go 1.20
|
||||
// or lower. We keep the old implementation for compatibility with client_golang.
|
||||
// Once client golang drops support for go 1.20 (scheduled for August 2024), this
|
||||
// file can be removed.
|
||||
func (l LabelSet) String() string {
|
||||
labelNames := make([]string, 0, len(l))
|
||||
for name := range l {
|
||||
labelNames = append(labelNames, string(name))
|
||||
}
|
||||
sort.Strings(labelNames)
|
||||
lstrs := make([]string, 0, len(l))
|
||||
for _, name := range labelNames {
|
||||
lstrs = append(lstrs, fmt.Sprintf("%s=%q", name, l[LabelName(name)]))
|
||||
}
|
||||
return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
|
||||
}
|
||||
92
vendor/github.com/prometheus/common/model/metric.go
generated
vendored
92
vendor/github.com/prometheus/common/model/metric.go
generated
vendored
@@ -14,9 +14,11 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -25,19 +27,34 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// NameValidationScheme determines the method of name validation to be used by
|
||||
// all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 mode
|
||||
// in isolation from other components that don't support UTF-8 may result in
|
||||
// bugs or other undefined behavior. This value is intended to be set by
|
||||
// UTF-8-aware binaries as part of their startup. To avoid need for locking,
|
||||
// this value should be set once, ideally in an init(), before multiple
|
||||
// goroutines are started.
|
||||
NameValidationScheme = LegacyValidation
|
||||
// NameValidationScheme determines the global default method of the name
|
||||
// validation to be used by all calls to IsValidMetricName() and LabelName
|
||||
// IsValid().
|
||||
//
|
||||
// Deprecated: This variable should not be used and might be removed in the
|
||||
// far future. If you wish to stick to the legacy name validation use
|
||||
// `IsValidLegacyMetricName()` and `LabelName.IsValidLegacy()` methods
|
||||
// instead. This variable is here as an escape hatch for emergency cases,
|
||||
// given the recent change from `LegacyValidation` to `UTF8Validation`, e.g.,
|
||||
// to delay UTF-8 migrations in time or aid in debugging unforeseen results of
|
||||
// the change. In such a case, a temporary assignment to `LegacyValidation`
|
||||
// value in the `init()` function in your main.go or so, could be considered.
|
||||
//
|
||||
// Historically we opted for a global variable for feature gating different
|
||||
// validation schemes in operations that were not otherwise easily adjustable
|
||||
// (e.g. Labels yaml unmarshaling). That could have been a mistake, a separate
|
||||
// Labels structure or package might have been a better choice. Given the
|
||||
// change was made and many upgraded the common already, we live this as-is
|
||||
// with this warning and learning for the future.
|
||||
NameValidationScheme = UTF8Validation
|
||||
|
||||
// NameEscapingScheme defines the default way that names will be
|
||||
// escaped when presented to systems that do not support UTF-8 names. If the
|
||||
// Content-Type "escaping" term is specified, that will override this value.
|
||||
NameEscapingScheme = ValueEncodingEscaping
|
||||
// NameEscapingScheme defines the default way that names will be escaped when
|
||||
// presented to systems that do not support UTF-8 names. If the Content-Type
|
||||
// "escaping" term is specified, that will override this value.
|
||||
// NameEscapingScheme should not be set to the NoEscaping value. That string
|
||||
// is used in content negotiation to indicate that a system supports UTF-8 and
|
||||
// has that feature enabled.
|
||||
NameEscapingScheme = UnderscoreEscaping
|
||||
)
|
||||
|
||||
// ValidationScheme is a Go enum for determining how metric and label names will
|
||||
@@ -45,7 +62,7 @@ var (
|
||||
type ValidationScheme int
|
||||
|
||||
const (
|
||||
// LegacyValidation is a setting that requirets that metric and label names
|
||||
// LegacyValidation is a setting that requires that all metric and label names
|
||||
// conform to the original Prometheus character requirements described by
|
||||
// MetricNameRE and LabelNameRE.
|
||||
LegacyValidation ValidationScheme = iota
|
||||
@@ -161,7 +178,7 @@ func (m Metric) FastFingerprint() Fingerprint {
|
||||
func IsValidMetricName(n LabelValue) bool {
|
||||
switch NameValidationScheme {
|
||||
case LegacyValidation:
|
||||
return IsValidLegacyMetricName(n)
|
||||
return IsValidLegacyMetricName(string(n))
|
||||
case UTF8Validation:
|
||||
if len(n) == 0 {
|
||||
return false
|
||||
@@ -176,7 +193,7 @@ func IsValidMetricName(n LabelValue) bool {
|
||||
// legacy validation scheme regardless of the value of NameValidationScheme.
|
||||
// This function, however, does not use MetricNameRE for the check but a much
|
||||
// faster hardcoded implementation.
|
||||
func IsValidLegacyMetricName(n LabelValue) bool {
|
||||
func IsValidLegacyMetricName(n string) bool {
|
||||
if len(n) == 0 {
|
||||
return false
|
||||
}
|
||||
@@ -208,7 +225,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF
|
||||
}
|
||||
|
||||
// If the name is nil, copy as-is, don't try to escape.
|
||||
if v.Name == nil || IsValidLegacyMetricName(LabelValue(v.GetName())) {
|
||||
if v.Name == nil || IsValidLegacyMetricName(v.GetName()) {
|
||||
out.Name = v.Name
|
||||
} else {
|
||||
out.Name = proto.String(EscapeName(v.GetName(), scheme))
|
||||
@@ -230,7 +247,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF
|
||||
|
||||
for _, l := range m.Label {
|
||||
if l.GetName() == MetricNameLabel {
|
||||
if l.Value == nil || IsValidLegacyMetricName(LabelValue(l.GetValue())) {
|
||||
if l.Value == nil || IsValidLegacyMetricName(l.GetValue()) {
|
||||
escaped.Label = append(escaped.Label, l)
|
||||
continue
|
||||
}
|
||||
@@ -240,7 +257,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF
|
||||
})
|
||||
continue
|
||||
}
|
||||
if l.Name == nil || IsValidLegacyMetricName(LabelValue(l.GetName())) {
|
||||
if l.Name == nil || IsValidLegacyMetricName(l.GetName()) {
|
||||
escaped.Label = append(escaped.Label, l)
|
||||
continue
|
||||
}
|
||||
@@ -256,20 +273,16 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF
|
||||
|
||||
func metricNeedsEscaping(m *dto.Metric) bool {
|
||||
for _, l := range m.Label {
|
||||
if l.GetName() == MetricNameLabel && !IsValidLegacyMetricName(LabelValue(l.GetValue())) {
|
||||
if l.GetName() == MetricNameLabel && !IsValidLegacyMetricName(l.GetValue()) {
|
||||
return true
|
||||
}
|
||||
if !IsValidLegacyMetricName(LabelValue(l.GetName())) {
|
||||
if !IsValidLegacyMetricName(l.GetName()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
lowerhex = "0123456789abcdef"
|
||||
)
|
||||
|
||||
// EscapeName escapes the incoming name according to the provided escaping
|
||||
// scheme. Depending on the rules of escaping, this may cause no change in the
|
||||
// string that is returned. (Especially NoEscaping, which by definition is a
|
||||
@@ -283,7 +296,7 @@ func EscapeName(name string, scheme EscapingScheme) string {
|
||||
case NoEscaping:
|
||||
return name
|
||||
case UnderscoreEscaping:
|
||||
if IsValidLegacyMetricName(LabelValue(name)) {
|
||||
if IsValidLegacyMetricName(name) {
|
||||
return name
|
||||
}
|
||||
for i, b := range name {
|
||||
@@ -304,31 +317,25 @@ func EscapeName(name string, scheme EscapingScheme) string {
|
||||
} else if isValidLegacyRune(b, i) {
|
||||
escaped.WriteRune(b)
|
||||
} else {
|
||||
escaped.WriteRune('_')
|
||||
escaped.WriteString("__")
|
||||
}
|
||||
}
|
||||
return escaped.String()
|
||||
case ValueEncodingEscaping:
|
||||
if IsValidLegacyMetricName(LabelValue(name)) {
|
||||
if IsValidLegacyMetricName(name) {
|
||||
return name
|
||||
}
|
||||
escaped.WriteString("U__")
|
||||
for i, b := range name {
|
||||
if isValidLegacyRune(b, i) {
|
||||
if b == '_' {
|
||||
escaped.WriteString("__")
|
||||
} else if isValidLegacyRune(b, i) {
|
||||
escaped.WriteRune(b)
|
||||
} else if !utf8.ValidRune(b) {
|
||||
escaped.WriteString("_FFFD_")
|
||||
} else if b < 0x100 {
|
||||
} else {
|
||||
escaped.WriteRune('_')
|
||||
for s := 4; s >= 0; s -= 4 {
|
||||
escaped.WriteByte(lowerhex[b>>uint(s)&0xF])
|
||||
}
|
||||
escaped.WriteRune('_')
|
||||
} else if b < 0x10000 {
|
||||
escaped.WriteRune('_')
|
||||
for s := 12; s >= 0; s -= 4 {
|
||||
escaped.WriteByte(lowerhex[b>>uint(s)&0xF])
|
||||
}
|
||||
escaped.WriteString(strconv.FormatInt(int64(b), 16))
|
||||
escaped.WriteRune('_')
|
||||
}
|
||||
}
|
||||
@@ -386,8 +393,9 @@ func UnescapeName(name string, scheme EscapingScheme) string {
|
||||
// We think we are in a UTF-8 code, process it.
|
||||
var utf8Val uint
|
||||
for j := 0; i < len(escapedName); j++ {
|
||||
// This is too many characters for a utf8 value.
|
||||
if j > 4 {
|
||||
// This is too many characters for a utf8 value based on the MaxRune
|
||||
// value of '\U0010FFFF'.
|
||||
if j >= 6 {
|
||||
return name
|
||||
}
|
||||
// Found a closing underscore, convert to a rune, check validity, and append.
|
||||
@@ -440,7 +448,7 @@ func (e EscapingScheme) String() string {
|
||||
|
||||
func ToEscapingScheme(s string) (EscapingScheme, error) {
|
||||
if s == "" {
|
||||
return NoEscaping, fmt.Errorf("got empty string instead of escaping scheme")
|
||||
return NoEscaping, errors.New("got empty string instead of escaping scheme")
|
||||
}
|
||||
switch s {
|
||||
case AllowUTF8:
|
||||
@@ -452,6 +460,6 @@ func ToEscapingScheme(s string) (EscapingScheme, error) {
|
||||
case EscapeValues:
|
||||
return ValueEncodingEscaping, nil
|
||||
default:
|
||||
return NoEscaping, fmt.Errorf("unknown format scheme " + s)
|
||||
return NoEscaping, fmt.Errorf("unknown format scheme %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
17
vendor/github.com/prometheus/common/model/silence.go
generated
vendored
17
vendor/github.com/prometheus/common/model/silence.go
generated
vendored
@@ -15,6 +15,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
@@ -34,7 +35,7 @@ func (m *Matcher) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
if len(m.Name) == 0 {
|
||||
return fmt.Errorf("label name in matcher must not be empty")
|
||||
return errors.New("label name in matcher must not be empty")
|
||||
}
|
||||
if m.IsRegex {
|
||||
if _, err := regexp.Compile(m.Value); err != nil {
|
||||
@@ -77,7 +78,7 @@ type Silence struct {
|
||||
// Validate returns true iff all fields of the silence have valid values.
|
||||
func (s *Silence) Validate() error {
|
||||
if len(s.Matchers) == 0 {
|
||||
return fmt.Errorf("at least one matcher required")
|
||||
return errors.New("at least one matcher required")
|
||||
}
|
||||
for _, m := range s.Matchers {
|
||||
if err := m.Validate(); err != nil {
|
||||
@@ -85,22 +86,22 @@ func (s *Silence) Validate() error {
|
||||
}
|
||||
}
|
||||
if s.StartsAt.IsZero() {
|
||||
return fmt.Errorf("start time missing")
|
||||
return errors.New("start time missing")
|
||||
}
|
||||
if s.EndsAt.IsZero() {
|
||||
return fmt.Errorf("end time missing")
|
||||
return errors.New("end time missing")
|
||||
}
|
||||
if s.EndsAt.Before(s.StartsAt) {
|
||||
return fmt.Errorf("start time must be before end time")
|
||||
return errors.New("start time must be before end time")
|
||||
}
|
||||
if s.CreatedBy == "" {
|
||||
return fmt.Errorf("creator information missing")
|
||||
return errors.New("creator information missing")
|
||||
}
|
||||
if s.Comment == "" {
|
||||
return fmt.Errorf("comment missing")
|
||||
return errors.New("comment missing")
|
||||
}
|
||||
if s.CreatedAt.IsZero() {
|
||||
return fmt.Errorf("creation timestamp missing")
|
||||
return errors.New("creation timestamp missing")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
3
vendor/github.com/prometheus/common/model/value_float.go
generated
vendored
3
vendor/github.com/prometheus/common/model/value_float.go
generated
vendored
@@ -15,6 +15,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
@@ -39,7 +40,7 @@ func (v SampleValue) MarshalJSON() ([]byte, error) {
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (v *SampleValue) UnmarshalJSON(b []byte) error {
|
||||
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
|
||||
return fmt.Errorf("sample value must be a quoted string")
|
||||
return errors.New("sample value must be a quoted string")
|
||||
}
|
||||
f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
|
||||
if err != nil {
|
||||
|
||||
7
vendor/github.com/prometheus/common/model/value_histogram.go
generated
vendored
7
vendor/github.com/prometheus/common/model/value_histogram.go
generated
vendored
@@ -15,6 +15,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -32,7 +33,7 @@ func (v FloatString) MarshalJSON() ([]byte, error) {
|
||||
|
||||
func (v *FloatString) UnmarshalJSON(b []byte) error {
|
||||
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
|
||||
return fmt.Errorf("float value must be a quoted string")
|
||||
return errors.New("float value must be a quoted string")
|
||||
}
|
||||
f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
|
||||
if err != nil {
|
||||
@@ -141,7 +142,7 @@ type SampleHistogramPair struct {
|
||||
|
||||
func (s SampleHistogramPair) MarshalJSON() ([]byte, error) {
|
||||
if s.Histogram == nil {
|
||||
return nil, fmt.Errorf("histogram is nil")
|
||||
return nil, errors.New("histogram is nil")
|
||||
}
|
||||
t, err := json.Marshal(s.Timestamp)
|
||||
if err != nil {
|
||||
@@ -164,7 +165,7 @@ func (s *SampleHistogramPair) UnmarshalJSON(buf []byte) error {
|
||||
return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen)
|
||||
}
|
||||
if s.Histogram == nil {
|
||||
return fmt.Errorf("histogram is null")
|
||||
return errors.New("histogram is null")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
11
vendor/github.com/prometheus/procfs/.golangci.yml
generated
vendored
11
vendor/github.com/prometheus/procfs/.golangci.yml
generated
vendored
@@ -2,7 +2,10 @@
|
||||
linters:
|
||||
enable:
|
||||
- errcheck
|
||||
- forbidigo
|
||||
- godot
|
||||
- gofmt
|
||||
- goimports
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
@@ -12,11 +15,17 @@ linters:
|
||||
- testifylint
|
||||
- unused
|
||||
|
||||
linter-settings:
|
||||
linters-settings:
|
||||
forbidigo:
|
||||
forbid:
|
||||
- p: ^fmt\.Print.*$
|
||||
msg: Do not commit print statements.
|
||||
godot:
|
||||
capital: true
|
||||
exclude:
|
||||
# Ignore "See: URL"
|
||||
- 'See:'
|
||||
goimports:
|
||||
local-prefixes: github.com/prometheus/procfs
|
||||
misspell:
|
||||
locale: US
|
||||
|
||||
8
vendor/github.com/prometheus/procfs/Makefile.common
generated
vendored
8
vendor/github.com/prometheus/procfs/Makefile.common
generated
vendored
@@ -61,7 +61,7 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_
|
||||
SKIP_GOLANGCI_LINT :=
|
||||
GOLANGCI_LINT :=
|
||||
GOLANGCI_LINT_OPTS ?=
|
||||
GOLANGCI_LINT_VERSION ?= v1.59.0
|
||||
GOLANGCI_LINT_VERSION ?= v1.60.2
|
||||
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
|
||||
# windows isn't included here because of the path separator being different.
|
||||
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
|
||||
@@ -275,3 +275,9 @@ $(1)_precheck:
|
||||
exit 1; \
|
||||
fi
|
||||
endef
|
||||
|
||||
govulncheck: install-govulncheck
|
||||
govulncheck ./...
|
||||
|
||||
install-govulncheck:
|
||||
command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
|
||||
6
vendor/github.com/prometheus/procfs/README.md
generated
vendored
6
vendor/github.com/prometheus/procfs/README.md
generated
vendored
@@ -47,15 +47,15 @@ However, most of the API includes unit tests which can be run with `make test`.
|
||||
The procfs library includes a set of test fixtures which include many example files from
|
||||
the `/proc` and `/sys` filesystems. These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file
|
||||
which is extracted automatically during testing. To add/update the test fixtures, first
|
||||
ensure the `fixtures` directory is up to date by removing the existing directory and then
|
||||
extracting the ttar file using `make fixtures/.unpacked` or just `make test`.
|
||||
ensure the `testdata/fixtures` directory is up to date by removing the existing directory and then
|
||||
extracting the ttar file using `make testdata/fixtures/.unpacked` or just `make test`.
|
||||
|
||||
```bash
|
||||
rm -rf testdata/fixtures
|
||||
make test
|
||||
```
|
||||
|
||||
Next, make the required changes to the extracted files in the `fixtures` directory. When
|
||||
Next, make the required changes to the extracted files in the `testdata/fixtures` directory. When
|
||||
the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file
|
||||
based on the updated `fixtures` directory. And finally, verify the changes using
|
||||
`git diff testdata/fixtures.ttar`.
|
||||
|
||||
4
vendor/github.com/prometheus/procfs/arp.go
generated
vendored
4
vendor/github.com/prometheus/procfs/arp.go
generated
vendored
@@ -23,9 +23,9 @@ import (
|
||||
|
||||
// Learned from include/uapi/linux/if_arp.h.
|
||||
const (
|
||||
// completed entry (ha valid).
|
||||
// Completed entry (ha valid).
|
||||
ATFComplete = 0x02
|
||||
// permanent entry.
|
||||
// Permanent entry.
|
||||
ATFPermanent = 0x04
|
||||
// Publish entry.
|
||||
ATFPublish = 0x08
|
||||
|
||||
10
vendor/github.com/prometheus/procfs/fs.go
generated
vendored
10
vendor/github.com/prometheus/procfs/fs.go
generated
vendored
@@ -24,8 +24,14 @@ type FS struct {
|
||||
isReal bool
|
||||
}
|
||||
|
||||
// DefaultMountPoint is the common mount point of the proc filesystem.
|
||||
const DefaultMountPoint = fs.DefaultProcMountPoint
|
||||
const (
|
||||
// DefaultMountPoint is the common mount point of the proc filesystem.
|
||||
DefaultMountPoint = fs.DefaultProcMountPoint
|
||||
|
||||
// SectorSize represents the size of a sector in bytes.
|
||||
// It is specific to Linux block I/O operations.
|
||||
SectorSize = 512
|
||||
)
|
||||
|
||||
// NewDefaultFS returns a new proc FS mounted under the default proc mountPoint.
|
||||
// It will error if the mount point directory can't be read or is a file.
|
||||
|
||||
4
vendor/github.com/prometheus/procfs/fs_statfs_notype.go
generated
vendored
4
vendor/github.com/prometheus/procfs/fs_statfs_notype.go
generated
vendored
@@ -17,7 +17,7 @@
|
||||
package procfs
|
||||
|
||||
// isRealProc returns true on architectures that don't have a Type argument
|
||||
// in their Statfs_t struct
|
||||
func isRealProc(mountPoint string) (bool, error) {
|
||||
// in their Statfs_t struct.
|
||||
func isRealProc(_ string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
6
vendor/github.com/prometheus/procfs/fscache.go
generated
vendored
6
vendor/github.com/prometheus/procfs/fscache.go
generated
vendored
@@ -162,7 +162,7 @@ type Fscacheinfo struct {
|
||||
ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64
|
||||
// Number of release reqs ignored due to in-progress store
|
||||
ReleaseRequestsIgnoredDueToInProgressStore uint64
|
||||
// Number of page stores cancelled due to release req
|
||||
// Number of page stores canceled due to release req
|
||||
PageStoresCancelledByReleaseRequests uint64
|
||||
VmscanWaiting uint64
|
||||
// Number of times async ops added to pending queues
|
||||
@@ -171,11 +171,11 @@ type Fscacheinfo struct {
|
||||
OpsRunning uint64
|
||||
// Number of times async ops queued for processing
|
||||
OpsEnqueued uint64
|
||||
// Number of async ops cancelled
|
||||
// Number of async ops canceled
|
||||
OpsCancelled uint64
|
||||
// Number of async ops rejected due to object lookup/create failure
|
||||
OpsRejected uint64
|
||||
// Number of async ops initialised
|
||||
// Number of async ops initialized
|
||||
OpsInitialised uint64
|
||||
// Number of async ops queued for deferred release
|
||||
OpsDeferred uint64
|
||||
|
||||
3
vendor/github.com/prometheus/procfs/internal/fs/fs.go
generated
vendored
3
vendor/github.com/prometheus/procfs/internal/fs/fs.go
generated
vendored
@@ -28,6 +28,9 @@ const (
|
||||
|
||||
// DefaultConfigfsMountPoint is the common mount point of the configfs.
|
||||
DefaultConfigfsMountPoint = "/sys/kernel/config"
|
||||
|
||||
// DefaultSelinuxMountPoint is the common mount point of the selinuxfs.
|
||||
DefaultSelinuxMountPoint = "/sys/fs/selinux"
|
||||
)
|
||||
|
||||
// FS represents a pseudo-filesystem, normally /proc or /sys, which provides an
|
||||
|
||||
14
vendor/github.com/prometheus/procfs/internal/util/parse.go
generated
vendored
14
vendor/github.com/prometheus/procfs/internal/util/parse.go
generated
vendored
@@ -14,6 +14,7 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -110,3 +111,16 @@ func ParseBool(b string) *bool {
|
||||
}
|
||||
return &truth
|
||||
}
|
||||
|
||||
// ReadHexFromFile reads a file and attempts to parse a uint64 from a hexadecimal format 0xXX.
|
||||
func ReadHexFromFile(path string) (uint64, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
hexString := strings.TrimSpace(string(data))
|
||||
if !strings.HasPrefix(hexString, "0x") {
|
||||
return 0, errors.New("invalid format: hex string does not start with '0x'")
|
||||
}
|
||||
return strconv.ParseUint(hexString[2:], 16, 64)
|
||||
}
|
||||
|
||||
4
vendor/github.com/prometheus/procfs/mountstats.go
generated
vendored
4
vendor/github.com/prometheus/procfs/mountstats.go
generated
vendored
@@ -45,11 +45,11 @@ const (
|
||||
fieldTransport11TCPLen = 13
|
||||
fieldTransport11UDPLen = 10
|
||||
|
||||
// kernel version >= 4.14 MaxLen
|
||||
// Kernel version >= 4.14 MaxLen
|
||||
// See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393
|
||||
fieldTransport11RDMAMaxLen = 28
|
||||
|
||||
// kernel version <= 4.2 MinLen
|
||||
// Kernel version <= 4.2 MinLen
|
||||
// See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331
|
||||
fieldTransport11RDMAMinLen = 20
|
||||
)
|
||||
|
||||
96
vendor/github.com/prometheus/procfs/net_dev_snmp6.go
generated
vendored
Normal file
96
vendor/github.com/prometheus/procfs/net_dev_snmp6.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package procfs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NetDevSNMP6 is parsed from files in /proc/net/dev_snmp6/ or /proc/<PID>/net/dev_snmp6/.
|
||||
// The outer map's keys are interface names and the inner map's keys are stat names.
|
||||
//
|
||||
// If you'd like a total across all interfaces, please use the Snmp6() method of the Proc type.
|
||||
type NetDevSNMP6 map[string]map[string]uint64
|
||||
|
||||
// Returns kernel/system statistics read from interface files within the /proc/net/dev_snmp6/
|
||||
// directory.
|
||||
func (fs FS) NetDevSNMP6() (NetDevSNMP6, error) {
|
||||
return newNetDevSNMP6(fs.proc.Path("net/dev_snmp6"))
|
||||
}
|
||||
|
||||
// Returns kernel/system statistics read from interface files within the /proc/<PID>/net/dev_snmp6/
|
||||
// directory.
|
||||
func (p Proc) NetDevSNMP6() (NetDevSNMP6, error) {
|
||||
return newNetDevSNMP6(p.path("net/dev_snmp6"))
|
||||
}
|
||||
|
||||
// newNetDevSNMP6 creates a new NetDevSNMP6 from the contents of the given directory.
|
||||
func newNetDevSNMP6(dir string) (NetDevSNMP6, error) {
|
||||
netDevSNMP6 := make(NetDevSNMP6)
|
||||
|
||||
// The net/dev_snmp6 folders contain one file per interface
|
||||
ifaceFiles, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
// On systems with IPv6 disabled, this directory won't exist.
|
||||
// Do nothing.
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return netDevSNMP6, err
|
||||
}
|
||||
return netDevSNMP6, err
|
||||
}
|
||||
|
||||
for _, iFaceFile := range ifaceFiles {
|
||||
f, err := os.Open(dir + "/" + iFaceFile.Name())
|
||||
if err != nil {
|
||||
return netDevSNMP6, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
netDevSNMP6[iFaceFile.Name()], err = parseNetDevSNMP6Stats(f)
|
||||
if err != nil {
|
||||
return netDevSNMP6, err
|
||||
}
|
||||
}
|
||||
|
||||
return netDevSNMP6, nil
|
||||
}
|
||||
|
||||
func parseNetDevSNMP6Stats(r io.Reader) (map[string]uint64, error) {
|
||||
m := make(map[string]uint64)
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
stat := strings.Fields(scanner.Text())
|
||||
if len(stat) < 2 {
|
||||
continue
|
||||
}
|
||||
key, val := stat[0], stat[1]
|
||||
|
||||
// Expect stat name to contain "6" or be "ifIndex"
|
||||
if strings.Contains(key, "6") || key == "ifIndex" {
|
||||
v, err := strconv.ParseUint(val, 10, 64)
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
|
||||
m[key] = v
|
||||
}
|
||||
}
|
||||
return m, scanner.Err()
|
||||
}
|
||||
8
vendor/github.com/prometheus/procfs/net_ip_socket.go
generated
vendored
8
vendor/github.com/prometheus/procfs/net_ip_socket.go
generated
vendored
@@ -25,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// readLimit is used by io.LimitReader while reading the content of the
|
||||
// Maximum size limit used by io.LimitReader while reading the content of the
|
||||
// /proc/net/udp{,6} files. The number of lines inside such a file is dynamic
|
||||
// as each line represents a single used socket.
|
||||
// In theory, the number of available sockets is 65535 (2^16 - 1) per IP.
|
||||
@@ -50,12 +50,12 @@ type (
|
||||
// UsedSockets shows the total number of parsed lines representing the
|
||||
// number of used sockets.
|
||||
UsedSockets uint64
|
||||
// Drops shows the total number of dropped packets of all UPD sockets.
|
||||
// Drops shows the total number of dropped packets of all UDP sockets.
|
||||
Drops *uint64
|
||||
}
|
||||
|
||||
// netIPSocketLine represents the fields parsed from a single line
|
||||
// in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped.
|
||||
// A single line parser for fields from /proc/net/{t,u}dp{,6}.
|
||||
// Fields which are not used by IPSocket are skipped.
|
||||
// Drops is non-nil for udp{,6}, but nil for tcp{,6}.
|
||||
// For the proc file format details, see https://linux.die.net/man/5/proc.
|
||||
netIPSocketLine struct {
|
||||
|
||||
4
vendor/github.com/prometheus/procfs/net_tcp.go
generated
vendored
4
vendor/github.com/prometheus/procfs/net_tcp.go
generated
vendored
@@ -25,24 +25,28 @@ type (
|
||||
|
||||
// NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams
|
||||
// read from /proc/net/tcp.
|
||||
// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
|
||||
func (fs FS) NetTCP() (NetTCP, error) {
|
||||
return newNetTCP(fs.proc.Path("net/tcp"))
|
||||
}
|
||||
|
||||
// NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams
|
||||
// read from /proc/net/tcp6.
|
||||
// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
|
||||
func (fs FS) NetTCP6() (NetTCP, error) {
|
||||
return newNetTCP(fs.proc.Path("net/tcp6"))
|
||||
}
|
||||
|
||||
// NetTCPSummary returns already computed statistics like the total queue lengths
|
||||
// for TCP datagrams read from /proc/net/tcp.
|
||||
// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
|
||||
func (fs FS) NetTCPSummary() (*NetTCPSummary, error) {
|
||||
return newNetTCPSummary(fs.proc.Path("net/tcp"))
|
||||
}
|
||||
|
||||
// NetTCP6Summary returns already computed statistics like the total queue lengths
|
||||
// for TCP datagrams read from /proc/net/tcp6.
|
||||
// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
|
||||
func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) {
|
||||
return newNetTCPSummary(fs.proc.Path("net/tcp6"))
|
||||
}
|
||||
|
||||
8
vendor/github.com/prometheus/procfs/net_unix.go
generated
vendored
8
vendor/github.com/prometheus/procfs/net_unix.go
generated
vendored
@@ -121,12 +121,12 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) {
|
||||
return &nu, nil
|
||||
}
|
||||
|
||||
func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, error) {
|
||||
func (u *NetUNIX) parseLine(line string, hasInode bool, minFields int) (*NetUNIXLine, error) {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
l := len(fields)
|
||||
if l < min {
|
||||
return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l)
|
||||
if l < minFields {
|
||||
return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, minFields, l)
|
||||
}
|
||||
|
||||
// Field offsets are as follows:
|
||||
@@ -172,7 +172,7 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine,
|
||||
}
|
||||
|
||||
// Path field is optional.
|
||||
if l > min {
|
||||
if l > minFields {
|
||||
// Path occurs at either index 6 or 7 depending on whether inode is
|
||||
// already present.
|
||||
pathIdx := 7
|
||||
|
||||
2
vendor/github.com/prometheus/procfs/proc_cgroup.go
generated
vendored
2
vendor/github.com/prometheus/procfs/proc_cgroup.go
generated
vendored
@@ -24,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
// Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a
|
||||
// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource
|
||||
// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. The v1 has one hierarchy per available resource
|
||||
// controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies
|
||||
// contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in
|
||||
// this hierarchy' (where==what path on the specific cgroupfs). By prefixing this path with the mount point of
|
||||
|
||||
2
vendor/github.com/prometheus/procfs/proc_io.go
generated
vendored
2
vendor/github.com/prometheus/procfs/proc_io.go
generated
vendored
@@ -50,7 +50,7 @@ func (p Proc) IO() (ProcIO, error) {
|
||||
|
||||
ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" +
|
||||
"read_bytes: %d\nwrite_bytes: %d\n" +
|
||||
"cancelled_write_bytes: %d\n"
|
||||
"cancelled_write_bytes: %d\n" //nolint:misspell
|
||||
|
||||
_, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
|
||||
&pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
|
||||
|
||||
4
vendor/github.com/prometheus/procfs/proc_smaps.go
generated
vendored
4
vendor/github.com/prometheus/procfs/proc_smaps.go
generated
vendored
@@ -19,7 +19,6 @@ package procfs
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -29,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// match the header line before each mapped zone in `/proc/pid/smaps`.
|
||||
// Match the header line before each mapped zone in `/proc/pid/smaps`.
|
||||
procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`)
|
||||
)
|
||||
|
||||
@@ -117,7 +116,6 @@ func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) {
|
||||
func (s *ProcSMapsRollup) parseLine(line string) error {
|
||||
kv := strings.SplitN(line, ":", 2)
|
||||
if len(kv) != 2 {
|
||||
fmt.Println(line)
|
||||
return errors.New("invalid net/dev line, missing colon")
|
||||
}
|
||||
|
||||
|
||||
18
vendor/github.com/prometheus/procfs/proc_status.go
generated
vendored
18
vendor/github.com/prometheus/procfs/proc_status.go
generated
vendored
@@ -146,7 +146,11 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
|
||||
}
|
||||
}
|
||||
case "NSpid":
|
||||
s.NSpids = calcNSPidsList(vString)
|
||||
nspids, err := calcNSPidsList(vString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.NSpids = nspids
|
||||
case "VmPeak":
|
||||
s.VmPeak = vUintBytes
|
||||
case "VmSize":
|
||||
@@ -222,17 +226,17 @@ func calcCpusAllowedList(cpuString string) []uint64 {
|
||||
return g
|
||||
}
|
||||
|
||||
func calcNSPidsList(nspidsString string) []uint64 {
|
||||
s := strings.Split(nspidsString, " ")
|
||||
func calcNSPidsList(nspidsString string) ([]uint64, error) {
|
||||
s := strings.Split(nspidsString, "\t")
|
||||
var nspids []uint64
|
||||
|
||||
for _, nspid := range s {
|
||||
nspid, _ := strconv.ParseUint(nspid, 10, 64)
|
||||
if nspid == 0 {
|
||||
continue
|
||||
nspid, err := strconv.ParseUint(nspid, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nspids = append(nspids, nspid)
|
||||
}
|
||||
|
||||
return nspids
|
||||
return nspids, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user