feat(processors.defaults): Add support for specifying default tags (#16717)
Co-authored-by: Pieter Slabbert <pieter.slabbert@ilovezoona.com>
This commit is contained in:
parent
aa68d6175a
commit
9ed15a6194
|
|
@ -1,14 +1,14 @@
|
|||
# Defaults Processor Plugin
|
||||
|
||||
The _Defaults_ processor allows you to ensure certain fields will always exist
|
||||
with a specified default value on your metric(s).
|
||||
The _Defaults_ processor allows you to ensure certain fields and tags will
|
||||
always exist with a specified default value on your metric(s).
|
||||
|
||||
There are three cases where this processor will insert a configured default
|
||||
field.
|
||||
field or tag.
|
||||
|
||||
1. The field is nil on the incoming metric
|
||||
1. The field is not nil, but its value is an empty string.
|
||||
1. The field is not nil, but its value is a string of one or more empty spaces.
|
||||
1. The field/tag is nil on the incoming metric
|
||||
1. The field/tag is not nil, but its value is an empty string.
|
||||
1. The field/tag is not nil, but its value is a string of one or more empty spaces.
|
||||
|
||||
Telegraf minimum version: Telegraf 1.15.0
|
||||
|
||||
|
|
@ -24,11 +24,11 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
|||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
## Set default fields on your metric(s) when they are nil or empty
|
||||
## Set default fields and tags on your metric(s) when they are nil or empty
|
||||
[[processors.defaults]]
|
||||
## Ensures a set of fields always exists on your metric(s) with their
|
||||
## Ensures a set of fields or tags always exists on your metric(s) with their
|
||||
## respective default value.
|
||||
## For any given field pair (key = default), if it's not set, a field
|
||||
## For any given field/tag pair (key = default), if it's not set, a field/tag
|
||||
## is set on the metric with the specified default.
|
||||
##
|
||||
## A field is considered not set if it is nil on the incoming metric;
|
||||
|
|
@ -39,6 +39,12 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
|||
field_1 = "bar"
|
||||
time_idle = 0
|
||||
is_error = true
|
||||
## A tag is considered not set if it is nil on the incoming metric;
|
||||
## or it is not nil but it is empty string or a string of one or
|
||||
## more spaces.
|
||||
## <target-tag> = <value>
|
||||
[processors.defaults.tags]
|
||||
tag_1 = "foo"
|
||||
```
|
||||
|
||||
## Example
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ var sampleConfig string
|
|||
// on your Metrics with at least a default value.
|
||||
type Defaults struct {
|
||||
DefaultFieldsSets map[string]interface{} `toml:"fields"`
|
||||
DefaultTagsSets map[string]string `toml:"tags"`
|
||||
}
|
||||
|
||||
func (*Defaults) SampleConfig() string {
|
||||
|
|
@ -37,6 +38,14 @@ func (def *Defaults) Apply(inputMetrics ...telegraf.Metric) []telegraf.Metric {
|
|||
metric.AddField(defField, defValue)
|
||||
}
|
||||
}
|
||||
for defTag, defValue := range def.DefaultTagsSets {
|
||||
if maybeCurrent, isSet := metric.GetTag(defTag); !isSet {
|
||||
metric.AddTag(defTag, defValue)
|
||||
} else if trimmed := strings.TrimSpace(maybeCurrent); trimmed == "" {
|
||||
metric.RemoveTag(defTag)
|
||||
metric.AddTag(defTag, defValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
return inputMetrics
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,124 @@ func TestDefaults(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTagDefaults(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
defaults *Defaults
|
||||
input telegraf.Metric
|
||||
expected []telegraf.Metric
|
||||
}{
|
||||
{
|
||||
name: "Test that no values are changed since they are not nil or empty",
|
||||
defaults: &Defaults{
|
||||
DefaultTagsSets: map[string]string{
|
||||
"wind_feel": "very chill",
|
||||
},
|
||||
},
|
||||
input: testutil.MustMetric(
|
||||
"CPU metrics",
|
||||
map[string]string{
|
||||
"wind_feel": "a dragon's breath",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"usage": 45,
|
||||
"is_dead": false,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
expected: []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"CPU metrics",
|
||||
map[string]string{
|
||||
"wind_feel": "a dragon's breath",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"usage": 45,
|
||||
"is_dead": false,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Tests that the missing tags are set on the metric",
|
||||
defaults: &Defaults{
|
||||
DefaultTagsSets: map[string]string{
|
||||
"wind_feel": "Unknown",
|
||||
},
|
||||
},
|
||||
input: testutil.MustMetric(
|
||||
"CPU metrics",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"usage": 45,
|
||||
"temperature": 64,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
expected: []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"CPU metrics",
|
||||
map[string]string{
|
||||
"wind_feel": "Unknown",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"usage": 45,
|
||||
"temperature": 64,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Tests that set but empty tags are replaced by specified defaults",
|
||||
defaults: &Defaults{
|
||||
DefaultTagsSets: map[string]string{
|
||||
"wind_feel": "Unknown",
|
||||
"fan_loudness": "Inaudible",
|
||||
"boost_enabled": "false",
|
||||
},
|
||||
},
|
||||
input: testutil.MustMetric(
|
||||
"CPU metrics",
|
||||
map[string]string{
|
||||
"wind_feel": " ",
|
||||
"fan_loudness": " ",
|
||||
"boost_enabled": "",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"max_clock_gz": 0,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
expected: []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"CPU metrics",
|
||||
map[string]string{
|
||||
"wind_feel": "Unknown",
|
||||
"fan_loudness": "Inaudible",
|
||||
"boost_enabled": "false",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"max_clock_gz": 0,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
t.Run(scenario.name, func(t *testing.T) {
|
||||
defaults := scenario.defaults
|
||||
|
||||
resultMetrics := defaults.Apply(scenario.input)
|
||||
require.Len(t, resultMetrics, 1)
|
||||
testutil.RequireMetricsEqual(t, scenario.expected, resultMetrics)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTracking(t *testing.T) {
|
||||
inputRaw := []telegraf.Metric{
|
||||
metric.New("foo", map[string]string{}, map[string]interface{}{"value": 42, "topic": "telegraf"}, time.Unix(0, 0)),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
## Set default fields on your metric(s) when they are nil or empty
|
||||
## Set default fields and tags on your metric(s) when they are nil or empty
|
||||
[[processors.defaults]]
|
||||
## Ensures a set of fields always exists on your metric(s) with their
|
||||
## Ensures a set of fields or tags always exists on your metric(s) with their
|
||||
## respective default value.
|
||||
## For any given field pair (key = default), if it's not set, a field
|
||||
## For any given field/tag pair (key = default), if it's not set, a field/tag
|
||||
## is set on the metric with the specified default.
|
||||
##
|
||||
## A field is considered not set if it is nil on the incoming metric;
|
||||
|
|
@ -13,3 +13,9 @@
|
|||
field_1 = "bar"
|
||||
time_idle = 0
|
||||
is_error = true
|
||||
## A tag is considered not set if it is nil on the incoming metric;
|
||||
## or it is not nil but it is empty string or a string of one or
|
||||
## more spaces.
|
||||
## <target-tag> = <value>
|
||||
[processors.defaults.tags]
|
||||
tag_1 = "foo"
|
||||
|
|
|
|||
Loading…
Reference in New Issue