Add diff and non_negative_diff to basicstats aggregator (#4435)
This commit is contained in:
parent
df90230341
commit
282c8ce096
|
@ -1,6 +1,6 @@
|
||||||
# BasicStats Aggregator Plugin
|
# BasicStats Aggregator Plugin
|
||||||
|
|
||||||
The BasicStats aggregator plugin give us count,max,min,mean,sum,s2(variance), stdev for a set of values,
|
The BasicStats aggregator plugin give us count,diff,max,min,mean,non_negative_diff,sum,s2(variance), stdev for a set of values,
|
||||||
emitting the aggregate every `period` seconds.
|
emitting the aggregate every `period` seconds.
|
||||||
|
|
||||||
### Configuration:
|
### Configuration:
|
||||||
|
@ -15,20 +15,22 @@ emitting the aggregate every `period` seconds.
|
||||||
drop_original = false
|
drop_original = false
|
||||||
|
|
||||||
## Configures which basic stats to push as fields
|
## Configures which basic stats to push as fields
|
||||||
# stats = ["count", "min", "max", "mean", "stdev", "s2", "sum"]
|
# stats = ["count","diff","min","max","mean","non_negative_diff","stdev","s2","sum"]
|
||||||
```
|
```
|
||||||
|
|
||||||
- stats
|
- stats
|
||||||
- If not specified, then `count`, `min`, `max`, `mean`, `stdev`, and `s2` are aggregated and pushed as fields. `sum` is not aggregated by default to maintain backwards compatibility.
|
- If not specified, then `count`, `min`, `max`, `mean`, `stdev`, and `s2` are aggregated and pushed as fields. `sum`, `diff` and `non_negative_diff` are not aggregated by default to maintain backwards compatibility.
|
||||||
- If empty array, no stats are aggregated
|
- If empty array, no stats are aggregated
|
||||||
|
|
||||||
### Measurements & Fields:
|
### Measurements & Fields:
|
||||||
|
|
||||||
- measurement1
|
- measurement1
|
||||||
- field1_count
|
- field1_count
|
||||||
|
- field1_diff (difference)
|
||||||
- field1_max
|
- field1_max
|
||||||
- field1_min
|
- field1_min
|
||||||
- field1_mean
|
- field1_mean
|
||||||
|
- field1_non_negative_diff (non-negative difference)
|
||||||
- field1_sum
|
- field1_sum
|
||||||
- field1_s2 (variance)
|
- field1_s2 (variance)
|
||||||
- field1_stdev (standard deviation)
|
- field1_stdev (standard deviation)
|
||||||
|
@ -43,8 +45,8 @@ No tags are applied by this aggregator.
|
||||||
$ telegraf --config telegraf.conf --quiet
|
$ telegraf --config telegraf.conf --quiet
|
||||||
system,host=tars load1=1 1475583980000000000
|
system,host=tars load1=1 1475583980000000000
|
||||||
system,host=tars load1=1 1475583990000000000
|
system,host=tars load1=1 1475583990000000000
|
||||||
system,host=tars load1_count=2,load1_max=1,load1_min=1,load1_mean=1,load1_sum=2,load1_s2=0,load1_stdev=0 1475584010000000000
|
system,host=tars load1_count=2,load1_diff=0,load1_max=1,load1_min=1,load1_mean=1,load1_sum=2,load1_s2=0,load1_stdev=0 1475584010000000000
|
||||||
system,host=tars load1=1 1475584020000000000
|
system,host=tars load1=1 1475584020000000000
|
||||||
system,host=tars load1=3 1475584030000000000
|
system,host=tars load1=3 1475584030000000000
|
||||||
system,host=tars load1_count=2,load1_max=3,load1_min=1,load1_mean=2,load1_sum=4,load1_s2=2,load1_stdev=1.414162 1475584010000000000
|
system,host=tars load1_count=2,load1_diff=2,load1_max=3,load1_min=1,load1_mean=2,load1_sum=4,load1_s2=2,load1_stdev=1.414162 1475584010000000000
|
||||||
```
|
```
|
||||||
|
|
|
@ -16,13 +16,15 @@ type BasicStats struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type configuredStats struct {
|
type configuredStats struct {
|
||||||
count bool
|
count bool
|
||||||
min bool
|
min bool
|
||||||
max bool
|
max bool
|
||||||
mean bool
|
mean bool
|
||||||
variance bool
|
variance bool
|
||||||
stdev bool
|
stdev bool
|
||||||
sum bool
|
sum bool
|
||||||
|
diff bool
|
||||||
|
non_negative_diff bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBasicStats() *BasicStats {
|
func NewBasicStats() *BasicStats {
|
||||||
|
@ -43,7 +45,9 @@ type basicstats struct {
|
||||||
max float64
|
max float64
|
||||||
sum float64
|
sum float64
|
||||||
mean float64
|
mean float64
|
||||||
M2 float64 //intermedia value for variance/stdev
|
diff float64
|
||||||
|
M2 float64 //intermediate value for variance/stdev
|
||||||
|
LAST float64 //intermediate value for diff
|
||||||
}
|
}
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
|
@ -82,7 +86,9 @@ func (m *BasicStats) Add(in telegraf.Metric) {
|
||||||
max: fv,
|
max: fv,
|
||||||
mean: fv,
|
mean: fv,
|
||||||
sum: fv,
|
sum: fv,
|
||||||
|
diff: 0.0,
|
||||||
M2: 0.0,
|
M2: 0.0,
|
||||||
|
LAST: fv,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +104,9 @@ func (m *BasicStats) Add(in telegraf.Metric) {
|
||||||
max: fv,
|
max: fv,
|
||||||
mean: fv,
|
mean: fv,
|
||||||
sum: fv,
|
sum: fv,
|
||||||
|
diff: 0.0,
|
||||||
M2: 0.0,
|
M2: 0.0,
|
||||||
|
LAST: fv,
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -127,6 +135,8 @@ func (m *BasicStats) Add(in telegraf.Metric) {
|
||||||
}
|
}
|
||||||
//sum compute
|
//sum compute
|
||||||
tmp.sum += fv
|
tmp.sum += fv
|
||||||
|
//diff compute
|
||||||
|
tmp.diff = fv - tmp.LAST
|
||||||
//store final data
|
//store final data
|
||||||
m.cache[id].fields[field.Key] = tmp
|
m.cache[id].fields[field.Key] = tmp
|
||||||
}
|
}
|
||||||
|
@ -167,6 +177,13 @@ func (m *BasicStats) Push(acc telegraf.Accumulator) {
|
||||||
if config.stdev {
|
if config.stdev {
|
||||||
fields[k+"_stdev"] = math.Sqrt(variance)
|
fields[k+"_stdev"] = math.Sqrt(variance)
|
||||||
}
|
}
|
||||||
|
if config.diff {
|
||||||
|
fields[k+"_diff"] = v.diff
|
||||||
|
}
|
||||||
|
if config.non_negative_diff && v.diff >= 0 {
|
||||||
|
fields[k+"_non_negative_diff"] = v.diff
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//if count == 1 StdDev = infinite => so I won't send data
|
//if count == 1 StdDev = infinite => so I won't send data
|
||||||
}
|
}
|
||||||
|
@ -199,6 +216,10 @@ func parseStats(names []string) *configuredStats {
|
||||||
parsed.stdev = true
|
parsed.stdev = true
|
||||||
case "sum":
|
case "sum":
|
||||||
parsed.sum = true
|
parsed.sum = true
|
||||||
|
case "diff":
|
||||||
|
parsed.diff = true
|
||||||
|
case "non_negative_diff":
|
||||||
|
parsed.non_negative_diff = true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Printf("W! Unrecognized basic stat '%s', ignoring", name)
|
log.Printf("W! Unrecognized basic stat '%s', ignoring", name)
|
||||||
|
@ -219,6 +240,7 @@ func defaultStats() *configuredStats {
|
||||||
defaults.variance = true
|
defaults.variance = true
|
||||||
defaults.stdev = true
|
defaults.stdev = true
|
||||||
defaults.sum = false
|
defaults.sum = false
|
||||||
|
defaults.non_negative_diff = false
|
||||||
|
|
||||||
return defaults
|
return defaults
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ var m1, _ = metric.New("m1",
|
||||||
"b": int64(1),
|
"b": int64(1),
|
||||||
"c": float64(2),
|
"c": float64(2),
|
||||||
"d": float64(2),
|
"d": float64(2),
|
||||||
|
"g": int64(3),
|
||||||
},
|
},
|
||||||
time.Now(),
|
time.Now(),
|
||||||
)
|
)
|
||||||
|
@ -31,6 +32,7 @@ var m2, _ = metric.New("m1",
|
||||||
"f": uint64(200),
|
"f": uint64(200),
|
||||||
"ignoreme": "string",
|
"ignoreme": "string",
|
||||||
"andme": true,
|
"andme": true,
|
||||||
|
"g": int64(1),
|
||||||
},
|
},
|
||||||
time.Now(),
|
time.Now(),
|
||||||
)
|
)
|
||||||
|
@ -86,6 +88,12 @@ func TestBasicStatsWithPeriod(t *testing.T) {
|
||||||
"f_max": float64(200),
|
"f_max": float64(200),
|
||||||
"f_min": float64(200),
|
"f_min": float64(200),
|
||||||
"f_mean": float64(200),
|
"f_mean": float64(200),
|
||||||
|
"g_count": float64(2), //g
|
||||||
|
"g_max": float64(3),
|
||||||
|
"g_min": float64(1),
|
||||||
|
"g_mean": float64(2),
|
||||||
|
"g_s2": float64(2),
|
||||||
|
"g_stdev": math.Sqrt(2),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -118,6 +126,10 @@ func TestBasicStatsDifferentPeriods(t *testing.T) {
|
||||||
"d_max": float64(2),
|
"d_max": float64(2),
|
||||||
"d_min": float64(2),
|
"d_min": float64(2),
|
||||||
"d_mean": float64(2),
|
"d_mean": float64(2),
|
||||||
|
"g_count": float64(1), //g
|
||||||
|
"g_max": float64(3),
|
||||||
|
"g_min": float64(3),
|
||||||
|
"g_mean": float64(3),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -153,6 +165,10 @@ func TestBasicStatsDifferentPeriods(t *testing.T) {
|
||||||
"f_max": float64(200),
|
"f_max": float64(200),
|
||||||
"f_min": float64(200),
|
"f_min": float64(200),
|
||||||
"f_mean": float64(200),
|
"f_mean": float64(200),
|
||||||
|
"g_count": float64(1), //g
|
||||||
|
"g_max": float64(1),
|
||||||
|
"g_min": float64(1),
|
||||||
|
"g_mean": float64(1),
|
||||||
}
|
}
|
||||||
expectedTags = map[string]string{
|
expectedTags = map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -179,6 +195,7 @@ func TestBasicStatsWithOnlyCount(t *testing.T) {
|
||||||
"d_count": float64(2),
|
"d_count": float64(2),
|
||||||
"e_count": float64(1),
|
"e_count": float64(1),
|
||||||
"f_count": float64(1),
|
"f_count": float64(1),
|
||||||
|
"g_count": float64(2),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -205,6 +222,7 @@ func TestBasicStatsWithOnlyMin(t *testing.T) {
|
||||||
"d_min": float64(2),
|
"d_min": float64(2),
|
||||||
"e_min": float64(200),
|
"e_min": float64(200),
|
||||||
"f_min": float64(200),
|
"f_min": float64(200),
|
||||||
|
"g_min": float64(1),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -231,6 +249,7 @@ func TestBasicStatsWithOnlyMax(t *testing.T) {
|
||||||
"d_max": float64(6),
|
"d_max": float64(6),
|
||||||
"e_max": float64(200),
|
"e_max": float64(200),
|
||||||
"f_max": float64(200),
|
"f_max": float64(200),
|
||||||
|
"g_max": float64(3),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -257,6 +276,7 @@ func TestBasicStatsWithOnlyMean(t *testing.T) {
|
||||||
"d_mean": float64(4),
|
"d_mean": float64(4),
|
||||||
"e_mean": float64(200),
|
"e_mean": float64(200),
|
||||||
"f_mean": float64(200),
|
"f_mean": float64(200),
|
||||||
|
"g_mean": float64(2),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -283,6 +303,7 @@ func TestBasicStatsWithOnlySum(t *testing.T) {
|
||||||
"d_sum": float64(8),
|
"d_sum": float64(8),
|
||||||
"e_sum": float64(200),
|
"e_sum": float64(200),
|
||||||
"f_sum": float64(200),
|
"f_sum": float64(200),
|
||||||
|
"g_sum": float64(4),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -359,6 +380,7 @@ func TestBasicStatsWithOnlyVariance(t *testing.T) {
|
||||||
"b_s2": float64(2),
|
"b_s2": float64(2),
|
||||||
"c_s2": float64(2),
|
"c_s2": float64(2),
|
||||||
"d_s2": float64(8),
|
"d_s2": float64(8),
|
||||||
|
"g_s2": float64(2),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -383,6 +405,7 @@ func TestBasicStatsWithOnlyStandardDeviation(t *testing.T) {
|
||||||
"b_stdev": math.Sqrt(2),
|
"b_stdev": math.Sqrt(2),
|
||||||
"c_stdev": math.Sqrt(2),
|
"c_stdev": math.Sqrt(2),
|
||||||
"d_stdev": math.Sqrt(8),
|
"d_stdev": math.Sqrt(8),
|
||||||
|
"g_stdev": math.Sqrt(2),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -415,6 +438,57 @@ func TestBasicStatsWithMinAndMax(t *testing.T) {
|
||||||
"e_min": float64(200),
|
"e_min": float64(200),
|
||||||
"f_max": float64(200), //f
|
"f_max": float64(200), //f
|
||||||
"f_min": float64(200),
|
"f_min": float64(200),
|
||||||
|
"g_max": float64(3), //g
|
||||||
|
"g_min": float64(1),
|
||||||
|
}
|
||||||
|
expectedTags := map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
}
|
||||||
|
acc.AssertContainsTaggedFields(t, "m1", expectedFields, expectedTags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test only aggregating diff
|
||||||
|
func TestBasicStatsWithDiff(t *testing.T) {
|
||||||
|
|
||||||
|
aggregator := NewBasicStats()
|
||||||
|
aggregator.Stats = []string{"diff"}
|
||||||
|
|
||||||
|
aggregator.Add(m1)
|
||||||
|
aggregator.Add(m2)
|
||||||
|
|
||||||
|
acc := testutil.Accumulator{}
|
||||||
|
aggregator.Push(&acc)
|
||||||
|
|
||||||
|
expectedFields := map[string]interface{}{
|
||||||
|
"a_diff": float64(0),
|
||||||
|
"b_diff": float64(2),
|
||||||
|
"c_diff": float64(2),
|
||||||
|
"d_diff": float64(4),
|
||||||
|
"g_diff": float64(-2),
|
||||||
|
}
|
||||||
|
expectedTags := map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
}
|
||||||
|
acc.AssertContainsTaggedFields(t, "m1", expectedFields, expectedTags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test only aggregating non_negative_diff
|
||||||
|
func TestBasicStatsWithNonNegativeDiff(t *testing.T) {
|
||||||
|
|
||||||
|
aggregator := NewBasicStats()
|
||||||
|
aggregator.Stats = []string{"non_negative_diff"}
|
||||||
|
|
||||||
|
aggregator.Add(m1)
|
||||||
|
aggregator.Add(m2)
|
||||||
|
|
||||||
|
acc := testutil.Accumulator{}
|
||||||
|
aggregator.Push(&acc)
|
||||||
|
|
||||||
|
expectedFields := map[string]interface{}{
|
||||||
|
"a_non_negative_diff": float64(0),
|
||||||
|
"b_non_negative_diff": float64(2),
|
||||||
|
"c_non_negative_diff": float64(2),
|
||||||
|
"d_non_negative_diff": float64(4),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
@ -471,6 +545,13 @@ func TestBasicStatsWithAllStats(t *testing.T) {
|
||||||
"f_min": float64(200),
|
"f_min": float64(200),
|
||||||
"f_mean": float64(200),
|
"f_mean": float64(200),
|
||||||
"f_sum": float64(200),
|
"f_sum": float64(200),
|
||||||
|
"g_count": float64(2), //g
|
||||||
|
"g_max": float64(3),
|
||||||
|
"g_min": float64(1),
|
||||||
|
"g_mean": float64(2),
|
||||||
|
"g_s2": float64(2),
|
||||||
|
"g_stdev": math.Sqrt(2),
|
||||||
|
"g_sum": float64(4),
|
||||||
}
|
}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
|
Loading…
Reference in New Issue