diff options
author | qrort <qrort@yandex-team.com> | 2022-12-02 11:31:25 +0300 |
---|---|---|
committer | qrort <qrort@yandex-team.com> | 2022-12-02 11:31:25 +0300 |
commit | b1f4ffc9c8abff3ba58dc1ec9a9f92d2f0de6806 (patch) | |
tree | 2a23209faf0fea5586a6d4b9cee60d1b318d29fe /library/go/core/metrics | |
parent | 559174a9144de40d6bb3997ea4073c82289b4974 (diff) | |
download | ydb-b1f4ffc9c8abff3ba58dc1ec9a9f92d2f0de6806.tar.gz |
remove kikimr/driver DEPENDS
Diffstat (limited to 'library/go/core/metrics')
21 files changed, 0 insertions, 2717 deletions
diff --git a/library/go/core/metrics/buckets.go b/library/go/core/metrics/buckets.go deleted file mode 100644 index 063c0c4418..0000000000 --- a/library/go/core/metrics/buckets.go +++ /dev/null @@ -1,147 +0,0 @@ -package metrics - -import ( - "sort" - "time" -) - -var ( - _ DurationBuckets = (*durationBuckets)(nil) - _ Buckets = (*buckets)(nil) -) - -const ( - errBucketsCountNeedsGreaterThanZero = "n needs to be > 0" - errBucketsStartNeedsGreaterThanZero = "start needs to be > 0" - errBucketsFactorNeedsGreaterThanOne = "factor needs to be > 1" -) - -type durationBuckets struct { - buckets []time.Duration -} - -// NewDurationBuckets returns new DurationBuckets implementation. -func NewDurationBuckets(bk ...time.Duration) DurationBuckets { - sort.Slice(bk, func(i, j int) bool { - return bk[i] < bk[j] - }) - return durationBuckets{buckets: bk} -} - -func (d durationBuckets) Size() int { - return len(d.buckets) -} - -func (d durationBuckets) MapDuration(dv time.Duration) (idx int) { - for _, bound := range d.buckets { - if dv < bound { - break - } - idx++ - } - return -} - -func (d durationBuckets) UpperBound(idx int) time.Duration { - if idx > d.Size()-1 { - panic("idx is out of bounds") - } - return d.buckets[idx] -} - -type buckets struct { - buckets []float64 -} - -// NewBuckets returns new Buckets implementation. -func NewBuckets(bk ...float64) Buckets { - sort.Slice(bk, func(i, j int) bool { - return bk[i] < bk[j] - }) - return buckets{buckets: bk} -} - -func (d buckets) Size() int { - return len(d.buckets) -} - -func (d buckets) MapValue(v float64) (idx int) { - for _, bound := range d.buckets { - if v < bound { - break - } - idx++ - } - return -} - -func (d buckets) UpperBound(idx int) float64 { - if idx > d.Size()-1 { - panic("idx is out of bounds") - } - return d.buckets[idx] -} - -// MakeLinearBuckets creates a set of linear value buckets. -func MakeLinearBuckets(start, width float64, n int) Buckets { - if n <= 0 { - panic(errBucketsCountNeedsGreaterThanZero) - } - bounds := make([]float64, n) - for i := range bounds { - bounds[i] = start + (float64(i) * width) - } - return NewBuckets(bounds...) -} - -// MakeLinearDurationBuckets creates a set of linear duration buckets. -func MakeLinearDurationBuckets(start, width time.Duration, n int) DurationBuckets { - if n <= 0 { - panic(errBucketsCountNeedsGreaterThanZero) - } - buckets := make([]time.Duration, n) - for i := range buckets { - buckets[i] = start + (time.Duration(i) * width) - } - return NewDurationBuckets(buckets...) -} - -// MakeExponentialBuckets creates a set of exponential value buckets. -func MakeExponentialBuckets(start, factor float64, n int) Buckets { - if n <= 0 { - panic(errBucketsCountNeedsGreaterThanZero) - } - if start <= 0 { - panic(errBucketsStartNeedsGreaterThanZero) - } - if factor <= 1 { - panic(errBucketsFactorNeedsGreaterThanOne) - } - buckets := make([]float64, n) - curr := start - for i := range buckets { - buckets[i] = curr - curr *= factor - } - return NewBuckets(buckets...) -} - -// MakeExponentialDurationBuckets creates a set of exponential duration buckets. -func MakeExponentialDurationBuckets(start time.Duration, factor float64, n int) DurationBuckets { - if n <= 0 { - panic(errBucketsCountNeedsGreaterThanZero) - } - if start <= 0 { - panic(errBucketsStartNeedsGreaterThanZero) - } - if factor <= 1 { - panic(errBucketsFactorNeedsGreaterThanOne) - } - buckets := make([]time.Duration, n) - curr := start - for i := range buckets { - buckets[i] = curr - curr = time.Duration(float64(curr) * factor) - } - return NewDurationBuckets(buckets...) -} diff --git a/library/go/core/metrics/collect/collect.go b/library/go/core/metrics/collect/collect.go deleted file mode 100644 index 3abbbcdfa9..0000000000 --- a/library/go/core/metrics/collect/collect.go +++ /dev/null @@ -1,9 +0,0 @@ -package collect - -import ( - "context" - - "a.yandex-team.ru/library/go/core/metrics" -) - -type Func func(ctx context.Context, r metrics.Registry, c metrics.CollectPolicy) diff --git a/library/go/core/metrics/collect/system.go b/library/go/core/metrics/collect/system.go deleted file mode 100644 index 8ce89ebc05..0000000000 --- a/library/go/core/metrics/collect/system.go +++ /dev/null @@ -1,229 +0,0 @@ -package collect - -import ( - "context" - "os" - "runtime" - "runtime/debug" - "time" - - "github.com/prometheus/procfs" - - "a.yandex-team.ru/library/go/core/buildinfo" - "a.yandex-team.ru/library/go/core/metrics" -) - -var _ Func = GoMetrics - -func GoMetrics(_ context.Context, r metrics.Registry, c metrics.CollectPolicy) { - if r == nil { - return - } - r = r.WithPrefix("go") - - var stats debug.GCStats - stats.PauseQuantiles = make([]time.Duration, 5) // Minimum, 25%, 50%, 75%, and maximum pause times. - var numGoroutine, numThread int - var ms runtime.MemStats - - c.AddCollect(func(context.Context) { - debug.ReadGCStats(&stats) - runtime.ReadMemStats(&ms) - - numThread, _ = runtime.ThreadCreateProfile(nil) - numGoroutine = runtime.NumGoroutine() - }) - - gcRegistry := r.WithPrefix("gc") - gcRegistry.FuncCounter("num", c.RegisteredCounter(func() int64 { - return stats.NumGC - })) - gcRegistry.FuncCounter(r.ComposeName("pause", "total", "ns"), c.RegisteredCounter(func() int64 { - return stats.PauseTotal.Nanoseconds() - })) - gcRegistry.FuncGauge(r.ComposeName("pause", "quantile", "min"), c.RegisteredGauge(func() float64 { - return stats.PauseQuantiles[0].Seconds() - })) - gcRegistry.FuncGauge(r.ComposeName("pause", "quantile", "25"), c.RegisteredGauge(func() float64 { - return stats.PauseQuantiles[1].Seconds() - })) - gcRegistry.FuncGauge(r.ComposeName("pause", "quantile", "50"), c.RegisteredGauge(func() float64 { - return stats.PauseQuantiles[2].Seconds() - })) - gcRegistry.FuncGauge(r.ComposeName("pause", "quantile", "75"), c.RegisteredGauge(func() float64 { - return stats.PauseQuantiles[3].Seconds() - })) - gcRegistry.FuncGauge(r.ComposeName("pause", "quantile", "max"), c.RegisteredGauge(func() float64 { - return stats.PauseQuantiles[4].Seconds() - })) - gcRegistry.FuncGauge(r.ComposeName("last", "ts"), c.RegisteredGauge(func() float64 { - return float64(ms.LastGC) - })) - gcRegistry.FuncCounter(r.ComposeName("forced", "num"), c.RegisteredCounter(func() int64 { - return int64(ms.NumForcedGC) - })) - - r.FuncGauge(r.ComposeName("goroutine", "num"), c.RegisteredGauge(func() float64 { - return float64(numGoroutine) - })) - r.FuncGauge(r.ComposeName("thread", "num"), c.RegisteredGauge(func() float64 { - return float64(numThread) - })) - - memRegistry := r.WithPrefix("mem") - memRegistry.FuncCounter(r.ComposeName("alloc", "total"), c.RegisteredCounter(func() int64 { - return int64(ms.TotalAlloc) - })) - memRegistry.FuncGauge("sys", c.RegisteredGauge(func() float64 { - return float64(ms.Sys) - })) - memRegistry.FuncCounter("lookups", c.RegisteredCounter(func() int64 { - return int64(ms.Lookups) - })) - memRegistry.FuncCounter("mallocs", c.RegisteredCounter(func() int64 { - return int64(ms.Mallocs) - })) - memRegistry.FuncCounter("frees", c.RegisteredCounter(func() int64 { - return int64(ms.Frees) - })) - memRegistry.FuncGauge(r.ComposeName("heap", "alloc"), c.RegisteredGauge(func() float64 { - return float64(ms.HeapAlloc) - })) - memRegistry.FuncGauge(r.ComposeName("heap", "sys"), c.RegisteredGauge(func() float64 { - return float64(ms.HeapSys) - })) - memRegistry.FuncGauge(r.ComposeName("heap", "idle"), c.RegisteredGauge(func() float64 { - return float64(ms.HeapIdle) - })) - memRegistry.FuncGauge(r.ComposeName("heap", "inuse"), c.RegisteredGauge(func() float64 { - return float64(ms.HeapInuse) - })) - memRegistry.FuncGauge(r.ComposeName("heap", "released"), c.RegisteredGauge(func() float64 { - return float64(ms.HeapReleased) - })) - memRegistry.FuncGauge(r.ComposeName("heap", "objects"), c.RegisteredGauge(func() float64 { - return float64(ms.HeapObjects) - })) - - memRegistry.FuncGauge(r.ComposeName("stack", "inuse"), c.RegisteredGauge(func() float64 { - return float64(ms.StackInuse) - })) - memRegistry.FuncGauge(r.ComposeName("stack", "sys"), c.RegisteredGauge(func() float64 { - return float64(ms.StackSys) - })) - - memRegistry.FuncGauge(r.ComposeName("span", "inuse"), c.RegisteredGauge(func() float64 { - return float64(ms.MSpanInuse) - })) - memRegistry.FuncGauge(r.ComposeName("span", "sys"), c.RegisteredGauge(func() float64 { - return float64(ms.MSpanSys) - })) - - memRegistry.FuncGauge(r.ComposeName("cache", "inuse"), c.RegisteredGauge(func() float64 { - return float64(ms.MCacheInuse) - })) - memRegistry.FuncGauge(r.ComposeName("cache", "sys"), c.RegisteredGauge(func() float64 { - return float64(ms.MCacheSys) - })) - - memRegistry.FuncGauge(r.ComposeName("buck", "hash", "sys"), c.RegisteredGauge(func() float64 { - return float64(ms.BuckHashSys) - })) - memRegistry.FuncGauge(r.ComposeName("gc", "sys"), c.RegisteredGauge(func() float64 { - return float64(ms.GCSys) - })) - memRegistry.FuncGauge(r.ComposeName("other", "sys"), c.RegisteredGauge(func() float64 { - return float64(ms.OtherSys) - })) - memRegistry.FuncGauge(r.ComposeName("gc", "next"), c.RegisteredGauge(func() float64 { - return float64(ms.NextGC) - })) - - memRegistry.FuncGauge(r.ComposeName("gc", "cpu", "fraction"), c.RegisteredGauge(func() float64 { - return ms.GCCPUFraction - })) -} - -var _ Func = ProcessMetrics - -func ProcessMetrics(_ context.Context, r metrics.Registry, c metrics.CollectPolicy) { - if r == nil { - return - } - buildVersion := buildinfo.Info.ArcadiaSourceRevision - r.WithTags(map[string]string{"revision": buildVersion}).Gauge("build").Set(1.0) - - pid := os.Getpid() - proc, err := procfs.NewProc(pid) - if err != nil { - return - } - - procRegistry := r.WithPrefix("proc") - - var ioStat procfs.ProcIO - var procStat procfs.ProcStat - var fd int - var cpuWait uint64 - - const clocksPerSec = 100 - - c.AddCollect(func(ctx context.Context) { - if gatheredFD, err := proc.FileDescriptorsLen(); err == nil { - fd = gatheredFD - } - - if gatheredIOStat, err := proc.IO(); err == nil { - ioStat.SyscW = gatheredIOStat.SyscW - ioStat.WriteBytes = gatheredIOStat.WriteBytes - ioStat.SyscR = gatheredIOStat.SyscR - ioStat.ReadBytes = gatheredIOStat.ReadBytes - } - - if gatheredStat, err := proc.Stat(); err == nil { - procStat.UTime = gatheredStat.UTime - procStat.STime = gatheredStat.STime - procStat.RSS = gatheredStat.RSS - } - - if gatheredSched, err := proc.Schedstat(); err == nil { - cpuWait = gatheredSched.WaitingNanoseconds - } - }) - - procRegistry.FuncGauge("fd", c.RegisteredGauge(func() float64 { - return float64(fd) - })) - - ioRegistry := procRegistry.WithPrefix("io") - ioRegistry.FuncCounter(r.ComposeName("read", "count"), c.RegisteredCounter(func() int64 { - return int64(ioStat.SyscR) - })) - ioRegistry.FuncCounter(r.ComposeName("read", "bytes"), c.RegisteredCounter(func() int64 { - return int64(ioStat.ReadBytes) - })) - ioRegistry.FuncCounter(r.ComposeName("write", "count"), c.RegisteredCounter(func() int64 { - return int64(ioStat.SyscW) - })) - ioRegistry.FuncCounter(r.ComposeName("write", "bytes"), c.RegisteredCounter(func() int64 { - return int64(ioStat.WriteBytes) - })) - - cpuRegistry := procRegistry.WithPrefix("cpu") - cpuRegistry.FuncCounter(r.ComposeName("total", "ns"), c.RegisteredCounter(func() int64 { - return int64(procStat.UTime+procStat.STime) * (1_000_000_000 / clocksPerSec) - })) - cpuRegistry.FuncCounter(r.ComposeName("user", "ns"), c.RegisteredCounter(func() int64 { - return int64(procStat.UTime) * (1_000_000_000 / clocksPerSec) - })) - cpuRegistry.FuncCounter(r.ComposeName("system", "ns"), c.RegisteredCounter(func() int64 { - return int64(procStat.STime) * (1_000_000_000 / clocksPerSec) - })) - cpuRegistry.FuncCounter(r.ComposeName("wait", "ns"), c.RegisteredCounter(func() int64 { - return int64(cpuWait) - })) - - procRegistry.FuncGauge(r.ComposeName("mem", "rss"), c.RegisteredGauge(func() float64 { - return float64(procStat.RSS) - })) -} diff --git a/library/go/core/metrics/internal/pkg/metricsutil/buckets.go b/library/go/core/metrics/internal/pkg/metricsutil/buckets.go deleted file mode 100644 index 5db605cd4d..0000000000 --- a/library/go/core/metrics/internal/pkg/metricsutil/buckets.go +++ /dev/null @@ -1,27 +0,0 @@ -package metricsutil - -import ( - "sort" - - "a.yandex-team.ru/library/go/core/metrics" -) - -// BucketsBounds unwraps Buckets bounds to slice of float64. -func BucketsBounds(b metrics.Buckets) []float64 { - bkts := make([]float64, b.Size()) - for i := range bkts { - bkts[i] = b.UpperBound(i) - } - sort.Float64s(bkts) - return bkts -} - -// DurationBucketsBounds unwraps DurationBuckets bounds to slice of float64. -func DurationBucketsBounds(b metrics.DurationBuckets) []float64 { - bkts := make([]float64, b.Size()) - for i := range bkts { - bkts[i] = b.UpperBound(i).Seconds() - } - sort.Float64s(bkts) - return bkts -} diff --git a/library/go/core/metrics/internal/pkg/registryutil/registryutil.go b/library/go/core/metrics/internal/pkg/registryutil/registryutil.go deleted file mode 100644 index ebce50d8cb..0000000000 --- a/library/go/core/metrics/internal/pkg/registryutil/registryutil.go +++ /dev/null @@ -1,104 +0,0 @@ -package registryutil - -import ( - "errors" - "fmt" - "sort" - "strconv" - "strings" - - "github.com/OneOfOne/xxhash" -) - -// BuildRegistryKey creates registry name based on given prefix and tags -func BuildRegistryKey(prefix string, tags map[string]string) string { - var builder strings.Builder - - builder.WriteString(strconv.Quote(prefix)) - builder.WriteRune('{') - builder.WriteString(StringifyTags(tags)) - builder.WriteByte('}') - - return builder.String() -} - -// BuildFQName returns name parts joined by given separator. -// Mainly used to append prefix to registry -func BuildFQName(separator string, parts ...string) (name string) { - var b strings.Builder - for _, p := range parts { - if p == "" { - continue - } - if b.Len() > 0 { - b.WriteString(separator) - } - b.WriteString(strings.Trim(p, separator)) - } - return b.String() -} - -// MergeTags merges 2 sets of tags with the tags from tagsRight overriding values from tagsLeft -func MergeTags(leftTags map[string]string, rightTags map[string]string) map[string]string { - if leftTags == nil && rightTags == nil { - return nil - } - - if len(leftTags) == 0 { - return rightTags - } - - if len(rightTags) == 0 { - return leftTags - } - - newTags := make(map[string]string) - for key, value := range leftTags { - newTags[key] = value - } - for key, value := range rightTags { - newTags[key] = value - } - return newTags -} - -// StringifyTags returns string representation of given tags map. -// It is guaranteed that equal sets of tags will produce equal strings. -func StringifyTags(tags map[string]string) string { - keys := make([]string, 0, len(tags)) - for key := range tags { - keys = append(keys, key) - } - sort.Strings(keys) - - var builder strings.Builder - for i, key := range keys { - if i > 0 { - builder.WriteByte(',') - } - builder.WriteString(key + "=" + tags[key]) - } - - return builder.String() -} - -// VectorHash computes hash of metrics vector element -func VectorHash(tags map[string]string, labels []string) (uint64, error) { - if len(tags) != len(labels) { - return 0, errors.New("inconsistent tags and labels sets") - } - - h := xxhash.New64() - - for _, label := range labels { - v, ok := tags[label] - if !ok { - return 0, fmt.Errorf("label '%s' not found in tags", label) - } - _, _ = h.WriteString(label) - _, _ = h.WriteString(v) - _, _ = h.WriteString(",") - } - - return h.Sum64(), nil -} diff --git a/library/go/core/metrics/metrics.go b/library/go/core/metrics/metrics.go deleted file mode 100644 index 0eb436046b..0000000000 --- a/library/go/core/metrics/metrics.go +++ /dev/null @@ -1,140 +0,0 @@ -// Package metrics provides interface collecting performance metrics. -package metrics - -import ( - "context" - "time" -) - -// Gauge tracks single float64 value. -type Gauge interface { - Set(value float64) - Add(value float64) -} - -// FuncGauge is Gauge with value provided by callback function. -type FuncGauge interface { - Function() func() float64 -} - -// Counter tracks monotonically increasing value. -type Counter interface { - // Inc increments counter by 1. - Inc() - - // Add adds delta to the counter. Delta must be >=0. - Add(delta int64) -} - -// FuncCounter is Counter with value provided by callback function. -type FuncCounter interface { - Function() func() int64 -} - -// Histogram tracks distribution of value. -type Histogram interface { - RecordValue(value float64) -} - -// Timer measures durations. -type Timer interface { - RecordDuration(value time.Duration) -} - -// DurationBuckets defines buckets of the duration histogram. -type DurationBuckets interface { - // Size returns number of buckets. - Size() int - - // MapDuration returns index of the bucket. - // - // index is integer in range [0, Size()). - MapDuration(d time.Duration) int - - // UpperBound of the last bucket is always +Inf. - // - // bucketIndex is integer in range [0, Size()-1). - UpperBound(bucketIndex int) time.Duration -} - -// Buckets defines intervals of the regular histogram. -type Buckets interface { - // Size returns number of buckets. - Size() int - - // MapValue returns index of the bucket. - // - // Index is integer in range [0, Size()). - MapValue(v float64) int - - // UpperBound of the last bucket is always +Inf. - // - // bucketIndex is integer in range [0, Size()-1). - UpperBound(bucketIndex int) float64 -} - -// GaugeVec stores multiple dynamically created gauges. -type GaugeVec interface { - With(map[string]string) Gauge - - // Reset deletes all metrics in vector. - Reset() -} - -// CounterVec stores multiple dynamically created counters. -type CounterVec interface { - With(map[string]string) Counter - - // Reset deletes all metrics in vector. - Reset() -} - -// TimerVec stores multiple dynamically created timers. -type TimerVec interface { - With(map[string]string) Timer - - // Reset deletes all metrics in vector. - Reset() -} - -// HistogramVec stores multiple dynamically created histograms. -type HistogramVec interface { - With(map[string]string) Histogram - - // Reset deletes all metrics in vector. - Reset() -} - -// Registry creates profiling metrics. -type Registry interface { - // WithTags creates new sub-scope, where each metric has tags attached to it. - WithTags(tags map[string]string) Registry - // WithPrefix creates new sub-scope, where each metric has prefix added to it name. - WithPrefix(prefix string) Registry - - ComposeName(parts ...string) string - - Counter(name string) Counter - CounterVec(name string, labels []string) CounterVec - FuncCounter(name string, function func() int64) FuncCounter - - Gauge(name string) Gauge - GaugeVec(name string, labels []string) GaugeVec - FuncGauge(name string, function func() float64) FuncGauge - - Timer(name string) Timer - TimerVec(name string, labels []string) TimerVec - - Histogram(name string, buckets Buckets) Histogram - HistogramVec(name string, buckets Buckets, labels []string) HistogramVec - - DurationHistogram(name string, buckets DurationBuckets) Timer - DurationHistogramVec(name string, buckets DurationBuckets, labels []string) TimerVec -} - -// CollectPolicy defines how registered gauge metrics are updated via collect func. -type CollectPolicy interface { - RegisteredCounter(counterFunc func() int64) func() int64 - RegisteredGauge(gaugeFunc func() float64) func() float64 - AddCollect(collect func(ctx context.Context)) -} diff --git a/library/go/core/metrics/solomon/converter.go b/library/go/core/metrics/solomon/converter.go deleted file mode 100644 index 4458d1a932..0000000000 --- a/library/go/core/metrics/solomon/converter.go +++ /dev/null @@ -1,73 +0,0 @@ -package solomon - -import ( - "fmt" - - dto "github.com/prometheus/client_model/go" - "go.uber.org/atomic" -) - -// PrometheusMetrics converts Prometheus metrics to Solomon metrics. -func PrometheusMetrics(metrics []*dto.MetricFamily) (*Metrics, error) { - s := &Metrics{ - metrics: make([]Metric, 0, len(metrics)), - } - - if len(metrics) == 0 { - return s, nil - } - - for _, mf := range metrics { - if len(mf.Metric) == 0 { - continue - } - - metric := mf.Metric[0] - - tags := make(map[string]string, len(metric.Label)) - for _, label := range metric.Label { - tags[label.GetName()] = label.GetValue() - } - - switch *mf.Type { - case dto.MetricType_COUNTER: - s.metrics = append(s.metrics, &Counter{ - name: mf.GetName(), - tags: tags, - value: *atomic.NewInt64(int64(metric.Counter.GetValue())), - }) - case dto.MetricType_GAUGE: - s.metrics = append(s.metrics, &Gauge{ - name: mf.GetName(), - tags: tags, - value: *atomic.NewFloat64(metric.Gauge.GetValue()), - }) - case dto.MetricType_HISTOGRAM: - bounds := make([]float64, 0, len(metric.Histogram.Bucket)) - values := make([]int64, 0, len(metric.Histogram.Bucket)) - - var prevValuesSum int64 - - for _, bucket := range metric.Histogram.Bucket { - // prometheus uses cumulative buckets where solomon uses instant - bucketValue := int64(bucket.GetCumulativeCount()) - bucketValue -= prevValuesSum - prevValuesSum += bucketValue - - bounds = append(bounds, bucket.GetUpperBound()) - values = append(values, bucketValue) - } - - s.metrics = append(s.metrics, &Histogram{ - name: mf.GetName(), - tags: tags, - bucketBounds: bounds, - bucketValues: values, - }) - default: - return nil, fmt.Errorf("unsupported type: %s", mf.Type.String()) - } - } - - return s, nil -} diff --git a/library/go/core/metrics/solomon/counter.go b/library/go/core/metrics/solomon/counter.go deleted file mode 100644 index 64ea1b47ca..0000000000 --- a/library/go/core/metrics/solomon/counter.go +++ /dev/null @@ -1,98 +0,0 @@ -package solomon - -import ( - "encoding/json" - "time" - - "go.uber.org/atomic" - - "a.yandex-team.ru/library/go/core/metrics" -) - -var ( - _ metrics.Counter = (*Counter)(nil) - _ Metric = (*Counter)(nil) -) - -// Counter tracks monotonically increasing value. -type Counter struct { - name string - metricType metricType - tags map[string]string - value atomic.Int64 - timestamp *time.Time - - useNameTag bool -} - -// Inc increments counter by 1. -func (c *Counter) Inc() { - c.Add(1) -} - -// Add adds delta to the counter. Delta must be >=0. -func (c *Counter) Add(delta int64) { - c.value.Add(delta) -} - -func (c *Counter) Name() string { - return c.name -} - -func (c *Counter) getType() metricType { - return c.metricType -} - -func (c *Counter) getLabels() map[string]string { - return c.tags -} - -func (c *Counter) getValue() interface{} { - return c.value.Load() -} - -func (c *Counter) getTimestamp() *time.Time { - return c.timestamp -} - -func (c *Counter) getNameTag() string { - if c.useNameTag { - return "name" - } else { - return "sensor" - } -} - -// MarshalJSON implements json.Marshaler. -func (c *Counter) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string `json:"type"` - Labels map[string]string `json:"labels"` - Value int64 `json:"value"` - Timestamp *int64 `json:"ts,omitempty"` - }{ - Type: c.metricType.String(), - Value: c.value.Load(), - Labels: func() map[string]string { - labels := make(map[string]string, len(c.tags)+1) - labels[c.getNameTag()] = c.Name() - for k, v := range c.tags { - labels[k] = v - } - return labels - }(), - Timestamp: tsAsRef(c.timestamp), - }) -} - -// Snapshot returns independent copy on metric. -func (c *Counter) Snapshot() Metric { - return &Counter{ - name: c.name, - metricType: c.metricType, - tags: c.tags, - value: *atomic.NewInt64(c.value.Load()), - - useNameTag: c.useNameTag, - } -} diff --git a/library/go/core/metrics/solomon/func_counter.go b/library/go/core/metrics/solomon/func_counter.go deleted file mode 100644 index db862869e4..0000000000 --- a/library/go/core/metrics/solomon/func_counter.go +++ /dev/null @@ -1,86 +0,0 @@ -package solomon - -import ( - "encoding/json" - "time" - - "go.uber.org/atomic" -) - -var _ Metric = (*FuncCounter)(nil) - -// FuncCounter tracks int64 value returned by function. -type FuncCounter struct { - name string - metricType metricType - tags map[string]string - function func() int64 - timestamp *time.Time - useNameTag bool -} - -func (c *FuncCounter) Name() string { - return c.name -} - -func (c *FuncCounter) Function() func() int64 { - return c.function -} - -func (c *FuncCounter) getType() metricType { - return c.metricType -} - -func (c *FuncCounter) getLabels() map[string]string { - return c.tags -} - -func (c *FuncCounter) getValue() interface{} { - return c.function() -} - -func (c *FuncCounter) getTimestamp() *time.Time { - return c.timestamp -} - -func (c *FuncCounter) getNameTag() string { - if c.useNameTag { - return "name" - } else { - return "sensor" - } -} - -// MarshalJSON implements json.Marshaler. -func (c *FuncCounter) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string `json:"type"` - Labels map[string]string `json:"labels"` - Value int64 `json:"value"` - Timestamp *int64 `json:"ts,omitempty"` - }{ - Type: c.metricType.String(), - Value: c.function(), - Labels: func() map[string]string { - labels := make(map[string]string, len(c.tags)+1) - labels[c.getNameTag()] = c.Name() - for k, v := range c.tags { - labels[k] = v - } - return labels - }(), - Timestamp: tsAsRef(c.timestamp), - }) -} - -// Snapshot returns independent copy on metric. -func (c *FuncCounter) Snapshot() Metric { - return &Counter{ - name: c.name, - metricType: c.metricType, - tags: c.tags, - value: *atomic.NewInt64(c.function()), - - useNameTag: c.useNameTag, - } -} diff --git a/library/go/core/metrics/solomon/func_gauge.go b/library/go/core/metrics/solomon/func_gauge.go deleted file mode 100644 index ce824c6fa8..0000000000 --- a/library/go/core/metrics/solomon/func_gauge.go +++ /dev/null @@ -1,87 +0,0 @@ -package solomon - -import ( - "encoding/json" - "time" - - "go.uber.org/atomic" -) - -var _ Metric = (*FuncGauge)(nil) - -// FuncGauge tracks float64 value returned by function. -type FuncGauge struct { - name string - metricType metricType - tags map[string]string - function func() float64 - timestamp *time.Time - - useNameTag bool -} - -func (g *FuncGauge) Name() string { - return g.name -} - -func (g *FuncGauge) Function() func() float64 { - return g.function -} - -func (g *FuncGauge) getType() metricType { - return g.metricType -} - -func (g *FuncGauge) getLabels() map[string]string { - return g.tags -} - -func (g *FuncGauge) getValue() interface{} { - return g.function() -} - -func (g *FuncGauge) getTimestamp() *time.Time { - return g.timestamp -} - -func (g *FuncGauge) getNameTag() string { - if g.useNameTag { - return "name" - } else { - return "sensor" - } -} - -// MarshalJSON implements json.Marshaler. -func (g *FuncGauge) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string `json:"type"` - Labels map[string]string `json:"labels"` - Value float64 `json:"value"` - Timestamp *int64 `json:"ts,omitempty"` - }{ - Type: g.metricType.String(), - Value: g.function(), - Labels: func() map[string]string { - labels := make(map[string]string, len(g.tags)+1) - labels[g.getNameTag()] = g.Name() - for k, v := range g.tags { - labels[k] = v - } - return labels - }(), - Timestamp: tsAsRef(g.timestamp), - }) -} - -// Snapshot returns independent copy on metric. -func (g *FuncGauge) Snapshot() Metric { - return &Gauge{ - name: g.name, - metricType: g.metricType, - tags: g.tags, - value: *atomic.NewFloat64(g.function()), - - useNameTag: g.useNameTag, - } -} diff --git a/library/go/core/metrics/solomon/gauge.go b/library/go/core/metrics/solomon/gauge.go deleted file mode 100644 index 4d7e17195d..0000000000 --- a/library/go/core/metrics/solomon/gauge.go +++ /dev/null @@ -1,116 +0,0 @@ -package solomon - -import ( - "encoding/json" - "time" - - "go.uber.org/atomic" - - "a.yandex-team.ru/library/go/core/metrics" -) - -var ( - _ metrics.Gauge = (*Gauge)(nil) - _ Metric = (*Gauge)(nil) -) - -// Gauge tracks single float64 value. -type Gauge struct { - name string - metricType metricType - tags map[string]string - value atomic.Float64 - timestamp *time.Time - - useNameTag bool -} - -func NewGauge(name string, value float64, opts ...metricOpts) Gauge { - mOpts := MetricsOpts{} - for _, op := range opts { - op(&mOpts) - } - return Gauge{ - name: name, - metricType: typeGauge, - tags: mOpts.tags, - value: *atomic.NewFloat64(value), - useNameTag: mOpts.useNameTag, - timestamp: mOpts.timestamp, - } -} - -func (g *Gauge) Set(value float64) { - g.value.Store(value) -} - -func (g *Gauge) Add(value float64) { - g.value.Add(value) -} - -func (g *Gauge) Name() string { - return g.name -} - -func (g *Gauge) getType() metricType { - return g.metricType -} - -func (g *Gauge) getLabels() map[string]string { - return g.tags -} - -func (g *Gauge) getValue() interface{} { - return g.value.Load() -} - -func (g *Gauge) getTimestamp() *time.Time { - return g.timestamp -} - -func (g *Gauge) getNameTag() string { - if g.useNameTag { - return "name" - } else { - return "sensor" - } -} - -// MarshalJSON implements json.Marshaler. -func (g *Gauge) MarshalJSON() ([]byte, error) { - metricType := g.metricType.String() - value := g.value.Load() - labels := func() map[string]string { - labels := make(map[string]string, len(g.tags)+1) - labels[g.getNameTag()] = g.Name() - for k, v := range g.tags { - labels[k] = v - } - return labels - }() - - return json.Marshal(struct { - Type string `json:"type"` - Labels map[string]string `json:"labels"` - Value float64 `json:"value"` - Timestamp *int64 `json:"ts,omitempty"` - }{ - Type: metricType, - Value: value, - Labels: labels, - Timestamp: tsAsRef(g.timestamp), - }) -} - -// Snapshot returns independent copy of metric. -func (g *Gauge) Snapshot() Metric { - return &Gauge{ - name: g.name, - metricType: g.metricType, - tags: g.tags, - value: *atomic.NewFloat64(g.value.Load()), - - useNameTag: g.useNameTag, - timestamp: g.timestamp, - } -} diff --git a/library/go/core/metrics/solomon/histogram.go b/library/go/core/metrics/solomon/histogram.go deleted file mode 100644 index 574aeaccf6..0000000000 --- a/library/go/core/metrics/solomon/histogram.go +++ /dev/null @@ -1,177 +0,0 @@ -package solomon - -import ( - "encoding/binary" - "encoding/json" - "io" - "sort" - "sync" - "time" - - "go.uber.org/atomic" - - "a.yandex-team.ru/library/go/core/metrics" - "a.yandex-team.ru/library/go/core/xerrors" -) - -var ( - _ metrics.Histogram = (*Histogram)(nil) - _ metrics.Timer = (*Histogram)(nil) - _ Metric = (*Histogram)(nil) -) - -type Histogram struct { - name string - metricType metricType - tags map[string]string - bucketBounds []float64 - bucketValues []int64 - infValue atomic.Int64 - mutex sync.Mutex - timestamp *time.Time - useNameTag bool -} - -type histogram struct { - Bounds []float64 `json:"bounds"` - Buckets []int64 `json:"buckets"` - Inf int64 `json:"inf,omitempty"` -} - -func (h *histogram) writeHistogram(w io.Writer) error { - err := writeULEB128(w, uint32(len(h.Buckets))) - if err != nil { - return xerrors.Errorf("writeULEB128 size histogram buckets failed: %w", err) - } - - for _, upperBound := range h.Bounds { - err = binary.Write(w, binary.LittleEndian, float64(upperBound)) - if err != nil { - return xerrors.Errorf("binary.Write upper bound failed: %w", err) - } - } - - for _, bucketValue := range h.Buckets { - err = binary.Write(w, binary.LittleEndian, uint64(bucketValue)) - if err != nil { - return xerrors.Errorf("binary.Write histogram buckets failed: %w", err) - } - } - return nil -} - -func (h *Histogram) RecordValue(value float64) { - boundIndex := sort.SearchFloat64s(h.bucketBounds, value) - - if boundIndex < len(h.bucketValues) { - h.mutex.Lock() - h.bucketValues[boundIndex] += 1 - h.mutex.Unlock() - } else { - h.infValue.Inc() - } -} - -func (h *Histogram) RecordDuration(value time.Duration) { - h.RecordValue(value.Seconds()) -} - -func (h *Histogram) Reset() { - h.mutex.Lock() - defer h.mutex.Unlock() - - h.bucketValues = make([]int64, len(h.bucketValues)) - h.infValue.Store(0) -} - -func (h *Histogram) Name() string { - return h.name -} - -func (h *Histogram) getType() metricType { - return h.metricType -} - -func (h *Histogram) getLabels() map[string]string { - return h.tags -} - -func (h *Histogram) getValue() interface{} { - return histogram{ - Bounds: h.bucketBounds, - Buckets: h.bucketValues, - } -} - -func (h *Histogram) getTimestamp() *time.Time { - return h.timestamp -} - -func (h *Histogram) getNameTag() string { - if h.useNameTag { - return "name" - } else { - return "sensor" - } -} - -// MarshalJSON implements json.Marshaler. -func (h *Histogram) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string `json:"type"` - Labels map[string]string `json:"labels"` - Histogram histogram `json:"hist"` - Timestamp *int64 `json:"ts,omitempty"` - }{ - Type: h.metricType.String(), - Histogram: histogram{ - Bounds: h.bucketBounds, - Buckets: h.bucketValues, - Inf: h.infValue.Load(), - }, - Labels: func() map[string]string { - labels := make(map[string]string, len(h.tags)+1) - labels[h.getNameTag()] = h.Name() - for k, v := range h.tags { - labels[k] = v - } - return labels - }(), - Timestamp: tsAsRef(h.timestamp), - }) -} - -// Snapshot returns independent copy on metric. -func (h *Histogram) Snapshot() Metric { - bucketBounds := make([]float64, len(h.bucketBounds)) - bucketValues := make([]int64, len(h.bucketValues)) - - copy(bucketBounds, h.bucketBounds) - copy(bucketValues, h.bucketValues) - - return &Histogram{ - name: h.name, - metricType: h.metricType, - tags: h.tags, - bucketBounds: bucketBounds, - bucketValues: bucketValues, - infValue: *atomic.NewInt64(h.infValue.Load()), - useNameTag: h.useNameTag, - } -} - -// InitBucketValues cleans internal bucketValues and saves new values in order. -// Length of internal bucketValues stays unchanged. -// If length of slice in argument bucketValues more than length of internal one, -// the first extra element of bucketValues is stored in infValue. -func (h *Histogram) InitBucketValues(bucketValues []int64) { - h.mutex.Lock() - defer h.mutex.Unlock() - - h.bucketValues = make([]int64, len(h.bucketValues)) - h.infValue.Store(0) - copy(h.bucketValues, bucketValues) - if len(bucketValues) > len(h.bucketValues) { - h.infValue.Store(bucketValues[len(h.bucketValues)]) - } -} diff --git a/library/go/core/metrics/solomon/metrics.go b/library/go/core/metrics/solomon/metrics.go deleted file mode 100644 index 7f4bf4b5ec..0000000000 --- a/library/go/core/metrics/solomon/metrics.go +++ /dev/null @@ -1,178 +0,0 @@ -package solomon - -import ( - "bytes" - "context" - "encoding" - "encoding/json" - "fmt" - "time" - - "a.yandex-team.ru/library/go/core/xerrors" -) - -// Gather collects all metrics data via snapshots. -func (r Registry) Gather() (*Metrics, error) { - metrics := make([]Metric, 0) - - var err error - r.metrics.Range(func(_, v interface{}) bool { - if s, ok := v.(Metric); ok { - metrics = append(metrics, s.Snapshot()) - return true - } - err = fmt.Errorf("unexpected value type: %T", v) - return false - }) - - if err != nil { - return nil, err - } - - return &Metrics{metrics: metrics}, nil -} - -func NewMetrics(metrics []Metric) Metrics { - return Metrics{metrics: metrics} -} - -func NewMetricsWithTimestamp(metrics []Metric, ts time.Time) Metrics { - return Metrics{metrics: metrics, timestamp: &ts} -} - -type valueType uint8 - -const ( - valueTypeNone valueType = iota - valueTypeOneWithoutTS valueType = 0x01 - valueTypeOneWithTS valueType = 0x02 - valueTypeManyWithTS valueType = 0x03 -) - -type metricType uint8 - -const ( - typeUnspecified metricType = iota - typeGauge metricType = 0x01 - typeCounter metricType = 0x02 - typeRated metricType = 0x03 - typeHistogram metricType = 0x05 - typeRatedHistogram metricType = 0x06 -) - -func (k metricType) String() string { - switch k { - case typeCounter: - return "COUNTER" - case typeGauge: - return "DGAUGE" - case typeHistogram: - return "HIST" - case typeRated: - return "RATE" - case typeRatedHistogram: - return "HIST_RATE" - default: - panic("unknown metric type") - } -} - -// Metric is an any abstract solomon Metric. -type Metric interface { - json.Marshaler - - Name() string - getType() metricType - getLabels() map[string]string - getValue() interface{} - getNameTag() string - getTimestamp() *time.Time - - Snapshot() Metric -} - -// Rated marks given Solomon metric or vector as rated. -// Example: -// -// cnt := r.Counter("mycounter") -// Rated(cnt) -// -// cntvec := r.CounterVec("mycounter", []string{"mytag"}) -// Rated(cntvec) -// -// For additional info: https://docs.yandex-team.ru/solomon/data-collection/dataformat/json -func Rated(s interface{}) { - switch st := s.(type) { - case *Counter: - st.metricType = typeRated - case *FuncCounter: - st.metricType = typeRated - case *Histogram: - st.metricType = typeRatedHistogram - - case *CounterVec: - st.vec.rated = true - case *HistogramVec: - st.vec.rated = true - case *DurationHistogramVec: - st.vec.rated = true - } - // any other metrics types are unrateable -} - -var ( - _ json.Marshaler = (*Metrics)(nil) - _ encoding.BinaryMarshaler = (*Metrics)(nil) -) - -type Metrics struct { - metrics []Metric - timestamp *time.Time -} - -// MarshalJSON implements json.Marshaler. -func (s Metrics) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Metrics []Metric `json:"metrics"` - Timestamp *int64 `json:"ts,omitempty"` - }{s.metrics, tsAsRef(s.timestamp)}) -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s Metrics) MarshalBinary() ([]byte, error) { - var buf bytes.Buffer - se := NewSpackEncoder(context.Background(), CompressionNone, &s) - n, err := se.Encode(&buf) - if err != nil { - return nil, xerrors.Errorf("encode only %d bytes: %w", n, err) - } - return buf.Bytes(), nil -} - -// SplitToChunks splits Metrics into a slice of chunks, each at most maxChunkSize long. -// The length of returned slice is always at least one. -// Zero maxChunkSize denotes unlimited chunk length. -func (s Metrics) SplitToChunks(maxChunkSize int) []Metrics { - if maxChunkSize == 0 || len(s.metrics) == 0 { - return []Metrics{s} - } - chunks := make([]Metrics, 0, len(s.metrics)/maxChunkSize+1) - - for leftBound := 0; leftBound < len(s.metrics); leftBound += maxChunkSize { - rightBound := leftBound + maxChunkSize - if rightBound > len(s.metrics) { - rightBound = len(s.metrics) - } - chunk := s.metrics[leftBound:rightBound] - chunks = append(chunks, Metrics{metrics: chunk}) - } - return chunks -} - -func tsAsRef(t *time.Time) *int64 { - if t == nil { - return nil - } - ts := t.Unix() - return &ts -} diff --git a/library/go/core/metrics/solomon/metrics_opts.go b/library/go/core/metrics/solomon/metrics_opts.go deleted file mode 100644 index d9ade67966..0000000000 --- a/library/go/core/metrics/solomon/metrics_opts.go +++ /dev/null @@ -1,29 +0,0 @@ -package solomon - -import "time" - -type MetricsOpts struct { - useNameTag bool - tags map[string]string - timestamp *time.Time -} - -type metricOpts func(*MetricsOpts) - -func WithTags(tags map[string]string) func(*MetricsOpts) { - return func(m *MetricsOpts) { - m.tags = tags - } -} - -func WithUseNameTag() func(*MetricsOpts) { - return func(m *MetricsOpts) { - m.useNameTag = true - } -} - -func WithTimestamp(t time.Time) func(*MetricsOpts) { - return func(m *MetricsOpts) { - m.timestamp = &t - } -} diff --git a/library/go/core/metrics/solomon/registry.go b/library/go/core/metrics/solomon/registry.go deleted file mode 100644 index cdd7489843..0000000000 --- a/library/go/core/metrics/solomon/registry.go +++ /dev/null @@ -1,221 +0,0 @@ -package solomon - -import ( - "reflect" - "strconv" - "sync" - - "a.yandex-team.ru/library/go/core/metrics" - "a.yandex-team.ru/library/go/core/metrics/internal/pkg/metricsutil" - "a.yandex-team.ru/library/go/core/metrics/internal/pkg/registryutil" -) - -var _ metrics.Registry = (*Registry)(nil) - -type Registry struct { - separator string - prefix string - tags map[string]string - rated bool - useNameTag bool - - subregistries map[string]*Registry - m *sync.Mutex - - metrics *sync.Map -} - -func NewRegistry(opts *RegistryOpts) *Registry { - r := &Registry{ - separator: ".", - useNameTag: false, - - subregistries: make(map[string]*Registry), - m: new(sync.Mutex), - - metrics: new(sync.Map), - } - - if opts != nil { - r.separator = string(opts.Separator) - r.prefix = opts.Prefix - r.tags = opts.Tags - r.rated = opts.Rated - r.useNameTag = opts.UseNameTag - for _, collector := range opts.Collectors { - collector(r) - } - } - - return r -} - -// Rated returns copy of registry with rated set to desired value. -func (r Registry) Rated(rated bool) metrics.Registry { - return &Registry{ - separator: r.separator, - prefix: r.prefix, - tags: r.tags, - rated: rated, - useNameTag: r.useNameTag, - - subregistries: r.subregistries, - m: r.m, - - metrics: r.metrics, - } -} - -// WithTags creates new sub-scope, where each metric has tags attached to it. -func (r Registry) WithTags(tags map[string]string) metrics.Registry { - return r.newSubregistry(r.prefix, registryutil.MergeTags(r.tags, tags)) -} - -// WithPrefix creates new sub-scope, where each metric has prefix added to it name. -func (r Registry) WithPrefix(prefix string) metrics.Registry { - return r.newSubregistry(registryutil.BuildFQName(r.separator, r.prefix, prefix), r.tags) -} - -// ComposeName builds FQ name with appropriate separator. -func (r Registry) ComposeName(parts ...string) string { - return registryutil.BuildFQName(r.separator, parts...) -} - -func (r Registry) Counter(name string) metrics.Counter { - s := &Counter{ - name: r.newMetricName(name), - metricType: typeCounter, - tags: r.tags, - - useNameTag: r.useNameTag, - } - - return r.registerMetric(s).(metrics.Counter) -} - -func (r Registry) FuncCounter(name string, function func() int64) metrics.FuncCounter { - s := &FuncCounter{ - name: r.newMetricName(name), - metricType: typeCounter, - tags: r.tags, - function: function, - useNameTag: r.useNameTag, - } - - return r.registerMetric(s).(metrics.FuncCounter) -} - -func (r Registry) Gauge(name string) metrics.Gauge { - s := &Gauge{ - name: r.newMetricName(name), - metricType: typeGauge, - tags: r.tags, - useNameTag: r.useNameTag, - } - - return r.registerMetric(s).(metrics.Gauge) -} - -func (r Registry) FuncGauge(name string, function func() float64) metrics.FuncGauge { - s := &FuncGauge{ - name: r.newMetricName(name), - metricType: typeGauge, - tags: r.tags, - function: function, - useNameTag: r.useNameTag, - } - - return r.registerMetric(s).(metrics.FuncGauge) -} - -func (r Registry) Timer(name string) metrics.Timer { - s := &Timer{ - name: r.newMetricName(name), - metricType: typeGauge, - tags: r.tags, - useNameTag: r.useNameTag, - } - - return r.registerMetric(s).(metrics.Timer) -} - -func (r Registry) Histogram(name string, buckets metrics.Buckets) metrics.Histogram { - s := &Histogram{ - name: r.newMetricName(name), - metricType: typeHistogram, - tags: r.tags, - bucketBounds: metricsutil.BucketsBounds(buckets), - bucketValues: make([]int64, buckets.Size()), - useNameTag: r.useNameTag, - } - - return r.registerMetric(s).(metrics.Histogram) -} - -func (r Registry) DurationHistogram(name string, buckets metrics.DurationBuckets) metrics.Timer { - s := &Histogram{ - name: r.newMetricName(name), - metricType: typeHistogram, - tags: r.tags, - bucketBounds: metricsutil.DurationBucketsBounds(buckets), - bucketValues: make([]int64, buckets.Size()), - useNameTag: r.useNameTag, - } - - return r.registerMetric(s).(metrics.Timer) -} - -func (r *Registry) newSubregistry(prefix string, tags map[string]string) *Registry { - // differ simple and rated registries - keyTags := registryutil.MergeTags(tags, map[string]string{"rated": strconv.FormatBool(r.rated)}) - registryKey := registryutil.BuildRegistryKey(prefix, keyTags) - - r.m.Lock() - defer r.m.Unlock() - - if existing, ok := r.subregistries[registryKey]; ok { - return existing - } - - subregistry := &Registry{ - separator: r.separator, - prefix: prefix, - tags: tags, - rated: r.rated, - useNameTag: r.useNameTag, - - subregistries: r.subregistries, - m: r.m, - - metrics: r.metrics, - } - - r.subregistries[registryKey] = subregistry - return subregistry -} - -func (r *Registry) newMetricName(name string) string { - return registryutil.BuildFQName(r.separator, r.prefix, name) -} - -func (r *Registry) registerMetric(s Metric) Metric { - if r.rated { - Rated(s) - } - - // differ simple and rated registries - keyTags := registryutil.MergeTags(r.tags, map[string]string{"rated": strconv.FormatBool(r.rated)}) - key := registryutil.BuildRegistryKey(s.Name(), keyTags) - - oldMetric, loaded := r.metrics.LoadOrStore(key, s) - if !loaded { - return s - } - - if reflect.TypeOf(oldMetric) == reflect.TypeOf(s) { - return oldMetric.(Metric) - } else { - r.metrics.Store(key, s) - return s - } -} diff --git a/library/go/core/metrics/solomon/registry_opts.go b/library/go/core/metrics/solomon/registry_opts.go deleted file mode 100644 index d2d19718ee..0000000000 --- a/library/go/core/metrics/solomon/registry_opts.go +++ /dev/null @@ -1,87 +0,0 @@ -package solomon - -import ( - "context" - - "a.yandex-team.ru/library/go/core/metrics" - "a.yandex-team.ru/library/go/core/metrics/collect" - "a.yandex-team.ru/library/go/core/metrics/internal/pkg/registryutil" -) - -type RegistryOpts struct { - Separator rune - Prefix string - Tags map[string]string - Rated bool - UseNameTag bool - Collectors []func(metrics.Registry) -} - -// NewRegistryOpts returns new initialized instance of RegistryOpts -func NewRegistryOpts() *RegistryOpts { - return &RegistryOpts{ - Separator: '.', - Tags: make(map[string]string), - UseNameTag: false, - } -} - -// SetUseNameTag overrides current UseNameTag opt -func (o *RegistryOpts) SetUseNameTag(useNameTag bool) *RegistryOpts { - o.UseNameTag = useNameTag - return o -} - -// SetTags overrides existing tags -func (o *RegistryOpts) SetTags(tags map[string]string) *RegistryOpts { - o.Tags = tags - return o -} - -// AddTags merges given tags with existing -func (o *RegistryOpts) AddTags(tags map[string]string) *RegistryOpts { - for k, v := range tags { - o.Tags[k] = v - } - return o -} - -// SetPrefix overrides existing prefix -func (o *RegistryOpts) SetPrefix(prefix string) *RegistryOpts { - o.Prefix = prefix - return o -} - -// AppendPrefix adds given prefix as postfix to existing using separator -func (o *RegistryOpts) AppendPrefix(prefix string) *RegistryOpts { - o.Prefix = registryutil.BuildFQName(string(o.Separator), o.Prefix, prefix) - return o -} - -// SetSeparator overrides existing separator -func (o *RegistryOpts) SetSeparator(separator rune) *RegistryOpts { - o.Separator = separator - return o -} - -// SetRated overrides existing rated flag -func (o *RegistryOpts) SetRated(rated bool) *RegistryOpts { - o.Rated = rated - return o -} - -// AddCollectors adds collectors that handle their metrics automatically (e.g. system metrics). -func (o *RegistryOpts) AddCollectors( - ctx context.Context, c metrics.CollectPolicy, collectors ...collect.Func, -) *RegistryOpts { - if len(collectors) == 0 { - return o - } - - o.Collectors = append(o.Collectors, func(r metrics.Registry) { - for _, collector := range collectors { - collector(ctx, r, c) - } - }) - return o -} diff --git a/library/go/core/metrics/solomon/spack.go b/library/go/core/metrics/solomon/spack.go deleted file mode 100644 index 9dc0434716..0000000000 --- a/library/go/core/metrics/solomon/spack.go +++ /dev/null @@ -1,340 +0,0 @@ -package solomon - -import ( - "bytes" - "context" - "encoding/binary" - "io" - - "a.yandex-team.ru/library/go/core/xerrors" -) - -type errWriter struct { - w io.Writer - err error -} - -func (ew *errWriter) binaryWrite(data interface{}) { - if ew.err != nil { - return - } - switch t := data.(type) { - case uint8: - ew.err = binary.Write(ew.w, binary.LittleEndian, data.(uint8)) - case uint16: - ew.err = binary.Write(ew.w, binary.LittleEndian, data.(uint16)) - case uint32: - ew.err = binary.Write(ew.w, binary.LittleEndian, data.(uint32)) - default: - ew.err = xerrors.Errorf("binaryWrite not supported type %v", t) - } -} - -func writeULEB128(w io.Writer, value uint32) error { - remaining := value >> 7 - for remaining != 0 { - err := binary.Write(w, binary.LittleEndian, uint8(value&0x7f|0x80)) - if err != nil { - return xerrors.Errorf("binary.Write failed: %w", err) - } - value = remaining - remaining >>= 7 - } - err := binary.Write(w, binary.LittleEndian, uint8(value&0x7f)) - if err != nil { - return xerrors.Errorf("binary.Write failed: %w", err) - } - return err -} - -type spackMetric struct { - flags uint8 - - labelsCount uint32 - labels bytes.Buffer - - metric Metric -} - -func (s *spackMetric) writeLabel(se *spackEncoder, namesIdx map[string]uint32, valuesIdx map[string]uint32, name string, value string) error { - s.labelsCount++ - - _, ok := namesIdx[name] - if !ok { - namesIdx[name] = se.nameCounter - se.nameCounter++ - _, err := se.labelNamePool.WriteString(name) - if err != nil { - return err - } - err = se.labelNamePool.WriteByte(0) - if err != nil { - return err - } - } - - _, ok = valuesIdx[value] - if !ok { - valuesIdx[value] = se.valueCounter - se.valueCounter++ - _, err := se.labelValuePool.WriteString(value) - if err != nil { - return err - } - err = se.labelValuePool.WriteByte(0) - if err != nil { - return err - } - } - - err := writeULEB128(&s.labels, uint32(namesIdx[name])) - if err != nil { - return err - } - err = writeULEB128(&s.labels, uint32(valuesIdx[value])) - if err != nil { - return err - } - - return nil -} - -func (s *spackMetric) writeMetric(w io.Writer) error { - metricValueType := valueTypeOneWithoutTS - if s.metric.getTimestamp() != nil { - metricValueType = valueTypeOneWithTS - } - // library/cpp/monlib/encode/spack/spack_v1_encoder.cpp?rev=r9098142#L190 - types := uint8(s.metric.getType()<<2) | uint8(metricValueType) - err := binary.Write(w, binary.LittleEndian, types) - if err != nil { - return xerrors.Errorf("binary.Write types failed: %w", err) - } - - err = binary.Write(w, binary.LittleEndian, uint8(s.flags)) - if err != nil { - return xerrors.Errorf("binary.Write flags failed: %w", err) - } - - err = writeULEB128(w, uint32(s.labelsCount)) - if err != nil { - return xerrors.Errorf("writeULEB128 labels count failed: %w", err) - } - - _, err = w.Write(s.labels.Bytes()) // s.writeLabels(w) - if err != nil { - return xerrors.Errorf("write labels failed: %w", err) - } - if s.metric.getTimestamp() != nil { - err = binary.Write(w, binary.LittleEndian, uint32(s.metric.getTimestamp().Unix())) - if err != nil { - return xerrors.Errorf("write timestamp failed: %w", err) - } - } - - switch s.metric.getType() { - case typeGauge: - err = binary.Write(w, binary.LittleEndian, s.metric.getValue().(float64)) - if err != nil { - return xerrors.Errorf("binary.Write gauge value failed: %w", err) - } - case typeCounter, typeRated: - err = binary.Write(w, binary.LittleEndian, uint64(s.metric.getValue().(int64))) - if err != nil { - return xerrors.Errorf("binary.Write counter value failed: %w", err) - } - case typeHistogram, typeRatedHistogram: - h := s.metric.getValue().(histogram) - err = h.writeHistogram(w) - if err != nil { - return xerrors.Errorf("writeHistogram failed: %w", err) - } - default: - return xerrors.Errorf("unknown metric type: %v", s.metric.getType()) - } - return nil -} - -type spackEncoder struct { - context context.Context - compression uint8 - - nameCounter uint32 - valueCounter uint32 - - labelNamePool bytes.Buffer - labelValuePool bytes.Buffer - - metrics Metrics -} - -func NewSpackEncoder(ctx context.Context, compression CompressionType, metrics *Metrics) *spackEncoder { - if metrics == nil { - metrics = &Metrics{} - } - return &spackEncoder{ - context: ctx, - compression: uint8(compression), - metrics: *metrics, - } -} - -func (se *spackEncoder) writeLabels() ([]spackMetric, error) { - namesIdx := make(map[string]uint32) - valuesIdx := make(map[string]uint32) - spackMetrics := make([]spackMetric, len(se.metrics.metrics)) - - for idx, metric := range se.metrics.metrics { - m := spackMetric{metric: metric} - - err := m.writeLabel(se, namesIdx, valuesIdx, metric.getNameTag(), metric.Name()) - if err != nil { - return nil, err - } - - for name, value := range metric.getLabels() { - if err := m.writeLabel(se, namesIdx, valuesIdx, name, value); err != nil { - return nil, err - } - - } - spackMetrics[idx] = m - } - - return spackMetrics, nil -} - -func (se *spackEncoder) Encode(w io.Writer) (written int, err error) { - spackMetrics, err := se.writeLabels() - if err != nil { - return written, xerrors.Errorf("writeLabels failed: %w", err) - } - - err = se.writeHeader(w) - if err != nil { - return written, xerrors.Errorf("writeHeader failed: %w", err) - } - written += HeaderSize - compression := CompressionType(se.compression) - - cw := newCompressedWriter(w, compression) - - err = se.writeLabelNamesPool(cw) - if err != nil { - return written, xerrors.Errorf("writeLabelNamesPool failed: %w", err) - } - - err = se.writeLabelValuesPool(cw) - if err != nil { - return written, xerrors.Errorf("writeLabelValuesPool failed: %w", err) - } - - err = se.writeCommonTime(cw) - if err != nil { - return written, xerrors.Errorf("writeCommonTime failed: %w", err) - } - - err = se.writeCommonLabels(cw) - if err != nil { - return written, xerrors.Errorf("writeCommonLabels failed: %w", err) - } - - err = se.writeMetricsData(cw, spackMetrics) - if err != nil { - return written, xerrors.Errorf("writeMetricsData failed: %w", err) - } - - err = cw.Close() - if err != nil { - return written, xerrors.Errorf("close failed: %w", err) - } - - switch compression { - case CompressionNone: - written += cw.(*noCompressionWriteCloser).written - case CompressionLz4: - written += cw.(*lz4CompressionWriteCloser).written - } - - return written, nil -} - -func (se *spackEncoder) writeHeader(w io.Writer) error { - if se.context.Err() != nil { - return xerrors.Errorf("streamSpack context error: %w", se.context.Err()) - } - ew := &errWriter{w: w} - ew.binaryWrite(uint16(0x5053)) // Magic - ew.binaryWrite(uint16(0x0101)) // Version - ew.binaryWrite(uint16(24)) // HeaderSize - ew.binaryWrite(uint8(0)) // TimePrecision(SECONDS) - ew.binaryWrite(uint8(se.compression)) // CompressionAlg - ew.binaryWrite(uint32(se.labelNamePool.Len())) // LabelNamesSize - ew.binaryWrite(uint32(se.labelValuePool.Len())) // LabelValuesSize - ew.binaryWrite(uint32(len(se.metrics.metrics))) // MetricsCount - ew.binaryWrite(uint32(len(se.metrics.metrics))) // PointsCount - if ew.err != nil { - return xerrors.Errorf("binaryWrite failed: %w", ew.err) - } - return nil -} - -func (se *spackEncoder) writeLabelNamesPool(w io.Writer) error { - if se.context.Err() != nil { - return xerrors.Errorf("streamSpack context error: %w", se.context.Err()) - } - _, err := w.Write(se.labelNamePool.Bytes()) - if err != nil { - return xerrors.Errorf("write labelNamePool failed: %w", err) - } - return nil -} - -func (se *spackEncoder) writeLabelValuesPool(w io.Writer) error { - if se.context.Err() != nil { - return xerrors.Errorf("streamSpack context error: %w", se.context.Err()) - } - - _, err := w.Write(se.labelValuePool.Bytes()) - if err != nil { - return xerrors.Errorf("write labelValuePool failed: %w", err) - } - return nil -} - -func (se *spackEncoder) writeCommonTime(w io.Writer) error { - if se.context.Err() != nil { - return xerrors.Errorf("streamSpack context error: %w", se.context.Err()) - } - - if se.metrics.timestamp == nil { - return binary.Write(w, binary.LittleEndian, uint32(0)) - } - return binary.Write(w, binary.LittleEndian, uint32(se.metrics.timestamp.Unix())) -} - -func (se *spackEncoder) writeCommonLabels(w io.Writer) error { - if se.context.Err() != nil { - return xerrors.Errorf("streamSpack context error: %w", se.context.Err()) - } - - _, err := w.Write([]byte{0}) - if err != nil { - return xerrors.Errorf("write commonLabels failed: %w", err) - } - return nil -} - -func (se *spackEncoder) writeMetricsData(w io.Writer, metrics []spackMetric) error { - for _, s := range metrics { - if se.context.Err() != nil { - return xerrors.Errorf("streamSpack context error: %w", se.context.Err()) - } - - err := s.writeMetric(w) - if err != nil { - return xerrors.Errorf("write metric failed: %w", err) - } - } - return nil -} diff --git a/library/go/core/metrics/solomon/spack_compression.go b/library/go/core/metrics/solomon/spack_compression.go deleted file mode 100644 index 004fe0150d..0000000000 --- a/library/go/core/metrics/solomon/spack_compression.go +++ /dev/null @@ -1,162 +0,0 @@ -package solomon - -import ( - "encoding/binary" - "io" - - "github.com/OneOfOne/xxhash" - "github.com/pierrec/lz4" -) - -type CompressionType uint8 - -const ( - CompressionNone CompressionType = 0x0 - CompressionZlib CompressionType = 0x1 - CompressionZstd CompressionType = 0x2 - CompressionLz4 CompressionType = 0x3 -) - -const ( - compressionFrameLength = 512 * 1024 - hashTableSize = 64 * 1024 -) - -type noCompressionWriteCloser struct { - underlying io.Writer - written int -} - -func (w *noCompressionWriteCloser) Write(p []byte) (int, error) { - n, err := w.underlying.Write(p) - w.written += n - return n, err -} - -func (w *noCompressionWriteCloser) Close() error { - return nil -} - -type lz4CompressionWriteCloser struct { - underlying io.Writer - buffer []byte - table []int - written int -} - -func (w *lz4CompressionWriteCloser) flushFrame() (written int, err error) { - src := w.buffer - dst := make([]byte, lz4.CompressBlockBound(len(src))) - - sz, err := lz4.CompressBlock(src, dst, w.table) - if err != nil { - return written, err - } - - if sz == 0 { - dst = src - } else { - dst = dst[:sz] - } - - err = binary.Write(w.underlying, binary.LittleEndian, uint32(len(dst))) - if err != nil { - return written, err - } - w.written += 4 - - err = binary.Write(w.underlying, binary.LittleEndian, uint32(len(src))) - if err != nil { - return written, err - } - w.written += 4 - - n, err := w.underlying.Write(dst) - if err != nil { - return written, err - } - w.written += n - - checksum := xxhash.Checksum32S(dst, 0x1337c0de) - err = binary.Write(w.underlying, binary.LittleEndian, checksum) - if err != nil { - return written, err - } - w.written += 4 - - w.buffer = w.buffer[:0] - - return written, nil -} - -func (w *lz4CompressionWriteCloser) Write(p []byte) (written int, err error) { - q := p[:] - for len(q) > 0 { - space := compressionFrameLength - len(w.buffer) - if space == 0 { - n, err := w.flushFrame() - if err != nil { - return written, err - } - w.written += n - space = compressionFrameLength - } - length := len(q) - if length > space { - length = space - } - w.buffer = append(w.buffer, q[:length]...) - q = q[length:] - } - return written, nil -} - -func (w *lz4CompressionWriteCloser) Close() error { - var err error - if len(w.buffer) > 0 { - n, err := w.flushFrame() - if err != nil { - return err - } - w.written += n - } - err = binary.Write(w.underlying, binary.LittleEndian, uint32(0)) - if err != nil { - return nil - } - w.written += 4 - - err = binary.Write(w.underlying, binary.LittleEndian, uint32(0)) - if err != nil { - return nil - } - w.written += 4 - - err = binary.Write(w.underlying, binary.LittleEndian, uint32(0)) - if err != nil { - return nil - } - w.written += 4 - - return nil -} - -func newCompressedWriter(w io.Writer, compression CompressionType) io.WriteCloser { - switch compression { - case CompressionNone: - return &noCompressionWriteCloser{w, 0} - case CompressionZlib: - panic("zlib compression not supported") - case CompressionZstd: - panic("zstd compression not supported") - case CompressionLz4: - return &lz4CompressionWriteCloser{ - w, - make([]byte, 0, compressionFrameLength), - make([]int, hashTableSize), - 0, - } - default: - panic("unsupported compression algorithm") - } -} diff --git a/library/go/core/metrics/solomon/stream.go b/library/go/core/metrics/solomon/stream.go deleted file mode 100644 index 26dc768c98..0000000000 --- a/library/go/core/metrics/solomon/stream.go +++ /dev/null @@ -1,89 +0,0 @@ -package solomon - -import ( - "context" - "encoding/json" - "io" - - "a.yandex-team.ru/library/go/core/xerrors" -) - -const HeaderSize = 24 - -type StreamFormat string - -func (r *Registry) StreamJSON(ctx context.Context, w io.Writer) (written int, err error) { - cw := newCompressedWriter(w, CompressionNone) - - if ctx.Err() != nil { - return written, xerrors.Errorf("streamJSON context error: %w", ctx.Err()) - } - _, err = cw.Write([]byte("{\"metrics\":[")) - if err != nil { - return written, xerrors.Errorf("write metrics failed: %w", err) - } - - first := true - r.metrics.Range(func(_, s interface{}) bool { - if ctx.Err() != nil { - err = xerrors.Errorf("streamJSON context error: %w", ctx.Err()) - return false - } - - // write trailing comma - if !first { - _, err = cw.Write([]byte(",")) - if err != nil { - err = xerrors.Errorf("write metrics failed: %w", err) - return false - } - } - - var b []byte - - b, err = json.Marshal(s) - if err != nil { - err = xerrors.Errorf("marshal metric failed: %w", err) - return false - } - - // write metric json - _, err = cw.Write(b) - if err != nil { - err = xerrors.Errorf("write metric failed: %w", err) - return false - } - - first = false - return true - }) - if err != nil { - return written, err - } - - if ctx.Err() != nil { - return written, xerrors.Errorf("streamJSON context error: %w", ctx.Err()) - } - _, err = cw.Write([]byte("]}")) - if err != nil { - return written, xerrors.Errorf("write metrics failed: %w", err) - } - - if ctx.Err() != nil { - return written, xerrors.Errorf("streamJSON context error: %w", ctx.Err()) - } - err = cw.Close() - if err != nil { - return written, xerrors.Errorf("close failed: %w", err) - } - - return cw.(*noCompressionWriteCloser).written, nil -} - -func (r *Registry) StreamSpack(ctx context.Context, w io.Writer, compression CompressionType) (int, error) { - metrics, err := r.Gather() - if err != nil { - return 0, err - } - return NewSpackEncoder(ctx, compression, metrics).Encode(w) -} diff --git a/library/go/core/metrics/solomon/timer.go b/library/go/core/metrics/solomon/timer.go deleted file mode 100644 index b26acc490b..0000000000 --- a/library/go/core/metrics/solomon/timer.go +++ /dev/null @@ -1,92 +0,0 @@ -package solomon - -import ( - "encoding/json" - "time" - - "go.uber.org/atomic" - - "a.yandex-team.ru/library/go/core/metrics" -) - -var ( - _ metrics.Timer = (*Timer)(nil) - _ Metric = (*Timer)(nil) -) - -// Timer measures gauge duration. -type Timer struct { - name string - metricType metricType - tags map[string]string - value atomic.Duration - timestamp *time.Time - - useNameTag bool -} - -func (t *Timer) RecordDuration(value time.Duration) { - t.value.Store(value) -} - -func (t *Timer) Name() string { - return t.name -} - -func (t *Timer) getType() metricType { - return t.metricType -} - -func (t *Timer) getLabels() map[string]string { - return t.tags -} - -func (t *Timer) getValue() interface{} { - return t.value.Load().Seconds() -} - -func (t *Timer) getTimestamp() *time.Time { - return t.timestamp -} - -func (t *Timer) getNameTag() string { - if t.useNameTag { - return "name" - } else { - return "sensor" - } -} - -// MarshalJSON implements json.Marshaler. -func (t *Timer) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string `json:"type"` - Labels map[string]string `json:"labels"` - Value float64 `json:"value"` - Timestamp *int64 `json:"ts,omitempty"` - }{ - Type: t.metricType.String(), - Value: t.value.Load().Seconds(), - Labels: func() map[string]string { - labels := make(map[string]string, len(t.tags)+1) - labels[t.getNameTag()] = t.Name() - for k, v := range t.tags { - labels[k] = v - } - return labels - }(), - Timestamp: tsAsRef(t.timestamp), - }) -} - -// Snapshot returns independent copy on metric. -func (t *Timer) Snapshot() Metric { - return &Timer{ - name: t.name, - metricType: t.metricType, - tags: t.tags, - value: *atomic.NewDuration(t.value.Load()), - - useNameTag: t.useNameTag, - } -} diff --git a/library/go/core/metrics/solomon/vec.go b/library/go/core/metrics/solomon/vec.go deleted file mode 100644 index a4d3ab1a83..0000000000 --- a/library/go/core/metrics/solomon/vec.go +++ /dev/null @@ -1,226 +0,0 @@ -package solomon - -import ( - "sync" - - "a.yandex-team.ru/library/go/core/metrics" - "a.yandex-team.ru/library/go/core/metrics/internal/pkg/registryutil" -) - -// metricsVector is a base implementation of vector of metrics of any supported type. -type metricsVector struct { - labels []string - mtx sync.RWMutex // Protects metrics. - metrics map[uint64]Metric - rated bool - newMetric func(map[string]string) Metric -} - -func (v *metricsVector) with(tags map[string]string) Metric { - hv, err := registryutil.VectorHash(tags, v.labels) - if err != nil { - panic(err) - } - - v.mtx.RLock() - metric, ok := v.metrics[hv] - v.mtx.RUnlock() - if ok { - return metric - } - - v.mtx.Lock() - defer v.mtx.Unlock() - - metric, ok = v.metrics[hv] - if !ok { - metric = v.newMetric(tags) - v.metrics[hv] = metric - } - - return metric -} - -// reset deletes all metrics in this vector. -func (v *metricsVector) reset() { - v.mtx.Lock() - defer v.mtx.Unlock() - - for h := range v.metrics { - delete(v.metrics, h) - } -} - -var _ metrics.CounterVec = (*CounterVec)(nil) - -// CounterVec stores counters and -// implements metrics.CounterVec interface. -type CounterVec struct { - vec *metricsVector -} - -// CounterVec creates a new counters vector with given metric name and -// partitioned by the given label names. -func (r *Registry) CounterVec(name string, labels []string) metrics.CounterVec { - var vec *metricsVector - vec = &metricsVector{ - labels: append([]string(nil), labels...), - metrics: make(map[uint64]Metric), - rated: r.rated, - newMetric: func(tags map[string]string) Metric { - return r.Rated(vec.rated). - WithTags(tags). - Counter(name).(*Counter) - }, - } - return &CounterVec{vec: vec} -} - -// With creates new or returns existing counter with given tags from vector. -// It will panic if tags keys set is not equal to vector labels. -func (v *CounterVec) With(tags map[string]string) metrics.Counter { - return v.vec.with(tags).(*Counter) -} - -// Reset deletes all metrics in this vector. -func (v *CounterVec) Reset() { - v.vec.reset() -} - -var _ metrics.GaugeVec = (*GaugeVec)(nil) - -// GaugeVec stores gauges and -// implements metrics.GaugeVec interface. -type GaugeVec struct { - vec *metricsVector -} - -// GaugeVec creates a new gauges vector with given metric name and -// partitioned by the given label names. -func (r *Registry) GaugeVec(name string, labels []string) metrics.GaugeVec { - return &GaugeVec{ - vec: &metricsVector{ - labels: append([]string(nil), labels...), - metrics: make(map[uint64]Metric), - newMetric: func(tags map[string]string) Metric { - return r.WithTags(tags).Gauge(name).(*Gauge) - }, - }, - } -} - -// With creates new or returns existing gauge with given tags from vector. -// It will panic if tags keys set is not equal to vector labels. -func (v *GaugeVec) With(tags map[string]string) metrics.Gauge { - return v.vec.with(tags).(*Gauge) -} - -// Reset deletes all metrics in this vector. -func (v *GaugeVec) Reset() { - v.vec.reset() -} - -var _ metrics.TimerVec = (*TimerVec)(nil) - -// TimerVec stores timers and -// implements metrics.TimerVec interface. -type TimerVec struct { - vec *metricsVector -} - -// TimerVec creates a new timers vector with given metric name and -// partitioned by the given label names. -func (r *Registry) TimerVec(name string, labels []string) metrics.TimerVec { - return &TimerVec{ - vec: &metricsVector{ - labels: append([]string(nil), labels...), - metrics: make(map[uint64]Metric), - newMetric: func(tags map[string]string) Metric { - return r.WithTags(tags).Timer(name).(*Timer) - }, - }, - } -} - -// With creates new or returns existing timer with given tags from vector. -// It will panic if tags keys set is not equal to vector labels. -func (v *TimerVec) With(tags map[string]string) metrics.Timer { - return v.vec.with(tags).(*Timer) -} - -// Reset deletes all metrics in this vector. -func (v *TimerVec) Reset() { - v.vec.reset() -} - -var _ metrics.HistogramVec = (*HistogramVec)(nil) - -// HistogramVec stores histograms and -// implements metrics.HistogramVec interface. -type HistogramVec struct { - vec *metricsVector -} - -// HistogramVec creates a new histograms vector with given metric name and buckets and -// partitioned by the given label names. -func (r *Registry) HistogramVec(name string, buckets metrics.Buckets, labels []string) metrics.HistogramVec { - var vec *metricsVector - vec = &metricsVector{ - labels: append([]string(nil), labels...), - metrics: make(map[uint64]Metric), - rated: r.rated, - newMetric: func(tags map[string]string) Metric { - return r.Rated(vec.rated). - WithTags(tags). - Histogram(name, buckets).(*Histogram) - }, - } - return &HistogramVec{vec: vec} -} - -// With creates new or returns existing histogram with given tags from vector. -// It will panic if tags keys set is not equal to vector labels. -func (v *HistogramVec) With(tags map[string]string) metrics.Histogram { - return v.vec.with(tags).(*Histogram) -} - -// Reset deletes all metrics in this vector. -func (v *HistogramVec) Reset() { - v.vec.reset() -} - -var _ metrics.TimerVec = (*DurationHistogramVec)(nil) - -// DurationHistogramVec stores duration histograms and -// implements metrics.TimerVec interface. -type DurationHistogramVec struct { - vec *metricsVector -} - -// DurationHistogramVec creates a new duration histograms vector with given metric name and buckets and -// partitioned by the given label names. -func (r *Registry) DurationHistogramVec(name string, buckets metrics.DurationBuckets, labels []string) metrics.TimerVec { - var vec *metricsVector - vec = &metricsVector{ - labels: append([]string(nil), labels...), - metrics: make(map[uint64]Metric), - rated: r.rated, - newMetric: func(tags map[string]string) Metric { - return r.Rated(vec.rated). - WithTags(tags). - DurationHistogram(name, buckets).(*Histogram) - }, - } - return &DurationHistogramVec{vec: vec} -} - -// With creates new or returns existing duration histogram with given tags from vector. -// It will panic if tags keys set is not equal to vector labels. -func (v *DurationHistogramVec) With(tags map[string]string) metrics.Timer { - return v.vec.with(tags).(*Histogram) -} - -// Reset deletes all metrics in this vector. -func (v *DurationHistogramVec) Reset() { - v.vec.reset() -} |