diff --git a/pkg/metrics/graphitepublisher/graphite.go b/pkg/metrics/graphitebridge/graphite.go similarity index 87% rename from pkg/metrics/graphitepublisher/graphite.go rename to pkg/metrics/graphitebridge/graphite.go index 66948578174..e23b7ebe538 100644 --- a/pkg/metrics/graphitepublisher/graphite.go +++ b/pkg/metrics/graphitebridge/graphite.go @@ -13,7 +13,7 @@ // Package graphite provides a bridge to push Prometheus metrics to a Graphite // server. -package graphitepublisher +package graphitebridge import ( "bufio" @@ -275,14 +275,40 @@ func writeMetric(buf *bufio.Writer, m model.Metric, mf *dto.MetricFamily) error } } - if mf.GetType() == dto.MetricType_COUNTER { - // Adding the `.count` suffix makes it possible to configure - // `sum` as rollup strategy for counters + if err = addExtentionConventionForRollups(buf, mf, m); err != nil { + return err + } + + 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 { 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 } @@ -318,19 +344,31 @@ func replaceInvalidRune(c rune) rune { } 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 { 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()) //TODO(bergquist): turn _count in summery into delta //TODO(bergquist): turn _count in histogram into delta +} + +func (b *Bridge) returnDelta(metric model.Metric, value model.SampleValue) float64 { key := metric.Fingerprint() _, exists := b.lastValue[key] if !exists { diff --git a/pkg/metrics/graphitepublisher/graphite_test.go b/pkg/metrics/graphitebridge/graphite_test.go similarity index 96% rename from pkg/metrics/graphitepublisher/graphite_test.go rename to pkg/metrics/graphitebridge/graphite_test.go index 2b35c47916b..1994fbde5a9 100644 --- a/pkg/metrics/graphitepublisher/graphite_test.go +++ b/pkg/metrics/graphitebridge/graphite_test.go @@ -1,4 +1,4 @@ -package graphitepublisher +package graphitebridge import ( "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_99 30 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_9 40 1477043 prefix.name.constname.constvalue.labelname.val2.quantile.0_99 40 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 { @@ -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_05 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_count.constname.constvalue.labelname.val1 3 1477043 +prefix.name_sum.constname.constvalue.labelname.val1.sum 60 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.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_05 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_count.constname.constvalue.labelname.val2 3 1477043 +prefix.name_sum.constname.constvalue.labelname.val2.sum 90 1477043 +prefix.name_count.constname.constvalue.labelname.val2.count 3 1477043 prefix.name_bucket.constname.constvalue.labelname.val2.le._Inf 3 1477043 ` if got := buf.String(); want != got { diff --git a/pkg/metrics/publish.go b/pkg/metrics/publish.go index 8da0c94ceed..ebbeb2962d6 100644 --- a/pkg/metrics/publish.go +++ b/pkg/metrics/publish.go @@ -4,7 +4,7 @@ import ( "context" "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") @@ -22,7 +22,7 @@ func Init(settings *MetricSettings) { initMetricVars(settings) if settings.GraphiteBridgeConfig != nil { - bridge, err := graphitepublisher.NewBridge(settings.GraphiteBridgeConfig) + bridge, err := graphitebridge.NewBridge(settings.GraphiteBridgeConfig) if err != nil { metricsLogger.Error("failed to create graphite bridge", "error", err) } else { diff --git a/pkg/metrics/settings.go b/pkg/metrics/settings.go index ab96e9aaa92..5e51f85768a 100644 --- a/pkg/metrics/settings.go +++ b/pkg/metrics/settings.go @@ -4,7 +4,7 @@ import ( "strings" "time" - "github.com/grafana/grafana/pkg/metrics/graphitepublisher" + "github.com/grafana/grafana/pkg/metrics/graphitebridge" "github.com/grafana/grafana/pkg/setting" "github.com/prometheus/client_golang/prometheus" ini "gopkg.in/ini.v1" @@ -13,7 +13,7 @@ import ( type MetricSettings struct { Enabled bool IntervalSeconds int64 - GraphiteBridgeConfig *graphitepublisher.Config + GraphiteBridgeConfig *graphitebridge.Config } func ReadSettings(file *ini.File) *MetricSettings { @@ -45,7 +45,7 @@ func ReadSettings(file *ini.File) *MetricSettings { 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") if err != nil { return nil, nil @@ -56,7 +56,7 @@ func parseGraphiteSettings(settings *MetricSettings, file *ini.File) (*graphitep return nil, nil } - cfg := &graphitepublisher.Config{ + cfg := &graphitebridge.Config{ URL: address, Prefix: graphiteSection.Key("prefix").MustString("prod.grafana.%(instance_name)s"), CountersAsDelta: true, @@ -64,7 +64,7 @@ func parseGraphiteSettings(settings *MetricSettings, file *ini.File) (*graphitep Interval: time.Duration(settings.IntervalSeconds) * time.Second, Timeout: 10 * time.Second, Logger: &logWrapper{logger: metricsLogger}, - ErrorHandling: graphitepublisher.ContinueOnError, + ErrorHandling: graphitebridge.ContinueOnError, } safeInstanceName := strings.Replace(setting.InstanceName, ".", "_", -1)