From e1975120cb7ae9e3b15ed9b5390ff70fa2af26cf Mon Sep 17 00:00:00 2001 From: Josh Powers Date: Wed, 23 Aug 2023 07:20:11 -0600 Subject: [PATCH 1/2] feat(processors.enum): Add fields and tags config options fixes: #10892 --- plugins/processors/enum/enum.go | 31 +++++++++++++++++++++++---- plugins/processors/enum/enum_test.go | 32 ++++++++++++++++++++++++++++ plugins/processors/enum/sample.conf | 8 +++++++ 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/plugins/processors/enum/enum.go b/plugins/processors/enum/enum.go index 36a509f8e3d3e..78e601c0eaf33 100644 --- a/plugins/processors/enum/enum.go +++ b/plugins/processors/enum/enum.go @@ -23,7 +23,9 @@ type EnumMapper struct { type Mapping struct { Tag string + Tags []string Field string + Fields []string Dest string Default interface{} ValueMappings map[string]interface{} @@ -37,17 +39,38 @@ 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 != "" && len(mapping.Fields) != 0 { + return fmt.Errorf("use field or fields, but not both") + } 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) + return fmt.Errorf("failed to create new field filter from field: %w", err) } mapper.FieldFilters[mapping.Field] = fieldFilter } + if len(mapping.Fields) != 0 { + fieldFilter, err := filter.NewIncludeExcludeFilter(mapping.Fields, nil) + if err != nil { + return fmt.Errorf("failed to create new field filter from fields: %w", err) + } + mapper.FieldFilters[mapping.Field] = fieldFilter + } + + if mapping.Tag != "" && len(mapping.Tags) != 0 { + return fmt.Errorf("use tag or tags, but not both") + } if mapping.Tag != "" { tagFilter, err := filter.NewIncludeExcludeFilter([]string{mapping.Tag}, nil) if err != nil { - return fmt.Errorf("failed to create new tag filter: %w", err) + return fmt.Errorf("failed to create new tag filter from tag: %w", err) + } + mapper.TagFilters[mapping.Tag] = tagFilter + } + if len(mapping.Tags) != 0 { + tagFilter, err := filter.NewIncludeExcludeFilter(mapping.Tags, nil) + if err != nil { + return fmt.Errorf("failed to create new tag filter from tags: %w", err) } mapper.TagFilters[mapping.Tag] = tagFilter } @@ -68,10 +91,10 @@ func (mapper *EnumMapper) applyMappings(metric telegraf.Metric) telegraf.Metric newTags := make(map[string]string) for _, mapping := range mapper.Mappings { - if mapping.Field != "" { + if mapping.Field != "" || len(mapping.Fields) != 0 { mapper.fieldMapping(metric, mapping, newFields) } - if mapping.Tag != "" { + if mapping.Tag != "" || len(mapping.Tags) != 0 { mapper.tagMapping(metric, mapping, newTags) } } diff --git a/plugins/processors/enum/enum_test.go b/plugins/processors/enum/enum_test.go index 09d019d4ae4b2..59da3f3872e83 100644 --- a/plugins/processors/enum/enum_test.go +++ b/plugins/processors/enum/enum_test.go @@ -196,3 +196,35 @@ func TestTagGlobMatching(t *testing.T) { assertTagValue(t, "glob", "tag", tags) } + +func TestFieldsAndTags(t *testing.T) { + mapper := EnumMapper{Mappings: []Mapping{ + { + Tags: []string{"tag", "duplicate_tag"}, + Fields: []string{"string_value", "duplicate_string_value"}, + ValueMappings: map[string]interface{}{ + "test": "0", + "tag_value": "1", + }, + }, + }} + require.NoError(t, mapper.Init()) + + tags := calculateProcessedTags(mapper, createTestMetric()) + assertTagValue(t, "1", "tag", tags) + assertTagValue(t, "1", "duplicate_tag", tags) + + fields := calculateProcessedValues(mapper, createTestMetric()) + assertFieldValue(t, "0", "string_value", fields) + assertFieldValue(t, "0", "duplicate_string_value", fields) +} + +func TestTagAndTagsError(t *testing.T) { + mapper := EnumMapper{Mappings: []Mapping{{Tag: "*", Tags: []string{"Foo"}, ValueMappings: map[string]interface{}{"tag_value": "glob"}}}} + require.Error(t, mapper.Init()) +} + +func TestFieldAndFieldsError(t *testing.T) { + mapper := EnumMapper{Mappings: []Mapping{{Field: "*", Fields: []string{"Bar"}, ValueMappings: map[string]interface{}{"tag_value": "glob"}}}} + require.Error(t, mapper.Init()) +} diff --git a/plugins/processors/enum/sample.conf b/plugins/processors/enum/sample.conf index 76842c2b82278..f9c843c674d2f 100644 --- a/plugins/processors/enum/sample.conf +++ b/plugins/processors/enum/sample.conf @@ -4,9 +4,17 @@ ## Name of the field to map. Globs accepted. field = "status" + ## List of fields to appply mapping to. Globs accepted. Use either field or + ## fields, but not both. + # fields = [] + ## Name of the tag to map. Globs accepted. # tag = "status" + ## List of tags to appply mapping to. Globs accepted. Use either tag or + ## tags, but not both. + # tags = [] + ## 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" From a9721ced2c08d1d598230ceb6b7956b907f0358c Mon Sep 17 00:00:00 2001 From: Josh Powers Date: Wed, 23 Aug 2023 07:20:44 -0600 Subject: [PATCH 2/2] make docs --- plugins/processors/enum/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/processors/enum/README.md b/plugins/processors/enum/README.md index 95886b701b262..94fd52ddc2d85 100644 --- a/plugins/processors/enum/README.md +++ b/plugins/processors/enum/README.md @@ -27,9 +27,17 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details. ## Name of the field to map. Globs accepted. field = "status" + ## List of fields to appply mapping to. Globs accepted. Use either field or + ## fields, but not both. + # fields = [] + ## Name of the tag to map. Globs accepted. # tag = "status" + ## List of tags to appply mapping to. Globs accepted. Use either tag or + ## tags, but not both. + # tags = [] + ## 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"