Support tags in enum processor (#5855)
This commit is contained in:
parent
43c6d13c33
commit
10fd5b35f0
|
@ -1,13 +1,13 @@
|
|||
# Enum Processor Plugin
|
||||
|
||||
The Enum Processor allows the configuration of value mappings for metric fields.
|
||||
The Enum Processor allows the configuration of value mappings for metric tags or fields.
|
||||
The main use-case for this is to rewrite status codes such as _red_, _amber_ and
|
||||
_green_ by numeric values such as 0, 1, 2. The plugin supports string and bool
|
||||
types for the field values. Multiple Fields can be configured with separate
|
||||
value mappings for each field. Default mapping values can be configured to be
|
||||
types for the field values. Multiple tags or fields can be configured with separate
|
||||
value mappings for each. Default mapping values can be configured to be
|
||||
used for all values, which are not contained in the value_mappings. The
|
||||
processor supports explicit configuration of a destination field. By default the
|
||||
source field is overwritten.
|
||||
processor supports explicit configuration of a destination tag or field. By default the
|
||||
source tag or field is overwritten.
|
||||
|
||||
### Configuration:
|
||||
|
||||
|
@ -17,8 +17,11 @@ source field is overwritten.
|
|||
## Name of the field to map
|
||||
field = "status"
|
||||
|
||||
## Destination field to be used for the mapped value. By default the source
|
||||
## field is used, overwriting the original value.
|
||||
## Name of the tag to map
|
||||
# tag = "status"
|
||||
|
||||
## Destination tag or field to be used for the mapped value. By default the
|
||||
## source tag or field is used, overwriting the original value.
|
||||
dest = "status_code"
|
||||
|
||||
## Default value to be used for all values not contained in the mapping
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package enum
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
|
@ -12,9 +13,12 @@ var sampleConfig = `
|
|||
## Name of the field to map
|
||||
field = "status"
|
||||
|
||||
## Destination field to be used for the mapped value. By default the source
|
||||
## field is used, overwriting the original value.
|
||||
# dest = "status_code"
|
||||
## Name of the tag to map
|
||||
# tag = "status"
|
||||
|
||||
## Destination tag or field to be used for the mapped value. By default the
|
||||
## source tag or field is used, overwriting the original value.
|
||||
dest = "status_code"
|
||||
|
||||
## Default value to be used for all values not contained in the mapping
|
||||
## table. When unset, the unmodified value for the field will be used if no
|
||||
|
@ -24,7 +28,7 @@ var sampleConfig = `
|
|||
## Table of mappings
|
||||
[processors.enum.mapping.value_mappings]
|
||||
green = 1
|
||||
yellow = 2
|
||||
amber = 2
|
||||
red = 3
|
||||
`
|
||||
|
||||
|
@ -33,6 +37,7 @@ type EnumMapper struct {
|
|||
}
|
||||
|
||||
type Mapping struct {
|
||||
Tag string
|
||||
Field string
|
||||
Dest string
|
||||
Default interface{}
|
||||
|
@ -56,14 +61,28 @@ func (mapper *EnumMapper) Apply(in ...telegraf.Metric) []telegraf.Metric {
|
|||
|
||||
func (mapper *EnumMapper) applyMappings(metric telegraf.Metric) telegraf.Metric {
|
||||
for _, mapping := range mapper.Mappings {
|
||||
if originalValue, isPresent := metric.GetField(mapping.Field); isPresent == true {
|
||||
if adjustedValue, isString := adjustBoolValue(originalValue).(string); isString == true {
|
||||
if mappedValue, isMappedValuePresent := mapping.mapValue(adjustedValue); isMappedValuePresent == true {
|
||||
if mapping.Field != "" {
|
||||
if originalValue, isPresent := metric.GetField(mapping.Field); isPresent {
|
||||
if adjustedValue, isString := adjustBoolValue(originalValue).(string); isString {
|
||||
if mappedValue, isMappedValuePresent := mapping.mapValue(adjustedValue); isMappedValuePresent {
|
||||
writeField(metric, mapping.getDestination(), mappedValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if mapping.Tag != "" {
|
||||
if originalValue, isPresent := metric.GetTag(mapping.Tag); isPresent {
|
||||
if mappedValue, isMappedValuePresent := mapping.mapValue(originalValue); isMappedValuePresent {
|
||||
switch val := mappedValue.(type) {
|
||||
case string:
|
||||
writeTag(metric, mapping.getDestinationTag(), val)
|
||||
default:
|
||||
writeTag(metric, mapping.getDestinationTag(), fmt.Sprintf("%v", val))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return metric
|
||||
}
|
||||
|
||||
|
@ -91,11 +110,23 @@ func (mapping *Mapping) getDestination() string {
|
|||
return mapping.Field
|
||||
}
|
||||
|
||||
func (mapping *Mapping) getDestinationTag() string {
|
||||
if mapping.Dest != "" {
|
||||
return mapping.Dest
|
||||
}
|
||||
return mapping.Tag
|
||||
}
|
||||
|
||||
func writeField(metric telegraf.Metric, name string, value interface{}) {
|
||||
metric.RemoveField(name)
|
||||
metric.AddField(name, value)
|
||||
}
|
||||
|
||||
func writeTag(metric telegraf.Metric, name string, value string) {
|
||||
metric.RemoveTag(name)
|
||||
metric.AddTag(name, value)
|
||||
}
|
||||
|
||||
func init() {
|
||||
processors.Add("enum", func() telegraf.Processor {
|
||||
return &EnumMapper{}
|
||||
|
|
|
@ -27,12 +27,23 @@ func calculateProcessedValues(mapper EnumMapper, metric telegraf.Metric) map[str
|
|||
return processed[0].Fields()
|
||||
}
|
||||
|
||||
func calculateProcessedTags(mapper EnumMapper, metric telegraf.Metric) map[string]string {
|
||||
processed := mapper.Apply(metric)
|
||||
return processed[0].Tags()
|
||||
}
|
||||
|
||||
func assertFieldValue(t *testing.T, expected interface{}, field string, fields map[string]interface{}) {
|
||||
value, present := fields[field]
|
||||
assert.True(t, present, "value of field '"+field+"' was not present")
|
||||
assert.EqualValues(t, expected, value)
|
||||
}
|
||||
|
||||
func assertTagValue(t *testing.T, expected interface{}, tag string, tags map[string]string) {
|
||||
value, present := tags[tag]
|
||||
assert.True(t, present, "value of tag '"+tag+"' was not present")
|
||||
assert.EqualValues(t, expected, value)
|
||||
}
|
||||
|
||||
func TestRetainsMetric(t *testing.T) {
|
||||
mapper := EnumMapper{}
|
||||
source := createTestMetric()
|
||||
|
@ -56,6 +67,14 @@ func TestMapsSingleStringValue(t *testing.T) {
|
|||
assertFieldValue(t, 1, "string_value", fields)
|
||||
}
|
||||
|
||||
func TestMapsSingleStringValueTag(t *testing.T) {
|
||||
mapper := EnumMapper{Mappings: []Mapping{{Tag: "tag", ValueMappings: map[string]interface{}{"tag_value": "valuable"}}}}
|
||||
|
||||
tags := calculateProcessedTags(mapper, createTestMetric())
|
||||
|
||||
assertTagValue(t, "valuable", "tag", tags)
|
||||
}
|
||||
|
||||
func TestNoFailureOnMappingsOnNonStringValuedFields(t *testing.T) {
|
||||
mapper := EnumMapper{Mappings: []Mapping{{Field: "int_value", ValueMappings: map[string]interface{}{"13i": int64(7)}}}}
|
||||
|
||||
|
|
Loading…
Reference in New Issue