From 8e4be13aeddde0ddff26263e2882fd0a4e7a798e Mon Sep 17 00:00:00 2001 From: dmsa0618 <dmitrii.samoilov@netcracker.com> Date: Thu, 6 Aug 2020 17:13:01 +0400 Subject: [PATCH 1/5] add configurable sliding window --- config/v3/configV3.go | 21 +++++++++++++++------ exporter/metrics.go | 3 +++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/config/v3/configV3.go b/config/v3/configV3.go index 9479205c..fd88286a 100644 --- a/config/v3/configV3.go +++ b/config/v3/configV3.go @@ -123,6 +123,7 @@ type MetricConfig struct { Cumulative bool `yaml:",omitempty"` Buckets []float64 `yaml:",flow,omitempty"` Quantiles map[float64]float64 `yaml:",flow,omitempty"` + MaxAge time.Duration `yaml:",omitempty"` Labels map[string]string `yaml:",omitempty"` LabelTemplates []template.Template `yaml:"-"` // parsed version of Labels, will not be serialized to yaml. ValueTemplate template.Template `yaml:"-"` // parsed version of Value, will not be serialized to yaml. @@ -147,6 +148,7 @@ type DefaultConfig struct { Retention time.Duration `yaml:",omitempty"` // implicitly parsed with time.ParseDuration() Buckets []float64 `yaml:",flow,omitempty"` Quantiles map[float64]float64 `yaml:",flow,omitempty"` + MaxAge time.Duration `yaml:",omitempty"` Labels map[string]string `yaml:",omitempty"` } @@ -211,6 +213,10 @@ func applyImportDefaults(metricConfig *MetricConfig, defaults DefaultConfig) { if metricConfig.Type == "summary" && len(metricConfig.Quantiles) == 0 { metricConfig.Quantiles = defaults.Quantiles } + if metricConfig.Type == "summary" && metricConfig.MaxAge == 0 { + fmt.Print("set max age default") + metricConfig.MaxAge = defaults.MaxAge + } if metricConfig.Type == "histogram" && len(metricConfig.Buckets) == 0 { metricConfig.Buckets = defaults.Buckets } @@ -416,6 +422,7 @@ func (c ImportConfig) validate() error { {"retention", c.Defaults.Retention != 0}, {"buckets", len(c.Defaults.Buckets) > 0}, {"quantiles", len(c.Defaults.Quantiles) > 0}, + {"max_age", c.Defaults.MaxAge != 0}, {"labels", len(c.Defaults.Labels) > 0}, } { if field.present { @@ -496,16 +503,16 @@ func (c *MetricConfig) validate() error { if err != nil { return err } - var cumulativeAllowed, bucketsAllowed, quantilesAllowed bool + var cumulativeAllowed, bucketsAllowed, quantilesAllowed, maxAgeAllowed bool switch c.Type { case "counter": - cumulativeAllowed, bucketsAllowed, quantilesAllowed = false, false, false + cumulativeAllowed, bucketsAllowed, quantilesAllowed, maxAgeAllowed = false, false, false, false case "gauge": - cumulativeAllowed, bucketsAllowed, quantilesAllowed = true, false, false + cumulativeAllowed, bucketsAllowed, quantilesAllowed, maxAgeAllowed = true, false, false, false case "histogram": - cumulativeAllowed, bucketsAllowed, quantilesAllowed = false, true, false + cumulativeAllowed, bucketsAllowed, quantilesAllowed, maxAgeAllowed = false, true, false, false case "summary": - cumulativeAllowed, bucketsAllowed, quantilesAllowed = false, false, true + cumulativeAllowed, bucketsAllowed, quantilesAllowed, maxAgeAllowed = false, false, true, true default: return fmt.Errorf("Invalid 'metrics.type': '%v'. We currently only support 'counter' and 'gauge'.", c.Type) } @@ -517,7 +524,9 @@ func (c *MetricConfig) validate() error { case !bucketsAllowed && len(c.Buckets) > 0: return fmt.Errorf("Invalid metric configuration: 'metrics.buckets' cannot be used for %v metrics.", c.Type) case !quantilesAllowed && len(c.Quantiles) > 0: - return fmt.Errorf("Invalid metric configuration: 'metrics.buckets' cannot be used for %v metrics.", c.Type) + return fmt.Errorf("Invalid metric configuration: 'metrics.quantiles' cannot be used for %v metrics.", c.Type) + case !maxAgeAllowed && c.MaxAge != 0: + return fmt.Errorf("Invalid metric configuration: 'metrics.max_age' cannot be used for %v metrics.", c.Type) } if len(c.DeleteMatch) > 0 && len(c.Labels) == 0 { return fmt.Errorf("Invalid metric configuration: 'metrics.delete_match' is only supported for metrics with labels.") diff --git a/exporter/metrics.go b/exporter/metrics.go index 9a8bb7a1..04d0b544 100644 --- a/exporter/metrics.go +++ b/exporter/metrics.go @@ -471,6 +471,9 @@ func NewSummaryMetric(cfg *configuration.MetricConfig, regex *oniguruma.Regex, d if len(cfg.Quantiles) > 0 { summaryOpts.Objectives = cfg.Quantiles } + if cfg.MaxAge != 0 { + summaryOpts.MaxAge = cfg.MaxAge + } if len(cfg.Labels) == 0 { return &summaryMetric{ observeMetric: newObserveMetric(cfg, regex, deleteRegex), From 3f6b741ece01d4c01d981fd4f98245212c7f1046 Mon Sep 17 00:00:00 2001 From: dmsa0618 <dmitrii.samoilov@netcracker.com> Date: Thu, 6 Aug 2020 17:21:33 +0400 Subject: [PATCH 2/5] add yaml key for max_age --- config/v3/configV3.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/v3/configV3.go b/config/v3/configV3.go index fd88286a..b3457a93 100644 --- a/config/v3/configV3.go +++ b/config/v3/configV3.go @@ -123,7 +123,7 @@ type MetricConfig struct { Cumulative bool `yaml:",omitempty"` Buckets []float64 `yaml:",flow,omitempty"` Quantiles map[float64]float64 `yaml:",flow,omitempty"` - MaxAge time.Duration `yaml:",omitempty"` + MaxAge time.Duration `yaml:"max_age,omitempty"` Labels map[string]string `yaml:",omitempty"` LabelTemplates []template.Template `yaml:"-"` // parsed version of Labels, will not be serialized to yaml. ValueTemplate template.Template `yaml:"-"` // parsed version of Value, will not be serialized to yaml. From 65abf1488b847514f325642a116a9b9184d8e8d9 Mon Sep 17 00:00:00 2001 From: dmsa0618 <dmitrii.samoilov@netcracker.com> Date: Thu, 6 Aug 2020 17:22:10 +0400 Subject: [PATCH 3/5] add yaml key for max_age #2 --- config/v3/configV3.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/v3/configV3.go b/config/v3/configV3.go index b3457a93..574fc717 100644 --- a/config/v3/configV3.go +++ b/config/v3/configV3.go @@ -148,7 +148,7 @@ type DefaultConfig struct { Retention time.Duration `yaml:",omitempty"` // implicitly parsed with time.ParseDuration() Buckets []float64 `yaml:",flow,omitempty"` Quantiles map[float64]float64 `yaml:",flow,omitempty"` - MaxAge time.Duration `yaml:",omitempty"` + MaxAge time.Duration `yaml:"max_age,omitempty"` Labels map[string]string `yaml:",omitempty"` } From 7647daf5a6210caf0a05517743b836c34cc946bb Mon Sep 17 00:00:00 2001 From: dmsa0618 <dmitrii.samoilov@netcracker.com> Date: Fri, 7 Aug 2020 08:09:34 +0400 Subject: [PATCH 4/5] remove debug artifact --- config/v3/configV3.go | 1 - 1 file changed, 1 deletion(-) diff --git a/config/v3/configV3.go b/config/v3/configV3.go index 574fc717..5e0b5bf4 100644 --- a/config/v3/configV3.go +++ b/config/v3/configV3.go @@ -214,7 +214,6 @@ func applyImportDefaults(metricConfig *MetricConfig, defaults DefaultConfig) { metricConfig.Quantiles = defaults.Quantiles } if metricConfig.Type == "summary" && metricConfig.MaxAge == 0 { - fmt.Print("set max age default") metricConfig.MaxAge = defaults.MaxAge } if metricConfig.Type == "histogram" && len(metricConfig.Buckets) == 0 { From 8ee5c6eb28e76bb232c6757ff3690186dbaf9ef3 Mon Sep 17 00:00:00 2001 From: dmsa0618 <dmitrii.samoilov@netcracker.com> Date: Fri, 7 Aug 2020 12:24:49 +0400 Subject: [PATCH 5/5] update readme --- CONFIG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONFIG.md b/CONFIG.md index 579c8629..848448a0 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -586,6 +586,7 @@ metrics: match: '%{DATE} %{TIME} %{USER:user} %{NUMBER:val}' value: '{{.val}}' quantiles: {0.5: 0.05, 0.9: 0.01, 0.99: 0.001} + max_age: 10m labels: user: '{{.user}}' ``` @@ -594,8 +595,7 @@ The configuration is as follows: * `type` is `summary`. * `name`, `help`, `match`, `labels`, and `value` have the same meaning as for `gauge` metrics. * `quantiles` is a list of quantiles to be observed. `grok_exporter` does not provide exact values for the quantiles, but only estimations. For each quantile, you also specify an uncertainty that is tolerated for the estimation. In the example, we measure the median (0.5 quantile) with uncertainty 5%, the 90% quantile with uncertainty 1%, and the 99% quantile with uncertainty 0.1%. `quantiles` is optional, the default value is `{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}`. - -Summaries represent a sliding time window of 10 minutes, i.e. if you observe a 0.5 quantile (median) of _x_, the value _x_ represents the median within the last 10 minutes. The time window is moved forward every 2 minutes. +* `max_age` is a summary sliding window. By default, summaries represent a sliding time window of 10 minutes, i.e. if you observe a 0.5 quantile (median) of _x_, the value _x_ represents the median within the last 10 minutes. The time window is moved forward every 2 minutes. Output for the example log lines above::