Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
134
plugins/processors/template/README.md
Normal file
134
plugins/processors/template/README.md
Normal file
|
@ -0,0 +1,134 @@
|
|||
# Template Processor Plugin
|
||||
|
||||
The `template` processor applies a Go template to metrics to generate a new
|
||||
tag. The primary use case of this plugin is to create a tag that can be used
|
||||
for dynamic routing to multiple output plugins or using an output specific
|
||||
routing option.
|
||||
|
||||
The template has access to each metric's measurement name, tags, fields, and
|
||||
timestamp using the [interface in `/template_metric.go`](template_metric.go).
|
||||
[Sprig](http://masterminds.github.io/sprig/) helper functions are available.
|
||||
|
||||
Read the full [Go Template Documentation][].
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Uses a Go template to create a new tag
|
||||
[[processors.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 of the output. In order to
|
||||
## ease TOML escaping requirements, you should use single quotes around
|
||||
## the template string.
|
||||
template = '{{ .Tag "hostname" }}.{{ .Tag "level" }}'
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Combine multiple tags to create a single tag
|
||||
|
||||
```toml
|
||||
[[processors.template]]
|
||||
tag = "topic"
|
||||
template = '{{ .Tag "hostname" }}.{{ .Tag "level" }}'
|
||||
```
|
||||
|
||||
```diff
|
||||
- cpu,level=debug,hostname=localhost time_idle=42
|
||||
+ 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
|
||||
[[processors.template]]
|
||||
tag = "measurement"
|
||||
template = '{{ .Name }}'
|
||||
```
|
||||
|
||||
```diff
|
||||
- cpu,hostname=localhost time_idle=42
|
||||
+ cpu,hostname=localhost,measurement=cpu time_idle=42
|
||||
```
|
||||
|
||||
### Add the year as a tag, similar to the date processor
|
||||
|
||||
```toml
|
||||
[[processors.template]]
|
||||
tag = "year"
|
||||
template = '{{.Time.UTC.Year}}'
|
||||
```
|
||||
|
||||
### Add all fields as a tag
|
||||
|
||||
Sometimes it is useful 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 `.Fields` or `.Tags`:
|
||||
|
||||
```toml
|
||||
[[processors.template]]
|
||||
tag = "message"
|
||||
template = 'Message about {{.Name}} fields: {{.Fields}}'
|
||||
```
|
||||
|
||||
```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 := .Fields -}}
|
||||
{{$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/
|
11
plugins/processors/template/sample.conf
Normal file
11
plugins/processors/template/sample.conf
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Uses a Go template to create a new tag
|
||||
[[processors.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 of the output. In order to
|
||||
## ease TOML escaping requirements, you should use single quotes around
|
||||
## the template string.
|
||||
template = '{{ .Tag "hostname" }}.{{ .Tag "level" }}'
|
85
plugins/processors/template/template.go
Normal file
85
plugins/processors/template/template.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package template
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/processors"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type TemplateProcessor struct {
|
||||
Tag string `toml:"tag"`
|
||||
Template string `toml:"template"`
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
|
||||
tmplTag *template.Template
|
||||
tmplValue *template.Template
|
||||
}
|
||||
|
||||
func (*TemplateProcessor) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (r *TemplateProcessor) Apply(in ...telegraf.Metric) []telegraf.Metric {
|
||||
// for each metric in "in" array
|
||||
for _, raw := range in {
|
||||
m := raw
|
||||
if wm, ok := raw.(telegraf.UnwrappableMetric); ok {
|
||||
m = wm.Unwrap()
|
||||
}
|
||||
tm, ok := m.(telegraf.TemplateMetric)
|
||||
if !ok {
|
||||
r.Log.Errorf("metric of type %T is not a template metric", raw)
|
||||
continue
|
||||
}
|
||||
newM := TemplateMetric{tm}
|
||||
|
||||
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()
|
||||
|
||||
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()
|
||||
|
||||
raw.AddTag(tag, value)
|
||||
}
|
||||
|
||||
return in
|
||||
}
|
||||
|
||||
func (r *TemplateProcessor) Init() error {
|
||||
var err error
|
||||
|
||||
r.tmplTag, err = template.New("tag template").Funcs(sprig.TxtFuncMap()).Parse(r.Tag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating tag name template failed: %w", err)
|
||||
}
|
||||
|
||||
r.tmplValue, err = template.New("value template").Funcs(sprig.TxtFuncMap()).Parse(r.Template)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating value template failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
processors.Add("template", func() telegraf.Processor {
|
||||
return &TemplateProcessor{}
|
||||
})
|
||||
}
|
74
plugins/processors/template/template_metric.go
Normal file
74
plugins/processors/template/template_metric.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package template
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
)
|
||||
|
||||
var (
|
||||
onceTagList sync.Once
|
||||
onceFieldList sync.Once
|
||||
)
|
||||
|
||||
type TemplateMetric struct {
|
||||
metric telegraf.TemplateMetric
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) Name() string {
|
||||
return m.metric.Name()
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) Tag(key string) string {
|
||||
return m.metric.Tag(key)
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) Field(key string) interface{} {
|
||||
return m.metric.Field(key)
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) Time() time.Time {
|
||||
return m.metric.Time()
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) Tags() map[string]string {
|
||||
return m.metric.Tags()
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) Fields() map[string]interface{} {
|
||||
return m.metric.Fields()
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) String() string {
|
||||
return m.metric.String()
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) TagList() map[string]string {
|
||||
onceTagList.Do(func() {
|
||||
config.PrintOptionValueDeprecationNotice(
|
||||
"processors.template", "template", "{{.TagList}}",
|
||||
telegraf.DeprecationInfo{
|
||||
Since: "1.28.0",
|
||||
RemovalIn: "1.34.0",
|
||||
Notice: "use '{{.Tags}}' instead",
|
||||
},
|
||||
)
|
||||
})
|
||||
return m.metric.Tags()
|
||||
}
|
||||
|
||||
func (m *TemplateMetric) FieldList() map[string]interface{} {
|
||||
onceFieldList.Do(func() {
|
||||
config.PrintOptionValueDeprecationNotice(
|
||||
"processors.template", "template", "{{.FieldList}}",
|
||||
telegraf.DeprecationInfo{
|
||||
Since: "1.28.0",
|
||||
RemovalIn: "1.34.0",
|
||||
Notice: "use '{{.Fields}}' instead",
|
||||
},
|
||||
)
|
||||
})
|
||||
return m.metric.Fields()
|
||||
}
|
344
plugins/processors/template/template_test.go
Normal file
344
plugins/processors/template/template_test.go
Normal file
|
@ -0,0 +1,344 @@
|
|||
package template
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/metric"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
plugin := TemplateProcessor{
|
||||
Tag: "measurement",
|
||||
Template: "{{ .Name }}",
|
||||
}
|
||||
|
||||
err := plugin.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
input := []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
}
|
||||
|
||||
actual := plugin.Apply(input...)
|
||||
expected := []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"measurement": "cpu",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
}
|
||||
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()
|
||||
|
||||
// Create Template processor
|
||||
tmp := TemplateProcessor{Tag: "topic", Template: `{{.Tag "hostname"}}.{{ .Tag "level" }}`}
|
||||
// manually init
|
||||
err := tmp.Init()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// create metric for testing
|
||||
input := []telegraf.Metric{testutil.MustMetric("Tags", map[string]string{"hostname": "localhost", "level": "debug"}, nil, now)}
|
||||
|
||||
// act
|
||||
actual := tmp.Apply(input[0])
|
||||
|
||||
// assert
|
||||
expected := []telegraf.Metric{
|
||||
testutil.MustMetric("Tags", map[string]string{"hostname": "localhost", "level": "debug", "topic": "localhost.debug"}, nil, now),
|
||||
}
|
||||
testutil.RequireMetricsEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestMetricMissingTagsIsNotLost(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
// Create Template processor
|
||||
tmp := TemplateProcessor{Tag: "topic", Template: `{{.Tag "hostname"}}.{{ .Tag "level" }}`}
|
||||
// manually init
|
||||
err := tmp.Init()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// create metrics for testing
|
||||
m1 := testutil.MustMetric("Works", map[string]string{"hostname": "localhost", "level": "debug"}, nil, now)
|
||||
m2 := testutil.MustMetric("Fails", map[string]string{"hostname": "localhost"}, nil, now)
|
||||
|
||||
// act
|
||||
actual := tmp.Apply(m1, m2)
|
||||
|
||||
// assert
|
||||
// make sure no metrics are lost when a template process fails
|
||||
require.Len(t, actual, 2, "Number of metrics input should equal number of metrics output")
|
||||
}
|
||||
|
||||
func TestTagAndFieldConcatenate(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
// Create Template processor
|
||||
tmp := TemplateProcessor{Tag: "LocalTemp", Template: `{{.Tag "location"}} is {{ .Field "temperature" }}`}
|
||||
// manually init
|
||||
err := tmp.Init()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// create metric for testing
|
||||
m1 := testutil.MustMetric("weather", map[string]string{"location": "us-midwest"}, map[string]interface{}{"temperature": "too warm"}, now)
|
||||
|
||||
// act
|
||||
actual := tmp.Apply(m1)
|
||||
|
||||
// assert
|
||||
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)
|
||||
}
|
||||
|
||||
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 TestFields(t *testing.T) {
|
||||
// Prepare
|
||||
plugin := TemplateProcessor{
|
||||
Tag: "fields",
|
||||
Template: "{{.Fields}}",
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
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 TestTags(t *testing.T) {
|
||||
// Prepare
|
||||
plugin := TemplateProcessor{
|
||||
Tag: "tags",
|
||||
Template: "{{.Tags}}",
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
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 TestString(t *testing.T) {
|
||||
// Prepare
|
||||
plugin := TemplateProcessor{
|
||||
Tag: "tags",
|
||||
Template: "{{.}}",
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
require.NoError(t, plugin.Init())
|
||||
|
||||
// Run
|
||||
m := testutil.TestMetric(1.23)
|
||||
actual := plugin.Apply(m)
|
||||
|
||||
// Verify
|
||||
expected := m.Copy()
|
||||
expected.AddTag("tags", "test1 map[tag1:value1] map[value:1.23] 1257894000000000000")
|
||||
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)
|
||||
}
|
||||
|
||||
func TestTracking(t *testing.T) {
|
||||
// Create a tracking metric and tap the delivery information
|
||||
var mu sync.Mutex
|
||||
delivered := make([]telegraf.DeliveryInfo, 0, 1)
|
||||
notify := func(di telegraf.DeliveryInfo) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
delivered = append(delivered, di)
|
||||
}
|
||||
m := testutil.TestMetric(1.23)
|
||||
input, _ := metric.WithTracking(m, notify)
|
||||
|
||||
// Create an expectation
|
||||
e := m.Copy()
|
||||
e.AddTag("metric", "test1 map[tag1:value1] map[value:1.23] 1257894000000000000")
|
||||
expected := []telegraf.Metric{e}
|
||||
|
||||
// Configure the plugin
|
||||
plugin := TemplateProcessor{Tag: "metric", Template: "{{.}}"}
|
||||
require.NoError(t, plugin.Init())
|
||||
|
||||
// Process expected metrics and compare with resulting metrics
|
||||
actual := plugin.Apply(input)
|
||||
testutil.RequireMetricsEqual(t, expected, actual)
|
||||
|
||||
// Simulate output acknowledging delivery
|
||||
for _, m := range actual {
|
||||
m.Accept()
|
||||
}
|
||||
|
||||
// Check delivery
|
||||
|
||||
// Check delivery
|
||||
require.Eventuallyf(t, func() bool {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
return len(delivered) == 1
|
||||
}, time.Second, 100*time.Millisecond, "%d delivered but 1 expected", len(delivered))
|
||||
}
|
||||
|
||||
func TestSprig(t *testing.T) {
|
||||
plugin := TemplateProcessor{
|
||||
Tag: `{{ .Tag "foo" | lower }}`,
|
||||
Template: `{{ .Name | upper }}`,
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue