mirror of
https://github.com/wahyd4/telegraf.git
synced 2026-08-21 18:46:07 +10:00
107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
package stats
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
"strconv"
|
|
|
|
"github.com/influxdata/telegraf"
|
|
"github.com/influxdata/telegraf/plugins/processors"
|
|
)
|
|
|
|
type Stats struct {
|
|
StatsField string `toml:"stats_field"`
|
|
WindowSize int `toml:"window_size"`
|
|
Window Window
|
|
Buffer Window
|
|
}
|
|
|
|
type Window struct {
|
|
Count int
|
|
ValueSum float64
|
|
DiffSum float64
|
|
Mean float64
|
|
Variance float64
|
|
Std float64
|
|
}
|
|
|
|
func (s *Stats) SampleConfig() string {
|
|
return `
|
|
[[processors.stats]]
|
|
|
|
## field to compile stats for
|
|
stats_field = "trace_id"
|
|
|
|
## number of metrics considered for stats at a time
|
|
window_size = 8`
|
|
}
|
|
|
|
func (s *Stats) Description() string {
|
|
return "will append a field to each metric indicating the running average of the specified field"
|
|
}
|
|
|
|
func (s *Stats) Apply(in ...telegraf.Metric) []telegraf.Metric {
|
|
for _, metric := range in {
|
|
value := metric.Fields()[s.StatsField]
|
|
sVal := fmt.Sprintf("%v", value)
|
|
fVal, err := strconv.ParseFloat(sVal, 64)
|
|
if err != nil {
|
|
log.Printf("E! cannot convert field: %v to float, %v", s.StatsField, err)
|
|
}
|
|
|
|
// for warmup
|
|
if s.Window.Count < s.WindowSize/2 {
|
|
s.Window.Count++
|
|
s.Window.ValueSum += fVal
|
|
s.Window.Mean = s.Window.ValueSum / float64(s.Window.Count)
|
|
s.Window.Variance = varianceCalculator(fVal, &s.Window)
|
|
s.Window.Std = math.Sqrt(s.Window.Variance)
|
|
continue
|
|
}
|
|
|
|
if s.Window.Count >= s.WindowSize {
|
|
s.Window = s.Buffer
|
|
s.Buffer = Window{}
|
|
}
|
|
|
|
// when window count is more than half, fill the buffer and window
|
|
s.Window.Count++
|
|
s.Buffer.Count++
|
|
|
|
s.Window.ValueSum += fVal
|
|
s.Buffer.ValueSum += fVal
|
|
|
|
s.Window.Mean = s.Window.ValueSum / float64(s.Window.Count)
|
|
s.Buffer.Mean = s.Buffer.ValueSum / float64(s.Buffer.Count)
|
|
|
|
s.Window.Variance = varianceCalculator(fVal, &s.Window)
|
|
s.Buffer.Variance = varianceCalculator(fVal, &s.Buffer)
|
|
|
|
s.Window.Std = math.Sqrt(s.Window.Variance)
|
|
s.Buffer.Std = math.Sqrt(s.Buffer.Variance)
|
|
|
|
metric.AddField(s.StatsField+"_mean", s.Window.Mean)
|
|
metric.AddField(s.StatsField+"_deviation", s.Window.Std)
|
|
metric.AddField(s.StatsField+"_variance", s.Window.Variance)
|
|
}
|
|
return in
|
|
}
|
|
|
|
func varianceCalculator(currentVal float64, w *Window) float64 {
|
|
diff := currentVal - w.Mean
|
|
sqrDiff := math.Pow(diff, 2)
|
|
w.DiffSum = w.DiffSum + sqrDiff
|
|
if w.Count-1 == 0 {
|
|
return 0
|
|
}
|
|
variance := w.DiffSum / float64(w.Count-1)
|
|
return variance
|
|
}
|
|
|
|
func init() {
|
|
processors.Add("stats", func() telegraf.Processor {
|
|
return &Stats{}
|
|
})
|
|
}
|