2018-07-04 06:32:52 +08:00
|
|
|
package enum
|
|
|
|
|
|
|
|
|
|
import (
|
2019-05-17 06:59:19 +08:00
|
|
|
"fmt"
|
2018-07-04 06:32:52 +08:00
|
|
|
"strconv"
|
|
|
|
|
|
|
|
|
|
"github.com/influxdata/telegraf"
|
2020-12-19 05:41:39 +08:00
|
|
|
"github.com/influxdata/telegraf/filter"
|
2018-07-04 06:32:52 +08:00
|
|
|
"github.com/influxdata/telegraf/plugins/processors"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var sampleConfig = `
|
2018-09-12 07:03:47 +08:00
|
|
|
[[processors.enum.mapping]]
|
2020-12-19 05:41:39 +08:00
|
|
|
## Name of the field to map. Globs accepted.
|
2018-09-12 07:03:47 +08:00
|
|
|
field = "status"
|
2018-07-04 07:10:55 +08:00
|
|
|
|
2020-12-19 05:41:39 +08:00
|
|
|
## Name of the tag to map. Globs accepted.
|
2019-05-17 06:59:19 +08:00
|
|
|
# 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"
|
2018-07-04 07:10:55 +08:00
|
|
|
|
|
|
|
|
## 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
|
|
|
|
|
## match is found.
|
|
|
|
|
# default = 0
|
|
|
|
|
|
|
|
|
|
## Table of mappings
|
2018-09-12 07:03:47 +08:00
|
|
|
[processors.enum.mapping.value_mappings]
|
|
|
|
|
green = 1
|
2019-05-17 06:59:19 +08:00
|
|
|
amber = 2
|
2018-09-12 07:03:47 +08:00
|
|
|
red = 3
|
2018-07-04 06:32:52 +08:00
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type EnumMapper struct {
|
2018-09-12 07:03:47 +08:00
|
|
|
Mappings []Mapping `toml:"mapping"`
|
2020-12-19 05:41:39 +08:00
|
|
|
|
|
|
|
|
FieldFilters map[string]filter.Filter
|
|
|
|
|
TagFilters map[string]filter.Filter
|
2018-07-04 06:32:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Mapping struct {
|
2019-05-17 06:59:19 +08:00
|
|
|
Tag string
|
2018-09-12 07:03:47 +08:00
|
|
|
Field string
|
|
|
|
|
Dest string
|
2018-07-04 06:32:52 +08:00
|
|
|
Default interface{}
|
|
|
|
|
ValueMappings map[string]interface{}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-19 05:41:39 +08:00
|
|
|
func (mapper *EnumMapper) Init() error {
|
|
|
|
|
mapper.FieldFilters = make(map[string]filter.Filter)
|
|
|
|
|
mapper.TagFilters = make(map[string]filter.Filter)
|
|
|
|
|
for _, mapping := range mapper.Mappings {
|
|
|
|
|
if mapping.Field != "" {
|
|
|
|
|
fieldFilter, err := filter.NewIncludeExcludeFilter([]string{mapping.Field}, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to create new field filter: %w", err)
|
|
|
|
|
}
|
|
|
|
|
mapper.FieldFilters[mapping.Field] = fieldFilter
|
|
|
|
|
}
|
|
|
|
|
if mapping.Tag != "" {
|
|
|
|
|
tagFilter, err := filter.NewIncludeExcludeFilter([]string{mapping.Tag}, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to create new tag filter: %s", err)
|
|
|
|
|
}
|
|
|
|
|
mapper.TagFilters[mapping.Tag] = tagFilter
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-04 06:32:52 +08:00
|
|
|
func (mapper *EnumMapper) SampleConfig() string {
|
|
|
|
|
return sampleConfig
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (mapper *EnumMapper) Description() string {
|
|
|
|
|
return "Map enum values according to given table."
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (mapper *EnumMapper) Apply(in ...telegraf.Metric) []telegraf.Metric {
|
|
|
|
|
for i := 0; i < len(in); i++ {
|
|
|
|
|
in[i] = mapper.applyMappings(in[i])
|
|
|
|
|
}
|
|
|
|
|
return in
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (mapper *EnumMapper) applyMappings(metric telegraf.Metric) telegraf.Metric {
|
2020-12-19 05:41:39 +08:00
|
|
|
newFields := make(map[string]interface{})
|
|
|
|
|
newTags := make(map[string]string)
|
|
|
|
|
|
2018-09-12 07:03:47 +08:00
|
|
|
for _, mapping := range mapper.Mappings {
|
2019-05-17 06:59:19 +08:00
|
|
|
if mapping.Field != "" {
|
2020-12-19 05:41:39 +08:00
|
|
|
mapper.fieldMapping(metric, mapping, newFields)
|
|
|
|
|
}
|
|
|
|
|
if mapping.Tag != "" {
|
|
|
|
|
mapper.tagMapping(metric, mapping, newTags)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for k, v := range newFields {
|
|
|
|
|
writeField(metric, k, v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for k, v := range newTags {
|
|
|
|
|
writeTag(metric, k, v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return metric
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (mapper *EnumMapper) fieldMapping(metric telegraf.Metric, mapping Mapping, newFields map[string]interface{}) {
|
|
|
|
|
fields := metric.FieldList()
|
|
|
|
|
for _, f := range fields {
|
|
|
|
|
if mapper.FieldFilters[mapping.Field].Match(f.Key) {
|
|
|
|
|
if adjustedValue, isString := adjustValue(f.Value).(string); isString {
|
|
|
|
|
if mappedValue, isMappedValuePresent := mapping.mapValue(adjustedValue); isMappedValuePresent {
|
|
|
|
|
newFields[mapping.getDestination(f.Key)] = mappedValue
|
2019-05-17 06:59:19 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-12-19 05:41:39 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (mapper *EnumMapper) tagMapping(metric telegraf.Metric, mapping Mapping, newTags map[string]string) {
|
|
|
|
|
tags := metric.TagList()
|
|
|
|
|
for _, t := range tags {
|
|
|
|
|
if mapper.TagFilters[mapping.Tag].Match(t.Key) {
|
|
|
|
|
if mappedValue, isMappedValuePresent := mapping.mapValue(t.Value); isMappedValuePresent {
|
|
|
|
|
switch val := mappedValue.(type) {
|
|
|
|
|
case string:
|
|
|
|
|
newTags[mapping.getDestination(t.Key)] = val
|
|
|
|
|
default:
|
|
|
|
|
newTags[mapping.getDestination(t.Key)] = fmt.Sprintf("%v", val)
|
2018-07-04 06:32:52 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-12 02:36:21 +08:00
|
|
|
func adjustValue(in interface{}) interface{} {
|
|
|
|
|
switch val := in.(type) {
|
|
|
|
|
case bool:
|
|
|
|
|
return strconv.FormatBool(val)
|
|
|
|
|
case int64:
|
|
|
|
|
return strconv.FormatInt(val, 10)
|
|
|
|
|
case uint64:
|
|
|
|
|
return strconv.FormatUint(val, 10)
|
|
|
|
|
default:
|
|
|
|
|
return in
|
2018-07-04 06:32:52 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (mapping *Mapping) mapValue(original string) (interface{}, bool) {
|
|
|
|
|
if mapped, found := mapping.ValueMappings[original]; found == true {
|
|
|
|
|
return mapped, true
|
|
|
|
|
}
|
|
|
|
|
if mapping.Default != nil {
|
|
|
|
|
return mapping.Default, true
|
|
|
|
|
}
|
|
|
|
|
return original, false
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-19 05:41:39 +08:00
|
|
|
func (mapping *Mapping) getDestination(defaultDest string) string {
|
2019-05-17 06:59:19 +08:00
|
|
|
if mapping.Dest != "" {
|
|
|
|
|
return mapping.Dest
|
|
|
|
|
}
|
2020-12-19 05:41:39 +08:00
|
|
|
return defaultDest
|
2019-05-17 06:59:19 +08:00
|
|
|
}
|
|
|
|
|
|
2018-07-04 06:32:52 +08:00
|
|
|
func writeField(metric telegraf.Metric, name string, value interface{}) {
|
2018-09-12 07:03:47 +08:00
|
|
|
metric.RemoveField(name)
|
2018-07-04 06:32:52 +08:00
|
|
|
metric.AddField(name, value)
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-17 06:59:19 +08:00
|
|
|
func writeTag(metric telegraf.Metric, name string, value string) {
|
|
|
|
|
metric.RemoveTag(name)
|
|
|
|
|
metric.AddTag(name, value)
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-04 06:32:52 +08:00
|
|
|
func init() {
|
|
|
|
|
processors.Add("enum", func() telegraf.Processor {
|
|
|
|
|
return &EnumMapper{}
|
|
|
|
|
})
|
|
|
|
|
}
|