feat(agent): Add option to avoid filtering of global tags (#13605)

This commit is contained in:
Sven Rebhan 2023-07-14 16:00:10 +02:00 committed by GitHub
parent 9ede0b0c49
commit 3da80fdfc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 135 additions and 46 deletions

View File

@ -263,6 +263,10 @@ type AgentConfig struct {
// Flag to always keep tags explicitly defined in the plugin itself and // Flag to always keep tags explicitly defined in the plugin itself and
// ensure those tags always pass filtering. // ensure those tags always pass filtering.
AlwaysIncludeLocalTags bool `toml:"always_include_local_tags"` AlwaysIncludeLocalTags bool `toml:"always_include_local_tags"`
// Flag to always keep tags explicitly defined in the global tags section
// and ensure those tags always pass filtering.
AlwaysIncludeGlobalTags bool `toml:"always_include_global_tags"`
} }
// InputNames returns a list of strings of the configured inputs. // InputNames returns a list of strings of the configured inputs.
@ -1461,6 +1465,7 @@ func (c *Config) buildInput(name string, tbl *ast.Table) (*models.InputConfig, e
cp := &models.InputConfig{ cp := &models.InputConfig{
Name: name, Name: name,
AlwaysIncludeLocalTags: c.Agent.AlwaysIncludeLocalTags, AlwaysIncludeLocalTags: c.Agent.AlwaysIncludeLocalTags,
AlwaysIncludeGlobalTags: c.Agent.AlwaysIncludeGlobalTags,
} }
c.getFieldDuration(tbl, "interval", &cp.Interval) c.getFieldDuration(tbl, "interval", &cp.Interval)
c.getFieldDuration(tbl, "precision", &cp.Precision) c.getFieldDuration(tbl, "precision", &cp.Precision)

View File

@ -326,6 +326,11 @@ The agent table configures Telegraf and the defaults used across all plugins.
via `taginclude` or `tagexclude`. This removes the need to specify local tags via `taginclude` or `tagexclude`. This removes the need to specify local tags
twice. twice.
- **always_include_global_tags**:
Ensure tags explicitly defined in the `global_tags` section will *always* pass
tag-filtering via `taginclude` or `tagexclude`. This removes the need to
specify those tags twice.
## Plugins ## Plugins
Telegraf plugins are divided into 4 types: [inputs][], [outputs][], Telegraf plugins are divided into 4 types: [inputs][], [outputs][],

View File

@ -77,6 +77,7 @@ type InputConfig struct {
Tags map[string]string Tags map[string]string
Filter Filter Filter Filter
AlwaysIncludeLocalTags bool AlwaysIncludeLocalTags bool
AlwaysIncludeGlobalTags bool
} }
func (r *RunningInput) metricFiltered(metric telegraf.Metric) { func (r *RunningInput) metricFiltered(metric telegraf.Metric) {
@ -113,17 +114,12 @@ func (r *RunningInput) MakeMetric(metric telegraf.Metric) telegraf.Metric {
return nil return nil
} }
tags := r.Config.Tags makemetric(
if r.Config.AlwaysIncludeLocalTags {
tags = nil
}
m := makemetric(
metric, metric,
r.Config.NameOverride, r.Config.NameOverride,
r.Config.MeasurementPrefix, r.Config.MeasurementPrefix,
r.Config.MeasurementSuffix, r.Config.MeasurementSuffix,
tags, r.Config.Tags,
r.defaultTags) r.defaultTags)
r.Config.Filter.Modify(metric) r.Config.Filter.Modify(metric)
@ -132,18 +128,20 @@ func (r *RunningInput) MakeMetric(metric telegraf.Metric) telegraf.Metric {
return nil return nil
} }
if r.Config.AlwaysIncludeLocalTags || r.Config.AlwaysIncludeGlobalTags {
var local, global map[string]string
if r.Config.AlwaysIncludeLocalTags { if r.Config.AlwaysIncludeLocalTags {
// Apply plugin tags after filtering local = r.Config.Tags
for k, v := range r.Config.Tags {
if _, ok := metric.GetTag(k); !ok {
metric.AddTag(k, v)
} }
if r.Config.AlwaysIncludeGlobalTags {
global = r.defaultTags
} }
makemetric(metric, "", "", "", local, global)
} }
r.MetricsGathered.Incr(1) r.MetricsGathered.Incr(1)
GlobalMetricsGathered.Incr(1) GlobalMetricsGathered.Incr(1)
return m return metric
} }
func (r *RunningInput) Gather(acc telegraf.Accumulator) error { func (r *RunningInput) Gather(acc telegraf.Accumulator) error {

View File

@ -55,8 +55,8 @@ func TestMakeMetricNoFields(t *testing.T) {
map[string]interface{}{}, map[string]interface{}{},
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
assert.Nil(t, m) require.Nil(t, actual)
} }
// nil fields should get dropped // nil fields should get dropped
@ -74,7 +74,7 @@ func TestMakeMetricNilFields(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
expected := metric.New("RITest", expected := metric.New("RITest",
map[string]string{}, map[string]string{},
@ -84,7 +84,7 @@ func TestMakeMetricNilFields(t *testing.T) {
now, now,
) )
require.Equal(t, expected, m) require.Equal(t, expected, actual)
} }
func TestMakeMetricWithPluginTags(t *testing.T) { func TestMakeMetricWithPluginTags(t *testing.T) {
@ -103,7 +103,7 @@ func TestMakeMetricWithPluginTags(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
expected := metric.New("RITest", expected := metric.New("RITest",
map[string]string{ map[string]string{
@ -114,7 +114,7 @@ func TestMakeMetricWithPluginTags(t *testing.T) {
}, },
now, now,
) )
require.Equal(t, expected, m) require.Equal(t, expected, actual)
} }
func TestMakeMetricFilteredOut(t *testing.T) { func TestMakeMetricFilteredOut(t *testing.T) {
@ -136,8 +136,8 @@ func TestMakeMetricFilteredOut(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
assert.Nil(t, m) require.Nil(t, actual)
} }
func TestMakeMetricWithDaemonTags(t *testing.T) { func TestMakeMetricWithDaemonTags(t *testing.T) {
@ -156,7 +156,7 @@ func TestMakeMetricWithDaemonTags(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
expected := metric.New("RITest", expected := metric.New("RITest",
map[string]string{ map[string]string{
"foo": "bar", "foo": "bar",
@ -166,7 +166,7 @@ func TestMakeMetricWithDaemonTags(t *testing.T) {
}, },
now, now,
) )
require.Equal(t, expected, m) require.Equal(t, expected, actual)
} }
func TestMakeMetricNameOverride(t *testing.T) { func TestMakeMetricNameOverride(t *testing.T) {
@ -183,7 +183,7 @@ func TestMakeMetricNameOverride(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
expected := metric.New("foobar", expected := metric.New("foobar",
nil, nil,
map[string]interface{}{ map[string]interface{}{
@ -191,7 +191,7 @@ func TestMakeMetricNameOverride(t *testing.T) {
}, },
now, now,
) )
require.Equal(t, expected, m) require.Equal(t, expected, actual)
} }
func TestMakeMetricNamePrefix(t *testing.T) { func TestMakeMetricNamePrefix(t *testing.T) {
@ -208,7 +208,7 @@ func TestMakeMetricNamePrefix(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
expected := metric.New("foobar_RITest", expected := metric.New("foobar_RITest",
nil, nil,
map[string]interface{}{ map[string]interface{}{
@ -216,7 +216,7 @@ func TestMakeMetricNamePrefix(t *testing.T) {
}, },
now, now,
) )
require.Equal(t, expected, m) require.Equal(t, expected, actual)
} }
func TestMakeMetricNameSuffix(t *testing.T) { func TestMakeMetricNameSuffix(t *testing.T) {
@ -233,7 +233,7 @@ func TestMakeMetricNameSuffix(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
expected := metric.New("RITest_foobar", expected := metric.New("RITest_foobar",
nil, nil,
map[string]interface{}{ map[string]interface{}{
@ -241,7 +241,7 @@ func TestMakeMetricNameSuffix(t *testing.T) {
}, },
now, now,
) )
require.Equal(t, expected, m) require.Equal(t, expected, actual)
} }
func TestMetricErrorCounters(t *testing.T) { func TestMetricErrorCounters(t *testing.T) {
@ -283,8 +283,8 @@ func TestMakeMetricWithAlwaysKeepingPluginTagsDisabled(t *testing.T) {
Filter: Filter{ Filter: Filter{
TagInclude: []string{"b"}, TagInclude: []string{"b"},
}, },
AlwaysIncludeLocalTags: false,
}) })
ri.SetDefaultTags(map[string]string{"logic": "rulez"})
require.NoError(t, ri.Config.Filter.Compile()) require.NoError(t, ri.Config.Filter.Compile())
m := testutil.MustMetric("RITest", m := testutil.MustMetric("RITest",
@ -296,7 +296,7 @@ func TestMakeMetricWithAlwaysKeepingPluginTagsDisabled(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
expected := metric.New("RITest", expected := metric.New("RITest",
map[string]string{ map[string]string{
@ -307,7 +307,85 @@ func TestMakeMetricWithAlwaysKeepingPluginTagsDisabled(t *testing.T) {
}, },
now, now,
) )
require.Equal(t, expected, m) require.Equal(t, expected, actual)
}
func TestMakeMetricWithAlwaysKeepingLocalPluginTagsEnabled(t *testing.T) {
now := time.Now()
ri := NewRunningInput(&testInput{}, &InputConfig{
Name: "TestRunningInput",
Tags: map[string]string{
"foo": "bar",
},
Filter: Filter{
TagInclude: []string{"b"},
},
AlwaysIncludeLocalTags: true,
})
ri.SetDefaultTags(map[string]string{"logic": "rulez"})
require.NoError(t, ri.Config.Filter.Compile())
m := testutil.MustMetric("RITest",
map[string]string{
"b": "test",
},
map[string]interface{}{
"value": int64(101),
},
now,
telegraf.Untyped)
actual := ri.MakeMetric(m)
expected := metric.New("RITest",
map[string]string{
"b": "test",
"foo": "bar",
},
map[string]interface{}{
"value": 101,
},
now,
)
require.Equal(t, expected, actual)
}
func TestMakeMetricWithAlwaysKeepingGlobalPluginTagsEnabled(t *testing.T) {
now := time.Now()
ri := NewRunningInput(&testInput{}, &InputConfig{
Name: "TestRunningInput",
Tags: map[string]string{
"foo": "bar",
},
Filter: Filter{
TagInclude: []string{"b"},
},
AlwaysIncludeGlobalTags: true,
})
ri.SetDefaultTags(map[string]string{"logic": "rulez"})
require.NoError(t, ri.Config.Filter.Compile())
m := testutil.MustMetric("RITest",
map[string]string{
"b": "test",
},
map[string]interface{}{
"value": int64(101),
},
now,
telegraf.Untyped)
actual := ri.MakeMetric(m)
expected := metric.New("RITest",
map[string]string{
"b": "test",
"logic": "rulez",
},
map[string]interface{}{
"value": 101,
},
now,
)
require.Equal(t, expected, actual)
} }
func TestMakeMetricWithAlwaysKeepingPluginTagsEnabled(t *testing.T) { func TestMakeMetricWithAlwaysKeepingPluginTagsEnabled(t *testing.T) {
@ -321,7 +399,9 @@ func TestMakeMetricWithAlwaysKeepingPluginTagsEnabled(t *testing.T) {
TagInclude: []string{"b"}, TagInclude: []string{"b"},
}, },
AlwaysIncludeLocalTags: true, AlwaysIncludeLocalTags: true,
AlwaysIncludeGlobalTags: true,
}) })
ri.SetDefaultTags(map[string]string{"logic": "rulez"})
require.NoError(t, ri.Config.Filter.Compile()) require.NoError(t, ri.Config.Filter.Compile())
m := testutil.MustMetric("RITest", m := testutil.MustMetric("RITest",
@ -333,19 +413,20 @@ func TestMakeMetricWithAlwaysKeepingPluginTagsEnabled(t *testing.T) {
}, },
now, now,
telegraf.Untyped) telegraf.Untyped)
m = ri.MakeMetric(m) actual := ri.MakeMetric(m)
expected := metric.New("RITest", expected := metric.New("RITest",
map[string]string{ map[string]string{
"b": "test", "b": "test",
"foo": "bar", "foo": "bar",
"logic": "rulez",
}, },
map[string]interface{}{ map[string]interface{}{
"value": 101, "value": 101,
}, },
now, now,
) )
require.Equal(t, expected, m) require.Equal(t, expected, actual)
} }
type testInput struct{} type testInput struct{}