-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(serializers.template): Add new template based serializer (#13656)
- Loading branch information
1 parent
3f8e916
commit 283af2b
Showing
7 changed files
with
349 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//go:build !custom || serializers || serializers.template | ||
|
||
package all | ||
|
||
import ( | ||
_ "github.com/influxdata/telegraf/plugins/serializers/template" // register plugin | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Template Serializer | ||
|
||
The `template` output data format outputs metrics using an user defined go template. | ||
[Sprig](http://masterminds.github.io/sprig/) helper functions are also available. | ||
|
||
## Configuration | ||
|
||
```toml | ||
[[outputs.file]] | ||
## Files to write to, "stdout" is a specially handled file. | ||
files = ["stdout", "/tmp/metrics.out"] | ||
|
||
## Data format to output. | ||
## Each data format has its own unique set of configuration options, read | ||
## more about them here: | ||
## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_OUTPUT.md | ||
data_format = "template" | ||
|
||
## Go template which defines output format | ||
template = '{{ .Tag "host" }} {{ .Field "available" }}' | ||
|
||
## When used with output plugins that allow for batch serialisation | ||
## the template for the entire batch can be defined | ||
# use_batch_format = true # The 'file' plugin allows batch mode with this option | ||
# batch_template = ''' | ||
{{range $metric := . -}} | ||
{{$metric.Tag "host"}}: {{range $metric.Fields | keys | initial -}} | ||
{{.}}={{get $metric.Fields .}}, {{end}} | ||
{{- $metric.Fields|keys|last}}={{$metric.Fields|values|last}} | ||
{{end -}} | ||
''' | ||
``` | ||
|
||
### Batch mode | ||
|
||
When an output plugin emits multiple metrics in a batch fashion, by default the | ||
template will just be repeated for each metric. If you would like to specifically | ||
define how a batch should be formatted, you can use a `batch_template` instead. | ||
In this mode, the context of the template (the 'dot') will be a slice of metrics. | ||
|
||
```toml | ||
batch_template = '''My batch metric names: {{range $index, $metric := . -}} | ||
{{if $index}}, {{ end }}{{ $metric.Name }} | ||
{{- end }}''' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package template | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"text/template" | ||
|
||
"github.com/Masterminds/sprig/v3" | ||
|
||
"github.com/influxdata/telegraf" | ||
"github.com/influxdata/telegraf/plugins/serializers" | ||
) | ||
|
||
type Serializer struct { | ||
Template string `toml:"template"` | ||
BatchTemplate string `toml:"batch_template"` | ||
Log telegraf.Logger `toml:"-"` | ||
|
||
tmplMetric *template.Template | ||
tmplBatch *template.Template | ||
} | ||
|
||
func (s *Serializer) Init() error { | ||
// Setting defaults | ||
var err error | ||
|
||
s.tmplMetric, err = template.New("template").Funcs(sprig.TxtFuncMap()).Parse(s.Template) | ||
if err != nil { | ||
return fmt.Errorf("creating template failed: %w", err) | ||
} | ||
if s.BatchTemplate == "" { | ||
s.BatchTemplate = fmt.Sprintf("{{range .}}%s{{end}}", s.Template) | ||
} | ||
s.tmplBatch, err = template.New("batch template").Funcs(sprig.TxtFuncMap()).Parse(s.BatchTemplate) | ||
if err != nil { | ||
return fmt.Errorf("creating batch template failed: %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
func (s *Serializer) Serialize(metric telegraf.Metric) ([]byte, error) { | ||
m, ok := metric.(telegraf.TemplateMetric) | ||
if !ok { | ||
s.Log.Errorf("metric of type %T is not a template metric", metric) | ||
return nil, nil | ||
} | ||
var b bytes.Buffer | ||
// The template was defined for one metric, just execute it | ||
if s.Template != "" { | ||
if err := s.tmplMetric.Execute(&b, &m); err != nil { | ||
s.Log.Errorf("failed to execute template: %v", err) | ||
return nil, nil | ||
} | ||
return b.Bytes(), nil | ||
} | ||
|
||
// The template was defined for a batch of metrics, so wrap the metric into a slice | ||
if s.BatchTemplate != "" { | ||
metrics := []telegraf.TemplateMetric{m} | ||
if err := s.tmplBatch.Execute(&b, &metrics); err != nil { | ||
s.Log.Errorf("failed to execute batch template: %v", err) | ||
return nil, nil | ||
} | ||
return b.Bytes(), nil | ||
} | ||
|
||
// No template was defined | ||
return nil, nil | ||
} | ||
|
||
func (s *Serializer) SerializeBatch(metrics []telegraf.Metric) ([]byte, error) { | ||
newMetrics := make([]telegraf.TemplateMetric, 0, len(metrics)) | ||
|
||
for _, metric := range metrics { | ||
m, ok := metric.(telegraf.TemplateMetric) | ||
if !ok { | ||
s.Log.Errorf("metric of type %T is not a template metric", metric) | ||
return nil, nil | ||
} | ||
newMetrics = append(newMetrics, m) | ||
} | ||
|
||
var b bytes.Buffer | ||
if err := s.tmplBatch.Execute(&b, &newMetrics); err != nil { | ||
s.Log.Errorf("failed to execute batch template: %v", err) | ||
return nil, nil | ||
} | ||
|
||
return b.Bytes(), nil | ||
} | ||
|
||
func init() { | ||
serializers.Add("template", | ||
func() serializers.Serializer { | ||
return &Serializer{} | ||
}, | ||
) | ||
} |
Oops, something went wrong.