vendor: update github.com/VictoriaMetrics/metrics from v1.7.2 to v1.8.0. This version supports histograms

This commit is contained in:
Aliaksandr Valialkin 2019-11-23 00:19:44 +02:00
parent c4287b3c86
commit 9d1fcb2be6
6 changed files with 269 additions and 5 deletions

2
go.mod
View file

@ -4,7 +4,7 @@ require (
cloud.google.com/go v0.49.0 // indirect
cloud.google.com/go/storage v1.4.0
github.com/VictoriaMetrics/fastcache v1.5.2
github.com/VictoriaMetrics/metrics v1.7.2
github.com/VictoriaMetrics/metrics v1.8.0
github.com/aws/aws-sdk-go v1.25.37
github.com/cespare/xxhash/v2 v2.1.1
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 // indirect

4
go.sum
View file

@ -24,8 +24,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/VictoriaMetrics/fastcache v1.5.2 h1:Erd8iIuBAL9kke8JzM4+WxkKuFkHh3ktwLanJvDgR44=
github.com/VictoriaMetrics/fastcache v1.5.2/go.mod h1:+jv9Ckb+za/P1ZRg/sulP5Ni1v49daAVERr0H3CuscE=
github.com/VictoriaMetrics/metrics v1.7.2 h1:PzC0SEo5lbbNK7xaYwclCCdoaIGRmXOfflIMF3LpSW4=
github.com/VictoriaMetrics/metrics v1.7.2/go.mod h1:LU2j9qq7xqZYXz8tF3/RQnB2z2MbZms5TDiIg9/NHiQ=
github.com/VictoriaMetrics/metrics v1.8.0 h1:UnkixfF43kt0v8GRgkgFC6Ti+G0yvT9H1o5vNgaOv9k=
github.com/VictoriaMetrics/metrics v1.8.0/go.mod h1:LU2j9qq7xqZYXz8tF3/RQnB2z2MbZms5TDiIg9/NHiQ=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/aws/aws-sdk-go v1.25.37 h1:gBtB/F3dophWpsUQKN/Kni+JzYEH2mGHF4hWNtfED1w=

View file

@ -151,7 +151,7 @@ func gzipHandler(rh RequestHandler) http.HandlerFunc {
return http.HandlerFunc(hf)
}
var metricsHandlerDuration = metrics.NewSummary(`vm_http_request_duration_seconds{path="/metrics"}`)
var metricsHandlerDuration = metrics.NewHistogram(`vm_http_request_duration_seconds{path="/metrics"}`)
func handlerWrapper(w http.ResponseWriter, r *http.Request, rh RequestHandler) {
requestsTotal.Inc()

206
vendor/github.com/VictoriaMetrics/metrics/histogram.go generated vendored Normal file
View file

@ -0,0 +1,206 @@
package metrics
import (
"fmt"
"io"
"math"
"sync"
"sync/atomic"
"time"
)
// Histogram is a histogram that covers values with the following buckets:
//
// 0
// (0...1e-9]
// (1e-9...2e-9]
// (2e-9...3e-9]
// ...
// (9e-9...1e-8]
// (1e-8...2e-8]
// ...
// (1e11...2e11]
// (2e11...3e11]
// ...
// (9e11...1e12]
// (1e12...Inf]
//
// Each bucket contains a counter for values in the given range.
// Each non-zero bucket is exposed with the following name:
//
// <metric_name>_vmbucket{<optional_tags>,vmrange="<start>...<end>"} <counter>
//
// Where:
//
// - <metric_name> is the metric name passed to NewHistogram
// - <optional_tags> is optional tags for the <metric_name>, which are passed to NewHistogram
// - <start> and <end> - start and end values for the given bucket
// - <counter> - the number of hits to the given bucket during Update* calls.
//
// Only non-zero buckets are exposed.
//
// Histogram buckets can be converted to Prometheus-like buckets in VictoriaMetrics
// with `prometheus_buckets(<metric_name>_vmbucket)`:
//
// histogram_quantile(0.95, prometheus_buckets(rate(request_duration_vmbucket[5m])))
//
// Histogram cannot be used for negative values.
type Histogram struct {
buckets [bucketsCount]uint64
sumMu sync.Mutex
sum float64
count uint64
}
// NewHistogram creates and returns new histogram with the given name.
//
// name must be valid Prometheus-compatible metric with possible labels.
// For instance,
//
// * foo
// * foo{bar="baz"}
// * foo{bar="baz",aaa="b"}
//
// The returned histogram is safe to use from concurrent goroutines.
func NewHistogram(name string) *Histogram {
return defaultSet.NewHistogram(name)
}
// GetOrCreateHistogram returns registered histogram with the given name
// or creates new histogram if the registry doesn't contain histogram with
// the given name.
//
// name must be valid Prometheus-compatible metric with possible labels.
// For instance,
//
// * foo
// * foo{bar="baz"}
// * foo{bar="baz",aaa="b"}
//
// The returned histogram is safe to use from concurrent goroutines.
//
// Performance tip: prefer NewHistogram instead of GetOrCreateHistogram.
func GetOrCreateHistogram(name string) *Histogram {
return defaultSet.GetOrCreateHistogram(name)
}
// Update updates h with v.
//
// v cannot be negative.
func (h *Histogram) Update(v float64) {
idx := getBucketIdx(v)
if idx >= uint(len(h.buckets)) {
panic(fmt.Errorf("BUG: idx cannot exceed %d; got %d", len(h.buckets), idx))
}
atomic.AddUint64(&h.buckets[idx], 1)
atomic.AddUint64(&h.count, 1)
h.sumMu.Lock()
h.sum += v
h.sumMu.Unlock()
}
// UpdateDuration updates request duration based on the given startTime.
func (h *Histogram) UpdateDuration(startTime time.Time) {
d := time.Since(startTime).Seconds()
h.Update(d)
}
func (h *Histogram) marshalTo(prefix string, w io.Writer) {
count := atomic.LoadUint64(&h.count)
if count == 0 {
return
}
for i := range h.buckets[:] {
h.marshalBucket(prefix, w, i)
}
// Marshal `_sum` and `_count` metrics.
name, filters := splitMetricName(prefix)
h.sumMu.Lock()
sum := h.sum
h.sumMu.Unlock()
if float64(int64(sum)) == sum {
fmt.Fprintf(w, "%s_sum%s %d\n", name, filters, int64(sum))
} else {
fmt.Fprintf(w, "%s_sum%s %g\n", name, filters, sum)
}
fmt.Fprintf(w, "%s_count%s %d\n", name, filters, count)
}
func (h *Histogram) marshalBucket(prefix string, w io.Writer, idx int) {
v := h.buckets[idx]
if v == 0 {
return
}
start := float64(0)
if idx > 0 {
start = getRangeEndFromBucketIdx(uint(idx - 1))
}
end := getRangeEndFromBucketIdx(uint(idx))
tag := fmt.Sprintf(`vmrange="%g...%g"`, start, end)
prefix = addTag(prefix, tag)
name, filters := splitMetricName(prefix)
fmt.Fprintf(w, "%s_vmbucket%s %d\n", name, filters, v)
}
func getBucketIdx(v float64) uint {
if v < 0 {
panic(fmt.Errorf("BUG: v cannot be negative; got %v", v))
}
if v == 0 {
// Fast path for zero.
return 0
}
if math.IsInf(v, 1) {
return bucketsCount - 1
}
e10 := int(math.Floor(math.Log10(v)))
if e10 < e10Min {
return 1
}
if e10 > e10Max {
if e10 == e10Max+1 && math.Pow10(e10) == v {
// Adjust m to be on par with Prometheus 'le' buckets (aka 'less or equal')
return bucketsCount - 2
}
return bucketsCount - 1
}
mf := v / math.Pow10(e10)
m := uint(mf)
// Handle possible rounding errors
if m < 1 {
m = 1
} else if m > 9 {
m = 9
}
if float64(m) == mf {
// Adjust m to be on par with Prometheus 'le' buckets (aka 'less or equal')
m--
}
return 1 + m + uint(e10-e10Min)*9
}
func getRangeEndFromBucketIdx(idx uint) float64 {
if idx == 0 {
return 0
}
if idx == 1 {
return math.Pow10(e10Min)
}
if idx >= bucketsCount-1 {
return math.Inf(1)
}
idx -= 2
e10 := e10Min + int(idx/9)
m := 2 + (idx % 9)
return math.Pow10(e10) * float64(m)
}
// Each range (10^n..10^(n+1)] for e10Min<=n<=e10Max is split into 9 equal sub-ranges, plus 3 additional buckets:
// - a bucket for zeros
// - a bucket for the range (0..10^e10Min]
// - a bucket for the range (10^(e10Max+1)..Inf]
const bucketsCount = 3 + 9*(1+e10Max-e10Min)
const e10Min = -9
const e10Max = 11

View file

@ -45,6 +45,64 @@ func (s *Set) WritePrometheus(w io.Writer) {
s.mu.Unlock()
}
// NewHistogram creates and returns new histogram in s with the given name.
//
// name must be valid Prometheus-compatible metric with possible labels.
// For instance,
//
// * foo
// * foo{bar="baz"}
// * foo{bar="baz",aaa="b"}
//
// The returned histogram is safe to use from concurrent goroutines.
func (s *Set) NewHistogram(name string) *Histogram {
h := &Histogram{}
s.registerMetric(name, h)
return h
}
// GetOrCreateHistogram returns registered histogram in s with the given name
// or creates new histogram if s doesn't contain histogram with the given name.
//
// name must be valid Prometheus-compatible metric with possible labels.
// For instance,
//
// * foo
// * foo{bar="baz"}
// * foo{bar="baz",aaa="b"}
//
// The returned histogram is safe to use from concurrent goroutines.
//
// Performance tip: prefer NewHistogram instead of GetOrCreateHistogram.
func (s *Set) GetOrCreateHistogram(name string) *Histogram {
s.mu.Lock()
nm := s.m[name]
s.mu.Unlock()
if nm == nil {
// Slow path - create and register missing histogram.
if err := validateMetric(name); err != nil {
panic(fmt.Errorf("BUG: invalid metric name %q: %s", name, err))
}
nmNew := &namedMetric{
name: name,
metric: &Histogram{},
}
s.mu.Lock()
nm = s.m[name]
if nm == nil {
nm = nmNew
s.m[name] = nm
s.a = append(s.a, nm)
}
s.mu.Unlock()
}
h, ok := nm.metric.(*Histogram)
if !ok {
panic(fmt.Errorf("BUG: metric %q isn't a Histogram. It is %T", name, nm.metric))
}
return h
}
// NewCounter registers and returns new counter with the given name in the s.
//
// name must be valid Prometheus-compatible metric with possible labels.

2
vendor/modules.txt vendored
View file

@ -12,7 +12,7 @@ cloud.google.com/go/storage
github.com/BurntSushi/toml
# github.com/VictoriaMetrics/fastcache v1.5.2
github.com/VictoriaMetrics/fastcache
# github.com/VictoriaMetrics/metrics v1.7.2
# github.com/VictoriaMetrics/metrics v1.8.0
github.com/VictoriaMetrics/metrics
# github.com/aws/aws-sdk-go v1.25.37
github.com/aws/aws-sdk-go/aws