Remove metric recreation when filtering (#4767)
This commit is contained in:
@@ -1,117 +1,203 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"github.com/influxdata/telegraf/metric"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type TestProcessor struct {
|
||||
// MockProcessor is a Processor with an overrideable Apply implementation.
|
||||
type MockProcessor struct {
|
||||
ApplyF func(in ...telegraf.Metric) []telegraf.Metric
|
||||
}
|
||||
|
||||
func (f *TestProcessor) SampleConfig() string { return "" }
|
||||
func (f *TestProcessor) Description() string { return "" }
|
||||
|
||||
// Apply renames:
|
||||
// "foo" to "fuz"
|
||||
// "bar" to "baz"
|
||||
// And it also drops measurements named "dropme"
|
||||
func (f *TestProcessor) Apply(in ...telegraf.Metric) []telegraf.Metric {
|
||||
out := make([]telegraf.Metric, 0)
|
||||
for _, m := range in {
|
||||
switch m.Name() {
|
||||
case "foo":
|
||||
out = append(out, testutil.TestMetric(1, "fuz"))
|
||||
case "bar":
|
||||
out = append(out, testutil.TestMetric(1, "baz"))
|
||||
case "dropme":
|
||||
// drop the metric!
|
||||
default:
|
||||
out = append(out, m)
|
||||
}
|
||||
}
|
||||
return out
|
||||
func (p *MockProcessor) SampleConfig() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func NewTestRunningProcessor() *RunningProcessor {
|
||||
out := &RunningProcessor{
|
||||
Name: "test",
|
||||
Processor: &TestProcessor{},
|
||||
Config: &ProcessorConfig{Filter: Filter{}},
|
||||
}
|
||||
return out
|
||||
func (p *MockProcessor) Description() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func TestRunningProcessor(t *testing.T) {
|
||||
inmetrics := []telegraf.Metric{
|
||||
testutil.TestMetric(1, "foo"),
|
||||
testutil.TestMetric(1, "bar"),
|
||||
testutil.TestMetric(1, "baz"),
|
||||
}
|
||||
|
||||
expectedNames := []string{
|
||||
"fuz",
|
||||
"baz",
|
||||
"baz",
|
||||
}
|
||||
rfp := NewTestRunningProcessor()
|
||||
filteredMetrics := rfp.Apply(inmetrics...)
|
||||
|
||||
actualNames := []string{
|
||||
filteredMetrics[0].Name(),
|
||||
filteredMetrics[1].Name(),
|
||||
filteredMetrics[2].Name(),
|
||||
}
|
||||
assert.Equal(t, expectedNames, actualNames)
|
||||
func (p *MockProcessor) Apply(in ...telegraf.Metric) []telegraf.Metric {
|
||||
return p.ApplyF(in...)
|
||||
}
|
||||
|
||||
func TestRunningProcessor_WithNameDrop(t *testing.T) {
|
||||
inmetrics := []telegraf.Metric{
|
||||
testutil.TestMetric(1, "foo"),
|
||||
testutil.TestMetric(1, "bar"),
|
||||
testutil.TestMetric(1, "baz"),
|
||||
// TagProcessor returns a Processor whose Apply function adds the tag and
|
||||
// value.
|
||||
func TagProcessor(key, value string) *MockProcessor {
|
||||
return &MockProcessor{
|
||||
ApplyF: func(in ...telegraf.Metric) []telegraf.Metric {
|
||||
for _, m := range in {
|
||||
m.AddTag(key, value)
|
||||
}
|
||||
return in
|
||||
},
|
||||
}
|
||||
|
||||
expectedNames := []string{
|
||||
"foo",
|
||||
"baz",
|
||||
"baz",
|
||||
}
|
||||
rfp := NewTestRunningProcessor()
|
||||
|
||||
rfp.Config.Filter.NameDrop = []string{"foo"}
|
||||
assert.NoError(t, rfp.Config.Filter.Compile())
|
||||
|
||||
filteredMetrics := rfp.Apply(inmetrics...)
|
||||
|
||||
actualNames := []string{
|
||||
filteredMetrics[0].Name(),
|
||||
filteredMetrics[1].Name(),
|
||||
filteredMetrics[2].Name(),
|
||||
}
|
||||
assert.Equal(t, expectedNames, actualNames)
|
||||
}
|
||||
|
||||
func TestRunningProcessor_DroppedMetric(t *testing.T) {
|
||||
inmetrics := []telegraf.Metric{
|
||||
testutil.TestMetric(1, "dropme"),
|
||||
testutil.TestMetric(1, "foo"),
|
||||
testutil.TestMetric(1, "bar"),
|
||||
func Metric(
|
||||
name string,
|
||||
tags map[string]string,
|
||||
fields map[string]interface{},
|
||||
tm time.Time,
|
||||
tp ...telegraf.ValueType,
|
||||
) telegraf.Metric {
|
||||
m, err := metric.New(name, tags, fields, tm, tp...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
expectedNames := []string{
|
||||
"fuz",
|
||||
"baz",
|
||||
}
|
||||
rfp := NewTestRunningProcessor()
|
||||
filteredMetrics := rfp.Apply(inmetrics...)
|
||||
|
||||
actualNames := []string{
|
||||
filteredMetrics[0].Name(),
|
||||
filteredMetrics[1].Name(),
|
||||
}
|
||||
assert.Equal(t, expectedNames, actualNames)
|
||||
return m
|
||||
}
|
||||
|
||||
func TestRunningProcessor_Apply(t *testing.T) {
|
||||
type args struct {
|
||||
Processor telegraf.Processor
|
||||
Config *ProcessorConfig
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
input []telegraf.Metric
|
||||
expected []telegraf.Metric
|
||||
}{
|
||||
{
|
||||
name: "inactive filter applies metrics",
|
||||
args: args{
|
||||
Processor: TagProcessor("apply", "true"),
|
||||
Config: &ProcessorConfig{
|
||||
Filter: Filter{},
|
||||
},
|
||||
},
|
||||
input: []telegraf.Metric{
|
||||
Metric(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": 42.0,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
expected: []telegraf.Metric{
|
||||
Metric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"apply": "true",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"value": 42.0,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "filter applies",
|
||||
args: args{
|
||||
Processor: TagProcessor("apply", "true"),
|
||||
Config: &ProcessorConfig{
|
||||
Filter: Filter{
|
||||
NamePass: []string{"cpu"},
|
||||
},
|
||||
},
|
||||
},
|
||||
input: []telegraf.Metric{
|
||||
Metric(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": 42.0,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
expected: []telegraf.Metric{
|
||||
Metric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"apply": "true",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"value": 42.0,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "filter doesn't apply",
|
||||
args: args{
|
||||
Processor: TagProcessor("apply", "true"),
|
||||
Config: &ProcessorConfig{
|
||||
Filter: Filter{
|
||||
NameDrop: []string{"cpu"},
|
||||
},
|
||||
},
|
||||
},
|
||||
input: []telegraf.Metric{
|
||||
Metric(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": 42.0,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
expected: []telegraf.Metric{
|
||||
Metric(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": 42.0,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rp := &RunningProcessor{
|
||||
Processor: tt.args.Processor,
|
||||
Config: tt.args.Config,
|
||||
}
|
||||
rp.Config.Filter.Compile()
|
||||
|
||||
actual := rp.Apply(tt.input...)
|
||||
require.Equal(t, tt.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunningProcessor_Order(t *testing.T) {
|
||||
rp1 := &RunningProcessor{
|
||||
Config: &ProcessorConfig{
|
||||
Order: 1,
|
||||
},
|
||||
}
|
||||
rp2 := &RunningProcessor{
|
||||
Config: &ProcessorConfig{
|
||||
Order: 2,
|
||||
},
|
||||
}
|
||||
rp3 := &RunningProcessor{
|
||||
Config: &ProcessorConfig{
|
||||
Order: 3,
|
||||
},
|
||||
}
|
||||
|
||||
procs := RunningProcessors{rp2, rp3, rp1}
|
||||
sort.Sort(procs)
|
||||
require.Equal(t,
|
||||
RunningProcessors{rp1, rp2, rp3},
|
||||
procs)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user