Files
2018-08-24 10:13:59 -07:00

81 lines
2.2 KiB
Go

package threshold
import (
"fmt"
"log"
"math"
"strconv"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/processors"
)
type Threshold struct {
FieldName string `toml:"field_name"`
OutlierDistance float64 `toml:"outlier_distance"`
}
func (d *Threshold) SampleConfig() string {
return `
## must run metrics through average processor before this processor
[[processors.threshold]]
## field to compile a standard deviation of
## the processor will assume the average of the field
## can be found in the field deviation_field"_mean"
field_name = "trace_id"
## Determine the number of standard deviations
## away you want your outlier to be
outlier_distance = "2"`
}
func (d *Threshold) Description() string {
return "will append a field to each metric indicating whether it is a outlier or not"
}
func (d *Threshold) Apply(in ...telegraf.Metric) []telegraf.Metric {
for _, metric := range in {
if metric.Fields()[d.FieldName] != nil {
fVal, err := strconv.ParseFloat(fmt.Sprintf("%v", metric.Fields()[d.FieldName]), 64)
if err != nil {
log.Printf("E! %v must be a float or integer value, %v", d.FieldName, err)
continue
}
if metric.Fields()[d.FieldName+"_mean"] == nil {
log.Printf("E! missing field: %v from [processor.stats]", d.FieldName+"_mean")
continue
}
if metric.Fields()[d.FieldName+"_deviation"] == nil {
log.Printf("E! missing field: %v from [processor.stats]", d.FieldName+"_deviation")
continue
}
mean, err := strconv.ParseFloat(fmt.Sprintf("%v", metric.Fields()[d.FieldName+"_mean"]), 64)
if err != nil {
log.Printf("E! %v must be a float or integer value, %v", d.FieldName+"_mean", err)
continue
}
deviation, err := strconv.ParseFloat(fmt.Sprintf("%v", metric.Fields()[d.FieldName+"_deviation"]), 64)
if err != nil {
log.Printf("E! %v must be a float or integer value, %v", d.FieldName+"_deviation", err)
continue
}
if math.Abs(mean-fVal) >= d.OutlierDistance*deviation {
numOutliers := math.Abs(mean-fVal) / d.OutlierDistance
// adds a field to mark outliers
metric.AddField("stddev_away", numOutliers)
}
}
}
return in
}
func init() {
processors.Add("threshold", func() telegraf.Processor {
return &Threshold{}
})
}