feat(agent): Add option to avoid filtering of explicit plugin tags (#13364)
This commit is contained in:
parent
5a8ccbde6f
commit
0a491a7bf3
|
|
@ -252,6 +252,10 @@ type AgentConfig struct {
|
||||||
// stateful plugins on termination of Telegraf. If the file exists on start,
|
// stateful plugins on termination of Telegraf. If the file exists on start,
|
||||||
// the state in the file will be restored for the plugins.
|
// the state in the file will be restored for the plugins.
|
||||||
Statefile string `toml:"statefile"`
|
Statefile string `toml:"statefile"`
|
||||||
|
|
||||||
|
// Flag to always keep tags explicitly defined in the plugin itself and
|
||||||
|
// ensure those tags always pass filtering.
|
||||||
|
AlwaysIncludeLocalTags bool `toml:"always_include_local_tags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// InputNames returns a list of strings of the configured inputs.
|
// InputNames returns a list of strings of the configured inputs.
|
||||||
|
|
@ -1428,7 +1432,10 @@ func (c *Config) buildFilter(tbl *ast.Table) (models.Filter, error) {
|
||||||
// builds the filter and returns a
|
// builds the filter and returns a
|
||||||
// models.InputConfig to be inserted into models.RunningInput
|
// models.InputConfig to be inserted into models.RunningInput
|
||||||
func (c *Config) buildInput(name string, tbl *ast.Table) (*models.InputConfig, error) {
|
func (c *Config) buildInput(name string, tbl *ast.Table) (*models.InputConfig, error) {
|
||||||
cp := &models.InputConfig{Name: name}
|
cp := &models.InputConfig{
|
||||||
|
Name: name,
|
||||||
|
AlwaysIncludeLocalTags: c.Agent.AlwaysIncludeLocalTags,
|
||||||
|
}
|
||||||
c.getFieldDuration(tbl, "interval", &cp.Interval)
|
c.getFieldDuration(tbl, "interval", &cp.Interval)
|
||||||
c.getFieldDuration(tbl, "precision", &cp.Precision)
|
c.getFieldDuration(tbl, "precision", &cp.Precision)
|
||||||
c.getFieldDuration(tbl, "collection_jitter", &cp.CollectionJitter)
|
c.getFieldDuration(tbl, "collection_jitter", &cp.CollectionJitter)
|
||||||
|
|
@ -1523,7 +1530,7 @@ func (c *Config) buildOutput(name string, tbl *ast.Table) (*models.OutputConfig,
|
||||||
func (c *Config) missingTomlField(_ reflect.Type, key string) error {
|
func (c *Config) missingTomlField(_ reflect.Type, key string) error {
|
||||||
switch key {
|
switch key {
|
||||||
// General options to ignore
|
// General options to ignore
|
||||||
case "alias",
|
case "alias", "always_include_local_tags",
|
||||||
"collection_jitter", "collection_offset",
|
"collection_jitter", "collection_offset",
|
||||||
"data_format", "delay", "drop", "drop_original",
|
"data_format", "delay", "drop", "drop_original",
|
||||||
"fielddrop", "fieldpass", "flush_interval", "flush_jitter",
|
"fielddrop", "fieldpass", "flush_interval", "flush_jitter",
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,11 @@ The agent table configures Telegraf and the defaults used across all plugins.
|
||||||
stateful plugins on termination of Telegraf. If the file exists on start,
|
stateful plugins on termination of Telegraf. If the file exists on start,
|
||||||
the state in the file will be restored for the plugins.
|
the state in the file will be restored for the plugins.
|
||||||
|
|
||||||
|
- **always_include_local_tags**:
|
||||||
|
Ensure tags explicitly defined in a plugin will *always* pass tag-filtering
|
||||||
|
via `taginclude` or `tagexclude`. This removes the need to specify local tags
|
||||||
|
twice.
|
||||||
|
|
||||||
## Plugins
|
## Plugins
|
||||||
|
|
||||||
Telegraf plugins are divided into 4 types: [inputs][], [outputs][],
|
Telegraf plugins are divided into 4 types: [inputs][], [outputs][],
|
||||||
|
|
@ -402,7 +407,7 @@ Use the name_override parameter to emit measurements with the name `foobar`:
|
||||||
Emit measurements with two additional tags: `tag1=foo` and `tag2=bar`
|
Emit measurements with two additional tags: `tag1=foo` and `tag2=bar`
|
||||||
|
|
||||||
> **NOTE**: With TOML, order matters. Parameters belong to the last defined
|
> **NOTE**: With TOML, order matters. Parameters belong to the last defined
|
||||||
> table header, place `[inputs.cpu.tags]` table at the _end_ of the plugin
|
> table header, place `[inputs.cpu.tags]` table at the *end* of the plugin
|
||||||
> definition.
|
> definition.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
|
@ -638,7 +643,7 @@ for time-based filtering. An introduction to the CEL language can be found
|
||||||
are provided in the [language definition][CEL lang] as well as in the
|
are provided in the [language definition][CEL lang] as well as in the
|
||||||
[extension documentation][CEL ext].
|
[extension documentation][CEL ext].
|
||||||
|
|
||||||
> NOTE: As CEL is an _interpreted_ languguage, this type of filtering is much
|
> NOTE: As CEL is an *interpreted* languguage, this type of filtering is much
|
||||||
> slower compared to `namepass`/`namedrop` and friends. So consider to use the
|
> slower compared to `namepass`/`namedrop` and friends. So consider to use the
|
||||||
> more restricted filter options where possible in case of high-throughput
|
> more restricted filter options where possible in case of high-throughput
|
||||||
> scenarios.
|
> scenarios.
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,12 @@ type InputConfig struct {
|
||||||
CollectionOffset time.Duration
|
CollectionOffset time.Duration
|
||||||
Precision time.Duration
|
Precision time.Duration
|
||||||
|
|
||||||
NameOverride string
|
NameOverride string
|
||||||
MeasurementPrefix string
|
MeasurementPrefix string
|
||||||
MeasurementSuffix string
|
MeasurementSuffix string
|
||||||
Tags map[string]string
|
Tags map[string]string
|
||||||
Filter Filter
|
Filter Filter
|
||||||
|
AlwaysIncludeLocalTags bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RunningInput) metricFiltered(metric telegraf.Metric) {
|
func (r *RunningInput) metricFiltered(metric telegraf.Metric) {
|
||||||
|
|
@ -105,12 +106,17 @@ func (r *RunningInput) MakeMetric(metric telegraf.Metric) telegraf.Metric {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tags := r.Config.Tags
|
||||||
|
if r.Config.AlwaysIncludeLocalTags {
|
||||||
|
tags = nil
|
||||||
|
}
|
||||||
|
|
||||||
m := makemetric(
|
m := makemetric(
|
||||||
metric,
|
metric,
|
||||||
r.Config.NameOverride,
|
r.Config.NameOverride,
|
||||||
r.Config.MeasurementPrefix,
|
r.Config.MeasurementPrefix,
|
||||||
r.Config.MeasurementSuffix,
|
r.Config.MeasurementSuffix,
|
||||||
r.Config.Tags,
|
tags,
|
||||||
r.defaultTags)
|
r.defaultTags)
|
||||||
|
|
||||||
r.Config.Filter.Modify(metric)
|
r.Config.Filter.Modify(metric)
|
||||||
|
|
@ -119,6 +125,15 @@ func (r *RunningInput) MakeMetric(metric telegraf.Metric) telegraf.Metric {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.Config.AlwaysIncludeLocalTags {
|
||||||
|
// Apply plugin tags after filtering
|
||||||
|
for k, v := range r.Config.Tags {
|
||||||
|
if _, ok := metric.GetTag(k); !ok {
|
||||||
|
metric.AddTag(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r.MetricsGathered.Incr(1)
|
r.MetricsGathered.Incr(1)
|
||||||
GlobalMetricsGathered.Incr(1)
|
GlobalMetricsGathered.Incr(1)
|
||||||
return m
|
return m
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,81 @@ func TestMetricErrorCounters(t *testing.T) {
|
||||||
require.GreaterOrEqual(t, int64(1), GlobalGatherErrors.Get())
|
require.GreaterOrEqual(t, int64(1), GlobalGatherErrors.Get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMakeMetricWithAlwaysKeepingPluginTagsDisabled(t *testing.T) {
|
||||||
|
now := time.Now()
|
||||||
|
ri := NewRunningInput(&testInput{}, &InputConfig{
|
||||||
|
Name: "TestRunningInput",
|
||||||
|
Tags: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
Filter: Filter{
|
||||||
|
TagInclude: []string{"b"},
|
||||||
|
},
|
||||||
|
AlwaysIncludeLocalTags: false,
|
||||||
|
})
|
||||||
|
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)
|
||||||
|
m = ri.MakeMetric(m)
|
||||||
|
|
||||||
|
expected := metric.New("RITest",
|
||||||
|
map[string]string{
|
||||||
|
"b": "test",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"value": 101,
|
||||||
|
},
|
||||||
|
now,
|
||||||
|
)
|
||||||
|
require.Equal(t, expected, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakeMetricWithAlwaysKeepingPluginTagsEnabled(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,
|
||||||
|
})
|
||||||
|
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)
|
||||||
|
m = ri.MakeMetric(m)
|
||||||
|
|
||||||
|
expected := metric.New("RITest",
|
||||||
|
map[string]string{
|
||||||
|
"b": "test",
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"value": 101,
|
||||||
|
},
|
||||||
|
now,
|
||||||
|
)
|
||||||
|
require.Equal(t, expected, m)
|
||||||
|
}
|
||||||
|
|
||||||
type testInput struct{}
|
type testInput struct{}
|
||||||
|
|
||||||
func (t *testInput) Description() string { return "" }
|
func (t *testInput) Description() string { return "" }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue