mirror of https://github.com/docker/cli.git
vendor: github.com/moby/buildkit v0.10.0
full diff: https://github.com/moby/buildkit/compare/9f254e18360a...v0.10.0 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
adadd5472e
commit
5f74020ded
|
@ -20,9 +20,8 @@ require (
|
||||||
github.com/google/go-cmp v0.5.7
|
github.com/google/go-cmp v0.5.7
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
github.com/imdario/mergo v0.3.12
|
github.com/imdario/mergo v0.3.12
|
||||||
github.com/klauspost/compress v1.15.0 // indirect
|
|
||||||
github.com/mitchellh/mapstructure v1.3.2
|
github.com/mitchellh/mapstructure v1.3.2
|
||||||
github.com/moby/buildkit v0.8.2-0.20210615162540-9f254e18360a // master (v0.9.0-dev)
|
github.com/moby/buildkit v0.10.0
|
||||||
github.com/moby/sys/signal v0.7.0
|
github.com/moby/sys/signal v0.7.0
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
|
||||||
github.com/morikuni/aec v1.0.0
|
github.com/morikuni/aec v1.0.0
|
||||||
|
@ -41,7 +40,6 @@ require (
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
|
||||||
golang.org/x/text v0.3.7
|
golang.org/x/text v0.3.7
|
||||||
google.golang.org/grpc v1.44.0 // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
gotest.tools/v3 v3.1.0
|
gotest.tools/v3 v3.1.0
|
||||||
)
|
)
|
||||||
|
|
569
vendor.sum
569
vendor.sum
File diff suppressed because it is too large
Load Diff
|
@ -22,7 +22,12 @@ func Context() context.Context {
|
||||||
const exitLimit = 3
|
const exitLimit = 3
|
||||||
retries := 0
|
retries := 0
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx := context.Background()
|
||||||
|
for _, f := range inits {
|
||||||
|
ctx = f(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
appContextCache = ctx
|
appContextCache = ctx
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package appcontext
|
package appcontext
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package appcontext
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Initializer func(context.Context) context.Context
|
||||||
|
|
||||||
|
var inits []Initializer
|
||||||
|
|
||||||
|
// Register stores a new context initializer that runs on app context creation
|
||||||
|
func Register(f Initializer) {
|
||||||
|
inits = append(inits, f)
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
See [![go-doc](https://godoc.org/github.com/prometheus/client_golang/prometheus?status.svg)](https://godoc.org/github.com/prometheus/client_golang/prometheus).
|
See [![Go Reference](https://pkg.go.dev/badge/github.com/prometheus/client_golang/prometheus.svg)](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus).
|
||||||
|
|
38
vendor/github.com/prometheus/client_golang/prometheus/build_info_collector.go
generated
vendored
Normal file
38
vendor/github.com/prometheus/client_golang/prometheus/build_info_collector.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2021 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 prometheus
|
||||||
|
|
||||||
|
import "runtime/debug"
|
||||||
|
|
||||||
|
// NewBuildInfoCollector is the obsolete version of collectors.NewBuildInfoCollector.
|
||||||
|
// See there for documentation.
|
||||||
|
//
|
||||||
|
// Deprecated: Use collectors.NewBuildInfoCollector instead.
|
||||||
|
func NewBuildInfoCollector() Collector {
|
||||||
|
path, version, sum := "unknown", "unknown", "unknown"
|
||||||
|
if bi, ok := debug.ReadBuildInfo(); ok {
|
||||||
|
path = bi.Main.Path
|
||||||
|
version = bi.Main.Version
|
||||||
|
sum = bi.Main.Sum
|
||||||
|
}
|
||||||
|
c := &selfCollector{MustNewConstMetric(
|
||||||
|
NewDesc(
|
||||||
|
"go_build_info",
|
||||||
|
"Build information about the main Go module.",
|
||||||
|
nil, Labels{"path": path, "version": version, "checksum": sum},
|
||||||
|
),
|
||||||
|
GaugeValue, 1)}
|
||||||
|
c.init(c.self)
|
||||||
|
return c
|
||||||
|
}
|
|
@ -118,3 +118,11 @@ func (c *selfCollector) Describe(ch chan<- *Desc) {
|
||||||
func (c *selfCollector) Collect(ch chan<- Metric) {
|
func (c *selfCollector) Collect(ch chan<- Metric) {
|
||||||
ch <- c.self
|
ch <- c.self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collectorMetric is a metric that is also a collector.
|
||||||
|
// Because of selfCollector, most (if not all) Metrics in
|
||||||
|
// this package are also collectors.
|
||||||
|
type collectorMetric interface {
|
||||||
|
Metric
|
||||||
|
Collector
|
||||||
|
}
|
||||||
|
|
|
@ -133,10 +133,14 @@ func (c *counter) Inc() {
|
||||||
atomic.AddUint64(&c.valInt, 1)
|
atomic.AddUint64(&c.valInt, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *counter) Write(out *dto.Metric) error {
|
func (c *counter) get() float64 {
|
||||||
fval := math.Float64frombits(atomic.LoadUint64(&c.valBits))
|
fval := math.Float64frombits(atomic.LoadUint64(&c.valBits))
|
||||||
ival := atomic.LoadUint64(&c.valInt)
|
ival := atomic.LoadUint64(&c.valInt)
|
||||||
val := fval + float64(ival)
|
return fval + float64(ival)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *counter) Write(out *dto.Metric) error {
|
||||||
|
val := c.get()
|
||||||
|
|
||||||
var exemplar *dto.Exemplar
|
var exemplar *dto.Exemplar
|
||||||
if e := c.exemplar.Load(); e != nil {
|
if e := c.exemplar.Load(); e != nil {
|
||||||
|
|
|
@ -16,53 +16,11 @@ package prometheus
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type goCollector struct {
|
func goRuntimeMemStats() memStatsMetrics {
|
||||||
goroutinesDesc *Desc
|
return memStatsMetrics{
|
||||||
threadsDesc *Desc
|
|
||||||
gcDesc *Desc
|
|
||||||
goInfoDesc *Desc
|
|
||||||
|
|
||||||
// ms... are memstats related.
|
|
||||||
msLast *runtime.MemStats // Previously collected memstats.
|
|
||||||
msLastTimestamp time.Time
|
|
||||||
msMtx sync.Mutex // Protects msLast and msLastTimestamp.
|
|
||||||
msMetrics memStatsMetrics
|
|
||||||
msRead func(*runtime.MemStats) // For mocking in tests.
|
|
||||||
msMaxWait time.Duration // Wait time for fresh memstats.
|
|
||||||
msMaxAge time.Duration // Maximum allowed age of old memstats.
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGoCollector is the obsolete version of collectors.NewGoCollector.
|
|
||||||
// See there for documentation.
|
|
||||||
//
|
|
||||||
// Deprecated: Use collectors.NewGoCollector instead.
|
|
||||||
func NewGoCollector() Collector {
|
|
||||||
return &goCollector{
|
|
||||||
goroutinesDesc: NewDesc(
|
|
||||||
"go_goroutines",
|
|
||||||
"Number of goroutines that currently exist.",
|
|
||||||
nil, nil),
|
|
||||||
threadsDesc: NewDesc(
|
|
||||||
"go_threads",
|
|
||||||
"Number of OS threads created.",
|
|
||||||
nil, nil),
|
|
||||||
gcDesc: NewDesc(
|
|
||||||
"go_gc_duration_seconds",
|
|
||||||
"A summary of the pause duration of garbage collection cycles.",
|
|
||||||
nil, nil),
|
|
||||||
goInfoDesc: NewDesc(
|
|
||||||
"go_info",
|
|
||||||
"Information about the Go environment.",
|
|
||||||
nil, Labels{"version": runtime.Version()}),
|
|
||||||
msLast: &runtime.MemStats{},
|
|
||||||
msRead: runtime.ReadMemStats,
|
|
||||||
msMaxWait: time.Second,
|
|
||||||
msMaxAge: 5 * time.Minute,
|
|
||||||
msMetrics: memStatsMetrics{
|
|
||||||
{
|
{
|
||||||
desc: NewDesc(
|
desc: NewDesc(
|
||||||
memstatNamespace("alloc_bytes"),
|
memstatNamespace("alloc_bytes"),
|
||||||
|
@ -239,14 +197,6 @@ func NewGoCollector() Collector {
|
||||||
),
|
),
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
|
eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
|
||||||
valType: GaugeValue,
|
valType: GaugeValue,
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("last_gc_time_seconds"),
|
|
||||||
"Number of seconds since 1970 of last garbage collection.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) / 1e9 },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
}, {
|
||||||
desc: NewDesc(
|
desc: NewDesc(
|
||||||
memstatNamespace("gc_cpu_fraction"),
|
memstatNamespace("gc_cpu_fraction"),
|
||||||
|
@ -256,41 +206,53 @@ func NewGoCollector() Collector {
|
||||||
eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction },
|
eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction },
|
||||||
valType: GaugeValue,
|
valType: GaugeValue,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func memstatNamespace(s string) string {
|
type baseGoCollector struct {
|
||||||
return "go_memstats_" + s
|
goroutinesDesc *Desc
|
||||||
|
threadsDesc *Desc
|
||||||
|
gcDesc *Desc
|
||||||
|
gcLastTimeDesc *Desc
|
||||||
|
goInfoDesc *Desc
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBaseGoCollector() baseGoCollector {
|
||||||
|
return baseGoCollector{
|
||||||
|
goroutinesDesc: NewDesc(
|
||||||
|
"go_goroutines",
|
||||||
|
"Number of goroutines that currently exist.",
|
||||||
|
nil, nil),
|
||||||
|
threadsDesc: NewDesc(
|
||||||
|
"go_threads",
|
||||||
|
"Number of OS threads created.",
|
||||||
|
nil, nil),
|
||||||
|
gcDesc: NewDesc(
|
||||||
|
"go_gc_duration_seconds",
|
||||||
|
"A summary of the pause duration of garbage collection cycles.",
|
||||||
|
nil, nil),
|
||||||
|
gcLastTimeDesc: NewDesc(
|
||||||
|
memstatNamespace("last_gc_time_seconds"),
|
||||||
|
"Number of seconds since 1970 of last garbage collection.",
|
||||||
|
nil, nil),
|
||||||
|
goInfoDesc: NewDesc(
|
||||||
|
"go_info",
|
||||||
|
"Information about the Go environment.",
|
||||||
|
nil, Labels{"version": runtime.Version()}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe returns all descriptions of the collector.
|
// Describe returns all descriptions of the collector.
|
||||||
func (c *goCollector) Describe(ch chan<- *Desc) {
|
func (c *baseGoCollector) Describe(ch chan<- *Desc) {
|
||||||
ch <- c.goroutinesDesc
|
ch <- c.goroutinesDesc
|
||||||
ch <- c.threadsDesc
|
ch <- c.threadsDesc
|
||||||
ch <- c.gcDesc
|
ch <- c.gcDesc
|
||||||
|
ch <- c.gcLastTimeDesc
|
||||||
ch <- c.goInfoDesc
|
ch <- c.goInfoDesc
|
||||||
for _, i := range c.msMetrics {
|
|
||||||
ch <- i.desc
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect returns the current state of all metrics of the collector.
|
// Collect returns the current state of all metrics of the collector.
|
||||||
func (c *goCollector) Collect(ch chan<- Metric) {
|
func (c *baseGoCollector) Collect(ch chan<- Metric) {
|
||||||
var (
|
|
||||||
ms = &runtime.MemStats{}
|
|
||||||
done = make(chan struct{})
|
|
||||||
)
|
|
||||||
// Start reading memstats first as it might take a while.
|
|
||||||
go func() {
|
|
||||||
c.msRead(ms)
|
|
||||||
c.msMtx.Lock()
|
|
||||||
c.msLast = ms
|
|
||||||
c.msLastTimestamp = time.Now()
|
|
||||||
c.msMtx.Unlock()
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
|
|
||||||
ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine()))
|
ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine()))
|
||||||
n, _ := runtime.ThreadCreateProfile(nil)
|
n, _ := runtime.ThreadCreateProfile(nil)
|
||||||
ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n))
|
ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n))
|
||||||
|
@ -305,63 +267,19 @@ func (c *goCollector) Collect(ch chan<- Metric) {
|
||||||
}
|
}
|
||||||
quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
|
quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
|
||||||
ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), stats.PauseTotal.Seconds(), quantiles)
|
ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), stats.PauseTotal.Seconds(), quantiles)
|
||||||
|
ch <- MustNewConstMetric(c.gcLastTimeDesc, GaugeValue, float64(stats.LastGC.UnixNano())/1e9)
|
||||||
|
|
||||||
ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1)
|
ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1)
|
||||||
|
|
||||||
timer := time.NewTimer(c.msMaxWait)
|
|
||||||
select {
|
|
||||||
case <-done: // Our own ReadMemStats succeeded in time. Use it.
|
|
||||||
timer.Stop() // Important for high collection frequencies to not pile up timers.
|
|
||||||
c.msCollect(ch, ms)
|
|
||||||
return
|
|
||||||
case <-timer.C: // Time out, use last memstats if possible. Continue below.
|
|
||||||
}
|
|
||||||
c.msMtx.Lock()
|
|
||||||
if time.Since(c.msLastTimestamp) < c.msMaxAge {
|
|
||||||
// Last memstats are recent enough. Collect from them under the lock.
|
|
||||||
c.msCollect(ch, c.msLast)
|
|
||||||
c.msMtx.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// If we are here, the last memstats are too old or don't exist. We have
|
|
||||||
// to wait until our own ReadMemStats finally completes. For that to
|
|
||||||
// happen, we have to release the lock.
|
|
||||||
c.msMtx.Unlock()
|
|
||||||
<-done
|
|
||||||
c.msCollect(ch, ms)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *goCollector) msCollect(ch chan<- Metric, ms *runtime.MemStats) {
|
func memstatNamespace(s string) string {
|
||||||
for _, i := range c.msMetrics {
|
return "go_memstats_" + s
|
||||||
ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// memStatsMetrics provide description, value, and value type for memstat metrics.
|
// memStatsMetrics provide description, evaluator, runtime/metrics name, and
|
||||||
|
// value type for memstat metrics.
|
||||||
type memStatsMetrics []struct {
|
type memStatsMetrics []struct {
|
||||||
desc *Desc
|
desc *Desc
|
||||||
eval func(*runtime.MemStats) float64
|
eval func(*runtime.MemStats) float64
|
||||||
valType ValueType
|
valType ValueType
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBuildInfoCollector is the obsolete version of collectors.NewBuildInfoCollector.
|
|
||||||
// See there for documentation.
|
|
||||||
//
|
|
||||||
// Deprecated: Use collectors.NewBuildInfoCollector instead.
|
|
||||||
func NewBuildInfoCollector() Collector {
|
|
||||||
path, version, sum := "unknown", "unknown", "unknown"
|
|
||||||
if bi, ok := debug.ReadBuildInfo(); ok {
|
|
||||||
path = bi.Main.Path
|
|
||||||
version = bi.Main.Version
|
|
||||||
sum = bi.Main.Sum
|
|
||||||
}
|
|
||||||
c := &selfCollector{MustNewConstMetric(
|
|
||||||
NewDesc(
|
|
||||||
"go_build_info",
|
|
||||||
"Build information about the main Go module.",
|
|
||||||
nil, Labels{"path": path, "version": version, "checksum": sum},
|
|
||||||
),
|
|
||||||
GaugeValue, 1)}
|
|
||||||
c.init(c.self)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
107
vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go
generated
vendored
Normal file
107
vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
// Copyright 2021 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.17
|
||||||
|
// +build !go1.17
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type goCollector struct {
|
||||||
|
base baseGoCollector
|
||||||
|
|
||||||
|
// ms... are memstats related.
|
||||||
|
msLast *runtime.MemStats // Previously collected memstats.
|
||||||
|
msLastTimestamp time.Time
|
||||||
|
msMtx sync.Mutex // Protects msLast and msLastTimestamp.
|
||||||
|
msMetrics memStatsMetrics
|
||||||
|
msRead func(*runtime.MemStats) // For mocking in tests.
|
||||||
|
msMaxWait time.Duration // Wait time for fresh memstats.
|
||||||
|
msMaxAge time.Duration // Maximum allowed age of old memstats.
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGoCollector is the obsolete version of collectors.NewGoCollector.
|
||||||
|
// See there for documentation.
|
||||||
|
//
|
||||||
|
// Deprecated: Use collectors.NewGoCollector instead.
|
||||||
|
func NewGoCollector() Collector {
|
||||||
|
return &goCollector{
|
||||||
|
base: newBaseGoCollector(),
|
||||||
|
msLast: &runtime.MemStats{},
|
||||||
|
msRead: runtime.ReadMemStats,
|
||||||
|
msMaxWait: time.Second,
|
||||||
|
msMaxAge: 5 * time.Minute,
|
||||||
|
msMetrics: goRuntimeMemStats(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describe returns all descriptions of the collector.
|
||||||
|
func (c *goCollector) Describe(ch chan<- *Desc) {
|
||||||
|
c.base.Describe(ch)
|
||||||
|
for _, i := range c.msMetrics {
|
||||||
|
ch <- i.desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect returns the current state of all metrics of the collector.
|
||||||
|
func (c *goCollector) Collect(ch chan<- Metric) {
|
||||||
|
var (
|
||||||
|
ms = &runtime.MemStats{}
|
||||||
|
done = make(chan struct{})
|
||||||
|
)
|
||||||
|
// Start reading memstats first as it might take a while.
|
||||||
|
go func() {
|
||||||
|
c.msRead(ms)
|
||||||
|
c.msMtx.Lock()
|
||||||
|
c.msLast = ms
|
||||||
|
c.msLastTimestamp = time.Now()
|
||||||
|
c.msMtx.Unlock()
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Collect base non-memory metrics.
|
||||||
|
c.base.Collect(ch)
|
||||||
|
|
||||||
|
timer := time.NewTimer(c.msMaxWait)
|
||||||
|
select {
|
||||||
|
case <-done: // Our own ReadMemStats succeeded in time. Use it.
|
||||||
|
timer.Stop() // Important for high collection frequencies to not pile up timers.
|
||||||
|
c.msCollect(ch, ms)
|
||||||
|
return
|
||||||
|
case <-timer.C: // Time out, use last memstats if possible. Continue below.
|
||||||
|
}
|
||||||
|
c.msMtx.Lock()
|
||||||
|
if time.Since(c.msLastTimestamp) < c.msMaxAge {
|
||||||
|
// Last memstats are recent enough. Collect from them under the lock.
|
||||||
|
c.msCollect(ch, c.msLast)
|
||||||
|
c.msMtx.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// If we are here, the last memstats are too old or don't exist. We have
|
||||||
|
// to wait until our own ReadMemStats finally completes. For that to
|
||||||
|
// happen, we have to release the lock.
|
||||||
|
c.msMtx.Unlock()
|
||||||
|
<-done
|
||||||
|
c.msCollect(ch, ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *goCollector) msCollect(ch chan<- Metric, ms *runtime.MemStats) {
|
||||||
|
for _, i := range c.msMetrics {
|
||||||
|
ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
|
||||||
|
}
|
||||||
|
}
|
408
vendor/github.com/prometheus/client_golang/prometheus/go_collector_go117.go
generated
vendored
Normal file
408
vendor/github.com/prometheus/client_golang/prometheus/go_collector_go117.go
generated
vendored
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
// Copyright 2021 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.17
|
||||||
|
// +build go1.17
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"runtime"
|
||||||
|
"runtime/metrics"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/internal"
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type goCollector struct {
|
||||||
|
base baseGoCollector
|
||||||
|
|
||||||
|
// mu protects updates to all fields ensuring a consistent
|
||||||
|
// snapshot is always produced by Collect.
|
||||||
|
mu sync.Mutex
|
||||||
|
|
||||||
|
// rm... fields all pertain to the runtime/metrics package.
|
||||||
|
rmSampleBuf []metrics.Sample
|
||||||
|
rmSampleMap map[string]*metrics.Sample
|
||||||
|
rmMetrics []collectorMetric
|
||||||
|
|
||||||
|
// With Go 1.17, the runtime/metrics package was introduced.
|
||||||
|
// From that point on, metric names produced by the runtime/metrics
|
||||||
|
// package could be generated from runtime/metrics names. However,
|
||||||
|
// these differ from the old names for the same values.
|
||||||
|
//
|
||||||
|
// This field exist to export the same values under the old names
|
||||||
|
// as well.
|
||||||
|
msMetrics memStatsMetrics
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGoCollector is the obsolete version of collectors.NewGoCollector.
|
||||||
|
// See there for documentation.
|
||||||
|
//
|
||||||
|
// Deprecated: Use collectors.NewGoCollector instead.
|
||||||
|
func NewGoCollector() Collector {
|
||||||
|
descriptions := metrics.All()
|
||||||
|
|
||||||
|
// Collect all histogram samples so that we can get their buckets.
|
||||||
|
// The API guarantees that the buckets are always fixed for the lifetime
|
||||||
|
// of the process.
|
||||||
|
var histograms []metrics.Sample
|
||||||
|
for _, d := range descriptions {
|
||||||
|
if d.Kind == metrics.KindFloat64Histogram {
|
||||||
|
histograms = append(histograms, metrics.Sample{Name: d.Name})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metrics.Read(histograms)
|
||||||
|
bucketsMap := make(map[string][]float64)
|
||||||
|
for i := range histograms {
|
||||||
|
bucketsMap[histograms[i].Name] = histograms[i].Value.Float64Histogram().Buckets
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a Desc and ValueType for each runtime/metrics metric.
|
||||||
|
metricSet := make([]collectorMetric, 0, len(descriptions))
|
||||||
|
sampleBuf := make([]metrics.Sample, 0, len(descriptions))
|
||||||
|
sampleMap := make(map[string]*metrics.Sample, len(descriptions))
|
||||||
|
for i := range descriptions {
|
||||||
|
d := &descriptions[i]
|
||||||
|
namespace, subsystem, name, ok := internal.RuntimeMetricsToProm(d)
|
||||||
|
if !ok {
|
||||||
|
// Just ignore this metric; we can't do anything with it here.
|
||||||
|
// If a user decides to use the latest version of Go, we don't want
|
||||||
|
// to fail here. This condition is tested elsewhere.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up sample buffer for reading, and a map
|
||||||
|
// for quick lookup of sample values.
|
||||||
|
sampleBuf = append(sampleBuf, metrics.Sample{Name: d.Name})
|
||||||
|
sampleMap[d.Name] = &sampleBuf[len(sampleBuf)-1]
|
||||||
|
|
||||||
|
var m collectorMetric
|
||||||
|
if d.Kind == metrics.KindFloat64Histogram {
|
||||||
|
_, hasSum := rmExactSumMap[d.Name]
|
||||||
|
unit := d.Name[strings.IndexRune(d.Name, ':')+1:]
|
||||||
|
m = newBatchHistogram(
|
||||||
|
NewDesc(
|
||||||
|
BuildFQName(namespace, subsystem, name),
|
||||||
|
d.Description,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
internal.RuntimeMetricsBucketsForUnit(bucketsMap[d.Name], unit),
|
||||||
|
hasSum,
|
||||||
|
)
|
||||||
|
} else if d.Cumulative {
|
||||||
|
m = NewCounter(CounterOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Subsystem: subsystem,
|
||||||
|
Name: name,
|
||||||
|
Help: d.Description,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
m = NewGauge(GaugeOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Subsystem: subsystem,
|
||||||
|
Name: name,
|
||||||
|
Help: d.Description,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
metricSet = append(metricSet, m)
|
||||||
|
}
|
||||||
|
return &goCollector{
|
||||||
|
base: newBaseGoCollector(),
|
||||||
|
rmSampleBuf: sampleBuf,
|
||||||
|
rmSampleMap: sampleMap,
|
||||||
|
rmMetrics: metricSet,
|
||||||
|
msMetrics: goRuntimeMemStats(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describe returns all descriptions of the collector.
|
||||||
|
func (c *goCollector) Describe(ch chan<- *Desc) {
|
||||||
|
c.base.Describe(ch)
|
||||||
|
for _, i := range c.msMetrics {
|
||||||
|
ch <- i.desc
|
||||||
|
}
|
||||||
|
for _, m := range c.rmMetrics {
|
||||||
|
ch <- m.Desc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect returns the current state of all metrics of the collector.
|
||||||
|
func (c *goCollector) Collect(ch chan<- Metric) {
|
||||||
|
// Collect base non-memory metrics.
|
||||||
|
c.base.Collect(ch)
|
||||||
|
|
||||||
|
// Collect must be thread-safe, so prevent concurrent use of
|
||||||
|
// rmSampleBuf. Just read into rmSampleBuf but write all the data
|
||||||
|
// we get into our Metrics or MemStats.
|
||||||
|
//
|
||||||
|
// This lock also ensures that the Metrics we send out are all from
|
||||||
|
// the same updates, ensuring their mutual consistency insofar as
|
||||||
|
// is guaranteed by the runtime/metrics package.
|
||||||
|
//
|
||||||
|
// N.B. This locking is heavy-handed, but Collect is expected to be called
|
||||||
|
// relatively infrequently. Also the core operation here, metrics.Read,
|
||||||
|
// is fast (O(tens of microseconds)) so contention should certainly be
|
||||||
|
// low, though channel operations and any allocations may add to that.
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
// Populate runtime/metrics sample buffer.
|
||||||
|
metrics.Read(c.rmSampleBuf)
|
||||||
|
|
||||||
|
// Update all our metrics from rmSampleBuf.
|
||||||
|
for i, sample := range c.rmSampleBuf {
|
||||||
|
// N.B. switch on concrete type because it's significantly more efficient
|
||||||
|
// than checking for the Counter and Gauge interface implementations. In
|
||||||
|
// this case, we control all the types here.
|
||||||
|
switch m := c.rmMetrics[i].(type) {
|
||||||
|
case *counter:
|
||||||
|
// Guard against decreases. This should never happen, but a failure
|
||||||
|
// to do so will result in a panic, which is a harsh consequence for
|
||||||
|
// a metrics collection bug.
|
||||||
|
v0, v1 := m.get(), unwrapScalarRMValue(sample.Value)
|
||||||
|
if v1 > v0 {
|
||||||
|
m.Add(unwrapScalarRMValue(sample.Value) - m.get())
|
||||||
|
}
|
||||||
|
m.Collect(ch)
|
||||||
|
case *gauge:
|
||||||
|
m.Set(unwrapScalarRMValue(sample.Value))
|
||||||
|
m.Collect(ch)
|
||||||
|
case *batchHistogram:
|
||||||
|
m.update(sample.Value.Float64Histogram(), c.exactSumFor(sample.Name))
|
||||||
|
m.Collect(ch)
|
||||||
|
default:
|
||||||
|
panic("unexpected metric type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ms is a dummy MemStats that we populate ourselves so that we can
|
||||||
|
// populate the old metrics from it.
|
||||||
|
var ms runtime.MemStats
|
||||||
|
memStatsFromRM(&ms, c.rmSampleMap)
|
||||||
|
for _, i := range c.msMetrics {
|
||||||
|
ch <- MustNewConstMetric(i.desc, i.valType, i.eval(&ms))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unwrapScalarRMValue unwraps a runtime/metrics value that is assumed
|
||||||
|
// to be scalar and returns the equivalent float64 value. Panics if the
|
||||||
|
// value is not scalar.
|
||||||
|
func unwrapScalarRMValue(v metrics.Value) float64 {
|
||||||
|
switch v.Kind() {
|
||||||
|
case metrics.KindUint64:
|
||||||
|
return float64(v.Uint64())
|
||||||
|
case metrics.KindFloat64:
|
||||||
|
return v.Float64()
|
||||||
|
case metrics.KindBad:
|
||||||
|
// Unsupported metric.
|
||||||
|
//
|
||||||
|
// This should never happen because we always populate our metric
|
||||||
|
// set from the runtime/metrics package.
|
||||||
|
panic("unexpected unsupported 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rmExactSumMap = map[string]string{
|
||||||
|
"/gc/heap/allocs-by-size:bytes": "/gc/heap/allocs:bytes",
|
||||||
|
"/gc/heap/frees-by-size:bytes": "/gc/heap/frees:bytes",
|
||||||
|
}
|
||||||
|
|
||||||
|
// exactSumFor takes a runtime/metrics metric name (that is assumed to
|
||||||
|
// be of kind KindFloat64Histogram) and returns its exact sum and whether
|
||||||
|
// its exact sum exists.
|
||||||
|
//
|
||||||
|
// The runtime/metrics API for histograms doesn't currently expose exact
|
||||||
|
// sums, but some of the other metrics are in fact exact sums of histograms.
|
||||||
|
func (c *goCollector) exactSumFor(rmName string) float64 {
|
||||||
|
sumName, ok := rmExactSumMap[rmName]
|
||||||
|
if !ok {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
s, ok := c.rmSampleMap[sumName]
|
||||||
|
if !ok {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return unwrapScalarRMValue(s.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func memStatsFromRM(ms *runtime.MemStats, rm map[string]*metrics.Sample) {
|
||||||
|
lookupOrZero := func(name string) uint64 {
|
||||||
|
if s, ok := rm[name]; ok {
|
||||||
|
return s.Value.Uint64()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently, MemStats adds tiny alloc count to both Mallocs AND Frees.
|
||||||
|
// The reason for this is because MemStats couldn't be extended at the time
|
||||||
|
// but there was a desire to have Mallocs at least be a little more representative,
|
||||||
|
// while having Mallocs - Frees still represent a live object count.
|
||||||
|
// Unfortunately, MemStats doesn't actually export a large allocation count,
|
||||||
|
// so it's impossible to pull this number out directly.
|
||||||
|
tinyAllocs := lookupOrZero("/gc/heap/tiny/allocs:objects")
|
||||||
|
ms.Mallocs = lookupOrZero("/gc/heap/allocs:objects") + tinyAllocs
|
||||||
|
ms.Frees = lookupOrZero("/gc/heap/frees:objects") + tinyAllocs
|
||||||
|
|
||||||
|
ms.TotalAlloc = lookupOrZero("/gc/heap/allocs:bytes")
|
||||||
|
ms.Sys = lookupOrZero("/memory/classes/total:bytes")
|
||||||
|
ms.Lookups = 0 // Already always zero.
|
||||||
|
ms.HeapAlloc = lookupOrZero("/memory/classes/heap/objects:bytes")
|
||||||
|
ms.Alloc = ms.HeapAlloc
|
||||||
|
ms.HeapInuse = ms.HeapAlloc + lookupOrZero("/memory/classes/heap/unused:bytes")
|
||||||
|
ms.HeapReleased = lookupOrZero("/memory/classes/heap/released:bytes")
|
||||||
|
ms.HeapIdle = ms.HeapReleased + lookupOrZero("/memory/classes/heap/free:bytes")
|
||||||
|
ms.HeapSys = ms.HeapInuse + ms.HeapIdle
|
||||||
|
ms.HeapObjects = lookupOrZero("/gc/heap/objects:objects")
|
||||||
|
ms.StackInuse = lookupOrZero("/memory/classes/heap/stacks:bytes")
|
||||||
|
ms.StackSys = ms.StackInuse + lookupOrZero("/memory/classes/os-stacks:bytes")
|
||||||
|
ms.MSpanInuse = lookupOrZero("/memory/classes/metadata/mspan/inuse:bytes")
|
||||||
|
ms.MSpanSys = ms.MSpanInuse + lookupOrZero("/memory/classes/metadata/mspan/free:bytes")
|
||||||
|
ms.MCacheInuse = lookupOrZero("/memory/classes/metadata/mcache/inuse:bytes")
|
||||||
|
ms.MCacheSys = ms.MCacheInuse + lookupOrZero("/memory/classes/metadata/mcache/free:bytes")
|
||||||
|
ms.BuckHashSys = lookupOrZero("/memory/classes/profiling/buckets:bytes")
|
||||||
|
ms.GCSys = lookupOrZero("/memory/classes/metadata/other:bytes")
|
||||||
|
ms.OtherSys = lookupOrZero("/memory/classes/other:bytes")
|
||||||
|
ms.NextGC = lookupOrZero("/gc/heap/goal:bytes")
|
||||||
|
|
||||||
|
// N.B. LastGC is omitted because runtime.GCStats already has this.
|
||||||
|
// See https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034
|
||||||
|
// for more details.
|
||||||
|
ms.LastGC = 0
|
||||||
|
|
||||||
|
// N.B. GCCPUFraction is intentionally omitted. This metric is not useful,
|
||||||
|
// and often misleading due to the fact that it's an average over the lifetime
|
||||||
|
// of the process.
|
||||||
|
// See https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034
|
||||||
|
// for more details.
|
||||||
|
ms.GCCPUFraction = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// batchHistogram is a mutable histogram that is updated
|
||||||
|
// in batches.
|
||||||
|
type batchHistogram struct {
|
||||||
|
selfCollector
|
||||||
|
|
||||||
|
// Static fields updated only once.
|
||||||
|
desc *Desc
|
||||||
|
hasSum bool
|
||||||
|
|
||||||
|
// Because this histogram operates in batches, it just uses a
|
||||||
|
// single mutex for everything. updates are always serialized
|
||||||
|
// but Write calls may operate concurrently with updates.
|
||||||
|
// Contention between these two sources should be rare.
|
||||||
|
mu sync.Mutex
|
||||||
|
buckets []float64 // Inclusive lower bounds, like runtime/metrics.
|
||||||
|
counts []uint64
|
||||||
|
sum float64 // Used if hasSum is true.
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBatchHistogram creates a new batch histogram value with the given
|
||||||
|
// Desc, buckets, and whether or not it has an exact sum available.
|
||||||
|
//
|
||||||
|
// buckets must always be from the runtime/metrics package, following
|
||||||
|
// the same conventions.
|
||||||
|
func newBatchHistogram(desc *Desc, buckets []float64, hasSum bool) *batchHistogram {
|
||||||
|
h := &batchHistogram{
|
||||||
|
desc: desc,
|
||||||
|
buckets: buckets,
|
||||||
|
// Because buckets follows runtime/metrics conventions, there's
|
||||||
|
// 1 more value in the buckets list than there are buckets represented,
|
||||||
|
// because in runtime/metrics, the bucket values represent *boundaries*,
|
||||||
|
// and non-Inf boundaries are inclusive lower bounds for that bucket.
|
||||||
|
counts: make([]uint64, len(buckets)-1),
|
||||||
|
hasSum: hasSum,
|
||||||
|
}
|
||||||
|
h.init(h)
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// update updates the batchHistogram from a runtime/metrics histogram.
|
||||||
|
//
|
||||||
|
// sum must be provided if the batchHistogram was created to have an exact sum.
|
||||||
|
// h.buckets must be a strict subset of his.Buckets.
|
||||||
|
func (h *batchHistogram) update(his *metrics.Float64Histogram, sum float64) {
|
||||||
|
counts, buckets := his.Counts, his.Buckets
|
||||||
|
|
||||||
|
h.mu.Lock()
|
||||||
|
defer h.mu.Unlock()
|
||||||
|
|
||||||
|
// Clear buckets.
|
||||||
|
for i := range h.counts {
|
||||||
|
h.counts[i] = 0
|
||||||
|
}
|
||||||
|
// Copy and reduce buckets.
|
||||||
|
var j int
|
||||||
|
for i, count := range counts {
|
||||||
|
h.counts[j] += count
|
||||||
|
if buckets[i+1] == h.buckets[j+1] {
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if h.hasSum {
|
||||||
|
h.sum = sum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *batchHistogram) Desc() *Desc {
|
||||||
|
return h.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *batchHistogram) Write(out *dto.Metric) error {
|
||||||
|
h.mu.Lock()
|
||||||
|
defer h.mu.Unlock()
|
||||||
|
|
||||||
|
sum := float64(0)
|
||||||
|
if h.hasSum {
|
||||||
|
sum = h.sum
|
||||||
|
}
|
||||||
|
dtoBuckets := make([]*dto.Bucket, 0, len(h.counts))
|
||||||
|
totalCount := uint64(0)
|
||||||
|
for i, count := range h.counts {
|
||||||
|
totalCount += count
|
||||||
|
if !h.hasSum {
|
||||||
|
// N.B. This computed sum is an underestimate.
|
||||||
|
sum += h.buckets[i] * float64(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the +Inf bucket, but only for the bucket list.
|
||||||
|
// It must still count for sum and totalCount.
|
||||||
|
if math.IsInf(h.buckets[i+1], 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Float64Histogram's upper bound is exclusive, so make it inclusive
|
||||||
|
// by obtaining the next float64 value down, in order.
|
||||||
|
upperBound := math.Nextafter(h.buckets[i+1], h.buckets[i])
|
||||||
|
dtoBuckets = append(dtoBuckets, &dto.Bucket{
|
||||||
|
CumulativeCount: proto.Uint64(totalCount),
|
||||||
|
UpperBound: proto.Float64(upperBound),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
out.Histogram = &dto.Histogram{
|
||||||
|
Bucket: dtoBuckets,
|
||||||
|
SampleCount: proto.Uint64(totalCount),
|
||||||
|
SampleSum: proto.Float64(sum),
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -116,6 +116,34 @@ func ExponentialBuckets(start, factor float64, count int) []float64 {
|
||||||
return buckets
|
return buckets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExponentialBucketsRange creates 'count' buckets, where the lowest bucket is
|
||||||
|
// 'min' and the highest bucket is 'max'. The final +Inf bucket is not counted
|
||||||
|
// and not included in the returned slice. The returned slice is meant to be
|
||||||
|
// 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 {
|
||||||
|
if count < 1 {
|
||||||
|
panic("ExponentialBucketsRange count needs a positive count")
|
||||||
|
}
|
||||||
|
if min <= 0 {
|
||||||
|
panic("ExponentialBucketsRange min needs to be greater than 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formula for exponential buckets.
|
||||||
|
// 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))
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
return buckets
|
||||||
|
}
|
||||||
|
|
||||||
// HistogramOpts bundles the options for creating a Histogram metric. It is
|
// HistogramOpts bundles the options for creating a Histogram metric. It is
|
||||||
// mandatory to set Name to a non-empty string. All other fields are optional
|
// mandatory to set Name to a non-empty string. All other fields are optional
|
||||||
// and can safely be left at their zero value, although it is strongly
|
// and can safely be left at their zero value, although it is strongly
|
||||||
|
|
142
vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go
generated
vendored
Normal file
142
vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go
generated
vendored
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
// Copyright 2021 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.17
|
||||||
|
// +build go1.17
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"path"
|
||||||
|
"runtime/metrics"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/common/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RuntimeMetricsToProm produces a Prometheus metric name from a runtime/metrics
|
||||||
|
// metric description and validates whether the metric is suitable for integration
|
||||||
|
// with Prometheus.
|
||||||
|
//
|
||||||
|
// Returns false if a name could not be produced, or if Prometheus does not understand
|
||||||
|
// the runtime/metrics Kind.
|
||||||
|
//
|
||||||
|
// Note that the main reason a name couldn't be produced is if the runtime/metrics
|
||||||
|
// package exports a name with characters outside the valid Prometheus metric name
|
||||||
|
// character set. This is theoretically possible, but should never happen in practice.
|
||||||
|
// Still, don't rely on it.
|
||||||
|
func RuntimeMetricsToProm(d *metrics.Description) (string, string, string, bool) {
|
||||||
|
namespace := "go"
|
||||||
|
|
||||||
|
comp := strings.SplitN(d.Name, ":", 2)
|
||||||
|
key := comp[0]
|
||||||
|
unit := comp[1]
|
||||||
|
|
||||||
|
// The last path element in the key is the name,
|
||||||
|
// the rest is the subsystem.
|
||||||
|
subsystem := path.Dir(key[1:] /* remove leading / */)
|
||||||
|
name := path.Base(key)
|
||||||
|
|
||||||
|
// subsystem is translated by replacing all / and - with _.
|
||||||
|
subsystem = strings.ReplaceAll(subsystem, "/", "_")
|
||||||
|
subsystem = strings.ReplaceAll(subsystem, "-", "_")
|
||||||
|
|
||||||
|
// unit is translated assuming that the unit contains no
|
||||||
|
// non-ASCII characters.
|
||||||
|
unit = strings.ReplaceAll(unit, "-", "_")
|
||||||
|
unit = strings.ReplaceAll(unit, "*", "_")
|
||||||
|
unit = strings.ReplaceAll(unit, "/", "_per_")
|
||||||
|
|
||||||
|
// name has - replaced with _ and is concatenated with the unit and
|
||||||
|
// other data.
|
||||||
|
name = strings.ReplaceAll(name, "-", "_")
|
||||||
|
name = name + "_" + unit
|
||||||
|
if d.Cumulative {
|
||||||
|
name = name + "_total"
|
||||||
|
}
|
||||||
|
|
||||||
|
valid := model.IsValidMetricName(model.LabelValue(namespace + "_" + subsystem + "_" + name))
|
||||||
|
switch d.Kind {
|
||||||
|
case metrics.KindUint64:
|
||||||
|
case metrics.KindFloat64:
|
||||||
|
case metrics.KindFloat64Histogram:
|
||||||
|
default:
|
||||||
|
valid = false
|
||||||
|
}
|
||||||
|
return namespace, subsystem, name, valid
|
||||||
|
}
|
||||||
|
|
||||||
|
// RuntimeMetricsBucketsForUnit takes a set of buckets obtained for a runtime/metrics histogram
|
||||||
|
// type (so, lower-bound inclusive) and a unit from a runtime/metrics name, and produces
|
||||||
|
// a reduced set of buckets. This function always removes any -Inf bucket as it's represented
|
||||||
|
// as the bottom-most upper-bound inclusive bucket in Prometheus.
|
||||||
|
func RuntimeMetricsBucketsForUnit(buckets []float64, unit string) []float64 {
|
||||||
|
switch unit {
|
||||||
|
case "bytes":
|
||||||
|
// Rebucket as powers of 2.
|
||||||
|
return rebucketExp(buckets, 2)
|
||||||
|
case "seconds":
|
||||||
|
// Rebucket as powers of 10 and then merge all buckets greater
|
||||||
|
// than 1 second into the +Inf bucket.
|
||||||
|
b := rebucketExp(buckets, 10)
|
||||||
|
for i := range b {
|
||||||
|
if b[i] <= 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b[i] = math.Inf(1)
|
||||||
|
b = b[:i+1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
return buckets
|
||||||
|
}
|
||||||
|
|
||||||
|
// rebucketExp takes a list of bucket boundaries (lower bound inclusive) and
|
||||||
|
// downsamples the buckets to those a multiple of base apart. The end result
|
||||||
|
// is a roughly exponential (in many cases, perfectly exponential) bucketing
|
||||||
|
// scheme.
|
||||||
|
func rebucketExp(buckets []float64, base float64) []float64 {
|
||||||
|
bucket := buckets[0]
|
||||||
|
var newBuckets []float64
|
||||||
|
// We may see a -Inf here, in which case, add it and skip it
|
||||||
|
// since we risk producing NaNs otherwise.
|
||||||
|
//
|
||||||
|
// We need to preserve -Inf values to maintain runtime/metrics
|
||||||
|
// conventions. We'll strip it out later.
|
||||||
|
if bucket == math.Inf(-1) {
|
||||||
|
newBuckets = append(newBuckets, bucket)
|
||||||
|
buckets = buckets[1:]
|
||||||
|
bucket = buckets[0]
|
||||||
|
}
|
||||||
|
// From now on, bucket should always have a non-Inf value because
|
||||||
|
// Infs are only ever at the ends of the bucket lists, so
|
||||||
|
// arithmetic operations on it are non-NaN.
|
||||||
|
for i := 1; i < len(buckets); i++ {
|
||||||
|
if bucket >= 0 && buckets[i] < bucket*base {
|
||||||
|
// The next bucket we want to include is at least bucket*base.
|
||||||
|
continue
|
||||||
|
} else if bucket < 0 && buckets[i] < bucket/base {
|
||||||
|
// In this case the bucket we're targeting is negative, and since
|
||||||
|
// we're ascending through buckets here, we need to divide to get
|
||||||
|
// closer to zero exponentially.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The +Inf bucket will always be the last one, and we'll always
|
||||||
|
// end up including it here because bucket
|
||||||
|
newBuckets = append(newBuckets, bucket)
|
||||||
|
bucket = buckets[i]
|
||||||
|
}
|
||||||
|
return append(newBuckets, bucket)
|
||||||
|
}
|
1
vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go
generated
vendored
1
vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go
generated
vendored
|
@ -11,6 +11,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
28
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
generated
vendored
28
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
generated
vendored
|
@ -49,7 +49,10 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp
|
||||||
// http.RoundTripper to observe the request result with the provided CounterVec.
|
// http.RoundTripper to observe the request result with the provided CounterVec.
|
||||||
// The CounterVec must have zero, one, or two non-const non-curried labels. For
|
// The CounterVec must have zero, one, or two non-const non-curried labels. For
|
||||||
// those, the only allowed label names are "code" and "method". The function
|
// those, the only allowed label names are "code" and "method". The function
|
||||||
// panics otherwise. Partitioning of the CounterVec happens by HTTP status code
|
// panics otherwise. For the "method" label a predefined default label value set
|
||||||
|
// is used to filter given values. Values besides predefined values will count
|
||||||
|
// as `unknown` method.`WithExtraMethods` can be used to add more
|
||||||
|
// methods to the set. Partitioning of the CounterVec happens by HTTP status code
|
||||||
// and/or HTTP method if the respective instance label names are present in the
|
// and/or HTTP method if the respective instance label names are present in the
|
||||||
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
|
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
|
||||||
//
|
//
|
||||||
|
@ -57,13 +60,18 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp
|
||||||
// is not incremented.
|
// is not incremented.
|
||||||
//
|
//
|
||||||
// See the example for ExampleInstrumentRoundTripperDuration for example usage.
|
// See the example for ExampleInstrumentRoundTripperDuration for example usage.
|
||||||
func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc {
|
func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper, opts ...Option) RoundTripperFunc {
|
||||||
|
rtOpts := &option{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(rtOpts)
|
||||||
|
}
|
||||||
|
|
||||||
code, method := checkLabels(counter)
|
code, method := checkLabels(counter)
|
||||||
|
|
||||||
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
||||||
resp, err := next.RoundTrip(r)
|
resp, err := next.RoundTrip(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc()
|
counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Inc()
|
||||||
}
|
}
|
||||||
return resp, err
|
return resp, err
|
||||||
})
|
})
|
||||||
|
@ -73,7 +81,10 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou
|
||||||
// http.RoundTripper to observe the request duration with the provided
|
// http.RoundTripper to observe the request duration with the provided
|
||||||
// ObserverVec. The ObserverVec must have zero, one, or two non-const
|
// ObserverVec. The ObserverVec must have zero, one, or two non-const
|
||||||
// non-curried labels. For those, the only allowed label names are "code" and
|
// non-curried labels. For those, the only allowed label names are "code" and
|
||||||
// "method". The function panics otherwise. The Observe method of the Observer
|
// "method". The function panics otherwise. For the "method" label a predefined
|
||||||
|
// default label value set is used to filter given values. Values besides
|
||||||
|
// predefined values will count as `unknown` method. `WithExtraMethods`
|
||||||
|
// can be used to add more methods to the set. The Observe method of the Observer
|
||||||
// in the ObserverVec is called with the request duration in
|
// in the ObserverVec is called with the request duration in
|
||||||
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
|
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||||
// respective instance label names are present in the ObserverVec. For
|
// respective instance label names are present in the ObserverVec. For
|
||||||
|
@ -85,14 +96,19 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou
|
||||||
//
|
//
|
||||||
// Note that this method is only guaranteed to never observe negative durations
|
// Note that this method is only guaranteed to never observe negative durations
|
||||||
// if used with Go1.9+.
|
// if used with Go1.9+.
|
||||||
func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc {
|
func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper, opts ...Option) RoundTripperFunc {
|
||||||
|
rtOpts := &option{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(rtOpts)
|
||||||
|
}
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
resp, err := next.RoundTrip(r)
|
resp, err := next.RoundTrip(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds())
|
obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Observe(time.Since(start).Seconds())
|
||||||
}
|
}
|
||||||
return resp, err
|
return resp, err
|
||||||
})
|
})
|
||||||
|
|
107
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
107
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
|
@ -45,7 +45,10 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl
|
||||||
// http.Handler to observe the request duration with the provided ObserverVec.
|
// http.Handler to observe the request duration with the provided ObserverVec.
|
||||||
// The ObserverVec must have valid metric and label names and must have zero,
|
// The ObserverVec must have valid metric and label names and must have zero,
|
||||||
// one, or two non-const non-curried labels. For those, the only allowed label
|
// one, or two non-const non-curried labels. For those, the only allowed label
|
||||||
// names are "code" and "method". The function panics otherwise. The Observe
|
// names are "code" and "method". The function panics otherwise. For the "method"
|
||||||
|
// label a predefined default label value set is used to filter given values.
|
||||||
|
// Values besides predefined values will count as `unknown` method.
|
||||||
|
//`WithExtraMethods` can be used to add more methods to the set. The Observe
|
||||||
// method of the Observer in the ObserverVec is called with the request duration
|
// method of the Observer in the ObserverVec is called with the request duration
|
||||||
// in seconds. Partitioning happens by HTTP status code and/or HTTP method if
|
// in seconds. Partitioning happens by HTTP status code and/or HTTP method if
|
||||||
// the respective instance label names are present in the ObserverVec. For
|
// the respective instance label names are present in the ObserverVec. For
|
||||||
|
@ -58,7 +61,12 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl
|
||||||
//
|
//
|
||||||
// Note that this method is only guaranteed to never observe negative durations
|
// Note that this method is only guaranteed to never observe negative durations
|
||||||
// if used with Go1.9+.
|
// if used with Go1.9+.
|
||||||
func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
|
func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
|
||||||
|
mwOpts := &option{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(mwOpts)
|
||||||
|
}
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
if code {
|
if code {
|
||||||
|
@ -67,14 +75,14 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht
|
||||||
d := newDelegator(w, nil)
|
d := newDelegator(w, nil)
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
|
|
||||||
obs.With(labels(code, method, r.Method, d.Status())).Observe(time.Since(now).Seconds())
|
obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
obs.With(labels(code, method, r.Method, 0)).Observe(time.Since(now).Seconds())
|
obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +90,10 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht
|
||||||
// to observe the request result with the provided CounterVec. The CounterVec
|
// to observe the request result with the provided CounterVec. The CounterVec
|
||||||
// must have valid metric and label names and must have zero, one, or two
|
// must have valid metric and label names and must have zero, one, or two
|
||||||
// non-const non-curried labels. For those, the only allowed label names are
|
// non-const non-curried labels. For those, the only allowed label names are
|
||||||
// "code" and "method". The function panics otherwise. Partitioning of the
|
// "code" and "method". The function panics otherwise. For the "method"
|
||||||
|
// label a predefined default label value set is used to filter given values.
|
||||||
|
// Values besides predefined values will count as `unknown` method.
|
||||||
|
// `WithExtraMethods` can be used to add more methods to the set. Partitioning of the
|
||||||
// CounterVec happens by HTTP status code and/or HTTP method if the respective
|
// CounterVec happens by HTTP status code and/or HTTP method if the respective
|
||||||
// instance label names are present in the CounterVec. For unpartitioned
|
// instance label names are present in the CounterVec. For unpartitioned
|
||||||
// counting, use a CounterVec with zero labels.
|
// counting, use a CounterVec with zero labels.
|
||||||
|
@ -92,20 +103,25 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht
|
||||||
// If the wrapped Handler panics, the Counter is not incremented.
|
// If the wrapped Handler panics, the Counter is not incremented.
|
||||||
//
|
//
|
||||||
// See the example for InstrumentHandlerDuration for example usage.
|
// See the example for InstrumentHandlerDuration for example usage.
|
||||||
func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc {
|
func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, opts ...Option) http.HandlerFunc {
|
||||||
|
mwOpts := &option{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(mwOpts)
|
||||||
|
}
|
||||||
|
|
||||||
code, method := checkLabels(counter)
|
code, method := checkLabels(counter)
|
||||||
|
|
||||||
if code {
|
if code {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
d := newDelegator(w, nil)
|
d := newDelegator(w, nil)
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
counter.With(labels(code, method, r.Method, d.Status())).Inc()
|
counter.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Inc()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
counter.With(labels(code, method, r.Method, 0)).Inc()
|
counter.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Inc()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +130,10 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler)
|
||||||
// until the response headers are written. The ObserverVec must have valid
|
// until the response headers are written. The ObserverVec must have valid
|
||||||
// metric and label names and must have zero, one, or two non-const non-curried
|
// metric and label names and must have zero, one, or two non-const non-curried
|
||||||
// labels. For those, the only allowed label names are "code" and "method". The
|
// labels. For those, the only allowed label names are "code" and "method". The
|
||||||
// function panics otherwise. The Observe method of the Observer in the
|
// function panics otherwise. For the "method" label a predefined default label
|
||||||
|
// value set is used to filter given values. Values besides predefined values
|
||||||
|
// will count as `unknown` method.`WithExtraMethods` can be used to add more
|
||||||
|
// methods to the set. The Observe method of the Observer in the
|
||||||
// ObserverVec is called with the request duration in seconds. Partitioning
|
// ObserverVec is called with the request duration in seconds. Partitioning
|
||||||
// happens by HTTP status code and/or HTTP method if the respective instance
|
// happens by HTTP status code and/or HTTP method if the respective instance
|
||||||
// label names are present in the ObserverVec. For unpartitioned observations,
|
// label names are present in the ObserverVec. For unpartitioned observations,
|
||||||
|
@ -128,13 +147,18 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler)
|
||||||
// if used with Go1.9+.
|
// if used with Go1.9+.
|
||||||
//
|
//
|
||||||
// See the example for InstrumentHandlerDuration for example usage.
|
// See the example for InstrumentHandlerDuration for example usage.
|
||||||
func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
|
func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
|
||||||
|
mwOpts := &option{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(mwOpts)
|
||||||
|
}
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
d := newDelegator(w, func(status int) {
|
d := newDelegator(w, func(status int) {
|
||||||
obs.With(labels(code, method, r.Method, status)).Observe(time.Since(now).Seconds())
|
obs.With(labels(code, method, r.Method, status, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
|
||||||
})
|
})
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
})
|
})
|
||||||
|
@ -144,8 +168,11 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
|
||||||
// http.Handler to observe the request size with the provided ObserverVec. The
|
// http.Handler to observe the request size with the provided ObserverVec. The
|
||||||
// ObserverVec must have valid metric and label names and must have zero, one,
|
// ObserverVec must have valid metric and label names and must have zero, one,
|
||||||
// or two non-const non-curried labels. For those, the only allowed label names
|
// or two non-const non-curried labels. For those, the only allowed label names
|
||||||
// are "code" and "method". The function panics otherwise. The Observe method of
|
// are "code" and "method". The function panics otherwise. For the "method"
|
||||||
// the Observer in the ObserverVec is called with the request size in
|
// label a predefined default label value set is used to filter given values.
|
||||||
|
// Values besides predefined values will count as `unknown` method.
|
||||||
|
// `WithExtraMethods` can be used to add more methods to the set. The Observe
|
||||||
|
// method of the Observer in the ObserverVec is called with the request size in
|
||||||
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||||
// respective instance label names are present in the ObserverVec. For
|
// respective instance label names are present in the ObserverVec. For
|
||||||
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||||
|
@ -156,7 +183,12 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
|
||||||
// If the wrapped Handler panics, no values are reported.
|
// If the wrapped Handler panics, no values are reported.
|
||||||
//
|
//
|
||||||
// See the example for InstrumentHandlerDuration for example usage.
|
// See the example for InstrumentHandlerDuration for example usage.
|
||||||
func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
|
func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
|
||||||
|
mwOpts := &option{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(mwOpts)
|
||||||
|
}
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
if code {
|
if code {
|
||||||
|
@ -164,14 +196,14 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler)
|
||||||
d := newDelegator(w, nil)
|
d := newDelegator(w, nil)
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
size := computeApproximateRequestSize(r)
|
size := computeApproximateRequestSize(r)
|
||||||
obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(size))
|
obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(size))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
size := computeApproximateRequestSize(r)
|
size := computeApproximateRequestSize(r)
|
||||||
obs.With(labels(code, method, r.Method, 0)).Observe(float64(size))
|
obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(float64(size))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +211,11 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler)
|
||||||
// http.Handler to observe the response size with the provided ObserverVec. The
|
// http.Handler to observe the response size with the provided ObserverVec. The
|
||||||
// ObserverVec must have valid metric and label names and must have zero, one,
|
// ObserverVec must have valid metric and label names and must have zero, one,
|
||||||
// or two non-const non-curried labels. For those, the only allowed label names
|
// or two non-const non-curried labels. For those, the only allowed label names
|
||||||
// are "code" and "method". The function panics otherwise. The Observe method of
|
// are "code" and "method". The function panics otherwise. For the "method"
|
||||||
// the Observer in the ObserverVec is called with the response size in
|
// label a predefined default label value set is used to filter given values.
|
||||||
|
// Values besides predefined values will count as `unknown` method.
|
||||||
|
// `WithExtraMethods` can be used to add more methods to the set. The Observe
|
||||||
|
// method of the Observer in the ObserverVec is called with the response size in
|
||||||
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||||
// respective instance label names are present in the ObserverVec. For
|
// respective instance label names are present in the ObserverVec. For
|
||||||
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||||
|
@ -191,12 +226,18 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler)
|
||||||
// If the wrapped Handler panics, no values are reported.
|
// If the wrapped Handler panics, no values are reported.
|
||||||
//
|
//
|
||||||
// See the example for InstrumentHandlerDuration for example usage.
|
// See the example for InstrumentHandlerDuration for example usage.
|
||||||
func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler {
|
func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.Handler {
|
||||||
|
mwOpts := &option{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(mwOpts)
|
||||||
|
}
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
d := newDelegator(w, nil)
|
d := newDelegator(w, nil)
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(d.Written()))
|
obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(d.Written()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +331,7 @@ func isLabelCurried(c prometheus.Collector, label string) bool {
|
||||||
// unnecessary allocations on each request.
|
// unnecessary allocations on each request.
|
||||||
var emptyLabels = prometheus.Labels{}
|
var emptyLabels = prometheus.Labels{}
|
||||||
|
|
||||||
func labels(code, method bool, reqMethod string, status int) prometheus.Labels {
|
func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels {
|
||||||
if !(code || method) {
|
if !(code || method) {
|
||||||
return emptyLabels
|
return emptyLabels
|
||||||
}
|
}
|
||||||
|
@ -300,7 +341,7 @@ func labels(code, method bool, reqMethod string, status int) prometheus.Labels {
|
||||||
labels["code"] = sanitizeCode(status)
|
labels["code"] = sanitizeCode(status)
|
||||||
}
|
}
|
||||||
if method {
|
if method {
|
||||||
labels["method"] = sanitizeMethod(reqMethod)
|
labels["method"] = sanitizeMethod(reqMethod, extraMethods...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return labels
|
return labels
|
||||||
|
@ -330,7 +371,12 @@ func computeApproximateRequestSize(r *http.Request) int {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func sanitizeMethod(m string) string {
|
// If the wrapped http.Handler has a known method, it will be sanitized and returned.
|
||||||
|
// Otherwise, "unknown" will be returned. The known method list can be extended
|
||||||
|
// as needed by using extraMethods parameter.
|
||||||
|
func sanitizeMethod(m string, extraMethods ...string) string {
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for
|
||||||
|
// the methods chosen as default.
|
||||||
switch m {
|
switch m {
|
||||||
case "GET", "get":
|
case "GET", "get":
|
||||||
return "get"
|
return "get"
|
||||||
|
@ -348,15 +394,25 @@ func sanitizeMethod(m string) string {
|
||||||
return "options"
|
return "options"
|
||||||
case "NOTIFY", "notify":
|
case "NOTIFY", "notify":
|
||||||
return "notify"
|
return "notify"
|
||||||
|
case "TRACE", "trace":
|
||||||
|
return "trace"
|
||||||
|
case "PATCH", "patch":
|
||||||
|
return "patch"
|
||||||
default:
|
default:
|
||||||
|
for _, method := range extraMethods {
|
||||||
|
if strings.EqualFold(m, method) {
|
||||||
return strings.ToLower(m)
|
return strings.ToLower(m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the wrapped http.Handler has not set a status code, i.e. the value is
|
// If the wrapped http.Handler has not set a status code, i.e. the value is
|
||||||
// currently 0, santizeCode will return 200, for consistency with behavior in
|
// currently 0, sanitizeCode will return 200, for consistency with behavior in
|
||||||
// the stdlib.
|
// the stdlib.
|
||||||
func sanitizeCode(s int) string {
|
func sanitizeCode(s int) string {
|
||||||
|
// See for accepted codes https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||||
switch s {
|
switch s {
|
||||||
case 100:
|
case 100:
|
||||||
return "100"
|
return "100"
|
||||||
|
@ -453,6 +509,9 @@ func sanitizeCode(s int) string {
|
||||||
return "511"
|
return "511"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if s >= 100 && s <= 599 {
|
||||||
return strconv.Itoa(s)
|
return strconv.Itoa(s)
|
||||||
}
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
31
vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go
generated
vendored
Normal file
31
vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2022 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 promhttp
|
||||||
|
|
||||||
|
// Option are used to configure a middleware or round tripper..
|
||||||
|
type Option func(*option)
|
||||||
|
|
||||||
|
type option struct {
|
||||||
|
extraMethods []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithExtraMethods adds additional HTTP methods to the list of allowed methods.
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for the default list.
|
||||||
|
//
|
||||||
|
// See the example for ExampleInstrumentHandlerWithExtraMethods for example usage.
|
||||||
|
func WithExtraMethods(methods ...string) Option {
|
||||||
|
return func(o *option) {
|
||||||
|
o.extraMethods = methods
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ import (
|
||||||
|
|
||||||
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
|
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/golang/protobuf/ptypes"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
|
@ -183,8 +183,8 @@ const ExemplarMaxRunes = 64
|
||||||
func newExemplar(value float64, ts time.Time, l Labels) (*dto.Exemplar, error) {
|
func newExemplar(value float64, ts time.Time, l Labels) (*dto.Exemplar, error) {
|
||||||
e := &dto.Exemplar{}
|
e := &dto.Exemplar{}
|
||||||
e.Value = proto.Float64(value)
|
e.Value = proto.Float64(value)
|
||||||
tsProto, err := ptypes.TimestampProto(ts)
|
tsProto := timestamppb.New(ts)
|
||||||
if err != nil {
|
if err := tsProto.CheckValid(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
e.Timestamp = tsProto
|
e.Timestamp = tsProto
|
||||||
|
|
|
@ -133,7 +133,6 @@ github.com/imdario/mergo
|
||||||
# github.com/inconshreveable/mousetrap v1.0.0
|
# github.com/inconshreveable/mousetrap v1.0.0
|
||||||
github.com/inconshreveable/mousetrap
|
github.com/inconshreveable/mousetrap
|
||||||
# github.com/klauspost/compress v1.15.0
|
# github.com/klauspost/compress v1.15.0
|
||||||
## explicit
|
|
||||||
github.com/klauspost/compress
|
github.com/klauspost/compress
|
||||||
github.com/klauspost/compress/fse
|
github.com/klauspost/compress/fse
|
||||||
github.com/klauspost/compress/huff0
|
github.com/klauspost/compress/huff0
|
||||||
|
@ -147,7 +146,7 @@ github.com/miekg/pkcs11
|
||||||
# github.com/mitchellh/mapstructure v1.3.2
|
# github.com/mitchellh/mapstructure v1.3.2
|
||||||
## explicit
|
## explicit
|
||||||
github.com/mitchellh/mapstructure
|
github.com/mitchellh/mapstructure
|
||||||
# github.com/moby/buildkit v0.8.2-0.20210615162540-9f254e18360a
|
# github.com/moby/buildkit v0.10.0
|
||||||
## explicit
|
## explicit
|
||||||
github.com/moby/buildkit/frontend/dockerfile/dockerignore
|
github.com/moby/buildkit/frontend/dockerfile/dockerignore
|
||||||
github.com/moby/buildkit/util/appcontext
|
github.com/moby/buildkit/util/appcontext
|
||||||
|
@ -175,13 +174,13 @@ github.com/opencontainers/runc/libcontainer/user
|
||||||
# github.com/pkg/errors v0.9.1
|
# github.com/pkg/errors v0.9.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/pkg/errors
|
github.com/pkg/errors
|
||||||
# github.com/prometheus/client_golang v1.11.0
|
# github.com/prometheus/client_golang v1.12.1
|
||||||
github.com/prometheus/client_golang/prometheus
|
github.com/prometheus/client_golang/prometheus
|
||||||
github.com/prometheus/client_golang/prometheus/internal
|
github.com/prometheus/client_golang/prometheus/internal
|
||||||
github.com/prometheus/client_golang/prometheus/promhttp
|
github.com/prometheus/client_golang/prometheus/promhttp
|
||||||
# github.com/prometheus/client_model v0.2.0
|
# github.com/prometheus/client_model v0.2.0
|
||||||
github.com/prometheus/client_model/go
|
github.com/prometheus/client_model/go
|
||||||
# github.com/prometheus/common v0.30.0
|
# github.com/prometheus/common v0.32.1
|
||||||
github.com/prometheus/common/expfmt
|
github.com/prometheus/common/expfmt
|
||||||
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
|
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
|
||||||
github.com/prometheus/common/model
|
github.com/prometheus/common/model
|
||||||
|
@ -266,7 +265,6 @@ golang.org/x/xerrors/internal
|
||||||
# google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
|
# google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
|
||||||
google.golang.org/genproto/googleapis/rpc/status
|
google.golang.org/genproto/googleapis/rpc/status
|
||||||
# google.golang.org/grpc v1.44.0
|
# google.golang.org/grpc v1.44.0
|
||||||
## explicit
|
|
||||||
google.golang.org/grpc
|
google.golang.org/grpc
|
||||||
google.golang.org/grpc/attributes
|
google.golang.org/grpc/attributes
|
||||||
google.golang.org/grpc/backoff
|
google.golang.org/grpc/backoff
|
||||||
|
|
Loading…
Reference in New Issue