feat: add more functionality to template processor (#10316)

This commit is contained in:
Thomas Casteleyn 2021-12-23 17:51:26 +01:00 committed by GitHub
parent 55312accee
commit 0b99c6c20a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 106 additions and 4 deletions

View File

@ -23,9 +23,9 @@ Read the full [Go Template Documentation][].
template = '{{ .Tag "hostname" }}.{{ .Tag "level" }}' template = '{{ .Tag "hostname" }}.{{ .Tag "level" }}'
``` ```
## Example ## Examples
Combine multiple tags to create a single tag: ### Combine multiple tags to create a single tag
```toml ```toml
[[processors.template]] [[processors.template]]
@ -38,7 +38,7 @@ Combine multiple tags to create a single tag:
+ cpu,level=debug,hostname=localhost,topic=localhost.debug time_idle=42 + cpu,level=debug,hostname=localhost,topic=localhost.debug time_idle=42
``` ```
Add measurement name as a tag: ### Add measurement name as a tag
```toml ```toml
[[processors.template]] [[processors.template]]
@ -51,7 +51,7 @@ Add measurement name as a tag:
+ cpu,hostname=localhost,measurement=cpu time_idle=42 + cpu,hostname=localhost,measurement=cpu time_idle=42
``` ```
Add the year as a tag, similar to the date processor: ### Add the year as a tag, similar to the date processor
```toml ```toml
[[processors.template]] [[processors.template]]
@ -59,4 +59,48 @@ Add the year as a tag, similar to the date processor:
template = '{{.Time.UTC.Year}}' template = '{{.Time.UTC.Year}}'
``` ```
### Add all fields as a tag
Sometimes it is usefull to pass all fields with their values into a single message for sending it to a monitoring system (e.g. Syslog, GroundWork), then you can use `.FieldList` or `.TagList`:
```toml
[[processors.template]]
tag = "message"
template = 'Message about {{.Name}} fields: {{.FieldList}}'
```
```diff
- cpu,hostname=localhost time_idle=42
+ cpu,hostname=localhost,message=Message\ about\ cpu\ fields:\ map[time_idle:42] time_idle=42
```
More advanced example, which might make more sense:
```toml
[[processors.template]]
tag = "message"
template = '''Message about {{.Name}} fields:
{{ range $field, $value := .FieldList -}}
{{$field}}:{{$value}}
{{ end }}'''
```
```diff
- cpu,hostname=localhost time_idle=42
+ cpu,hostname=localhost,message=Message\ about\ cpu\ fields:\ntime_idle:42\n time_idle=42
```
### Just add the current metric as a tag
```toml
[[processors.template]]
tag = "metric"
template = '{{.}}'
```
```diff
- cpu,hostname=localhost time_idle=42
+ cpu,hostname=localhost,metric=cpu\ map[hostname:localhost]\ map[time_idle:42]\ 1257894000000000000 time_idle=42
```
[Go Template Documentation]: https://golang.org/pkg/text/template/ [Go Template Documentation]: https://golang.org/pkg/text/template/

View File

@ -1,6 +1,7 @@
package template package template
import ( import (
"fmt"
"time" "time"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
@ -27,3 +28,15 @@ func (m *TemplateMetric) Field(key string) interface{} {
func (m *TemplateMetric) Time() time.Time { func (m *TemplateMetric) Time() time.Time {
return m.metric.Time() return m.metric.Time()
} }
func (m *TemplateMetric) String() string {
return fmt.Sprint(m.metric)
}
func (m *TemplateMetric) TagList() map[string]string {
return m.metric.Tags()
}
func (m *TemplateMetric) FieldList() map[string]interface{} {
return m.metric.Fields()
}

View File

@ -115,3 +115,48 @@ func TestTagAndFieldConcatenate(t *testing.T) {
expected := []telegraf.Metric{testutil.MustMetric("weather", map[string]string{"location": "us-midwest", "LocalTemp": "us-midwest is too warm"}, map[string]interface{}{"temperature": "too warm"}, now)} expected := []telegraf.Metric{testutil.MustMetric("weather", map[string]string{"location": "us-midwest", "LocalTemp": "us-midwest is too warm"}, map[string]interface{}{"temperature": "too warm"}, now)}
testutil.RequireMetricsEqual(t, expected, actual) testutil.RequireMetricsEqual(t, expected, actual)
} }
func TestFieldList(t *testing.T) {
// Prepare
plugin := TemplateProcessor{Tag: "fields", Template: "{{.FieldList}}"}
require.NoError(t, plugin.Init())
// Run
m := testutil.TestMetric(1.23)
actual := plugin.Apply(m)
// Verify
expected := m.Copy()
expected.AddTag("fields", "map[value:1.23]")
testutil.RequireMetricsEqual(t, []telegraf.Metric{expected}, actual)
}
func TestTagList(t *testing.T) {
// Prepare
plugin := TemplateProcessor{Tag: "tags", Template: "{{.TagList}}"}
require.NoError(t, plugin.Init())
// Run
m := testutil.TestMetric(1.23)
actual := plugin.Apply(m)
// Verify
expected := m.Copy()
expected.AddTag("tags", "map[tag1:value1]")
testutil.RequireMetricsEqual(t, []telegraf.Metric{expected}, actual)
}
func TestDot(t *testing.T) {
// Prepare
plugin := TemplateProcessor{Tag: "metric", Template: "{{.}}"}
require.NoError(t, plugin.Init())
// Run
m := testutil.TestMetric(1.23)
actual := plugin.Apply(m)
// Verify
expected := m.Copy()
expected.AddTag("metric", "test1 map[tag1:value1] map[value:1.23] 1257894000000000000")
testutil.RequireMetricsEqual(t, []telegraf.Metric{expected}, actual)
}