2021-01-22 18:21:40 +03:00
|
|
|
// Package meter is for instrumentation
|
2024-03-06 18:45:32 +03:00
|
|
|
package meter
|
2021-01-22 18:21:40 +03:00
|
|
|
|
|
|
|
import (
|
2021-01-27 00:54:19 +03:00
|
|
|
"io"
|
|
|
|
"sort"
|
2021-07-21 12:39:59 +03:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2021-01-22 18:21:40 +03:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2021-01-22 19:18:28 +03:00
|
|
|
// DefaultMeter is the default meter
|
2024-12-09 13:06:43 +03:00
|
|
|
DefaultMeter = NewMeter()
|
2021-01-22 19:18:28 +03:00
|
|
|
// DefaultAddress data will be made available on this host:port
|
|
|
|
DefaultAddress = ":9090"
|
|
|
|
// DefaultPath the meter endpoint where the Meter data will be made available
|
|
|
|
DefaultPath = "/metrics"
|
2024-09-29 22:58:53 +03:00
|
|
|
// DefaultMeterStatsInterval specifies interval for meter updating
|
|
|
|
DefaultMeterStatsInterval = 5 * time.Second
|
2021-02-14 16:16:01 +03:00
|
|
|
// DefaultSummaryQuantiles is the default spread of stats for summary
|
|
|
|
DefaultSummaryQuantiles = []float64{0.5, 0.9, 0.97, 0.99, 1}
|
|
|
|
// DefaultSummaryWindow is the default window for summary
|
|
|
|
DefaultSummaryWindow = 5 * time.Minute
|
2024-05-04 19:05:07 +03:00
|
|
|
// DefaultSkipEndpoints is the slice of endpoint that must not be metered
|
|
|
|
DefaultSkipEndpoints = []string{
|
|
|
|
"MeterService.Metrics",
|
|
|
|
"HealthService.Live",
|
|
|
|
"HealthService.Ready",
|
|
|
|
"HealthService.Version",
|
|
|
|
}
|
2021-01-22 18:21:40 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// Meter is an interface for collecting and instrumenting metrics
|
|
|
|
type Meter interface {
|
2021-10-09 23:50:57 +03:00
|
|
|
// Name returns meter name
|
2021-01-29 13:17:32 +03:00
|
|
|
Name() string
|
2021-10-09 23:50:57 +03:00
|
|
|
// Init initialize meter
|
2021-02-14 16:16:01 +03:00
|
|
|
Init(opts ...Option) error
|
2021-10-09 23:50:57 +03:00
|
|
|
// Clone create meter copy with new options
|
|
|
|
Clone(opts ...Option) Meter
|
|
|
|
// Counter get or create counter
|
2021-04-26 23:13:36 +03:00
|
|
|
Counter(name string, labels ...string) Counter
|
2021-10-09 23:50:57 +03:00
|
|
|
// FloatCounter get or create float counter
|
2021-04-26 23:13:36 +03:00
|
|
|
FloatCounter(name string, labels ...string) FloatCounter
|
2021-10-09 23:50:57 +03:00
|
|
|
// Gauge get or create gauge
|
2021-04-26 23:13:36 +03:00
|
|
|
Gauge(name string, fn func() float64, labels ...string) Gauge
|
2021-10-09 23:50:57 +03:00
|
|
|
// Set create new meter metrics set
|
2021-02-14 16:16:01 +03:00
|
|
|
Set(opts ...Option) Meter
|
2021-10-09 23:50:57 +03:00
|
|
|
// Histogram get or create histogram
|
2021-04-26 23:13:36 +03:00
|
|
|
Histogram(name string, labels ...string) Histogram
|
2021-10-09 23:50:57 +03:00
|
|
|
// Summary get or create summary
|
2021-04-26 23:13:36 +03:00
|
|
|
Summary(name string, labels ...string) Summary
|
2021-10-09 23:50:57 +03:00
|
|
|
// SummaryExt get or create summary with spcified quantiles and window time
|
2021-04-26 23:13:36 +03:00
|
|
|
SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) Summary
|
2021-10-09 23:50:57 +03:00
|
|
|
// Write writes metrics to io.Writer
|
2021-02-14 16:16:01 +03:00
|
|
|
Write(w io.Writer, opts ...Option) error
|
2021-10-09 23:50:57 +03:00
|
|
|
// Options returns meter options
|
2021-01-22 18:21:40 +03:00
|
|
|
Options() Options
|
2021-10-09 23:50:57 +03:00
|
|
|
// String return meter type
|
2021-01-22 18:21:40 +03:00
|
|
|
String() string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Counter is a counter
|
|
|
|
type Counter interface {
|
|
|
|
Add(int)
|
|
|
|
Dec()
|
|
|
|
Get() uint64
|
|
|
|
Inc()
|
|
|
|
Set(uint64)
|
|
|
|
}
|
|
|
|
|
|
|
|
// FloatCounter is a float64 counter
|
|
|
|
type FloatCounter interface {
|
|
|
|
Add(float64)
|
|
|
|
Get() float64
|
|
|
|
Set(float64)
|
|
|
|
Sub(float64)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gauge is a float64 gauge
|
|
|
|
type Gauge interface {
|
|
|
|
Get() float64
|
|
|
|
}
|
|
|
|
|
|
|
|
// Histogram is a histogram for non-negative values with automatically created buckets
|
|
|
|
type Histogram interface {
|
|
|
|
Reset()
|
|
|
|
Update(float64)
|
|
|
|
UpdateDuration(time.Time)
|
|
|
|
// VisitNonZeroBuckets(f func(vmrange string, count uint64))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Summary is the summary
|
|
|
|
type Summary interface {
|
|
|
|
Update(float64)
|
|
|
|
UpdateDuration(time.Time)
|
|
|
|
}
|
2021-01-27 00:54:19 +03:00
|
|
|
|
2021-07-21 12:39:59 +03:00
|
|
|
// sort labels alphabeticaly by label name
|
2021-03-15 00:44:13 +03:00
|
|
|
type byKey []string
|
2021-02-18 15:57:42 +03:00
|
|
|
|
2021-03-15 00:44:13 +03:00
|
|
|
func (k byKey) Len() int { return len(k) / 2 }
|
|
|
|
func (k byKey) Less(i, j int) bool { return k[i*2] < k[j*2] }
|
|
|
|
func (k byKey) Swap(i, j int) {
|
2021-07-21 12:39:59 +03:00
|
|
|
k[i*2], k[j*2] = k[j*2], k[i*2]
|
|
|
|
k[i*2+1], k[j*2+1] = k[j*2+1], k[i*2+1]
|
2021-01-27 00:54:19 +03:00
|
|
|
}
|
|
|
|
|
2022-03-22 14:54:43 +03:00
|
|
|
// BuildLabels used to sort labels and delete duplicates.
|
2021-07-21 14:10:20 +03:00
|
|
|
// Last value wins in case of duplicate label keys.
|
|
|
|
func BuildLabels(labels ...string) []string {
|
|
|
|
if len(labels)%2 == 1 {
|
|
|
|
labels = labels[:len(labels)-1]
|
|
|
|
}
|
|
|
|
sort.Sort(byKey(labels))
|
|
|
|
return labels
|
|
|
|
}
|
|
|
|
|
2021-07-21 12:39:59 +03:00
|
|
|
// BuildName used to combine metric with labels.
|
|
|
|
// If labels count is odd, drop last element
|
|
|
|
func BuildName(name string, labels ...string) string {
|
|
|
|
if len(labels)%2 == 1 {
|
|
|
|
labels = labels[:len(labels)-1]
|
2021-01-27 00:54:19 +03:00
|
|
|
}
|
2021-07-21 12:39:59 +03:00
|
|
|
|
2021-07-21 14:29:13 +03:00
|
|
|
if len(labels) > 2 {
|
|
|
|
sort.Sort(byKey(labels))
|
|
|
|
|
|
|
|
idx := 0
|
|
|
|
for {
|
|
|
|
if labels[idx] == labels[idx+2] {
|
|
|
|
copy(labels[idx:], labels[idx+2:])
|
|
|
|
labels = labels[:len(labels)-2]
|
|
|
|
} else {
|
|
|
|
idx += 2
|
|
|
|
}
|
|
|
|
if idx+2 >= len(labels) {
|
|
|
|
break
|
|
|
|
}
|
2021-03-15 00:44:13 +03:00
|
|
|
}
|
|
|
|
}
|
2021-07-21 12:39:59 +03:00
|
|
|
|
|
|
|
var b strings.Builder
|
|
|
|
_, _ = b.WriteString(name)
|
|
|
|
_, _ = b.WriteRune('{')
|
|
|
|
for idx := 0; idx < len(labels); idx += 2 {
|
|
|
|
if idx > 0 {
|
|
|
|
_, _ = b.WriteRune(',')
|
|
|
|
}
|
|
|
|
_, _ = b.WriteString(labels[idx])
|
|
|
|
_, _ = b.WriteString(`=`)
|
|
|
|
_, _ = b.WriteString(strconv.Quote(labels[idx+1]))
|
|
|
|
}
|
|
|
|
_, _ = b.WriteRune('}')
|
|
|
|
|
|
|
|
return b.String()
|
2021-01-27 00:54:19 +03:00
|
|
|
}
|