add support for deltas in histogram and summaries

This commit is contained in:
bergquist 2017-09-06 19:23:03 +02:00 committed by Carl Bergquist
parent 2de94d6548
commit fca80ff525
4 changed files with 60 additions and 22 deletions

View File

@ -13,7 +13,7 @@
// Package graphite provides a bridge to push Prometheus metrics to a Graphite // Package graphite provides a bridge to push Prometheus metrics to a Graphite
// server. // server.
package graphitepublisher package graphitebridge
import ( import (
"bufio" "bufio"
@ -275,14 +275,40 @@ func writeMetric(buf *bufio.Writer, m model.Metric, mf *dto.MetricFamily) error
} }
} }
if mf.GetType() == dto.MetricType_COUNTER { if err = addExtentionConventionForRollups(buf, mf, m); err != nil {
// Adding the `.count` suffix makes it possible to configure return err
// `sum` as rollup strategy for counters }
return nil
}
func addExtentionConventionForRollups(buf *bufio.Writer, mf *dto.MetricFamily, m model.Metric) error {
// Adding `.count` `.sum` suffix makes it possible to configure
// different rollup strategies based on metric type
mfType := mf.GetType()
var err error
if mfType == dto.MetricType_COUNTER {
if _, err = fmt.Fprint(buf, ".count"); err != nil { if _, err = fmt.Fprint(buf, ".count"); err != nil {
return err return err
} }
} }
if mfType == dto.MetricType_SUMMARY || mfType == dto.MetricType_HISTOGRAM {
if strings.HasSuffix(string(m[model.MetricNameLabel]), "_count") {
if _, err = fmt.Fprint(buf, ".count"); err != nil {
return err
}
}
}
if mfType == dto.MetricType_HISTOGRAM {
if strings.HasSuffix(string(m[model.MetricNameLabel]), "_sum") {
if _, err = fmt.Fprint(buf, ".sum"); err != nil {
return err
}
}
}
return nil return nil
} }
@ -318,19 +344,31 @@ func replaceInvalidRune(c rune) rune {
} }
func (b *Bridge) replaceCounterWithDelta(mf *dto.MetricFamily, metric model.Metric, value model.SampleValue) float64 { func (b *Bridge) replaceCounterWithDelta(mf *dto.MetricFamily, metric model.Metric, value model.SampleValue) float64 {
if mf.GetType() != dto.MetricType_COUNTER {
return float64(value)
}
if !b.countersAsDetlas { if !b.countersAsDetlas {
return float64(value) return float64(value)
} }
mfType := mf.GetType()
if mfType == dto.MetricType_COUNTER {
return b.returnDelta(metric, value)
}
if mfType == dto.MetricType_SUMMARY {
if strings.HasSuffix(string(metric[model.MetricNameLabel]), "_count") {
return b.returnDelta(metric, value)
}
}
return float64(value)
//println("use delta for", metric[model.MetricNameLabel], mf.GetType().String()) //println("use delta for", metric[model.MetricNameLabel], mf.GetType().String())
//TODO(bergquist): turn _count in summery into delta //TODO(bergquist): turn _count in summery into delta
//TODO(bergquist): turn _count in histogram into delta //TODO(bergquist): turn _count in histogram into delta
}
func (b *Bridge) returnDelta(metric model.Metric, value model.SampleValue) float64 {
key := metric.Fingerprint() key := metric.Fingerprint()
_, exists := b.lastValue[key] _, exists := b.lastValue[key]
if !exists { if !exists {

View File

@ -1,4 +1,4 @@
package graphitepublisher package graphitebridge
import ( import (
"bufio" "bufio"
@ -142,12 +142,12 @@ func TestWriteSummary(t *testing.T) {
prefix.name.constname.constvalue.labelname.val1.quantile.0_9 30 1477043 prefix.name.constname.constvalue.labelname.val1.quantile.0_9 30 1477043
prefix.name.constname.constvalue.labelname.val1.quantile.0_99 30 1477043 prefix.name.constname.constvalue.labelname.val1.quantile.0_99 30 1477043
prefix.name_sum.constname.constvalue.labelname.val1 60 1477043 prefix.name_sum.constname.constvalue.labelname.val1 60 1477043
prefix.name_count.constname.constvalue.labelname.val1 3 1477043 prefix.name_count.constname.constvalue.labelname.val1.count 3 1477043
prefix.name.constname.constvalue.labelname.val2.quantile.0_5 30 1477043 prefix.name.constname.constvalue.labelname.val2.quantile.0_5 30 1477043
prefix.name.constname.constvalue.labelname.val2.quantile.0_9 40 1477043 prefix.name.constname.constvalue.labelname.val2.quantile.0_9 40 1477043
prefix.name.constname.constvalue.labelname.val2.quantile.0_99 40 1477043 prefix.name.constname.constvalue.labelname.val2.quantile.0_99 40 1477043
prefix.name_sum.constname.constvalue.labelname.val2 90 1477043 prefix.name_sum.constname.constvalue.labelname.val2 90 1477043
prefix.name_count.constname.constvalue.labelname.val2 3 1477043 prefix.name_count.constname.constvalue.labelname.val2.count 3 1477043
` `
if got := buf.String(); want != got { if got := buf.String(); want != got {
@ -201,15 +201,15 @@ func TestWriteHistogram(t *testing.T) {
prefix.name_bucket.constname.constvalue.labelname.val1.le.0_02 0 1477043 prefix.name_bucket.constname.constvalue.labelname.val1.le.0_02 0 1477043
prefix.name_bucket.constname.constvalue.labelname.val1.le.0_05 0 1477043 prefix.name_bucket.constname.constvalue.labelname.val1.le.0_05 0 1477043
prefix.name_bucket.constname.constvalue.labelname.val1.le.0_1 0 1477043 prefix.name_bucket.constname.constvalue.labelname.val1.le.0_1 0 1477043
prefix.name_sum.constname.constvalue.labelname.val1 60 1477043 prefix.name_sum.constname.constvalue.labelname.val1.sum 60 1477043
prefix.name_count.constname.constvalue.labelname.val1 3 1477043 prefix.name_count.constname.constvalue.labelname.val1.count 3 1477043
prefix.name_bucket.constname.constvalue.labelname.val1.le._Inf 3 1477043 prefix.name_bucket.constname.constvalue.labelname.val1.le._Inf 3 1477043
prefix.name_bucket.constname.constvalue.labelname.val2.le.0_01 0 1477043 prefix.name_bucket.constname.constvalue.labelname.val2.le.0_01 0 1477043
prefix.name_bucket.constname.constvalue.labelname.val2.le.0_02 0 1477043 prefix.name_bucket.constname.constvalue.labelname.val2.le.0_02 0 1477043
prefix.name_bucket.constname.constvalue.labelname.val2.le.0_05 0 1477043 prefix.name_bucket.constname.constvalue.labelname.val2.le.0_05 0 1477043
prefix.name_bucket.constname.constvalue.labelname.val2.le.0_1 0 1477043 prefix.name_bucket.constname.constvalue.labelname.val2.le.0_1 0 1477043
prefix.name_sum.constname.constvalue.labelname.val2 90 1477043 prefix.name_sum.constname.constvalue.labelname.val2.sum 90 1477043
prefix.name_count.constname.constvalue.labelname.val2 3 1477043 prefix.name_count.constname.constvalue.labelname.val2.count 3 1477043
prefix.name_bucket.constname.constvalue.labelname.val2.le._Inf 3 1477043 prefix.name_bucket.constname.constvalue.labelname.val2.le._Inf 3 1477043
` `
if got := buf.String(); want != got { if got := buf.String(); want != got {

View File

@ -4,7 +4,7 @@ import (
"context" "context"
"github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/metrics/graphitepublisher" "github.com/grafana/grafana/pkg/metrics/graphitebridge"
) )
var metricsLogger log.Logger = log.New("metrics") var metricsLogger log.Logger = log.New("metrics")
@ -22,7 +22,7 @@ func Init(settings *MetricSettings) {
initMetricVars(settings) initMetricVars(settings)
if settings.GraphiteBridgeConfig != nil { if settings.GraphiteBridgeConfig != nil {
bridge, err := graphitepublisher.NewBridge(settings.GraphiteBridgeConfig) bridge, err := graphitebridge.NewBridge(settings.GraphiteBridgeConfig)
if err != nil { if err != nil {
metricsLogger.Error("failed to create graphite bridge", "error", err) metricsLogger.Error("failed to create graphite bridge", "error", err)
} else { } else {

View File

@ -4,7 +4,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/grafana/grafana/pkg/metrics/graphitepublisher" "github.com/grafana/grafana/pkg/metrics/graphitebridge"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
ini "gopkg.in/ini.v1" ini "gopkg.in/ini.v1"
@ -13,7 +13,7 @@ import (
type MetricSettings struct { type MetricSettings struct {
Enabled bool Enabled bool
IntervalSeconds int64 IntervalSeconds int64
GraphiteBridgeConfig *graphitepublisher.Config GraphiteBridgeConfig *graphitebridge.Config
} }
func ReadSettings(file *ini.File) *MetricSettings { func ReadSettings(file *ini.File) *MetricSettings {
@ -45,7 +45,7 @@ func ReadSettings(file *ini.File) *MetricSettings {
return settings return settings
} }
func parseGraphiteSettings(settings *MetricSettings, file *ini.File) (*graphitepublisher.Config, error) { func parseGraphiteSettings(settings *MetricSettings, file *ini.File) (*graphitebridge.Config, error) {
graphiteSection, err := setting.Cfg.GetSection("metrics.graphite") graphiteSection, err := setting.Cfg.GetSection("metrics.graphite")
if err != nil { if err != nil {
return nil, nil return nil, nil
@ -56,7 +56,7 @@ func parseGraphiteSettings(settings *MetricSettings, file *ini.File) (*graphitep
return nil, nil return nil, nil
} }
cfg := &graphitepublisher.Config{ cfg := &graphitebridge.Config{
URL: address, URL: address,
Prefix: graphiteSection.Key("prefix").MustString("prod.grafana.%(instance_name)s"), Prefix: graphiteSection.Key("prefix").MustString("prod.grafana.%(instance_name)s"),
CountersAsDelta: true, CountersAsDelta: true,
@ -64,7 +64,7 @@ func parseGraphiteSettings(settings *MetricSettings, file *ini.File) (*graphitep
Interval: time.Duration(settings.IntervalSeconds) * time.Second, Interval: time.Duration(settings.IntervalSeconds) * time.Second,
Timeout: 10 * time.Second, Timeout: 10 * time.Second,
Logger: &logWrapper{logger: metricsLogger}, Logger: &logWrapper{logger: metricsLogger},
ErrorHandling: graphitepublisher.ContinueOnError, ErrorHandling: graphitebridge.ContinueOnError,
} }
safeInstanceName := strings.Replace(setting.InstanceName, ".", "_", -1) safeInstanceName := strings.Replace(setting.InstanceName, ".", "_", -1)