From 172be0c944a31c0dfd4ba75138183c253485bc4a Mon Sep 17 00:00:00 2001 From: Karsten Schnitter Date: Thu, 26 Oct 2017 13:41:44 +0200 Subject: [PATCH] Add Drop Strings Processor This processor will drop all metrics with string values. This is helpful in cases where the complete set of metrics is unknown or unsure but non numerical values should be avoided. Signed-off-by: Karsten Schnitter --- plugins/processors/all/all.go | 1 + plugins/processors/drop_strings/README.md | 14 +++++ .../processors/drop_strings/drop_strings.go | 60 +++++++++++++++++++ .../drop_strings/drop_strings_test.go | 60 +++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 plugins/processors/drop_strings/README.md create mode 100644 plugins/processors/drop_strings/drop_strings.go create mode 100644 plugins/processors/drop_strings/drop_strings_test.go diff --git a/plugins/processors/all/all.go b/plugins/processors/all/all.go index 462298f6bbbd1..4a3caa5672714 100644 --- a/plugins/processors/all/all.go +++ b/plugins/processors/all/all.go @@ -1,5 +1,6 @@ package all import ( + _ "github.com/influxdata/telegraf/plugins/processors/drop_strings" _ "github.com/influxdata/telegraf/plugins/processors/printer" ) diff --git a/plugins/processors/drop_strings/README.md b/plugins/processors/drop_strings/README.md new file mode 100644 index 0000000000000..b088f15cba6f6 --- /dev/null +++ b/plugins/processors/drop_strings/README.md @@ -0,0 +1,14 @@ +# Drop Strings Processor Plugin + +The drop strings processor plugin drops all fields of type string. + +### Configuration: + +```toml +# Drop all fields of type string, that pass through this processor. +[[processors.drop_strings]] +``` + +### Tags: + +No tags are applied by this processor. diff --git a/plugins/processors/drop_strings/drop_strings.go b/plugins/processors/drop_strings/drop_strings.go new file mode 100644 index 0000000000000..5c9403a344a09 --- /dev/null +++ b/plugins/processors/drop_strings/drop_strings.go @@ -0,0 +1,60 @@ +package drop_strings + +import ( + "fmt" + + "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/metric" + "github.com/influxdata/telegraf/plugins/processors" +) + +type DropStrings struct { +} + +var sampleConfig = ` +` + +func (d *DropStrings) SampleConfig() string { + return sampleConfig +} + +func (d *DropStrings) Description() string { + return "Drops all metrics of type string that pass through this filter." +} + +func (d *DropStrings) Apply(in ...telegraf.Metric) []telegraf.Metric { + out := make([]telegraf.Metric, 0, len(in)) + for _, source := range in { + target, error := dropStrings(source) + if error == nil { + out = append(out, target) + } + } + return out +} + +func dropStrings(source telegraf.Metric) (telegraf.Metric, error) { + inFields := source.Fields() + outFields := make(map[string]interface{}, len(inFields)) + changed := false + for key, value := range inFields { + if _, drop := value.(string); !drop { + outFields[key] = value + } else { + changed = true + } + } + if !changed { + return source, nil + } + if changed && len(outFields) > 0 { + return metric.New(source.Name(), source.Tags(), outFields, source.Time(), source.Type()) + } + return nil, fmt.Errorf("No more fields in metric '%s'", source.Name()) +} + +func init() { + processors.Add("drop_strings", func() telegraf.Processor { + return &DropStrings{} + }) +} diff --git a/plugins/processors/drop_strings/drop_strings_test.go b/plugins/processors/drop_strings/drop_strings_test.go new file mode 100644 index 0000000000000..20c891da3ce36 --- /dev/null +++ b/plugins/processors/drop_strings/drop_strings_test.go @@ -0,0 +1,60 @@ +package drop_strings + +import ( + "testing" + "time" + + "github.com/influxdata/telegraf/metric" + "github.com/stretchr/testify/assert" +) + +func TestDropStrings(t *testing.T) { + var metric, _ = metric.New("Test Metric", + map[string]string{"state": "full"}, + map[string]interface{}{ + "integer": int64(23), + "float": float64(3.1415), + "bool": true, + "string": "should be dropped", + }, + time.Now(), + ) + + dropStrings := DropStrings{} + + result := dropStrings.Apply(metric)[0] + fields := result.Fields() + + assert.NotContains(t, fields, "string") + + assertFieldValue(t, int64(23), "integer", fields) + assertFieldValue(t, float64(3.1415), "float", fields) + assertFieldValue(t, true, "bool", fields) + + assert.Equal(t, "Test Metric", result.Name()) + assert.Equal(t, metric.Tags(), result.Tags()) + assert.Equal(t, metric.Time(), result.Time()) +} + +func assertFieldValue(t *testing.T, expected interface{}, field string, fields map[string]interface{}) { + value, present := fields[field] + assert.True(t, present, "value of field '"+field+"' was not present") + assert.EqualValues(t, expected, value) +} + +func TestDropEntireMetricIfOnlyStrings(t *testing.T) { + var metric, _ = metric.New("Test Metric", + map[string]string{"state": "full"}, + map[string]interface{}{ + "string1": "should be dropped", + "string2": "should be dropped, also", + }, + time.Now(), + ) + + dropStrings := DropStrings{} + + result := dropStrings.Apply(metric) + + assert.Len(t, result, 0, "No metric should be emitted.") +}