Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Add dynamic name prefix & suffix to reset metric name #13418

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 69 additions & 5 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,12 @@ Parameters that can be used with any input plugin:
the name of the input).

- **name_prefix**: Specifies a prefix to attach to the measurement name.
If the prefix does not start with a `+` sign, directly overwrites the prefix
setting of the metric, otherwise appends it to the front of the prefixed name.

- **name_suffix**: Specifies a suffix to attach to the measurement name.
If the suffix does not start with a `+` sign, directly overwrites the suffix
setting of the metric, otherwise appends it to the back of the suffixed name.

- **tags**: A map of tags to apply to a specific input's measurements.

Expand Down Expand Up @@ -461,9 +465,13 @@ Parameters that can be used with any output plugin:
- **metric_buffer_limit**: The maximum number of unsent metrics to buffer.
Use this setting to override the agent `metric_buffer_limit` on a per plugin
basis.
- **name_override**: Override the original name of the measurement.
- **name_prefix**: Specifies a prefix to attach to the measurement name.
- **name_suffix**: Specifies a suffix to attach to the measurement name.
- **name_override**: Override the original name of the measurement. (Default is the name of input).
- **name_prefix**: Specifies a prefix to attach to the measurement name. (Default is the name prefix of input).
If the prefix does not start with a `+` sign, directly overwrites the prefix
setting of the metric, otherwise appends it to the front of the prefixed name.
- **name_suffix**: Specifies a suffix to attach to the measurement name. (Default is the name suffix of input).
If the suffix does not start with a `+` sign, directly overwrites the suffix
setting of the metric, otherwise appends it to the back of the suffixed name.

The [metric filtering][] parameters can be used to limit what metrics are
emitted from the output plugin.
Expand Down Expand Up @@ -551,8 +559,14 @@ Parameters that can be used with any aggregator plugin:
aggregator and will not get sent to the output plugins.
- **name_override**: Override the base name of the measurement. (Default is
the name of the input).
- **name_prefix**: Specifies a prefix to attach to the measurement name.
- **name_suffix**: Specifies a suffix to attach to the measurement name.
- **name_prefix**: Specifies a prefix to attach to the measurement name. (Default is
the name prefix of the input).
If the prefix does not start with a `+` sign, directly overwrites the prefix
setting of the metric, otherwise appends it to the front of the prefixed name.
- **name_suffix**: Specifies a suffix to attach to the measurement name. (Default is
the name suffix of the input).
If the suffix does not start with a `+` sign, directly overwrites the suffix
setting of the metric, otherwise appends it to the back of the suffixed name.
- **tags**: A map of tags to apply to the measurement - behavior varies based on aggregator.

The [metric filtering][] parameters can be used to limit what metrics are
Expand Down Expand Up @@ -806,6 +820,56 @@ select the output. The tag is removed in the outputs before writing.
influxdb_database = "other"
```

Metrics are prefixed in the input, which is then used to select the output.
The metric name will be removed/overrode/appended in the outputs before writing.

```toml
[[inputs.exec]]
# ...
name_prefix = "exec1_"

[[inputs.exec]]
# ...
name_prefix = "exec2_"

[[inputs.exec]]
# ...
name_prefix = "exec3_"

[[inputs.exec]]
# ...
name_prefix = "exec4_"

# this will only get exec1
[[outputs.influxdb]]
# ...
namepass = "exec1_*"

# this will only get exec2
[[outputs.influxdb]]
# ...
namepass = "exec2_*"
# this will remove the previously set prefix
# so final metric name will be first input name
name_prefix = ""

# this will only get exec3
[[outputs.influxdb]]
# ...
namepass = "exec3_*"
# this will override the previously set prefix
# so final metric name will start with exec3v1_
name_prefix = "exec3v1_"

# this will only get exec4
[[outputs.influxdb]]
# ...
namepass = "exec4_*"
# this will appends to the front of the previously set prefix
# so final metric name will start with telegraf_exec4_
name_prefix = "+telegraf_"
```

## Transport Layer Security (TLS)

Reference the detailed [TLS][] documentation.
Expand Down
76 changes: 67 additions & 9 deletions metric.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package telegraf

import (
"strings"
"time"
)

Expand All @@ -17,6 +18,48 @@ const (
Histogram
)

type Namer struct {
Name string
Prefix string
Suffix string
}

func (n *Namer) Value() string {
return n.Prefix + n.Name + n.Suffix
}

func (n *Namer) SetName(name string) {
n.Name = name
}

// SetPrefix on name, if the prefix does not start with a `+` sign,
// it directly overwrites the prefix setting of the metric, otherwise add it.
func (n *Namer) SetPrefix(prefix string) {
if strings.HasPrefix(prefix, "+") {
n.Prefix = prefix[1:] + n.Prefix
} else {
n.Prefix = prefix
}
}

// SetSuffix on name, if the suffix does not start with a `+` sign,
// it directly overwrites the suffix setting of the metric, otherwise add it.
func (n *Namer) SetSuffix(suffix string) {
if strings.HasPrefix(suffix, "+") {
n.Suffix += suffix[1:]
} else {
n.Suffix = suffix
}
}

func (n *Namer) Copy() *Namer {
return &Namer{
Name: n.Name,
Prefix: n.Prefix,
Suffix: n.Suffix,
}
}

// Tag represents a single tag key and value.
type Tag struct {
Key string
Expand All @@ -37,8 +80,16 @@ type Field struct {
type Metric interface {
// Name is the primary identifier for the Metric and corresponds to the
// measurement in the InfluxDB data model.
// The final name should be m.Name().Value().
//
// This method is deprecated, use Namer().Value() instead.
Name() string

// Namer is used to fetch the primary identifier for the Metric
// and corresponds to the measurement in the InfluxDB data model.
// The final name should be m.Namer().Value().
Namer() *Namer

// Tags returns the tags as a map. This method is deprecated, use TagList instead.
Tags() map[string]string

Expand All @@ -62,20 +113,27 @@ type Metric interface {
// might interpret, aggregate the values. Used by prometheus and statsd.
Type() ValueType

// SetName sets the metric name.
// SetName sets the metric name
// equivalent to m.Namer().SetName(nameOverride).
//
// This method is deprecated, use Namer().SetName instead.
SetName(name string)

// AddPrefix adds a string to the front of the metric name. It is
// equivalent to m.SetName(prefix + m.Name()).
// SetPrefix sets a string to the front of the metric name. It is
// equivalent to m.Namer().SetPrefix(prefix). It is different with
// AddPrefix sets a string to the front of the prefixed metric name,
// which equivalent to m.Namer().SetPrefix("+" + prefix).
//
// This method is deprecated, use SetName instead.
AddPrefix(prefix string)
// This method is deprecated, use Namer().SetPrefix instead.
SetPrefix(prefix string)

// AddSuffix appends a string to the back of the metric name. It is
// equivalent to m.SetName(m.Name() + suffix).
// SetSuffix sets a string to the back of the metric name. It is
// equivalent to m.Namer().SetSuffix(suffix). It is different with
// AddSuffix sets a string to the back of the suffixed metric name,
// which equivalent to m.Namer().SetSuffix("+" + suffix).
//
// This method is deprecated, use SetName instead.
AddSuffix(suffix string)
// This method is deprecated, use Namer().SetSuffix instead.
SetSuffix(suffix string)

// GetTag returns the value of a tag and a boolean to indicate if it was set.
GetTag(key string) (string, bool)
Expand Down
38 changes: 26 additions & 12 deletions metric/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

type metric struct {
name string
namer *telegraf.Namer
tags []*telegraf.Tag
fields []*telegraf.Field
tm time.Time
Expand All @@ -24,6 +24,16 @@ func New(
fields map[string]interface{},
tm time.Time,
tp ...telegraf.ValueType,
) telegraf.Metric {
return FromNamer(telegraf.Namer{Name: name}, tags, fields, tm, tp...)
}

func FromNamer(
namer telegraf.Namer,
tags map[string]string,
fields map[string]interface{},
tm time.Time,
tp ...telegraf.ValueType,
) telegraf.Metric {
var vtype telegraf.ValueType
if len(tp) > 0 {
Expand All @@ -33,7 +43,7 @@ func New(
}

m := &metric{
name: name,
namer: &namer,
tags: nil,
fields: nil,
tm: tm,
Expand Down Expand Up @@ -67,7 +77,7 @@ func New(
// removed.
func FromMetric(other telegraf.Metric) telegraf.Metric {
m := &metric{
name: other.Name(),
namer: other.Namer(),
tags: make([]*telegraf.Tag, len(other.TagList())),
fields: make([]*telegraf.Field, len(other.FieldList())),
tm: other.Time(),
Expand All @@ -85,11 +95,15 @@ func FromMetric(other telegraf.Metric) telegraf.Metric {
}

func (m *metric) String() string {
return fmt.Sprintf("%s %v %v %d", m.name, m.Tags(), m.Fields(), m.tm.UnixNano())
return fmt.Sprintf("%s %v %v %d", m.Name(), m.Tags(), m.Fields(), m.tm.UnixNano())
}

func (m *metric) Name() string {
return m.name
return m.namer.Value()
}

func (m *metric) Namer() *telegraf.Namer {
return m.namer
}

func (m *metric) Tags() map[string]string {
Expand Down Expand Up @@ -126,15 +140,15 @@ func (m *metric) Type() telegraf.ValueType {
}

func (m *metric) SetName(name string) {
m.name = name
m.namer.SetName(name)
}

func (m *metric) AddPrefix(prefix string) {
m.name = prefix + m.name
func (m *metric) SetPrefix(prefix string) {
m.namer.SetPrefix(prefix)
}

func (m *metric) AddSuffix(suffix string) {
m.name = m.name + suffix
func (m *metric) SetSuffix(suffix string) {
m.namer.SetSuffix(suffix)
}

func (m *metric) AddTag(key, value string) {
Expand Down Expand Up @@ -243,7 +257,7 @@ func (m *metric) SetTime(t time.Time) {

func (m *metric) Copy() telegraf.Metric {
m2 := &metric{
name: m.name,
namer: m.namer.Copy(),
tags: make([]*telegraf.Tag, len(m.tags)),
fields: make([]*telegraf.Field, len(m.fields)),
tm: m.tm,
Expand All @@ -262,7 +276,7 @@ func (m *metric) Copy() telegraf.Metric {

func (m *metric) HashID() uint64 {
h := fnv.New64a()
h.Write([]byte(m.name))
h.Write([]byte(m.Name()))
h.Write([]byte("\n"))
for _, tag := range m.tags {
h.Write([]byte(tag.Key))
Expand Down
30 changes: 24 additions & 6 deletions metric/metric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,20 +299,38 @@ func TestSetName(t *testing.T) {
require.Equal(t, "foo", m.Name())
}

func TestSetPrefix(t *testing.T) {
m := baseMetric()
m.SetPrefix("foo_")
require.Equal(t, "foo_cpu", m.Name())
m.Namer().SetPrefix("bar_")
require.Equal(t, "bar_cpu", m.Name())
}

func TestSetSuffix(t *testing.T) {
m := baseMetric()
m.Namer().SetSuffix("_foo")
require.Equal(t, "cpu_foo", m.Name())
m.Namer().SetSuffix("_bar")
require.Equal(t, "cpu_bar", m.Name())
}

func TestAddPrefix(t *testing.T) {
m := baseMetric()
m.AddPrefix("foo_")
m.SetPrefix("foo_")
require.Equal(t, "foo_cpu", m.Name())
m.AddPrefix("foo_")
require.Equal(t, "foo_foo_cpu", m.Name())
// append to the front of foo_cpu
m.Namer().SetPrefix("+bar_")
require.Equal(t, "bar_foo_cpu", m.Name())
}

func TestAddSuffix(t *testing.T) {
m := baseMetric()
m.AddSuffix("_foo")
m.Namer().SetSuffix("_foo")
require.Equal(t, "cpu_foo", m.Name())
m.AddSuffix("_foo")
require.Equal(t, "cpu_foo_foo", m.Name())
// append to the back of cpu_bar
m.Namer().SetSuffix("+_bar")
require.Equal(t, "cpu_foo_bar", m.Name())
}

func TestValueType(t *testing.T) {
Expand Down
8 changes: 4 additions & 4 deletions models/makemetric.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ func makemetric(
tags map[string]string,
globalTags map[string]string,
) telegraf.Metric {
namer := metric.Namer()
if len(nameOverride) != 0 {
metric.SetName(nameOverride)
namer.SetName(nameOverride)
}

if len(namePrefix) != 0 {
metric.AddPrefix(namePrefix)
namer.SetPrefix(namePrefix)
}
if len(nameSuffix) != 0 {
metric.AddSuffix(nameSuffix)
namer.SetSuffix(nameSuffix)
}

// Apply plugin-wide tags
Expand Down
4 changes: 2 additions & 2 deletions models/running_input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func TestMakeMetricNamePrefix(t *testing.T) {
now,
telegraf.Untyped)
m = ri.MakeMetric(m)
expected := metric.New("foobar_RITest",
expected := metric.FromNamer(telegraf.Namer{Name: "RITest", Prefix: "foobar_"},
nil,
map[string]interface{}{
"value": 101,
Expand All @@ -234,7 +234,7 @@ func TestMakeMetricNameSuffix(t *testing.T) {
now,
telegraf.Untyped)
m = ri.MakeMetric(m)
expected := metric.New("RITest_foobar",
expected := metric.FromNamer(telegraf.Namer{Name: "RITest", Suffix: "_foobar"},
nil,
map[string]interface{}{
"value": 101,
Expand Down
Loading