feat(processors.template): Allow `tag` to be a template (#13253)
This commit is contained in:
parent
d7dfe4ed48
commit
7da5d68315
|
|
@ -24,12 +24,14 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
|||
```toml @sample.conf
|
||||
# Uses a Go template to create a new tag
|
||||
[[processors.template]]
|
||||
## Tag to set with the output of the template.
|
||||
## Go template used to create the tag name of the output. In order to
|
||||
## ease TOML escaping requirements, you should use single quotes around
|
||||
## the template string.
|
||||
tag = "topic"
|
||||
|
||||
## Go template used to create the tag value. In order to ease TOML
|
||||
## escaping requirements, you may wish to use single quotes around the
|
||||
## template string.
|
||||
## Go template used to create the tag value of the output. In order to
|
||||
## ease TOML escaping requirements, you should use single quotes around
|
||||
## the template string.
|
||||
template = '{{ .Tag "hostname" }}.{{ .Tag "level" }}'
|
||||
```
|
||||
|
||||
|
|
@ -48,6 +50,19 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
|||
+ cpu,level=debug,hostname=localhost,topic=localhost.debug time_idle=42
|
||||
```
|
||||
|
||||
### Use a field value as tag name
|
||||
|
||||
```toml
|
||||
[[processors.template]]
|
||||
tag = '{{ .Field "type" }}'
|
||||
template = '{{ .Name }}'
|
||||
```
|
||||
|
||||
```diff
|
||||
- cpu,level=debug,hostname=localhost time_idle=42,type=sensor
|
||||
+ cpu,level=debug,hostname=localhost,sensor=cpu time_idle=42,type=sensor
|
||||
```
|
||||
|
||||
### Add measurement name as a tag
|
||||
|
||||
```toml
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
# Uses a Go template to create a new tag
|
||||
[[processors.template]]
|
||||
## Tag to set with the output of the template.
|
||||
## Go template used to create the tag name of the output. In order to
|
||||
## ease TOML escaping requirements, you should use single quotes around
|
||||
## the template string.
|
||||
tag = "topic"
|
||||
|
||||
## Go template used to create the tag value. In order to ease TOML
|
||||
## escaping requirements, you may wish to use single quotes around the
|
||||
## template string.
|
||||
## Go template used to create the tag value of the output. In order to
|
||||
## ease TOML escaping requirements, you should use single quotes around
|
||||
## the template string.
|
||||
template = '{{ .Tag "hostname" }}.{{ .Tag "level" }}'
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package template
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
|
|
@ -17,7 +18,9 @@ type TemplateProcessor struct {
|
|||
Tag string `toml:"tag"`
|
||||
Template string `toml:"template"`
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
tmpl *template.Template
|
||||
|
||||
tmplTag *template.Template
|
||||
tmplValue *template.Template
|
||||
}
|
||||
|
||||
func (*TemplateProcessor) SampleConfig() string {
|
||||
|
|
@ -27,27 +30,40 @@ func (*TemplateProcessor) SampleConfig() string {
|
|||
func (r *TemplateProcessor) Apply(in ...telegraf.Metric) []telegraf.Metric {
|
||||
// for each metric in "in" array
|
||||
for _, metric := range in {
|
||||
var b strings.Builder
|
||||
newM := TemplateMetric{metric}
|
||||
|
||||
// supply TemplateMetric and Template from configuration to Template.Execute
|
||||
err := r.tmpl.Execute(&b, &newM)
|
||||
if err != nil {
|
||||
r.Log.Errorf("failed to execute template: %v", err)
|
||||
var b strings.Builder
|
||||
if err := r.tmplTag.Execute(&b, &newM); err != nil {
|
||||
r.Log.Errorf("failed to execute tag name template: %v", err)
|
||||
continue
|
||||
}
|
||||
tag := b.String()
|
||||
|
||||
metric.AddTag(r.Tag, b.String())
|
||||
b.Reset()
|
||||
if err := r.tmplValue.Execute(&b, &newM); err != nil {
|
||||
r.Log.Errorf("failed to execute value template: %v", err)
|
||||
continue
|
||||
}
|
||||
value := b.String()
|
||||
|
||||
metric.AddTag(tag, value)
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
func (r *TemplateProcessor) Init() error {
|
||||
// create template
|
||||
t, err := template.New("configured_template").Parse(r.Template)
|
||||
var err error
|
||||
|
||||
r.tmpl = t
|
||||
return err
|
||||
r.tmplTag, err = template.New("tag template").Parse(r.Tag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating tag name template failed: %w", err)
|
||||
}
|
||||
|
||||
r.tmplValue, err = template.New("value template").Parse(r.Template)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating value template failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,43 @@ func TestName(t *testing.T) {
|
|||
testutil.RequireMetricsEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestNameTemplate(t *testing.T) {
|
||||
plugin := TemplateProcessor{
|
||||
Tag: `{{ .Tag "foo" }}`,
|
||||
Template: `{{ .Name }}`,
|
||||
}
|
||||
|
||||
err := plugin.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
input := []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{"foo": "measurement"},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
}
|
||||
|
||||
actual := plugin.Apply(input...)
|
||||
expected := []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"foo": "measurement",
|
||||
"measurement": "cpu",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
}
|
||||
testutil.RequireMetricsEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestTagTemplateConcatenate(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue