mirror of
https://github.com/wahyd4/telegraf.git
synced 2026-08-21 18:46:07 +10:00
81 lines
2.2 KiB
Go
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{}
|
|
})
|
|
}
|