Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
135
plugins/aggregators/histogram/README.md
Normal file
135
plugins/aggregators/histogram/README.md
Normal file
|
@ -0,0 +1,135 @@
|
|||
# Histogram Aggregator Plugin
|
||||
|
||||
This plugin creates histograms containing the counts of field values within the
|
||||
configured range. The histogram metric is emitted every `period`.
|
||||
|
||||
In `cumulative` mode, values added to a bucket are also added to the
|
||||
consecutive buckets in the distribution creating a [cumulative histogram][1].
|
||||
|
||||
> [!NOTE]
|
||||
> By default bucket counts are not reset between periods and will be
|
||||
> non-strictly increasing while Telegraf is running. This behavior can be
|
||||
> by setting the `reset` parameter.
|
||||
|
||||
⭐ Telegraf v1.4.0
|
||||
🏷️ statistics
|
||||
💻 all
|
||||
|
||||
[1]: https://en.wikipedia.org/wiki/Histogram#/media/File:Cumulative_vs_normal_histogram.svg
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Configuration for aggregate histogram metrics
|
||||
[[aggregators.histogram]]
|
||||
## The period in which to flush the aggregator.
|
||||
# period = "30s"
|
||||
|
||||
## If true, the original metric will be dropped by the
|
||||
## aggregator and will not get sent to the output plugins.
|
||||
# drop_original = false
|
||||
|
||||
## If true, the histogram will be reset on flush instead
|
||||
## of accumulating the results.
|
||||
reset = false
|
||||
|
||||
## Whether bucket values should be accumulated. If set to false, "gt" tag will be added.
|
||||
## Defaults to true.
|
||||
cumulative = true
|
||||
|
||||
## Expiration interval for each histogram. The histogram will be expired if
|
||||
## there are no changes in any buckets for this time interval. 0 == no expiration.
|
||||
# expiration_interval = "0m"
|
||||
|
||||
## If true, aggregated histogram are pushed to output only if it was updated since
|
||||
## previous push. Defaults to false.
|
||||
# push_only_on_update = false
|
||||
|
||||
## Example config that aggregates all fields of the metric.
|
||||
# [[aggregators.histogram.config]]
|
||||
# ## Right borders of buckets (with +Inf implicitly added).
|
||||
# buckets = [0.0, 15.6, 34.5, 49.1, 71.5, 80.5, 94.5, 100.0]
|
||||
# ## The name of metric.
|
||||
# measurement_name = "cpu"
|
||||
|
||||
## Example config that aggregates only specific fields of the metric.
|
||||
# [[aggregators.histogram.config]]
|
||||
# ## Right borders of buckets (with +Inf implicitly added).
|
||||
# buckets = [0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]
|
||||
# ## The name of metric.
|
||||
# measurement_name = "diskio"
|
||||
# ## The concrete fields of metric
|
||||
# fields = ["io_time", "read_time", "write_time"]
|
||||
```
|
||||
|
||||
The user is responsible for defining the bounds of the histogram bucket as
|
||||
well as the measurement name and fields to aggregate.
|
||||
|
||||
Each histogram config section must contain a `buckets` and `measurement_name`
|
||||
option. Optionally, if `fields` is set only the fields listed will be
|
||||
aggregated. If `fields` is not set all fields are aggregated.
|
||||
|
||||
The `buckets` option contains a list of floats which specify the bucket
|
||||
boundaries. Each float value defines the inclusive upper (right) bound of the
|
||||
bucket. The `+Inf` bucket is added automatically and does not need to be
|
||||
defined. (For left boundaries, these specified bucket borders and `-Inf` will
|
||||
be used).
|
||||
|
||||
## Measurements & Fields
|
||||
|
||||
The postfix `bucket` will be added to each field key.
|
||||
|
||||
- measurement1
|
||||
- field1_bucket
|
||||
- field2_bucket
|
||||
|
||||
### Tags
|
||||
|
||||
- `cumulative = true` (default):
|
||||
- `le`: Right bucket border. It means that the metric value is less than or
|
||||
equal to the value of this tag. If a metric value is sorted into a bucket,
|
||||
it is also sorted into all larger buckets. As a result, the value of
|
||||
`<field>_bucket` is rising with rising `le` value. When `le` is `+Inf`,
|
||||
the bucket value is the count of all metrics, because all metric values are
|
||||
less than or equal to positive infinity.
|
||||
- `cumulative = false`:
|
||||
- `gt`: Left bucket border. It means that the metric value is greater than
|
||||
(and not equal to) the value of this tag.
|
||||
- `le`: Right bucket border. It means that the metric value is less than or
|
||||
equal to the value of this tag.
|
||||
- As both `gt` and `le` are present, each metric is sorted in only exactly
|
||||
one bucket.
|
||||
|
||||
## Example Output
|
||||
|
||||
Let assume we have the buckets [0, 10, 50, 100] and the following field values
|
||||
for `usage_idle`: [50, 7, 99, 12]
|
||||
|
||||
With `cumulative = true`:
|
||||
|
||||
```text
|
||||
cpu,cpu=cpu1,host=localhost,le=0.0 usage_idle_bucket=0i 1486998330000000000 # none
|
||||
cpu,cpu=cpu1,host=localhost,le=10.0 usage_idle_bucket=1i 1486998330000000000 # 7
|
||||
cpu,cpu=cpu1,host=localhost,le=50.0 usage_idle_bucket=2i 1486998330000000000 # 7, 12
|
||||
cpu,cpu=cpu1,host=localhost,le=100.0 usage_idle_bucket=4i 1486998330000000000 # 7, 12, 50, 99
|
||||
cpu,cpu=cpu1,host=localhost,le=+Inf usage_idle_bucket=4i 1486998330000000000 # 7, 12, 50, 99
|
||||
```
|
||||
|
||||
With `cumulative = false`:
|
||||
|
||||
```text
|
||||
cpu,cpu=cpu1,host=localhost,gt=-Inf,le=0.0 usage_idle_bucket=0i 1486998330000000000 # none
|
||||
cpu,cpu=cpu1,host=localhost,gt=0.0,le=10.0 usage_idle_bucket=1i 1486998330000000000 # 7
|
||||
cpu,cpu=cpu1,host=localhost,gt=10.0,le=50.0 usage_idle_bucket=1i 1486998330000000000 # 12
|
||||
cpu,cpu=cpu1,host=localhost,gt=50.0,le=100.0 usage_idle_bucket=2i 1486998330000000000 # 50, 99
|
||||
cpu,cpu=cpu1,host=localhost,gt=100.0,le=+Inf usage_idle_bucket=0i 1486998330000000000 # none
|
||||
```
|
327
plugins/aggregators/histogram/histogram.go
Normal file
327
plugins/aggregators/histogram/histogram.go
Normal file
|
@ -0,0 +1,327 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package histogram
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/plugins/aggregators"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
// bucketRightTag is the tag, which contains right bucket border
|
||||
const bucketRightTag = "le"
|
||||
|
||||
// bucketPosInf is the right bucket border for infinite values
|
||||
const bucketPosInf = "+Inf"
|
||||
|
||||
// bucketLeftTag is the tag, which contains left bucket border (exclusive)
|
||||
const bucketLeftTag = "gt"
|
||||
|
||||
// bucketNegInf is the left bucket border for infinite values
|
||||
const bucketNegInf = "-Inf"
|
||||
|
||||
// HistogramAggregator is aggregator with histogram configs and particular histograms for defined metrics
|
||||
type HistogramAggregator struct {
|
||||
Configs []bucketConfig `toml:"config"`
|
||||
ResetBuckets bool `toml:"reset"`
|
||||
Cumulative bool `toml:"cumulative"`
|
||||
ExpirationInterval config.Duration `toml:"expiration_interval"`
|
||||
PushOnlyOnUpdate bool `toml:"push_only_on_update"`
|
||||
|
||||
buckets bucketsByMetrics
|
||||
cache map[uint64]metricHistogramCollection
|
||||
}
|
||||
|
||||
// bucketConfig is the config, which contains name, field of metric and histogram buckets.
|
||||
type bucketConfig struct {
|
||||
Metric string `toml:"measurement_name"`
|
||||
Fields []string `toml:"fields"`
|
||||
Buckets buckets `toml:"buckets"`
|
||||
}
|
||||
|
||||
// bucketsByMetrics contains the buckets grouped by metric and field name
|
||||
type bucketsByMetrics map[string]bucketsByFields
|
||||
|
||||
// bucketsByFields contains the buckets grouped by field name
|
||||
type bucketsByFields map[string]buckets
|
||||
|
||||
// buckets contains the right borders buckets
|
||||
type buckets []float64
|
||||
|
||||
// metricHistogramCollection aggregates the histogram data
|
||||
type metricHistogramCollection struct {
|
||||
histogramCollection map[string]counts
|
||||
name string
|
||||
tags map[string]string
|
||||
expireTime time.Time
|
||||
updated bool
|
||||
}
|
||||
|
||||
// counts is the number of hits in the bucket
|
||||
type counts []int64
|
||||
|
||||
// groupedByCountFields contains grouped fields by their count and fields values
|
||||
type groupedByCountFields struct {
|
||||
name string
|
||||
tags map[string]string
|
||||
fieldsWithCount map[string]int64
|
||||
}
|
||||
|
||||
var timeNow = time.Now
|
||||
|
||||
// NewHistogramAggregator creates new histogram aggregator
|
||||
func NewHistogramAggregator() *HistogramAggregator {
|
||||
h := &HistogramAggregator{
|
||||
Cumulative: true,
|
||||
}
|
||||
h.buckets = make(bucketsByMetrics)
|
||||
h.resetCache()
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func (*HistogramAggregator) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
// Add adds new hit to the buckets
|
||||
func (h *HistogramAggregator) Add(in telegraf.Metric) {
|
||||
addTime := timeNow()
|
||||
|
||||
bucketsByField := make(map[string][]float64)
|
||||
for field := range in.Fields() {
|
||||
buckets := h.getBuckets(in.Name(), field)
|
||||
if buckets != nil {
|
||||
bucketsByField[field] = buckets
|
||||
}
|
||||
}
|
||||
|
||||
if len(bucketsByField) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
id := in.HashID()
|
||||
agr, ok := h.cache[id]
|
||||
if !ok {
|
||||
agr = metricHistogramCollection{
|
||||
name: in.Name(),
|
||||
tags: in.Tags(),
|
||||
histogramCollection: make(map[string]counts),
|
||||
}
|
||||
}
|
||||
|
||||
for field, value := range in.Fields() {
|
||||
if buckets, ok := bucketsByField[field]; ok {
|
||||
if agr.histogramCollection[field] == nil {
|
||||
agr.histogramCollection[field] = make(counts, len(buckets)+1)
|
||||
}
|
||||
|
||||
if value, ok := convert(value); ok {
|
||||
index := sort.SearchFloat64s(buckets, value)
|
||||
agr.histogramCollection[field][index]++
|
||||
}
|
||||
if h.ExpirationInterval != 0 {
|
||||
agr.expireTime = addTime.Add(time.Duration(h.ExpirationInterval))
|
||||
}
|
||||
agr.updated = true
|
||||
}
|
||||
}
|
||||
|
||||
h.cache[id] = agr
|
||||
}
|
||||
|
||||
// Push returns histogram values for metrics
|
||||
func (h *HistogramAggregator) Push(acc telegraf.Accumulator) {
|
||||
now := timeNow()
|
||||
metricsWithGroupedFields := make([]groupedByCountFields, 0)
|
||||
for id, aggregate := range h.cache {
|
||||
if h.ExpirationInterval != 0 && now.After(aggregate.expireTime) {
|
||||
delete(h.cache, id)
|
||||
continue
|
||||
}
|
||||
if h.PushOnlyOnUpdate && !h.cache[id].updated {
|
||||
continue
|
||||
}
|
||||
aggregate.updated = false
|
||||
h.cache[id] = aggregate
|
||||
for field, counts := range aggregate.histogramCollection {
|
||||
h.groupFieldsByBuckets(&metricsWithGroupedFields, aggregate.name, field, copyTags(aggregate.tags), counts)
|
||||
}
|
||||
}
|
||||
|
||||
for _, metric := range metricsWithGroupedFields {
|
||||
acc.AddFields(metric.name, makeFieldsWithCount(metric.fieldsWithCount), metric.tags)
|
||||
}
|
||||
}
|
||||
|
||||
// groupFieldsByBuckets groups fields by metric buckets which are represented as tags
|
||||
func (h *HistogramAggregator) groupFieldsByBuckets(
|
||||
metricsWithGroupedFields *[]groupedByCountFields, name, field string, tags map[string]string, counts []int64,
|
||||
) {
|
||||
sum := int64(0)
|
||||
buckets := h.getBuckets(name, field) // note that len(buckets) + 1 == len(counts)
|
||||
|
||||
for index, count := range counts {
|
||||
if !h.Cumulative {
|
||||
sum = 0 // reset sum -> don't store cumulative counts
|
||||
|
||||
tags[bucketLeftTag] = bucketNegInf
|
||||
if index > 0 {
|
||||
tags[bucketLeftTag] = strconv.FormatFloat(buckets[index-1], 'f', -1, 64)
|
||||
}
|
||||
}
|
||||
|
||||
tags[bucketRightTag] = bucketPosInf
|
||||
if index < len(buckets) {
|
||||
tags[bucketRightTag] = strconv.FormatFloat(buckets[index], 'f', -1, 64)
|
||||
}
|
||||
|
||||
sum += count
|
||||
groupField(metricsWithGroupedFields, name, field, sum, copyTags(tags))
|
||||
}
|
||||
}
|
||||
|
||||
// groupField groups field by count value
|
||||
func groupField(metricsWithGroupedFields *[]groupedByCountFields, name, field string, count int64, tags map[string]string) {
|
||||
for key, metric := range *metricsWithGroupedFields {
|
||||
if name == metric.name && isTagsIdentical(tags, metric.tags) {
|
||||
(*metricsWithGroupedFields)[key].fieldsWithCount[field] = count
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fieldsWithCount := map[string]int64{
|
||||
field: count,
|
||||
}
|
||||
|
||||
*metricsWithGroupedFields = append(
|
||||
*metricsWithGroupedFields,
|
||||
groupedByCountFields{name: name, tags: tags, fieldsWithCount: fieldsWithCount},
|
||||
)
|
||||
}
|
||||
|
||||
// Reset does nothing by default, because we typically need to collect counts for a long time.
|
||||
// Otherwise if config parameter 'reset' has 'true' value, we will get a histogram
|
||||
// with a small amount of the distribution. However in some use cases a reset is useful.
|
||||
func (h *HistogramAggregator) Reset() {
|
||||
if h.ResetBuckets {
|
||||
h.resetCache()
|
||||
h.buckets = make(bucketsByMetrics)
|
||||
}
|
||||
}
|
||||
|
||||
// resetCache resets cached counts(hits) in the buckets
|
||||
func (h *HistogramAggregator) resetCache() {
|
||||
h.cache = make(map[uint64]metricHistogramCollection)
|
||||
}
|
||||
|
||||
// getBuckets finds buckets and returns them
|
||||
func (h *HistogramAggregator) getBuckets(metric, field string) []float64 {
|
||||
if buckets, ok := h.buckets[metric][field]; ok {
|
||||
return buckets
|
||||
}
|
||||
|
||||
for _, cfg := range h.Configs {
|
||||
if cfg.Metric == metric {
|
||||
if !isBucketExists(field, cfg) {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := h.buckets[metric]; !ok {
|
||||
h.buckets[metric] = make(bucketsByFields)
|
||||
}
|
||||
|
||||
h.buckets[metric][field] = sortBuckets(cfg.Buckets)
|
||||
}
|
||||
}
|
||||
|
||||
return h.buckets[metric][field]
|
||||
}
|
||||
|
||||
// isBucketExists checks if buckets exists for the passed field
|
||||
func isBucketExists(field string, cfg bucketConfig) bool {
|
||||
if len(cfg.Fields) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, fl := range cfg.Fields {
|
||||
if fl == field {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// sortBuckets sorts the buckets if it is needed
|
||||
func sortBuckets(buckets []float64) []float64 {
|
||||
for i, bucket := range buckets {
|
||||
if i < len(buckets)-1 && bucket >= buckets[i+1] {
|
||||
sort.Float64s(buckets)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return buckets
|
||||
}
|
||||
|
||||
// convert converts interface to concrete type
|
||||
func convert(in interface{}) (float64, bool) {
|
||||
switch v := in.(type) {
|
||||
case float64:
|
||||
return v, true
|
||||
case int64:
|
||||
return float64(v), true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
// copyTags copies tags
|
||||
func copyTags(tags map[string]string) map[string]string {
|
||||
copiedTags := make(map[string]string, len(tags))
|
||||
for key, val := range tags {
|
||||
copiedTags[key] = val
|
||||
}
|
||||
|
||||
return copiedTags
|
||||
}
|
||||
|
||||
// isTagsIdentical checks the identity of two list of tags
|
||||
func isTagsIdentical(originalTags, checkedTags map[string]string) bool {
|
||||
if len(originalTags) != len(checkedTags) {
|
||||
return false
|
||||
}
|
||||
|
||||
for tagName, tagValue := range originalTags {
|
||||
if tagValue != checkedTags[tagName] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// makeFieldsWithCount assigns count value to all metric fields
|
||||
func makeFieldsWithCount(fieldsWithCountIn map[string]int64) map[string]interface{} {
|
||||
fieldsWithCountOut := make(map[string]interface{}, len(fieldsWithCountIn))
|
||||
for field, count := range fieldsWithCountIn {
|
||||
fieldsWithCountOut[field+"_bucket"] = count
|
||||
}
|
||||
|
||||
return fieldsWithCountOut
|
||||
}
|
||||
|
||||
// init initializes histogram aggregator plugin
|
||||
func init() {
|
||||
aggregators.Add("histogram", func() telegraf.Aggregator {
|
||||
return NewHistogramAggregator()
|
||||
})
|
||||
}
|
529
plugins/aggregators/histogram/histogram_test.go
Normal file
529
plugins/aggregators/histogram/histogram_test.go
Normal file
|
@ -0,0 +1,529 @@
|
|||
package histogram
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/metric"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
type fields map[string]interface{}
|
||||
type tags map[string]string
|
||||
|
||||
// NewTestHistogram creates new test histogram aggregation with specified config
|
||||
func NewTestHistogram(cfg []bucketConfig, reset, cumulative, pushOnlyOnUpdate bool) telegraf.Aggregator {
|
||||
return NewTestHistogramWithExpirationInterval(cfg, reset, cumulative, pushOnlyOnUpdate, 0)
|
||||
}
|
||||
|
||||
func NewTestHistogramWithExpirationInterval(
|
||||
cfg []bucketConfig, reset, cumulative, pushOnlyOnUpdate bool, expirationInterval config.Duration,
|
||||
) telegraf.Aggregator {
|
||||
htm := NewHistogramAggregator()
|
||||
htm.Configs = cfg
|
||||
htm.ResetBuckets = reset
|
||||
htm.Cumulative = cumulative
|
||||
htm.ExpirationInterval = expirationInterval
|
||||
htm.PushOnlyOnUpdate = pushOnlyOnUpdate
|
||||
|
||||
return htm
|
||||
}
|
||||
|
||||
// firstMetric1 is the first test metric
|
||||
var firstMetric1 = metric.New(
|
||||
"first_metric_name",
|
||||
tags{},
|
||||
fields{
|
||||
"a": float64(15.3),
|
||||
"b": float64(40),
|
||||
},
|
||||
time.Now(),
|
||||
)
|
||||
|
||||
// firstMetric1 is the first test metric with other value
|
||||
var firstMetric2 = metric.New(
|
||||
"first_metric_name",
|
||||
tags{},
|
||||
fields{
|
||||
"a": float64(15.9),
|
||||
"c": float64(40),
|
||||
},
|
||||
time.Now(),
|
||||
)
|
||||
|
||||
// secondMetric is the second metric
|
||||
var secondMetric = metric.New(
|
||||
"second_metric_name",
|
||||
tags{},
|
||||
fields{
|
||||
"a": float64(105),
|
||||
"ignoreme": "string",
|
||||
"andme": true,
|
||||
},
|
||||
time.Now(),
|
||||
)
|
||||
|
||||
// BenchmarkApply runs benchmarks
|
||||
func BenchmarkApply(b *testing.B) {
|
||||
histogram := NewHistogramAggregator()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
histogram.Add(firstMetric1)
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Add(secondMetric)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHistogram tests metrics for one period and for one field
|
||||
func TestHistogram(t *testing.T) {
|
||||
var cfg []bucketConfig
|
||||
cfg = append(cfg, bucketConfig{Metric: "first_metric_name", Fields: []string{"a"}, Buckets: []float64{0.0, 10.0, 20.0, 30.0, 40.0}})
|
||||
histogram := NewTestHistogram(cfg, false, true, false)
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
histogram.Add(firstMetric1)
|
||||
histogram.Reset()
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Push(acc)
|
||||
|
||||
require.Len(t, acc.Metrics, 6, "Incorrect number of metrics")
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketRightTag: "0"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketRightTag: "10"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketRightTag: "20"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketRightTag: "30"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketRightTag: "40"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketRightTag: bucketPosInf})
|
||||
}
|
||||
|
||||
// TestHistogram tests metrics for one period, for one field and push only on histogram update
|
||||
func TestHistogramPushOnUpdate(t *testing.T) {
|
||||
var cfg []bucketConfig
|
||||
cfg = append(cfg, bucketConfig{Metric: "first_metric_name", Fields: []string{"a"}, Buckets: []float64{0.0, 10.0, 20.0, 30.0, 40.0}})
|
||||
histogram := NewTestHistogram(cfg, false, true, true)
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
histogram.Add(firstMetric1)
|
||||
histogram.Reset()
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Push(acc)
|
||||
|
||||
require.Len(t, acc.Metrics, 6, "Incorrect number of metrics")
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketRightTag: "0"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketRightTag: "10"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketRightTag: "20"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketRightTag: "30"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketRightTag: "40"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketRightTag: bucketPosInf})
|
||||
|
||||
acc.ClearMetrics()
|
||||
histogram.Push(acc)
|
||||
require.Empty(t, acc.Metrics, "Incorrect number of metrics")
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Push(acc)
|
||||
|
||||
require.Len(t, acc.Metrics, 6, "Incorrect number of metrics")
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketRightTag: "0"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketRightTag: "10"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(3)}, tags{bucketRightTag: "20"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(3)}, tags{bucketRightTag: "30"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(3)}, tags{bucketRightTag: "40"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(3)}, tags{bucketRightTag: bucketPosInf})
|
||||
}
|
||||
|
||||
// TestHistogramNonCumulative tests metrics for one period and for one field
|
||||
func TestHistogramNonCumulative(t *testing.T) {
|
||||
var cfg []bucketConfig
|
||||
cfg = append(cfg, bucketConfig{Metric: "first_metric_name", Fields: []string{"a"}, Buckets: []float64{0.0, 10.0, 20.0, 30.0, 40.0}})
|
||||
histogram := NewTestHistogram(cfg, false, false, false)
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
histogram.Add(firstMetric1)
|
||||
histogram.Reset()
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Push(acc)
|
||||
|
||||
require.Len(t, acc.Metrics, 6, "Incorrect number of metrics")
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketLeftTag: bucketNegInf, bucketRightTag: "0"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketLeftTag: "0", bucketRightTag: "10"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2)}, tags{bucketLeftTag: "10", bucketRightTag: "20"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketLeftTag: "20", bucketRightTag: "30"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketLeftTag: "30", bucketRightTag: "40"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketLeftTag: "40", bucketRightTag: bucketPosInf})
|
||||
}
|
||||
|
||||
// TestHistogramWithReset tests metrics for one period and for one field, with reset between metrics adding
|
||||
func TestHistogramWithReset(t *testing.T) {
|
||||
var cfg []bucketConfig
|
||||
cfg = append(cfg, bucketConfig{Metric: "first_metric_name", Fields: []string{"a"}, Buckets: []float64{0.0, 10.0, 20.0, 30.0, 40.0}})
|
||||
histogram := NewTestHistogram(cfg, true, true, false)
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
histogram.Add(firstMetric1)
|
||||
histogram.Reset()
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Push(acc)
|
||||
|
||||
require.Len(t, acc.Metrics, 6, "Incorrect number of metrics")
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketRightTag: "0"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0)}, tags{bucketRightTag: "10"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(1)}, tags{bucketRightTag: "20"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(1)}, tags{bucketRightTag: "30"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(1)}, tags{bucketRightTag: "40"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(1)}, tags{bucketRightTag: bucketPosInf})
|
||||
}
|
||||
|
||||
// TestHistogramWithAllFields tests two metrics for one period and for all fields
|
||||
func TestHistogramWithAllFields(t *testing.T) {
|
||||
cfg := []bucketConfig{
|
||||
{Metric: "first_metric_name", Buckets: []float64{0.0, 15.5, 20.0, 30.0, 40.0}},
|
||||
{Metric: "second_metric_name", Buckets: []float64{0.0, 4.0, 10.0, 23.0, 30.0}},
|
||||
}
|
||||
histogram := NewTestHistogram(cfg, false, true, false)
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
histogram.Add(firstMetric1)
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Add(secondMetric)
|
||||
histogram.Push(acc)
|
||||
|
||||
require.Len(t, acc.Metrics, 12, "Incorrect number of metrics")
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0), "b_bucket": int64(0), "c_bucket": int64(0)}, tags{bucketRightTag: "0"})
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(1), "b_bucket": int64(0), "c_bucket": int64(0)},
|
||||
tags{bucketRightTag: "15.5"},
|
||||
)
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2), "b_bucket": int64(0), "c_bucket": int64(0)}, tags{bucketRightTag: "20"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2), "b_bucket": int64(0), "c_bucket": int64(0)}, tags{bucketRightTag: "30"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2), "b_bucket": int64(1), "c_bucket": int64(1)}, tags{bucketRightTag: "40"})
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(2), "b_bucket": int64(1), "c_bucket": int64(1)},
|
||||
tags{bucketRightTag: bucketPosInf},
|
||||
)
|
||||
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "0"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "4"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "10"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "23"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "30"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(1), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: bucketPosInf},
|
||||
)
|
||||
}
|
||||
|
||||
// TestHistogramWithAllFieldsNonCumulative tests two metrics for one period and for all fields
|
||||
func TestHistogramWithAllFieldsNonCumulative(t *testing.T) {
|
||||
cfg := []bucketConfig{
|
||||
{Metric: "first_metric_name", Buckets: []float64{0.0, 15.5, 20.0, 30.0, 40.0}},
|
||||
{Metric: "second_metric_name", Buckets: []float64{0.0, 4.0, 10.0, 23.0, 30.0}},
|
||||
}
|
||||
histogram := NewTestHistogram(cfg, false, false, false)
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
histogram.Add(firstMetric1)
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Add(secondMetric)
|
||||
histogram.Push(acc)
|
||||
|
||||
require.Len(t, acc.Metrics, 12, "Incorrect number of metrics")
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(0), "b_bucket": int64(0), "c_bucket": int64(0)},
|
||||
tags{bucketLeftTag: bucketNegInf, bucketRightTag: "0"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(1), "b_bucket": int64(0), "c_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "0", bucketRightTag: "15.5"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(1), "b_bucket": int64(0), "c_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "15.5", bucketRightTag: "20"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(0), "b_bucket": int64(0), "c_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "20", bucketRightTag: "30"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(0), "b_bucket": int64(1), "c_bucket": int64(1)},
|
||||
tags{bucketLeftTag: "30", bucketRightTag: "40"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(0), "b_bucket": int64(0), "c_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "40", bucketRightTag: bucketPosInf},
|
||||
)
|
||||
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketLeftTag: bucketNegInf, bucketRightTag: "0"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "0", bucketRightTag: "4"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "4", bucketRightTag: "10"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "10", bucketRightTag: "23"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "23", bucketRightTag: "30"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(1), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketLeftTag: "30", bucketRightTag: bucketPosInf},
|
||||
)
|
||||
}
|
||||
|
||||
// TestHistogramWithTwoPeriodsAndAllFields tests two metrics getting added with a push/reset in between (simulates
|
||||
// getting added in different periods) for all fields
|
||||
func TestHistogramWithTwoPeriodsAndAllFields(t *testing.T) {
|
||||
var cfg []bucketConfig
|
||||
cfg = append(cfg, bucketConfig{Metric: "first_metric_name", Buckets: []float64{0.0, 10.0, 20.0, 30.0, 40.0}})
|
||||
histogram := NewTestHistogram(cfg, false, true, false)
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
histogram.Add(firstMetric1)
|
||||
histogram.Push(acc)
|
||||
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0), "b_bucket": int64(0)}, tags{bucketRightTag: "0"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0), "b_bucket": int64(0)}, tags{bucketRightTag: "10"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(1), "b_bucket": int64(0)}, tags{bucketRightTag: "20"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(1), "b_bucket": int64(0)}, tags{bucketRightTag: "30"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(1), "b_bucket": int64(1)}, tags{bucketRightTag: "40"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(1), "b_bucket": int64(1)}, tags{bucketRightTag: bucketPosInf})
|
||||
|
||||
acc.ClearMetrics()
|
||||
histogram.Add(firstMetric2)
|
||||
histogram.Push(acc)
|
||||
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0), "b_bucket": int64(0), "c_bucket": int64(0)}, tags{bucketRightTag: "0"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(0), "b_bucket": int64(0), "c_bucket": int64(0)}, tags{bucketRightTag: "10"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2), "b_bucket": int64(0), "c_bucket": int64(0)}, tags{bucketRightTag: "20"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2), "b_bucket": int64(0), "c_bucket": int64(0)}, tags{bucketRightTag: "30"})
|
||||
assertContainsTaggedField(t, acc, "first_metric_name", fields{"a_bucket": int64(2), "b_bucket": int64(1), "c_bucket": int64(1)}, tags{bucketRightTag: "40"})
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"first_metric_name",
|
||||
fields{"a_bucket": int64(2), "b_bucket": int64(1), "c_bucket": int64(1)},
|
||||
tags{bucketRightTag: bucketPosInf},
|
||||
)
|
||||
}
|
||||
|
||||
// TestWrongBucketsOrder tests the calling panic with incorrect order of buckets
|
||||
func TestWrongBucketsOrder(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
require.Equal(
|
||||
t,
|
||||
"histogram buckets must be in increasing order: 90.00 >= 20.00, metrics: first_metric_name, field: a",
|
||||
fmt.Sprint(r),
|
||||
)
|
||||
}
|
||||
}()
|
||||
|
||||
var cfg []bucketConfig
|
||||
cfg = append(cfg, bucketConfig{Metric: "first_metric_name", Buckets: []float64{0.0, 90.0, 20.0, 30.0, 40.0}})
|
||||
histogram := NewTestHistogram(cfg, false, true, false)
|
||||
histogram.Add(firstMetric2)
|
||||
}
|
||||
|
||||
// TestHistogram tests two metrics getting added and metric expiration
|
||||
func TestHistogramMetricExpiration(t *testing.T) {
|
||||
currentTime := time.Unix(10, 0)
|
||||
timeNow = func() time.Time {
|
||||
return currentTime
|
||||
}
|
||||
defer func() {
|
||||
timeNow = time.Now
|
||||
}()
|
||||
|
||||
cfg := []bucketConfig{
|
||||
{Metric: "first_metric_name", Fields: []string{"a"}, Buckets: []float64{0.0, 10.0, 20.0, 30.0, 40.0}},
|
||||
{Metric: "second_metric_name", Buckets: []float64{0.0, 4.0, 10.0, 23.0, 30.0}},
|
||||
}
|
||||
histogram := NewTestHistogramWithExpirationInterval(cfg, false, true, false, config.Duration(30))
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
histogram.Add(firstMetric1)
|
||||
currentTime = time.Unix(41, 0)
|
||||
histogram.Add(secondMetric)
|
||||
histogram.Push(acc)
|
||||
|
||||
require.Len(t, acc.Metrics, 6, "Incorrect number of metrics")
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "0"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "4"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "10"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "23"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(0), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: "30"},
|
||||
)
|
||||
assertContainsTaggedField(
|
||||
t,
|
||||
acc,
|
||||
"second_metric_name",
|
||||
fields{"a_bucket": int64(1), "ignoreme_bucket": int64(0), "andme_bucket": int64(0)},
|
||||
tags{bucketRightTag: bucketPosInf},
|
||||
)
|
||||
}
|
||||
|
||||
// assertContainsTaggedField is help functions to test histogram data
|
||||
func assertContainsTaggedField(t *testing.T, acc *testutil.Accumulator, metricName string, fields map[string]interface{}, tags map[string]string) {
|
||||
acc.Lock()
|
||||
defer acc.Unlock()
|
||||
|
||||
for _, checkedMetric := range acc.Metrics {
|
||||
// filter by metric name
|
||||
if checkedMetric.Measurement != metricName {
|
||||
continue
|
||||
}
|
||||
|
||||
// filter by tags
|
||||
isTagsIdentical := true
|
||||
for tag := range tags {
|
||||
if val, ok := checkedMetric.Tags[tag]; !ok || val != tags[tag] {
|
||||
isTagsIdentical = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isTagsIdentical {
|
||||
continue
|
||||
}
|
||||
|
||||
// filter by field keys
|
||||
isFieldKeysIdentical := true
|
||||
for field := range fields {
|
||||
if _, ok := checkedMetric.Fields[field]; !ok {
|
||||
isFieldKeysIdentical = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isFieldKeysIdentical {
|
||||
continue
|
||||
}
|
||||
|
||||
// check fields with their counts
|
||||
require.Equal(t, fields, checkedMetric.Fields)
|
||||
return
|
||||
}
|
||||
|
||||
require.Failf(t, "Unknown measurement", "Unknown measurement %q with tags: %v, fields: %v", metricName, tags, fields)
|
||||
}
|
40
plugins/aggregators/histogram/sample.conf
Normal file
40
plugins/aggregators/histogram/sample.conf
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Configuration for aggregate histogram metrics
|
||||
[[aggregators.histogram]]
|
||||
## The period in which to flush the aggregator.
|
||||
# period = "30s"
|
||||
|
||||
## If true, the original metric will be dropped by the
|
||||
## aggregator and will not get sent to the output plugins.
|
||||
# drop_original = false
|
||||
|
||||
## If true, the histogram will be reset on flush instead
|
||||
## of accumulating the results.
|
||||
reset = false
|
||||
|
||||
## Whether bucket values should be accumulated. If set to false, "gt" tag will be added.
|
||||
## Defaults to true.
|
||||
cumulative = true
|
||||
|
||||
## Expiration interval for each histogram. The histogram will be expired if
|
||||
## there are no changes in any buckets for this time interval. 0 == no expiration.
|
||||
# expiration_interval = "0m"
|
||||
|
||||
## If true, aggregated histogram are pushed to output only if it was updated since
|
||||
## previous push. Defaults to false.
|
||||
# push_only_on_update = false
|
||||
|
||||
## Example config that aggregates all fields of the metric.
|
||||
# [[aggregators.histogram.config]]
|
||||
# ## Right borders of buckets (with +Inf implicitly added).
|
||||
# buckets = [0.0, 15.6, 34.5, 49.1, 71.5, 80.5, 94.5, 100.0]
|
||||
# ## The name of metric.
|
||||
# measurement_name = "cpu"
|
||||
|
||||
## Example config that aggregates only specific fields of the metric.
|
||||
# [[aggregators.histogram.config]]
|
||||
# ## Right borders of buckets (with +Inf implicitly added).
|
||||
# buckets = [0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]
|
||||
# ## The name of metric.
|
||||
# measurement_name = "diskio"
|
||||
# ## The concrete fields of metric
|
||||
# fields = ["io_time", "read_time", "write_time"]
|
Loading…
Add table
Add a link
Reference in a new issue