Skip to content

Commit e714e10

Browse files
Berin Smaldonada-foss
authored andcommitted
re-worked implementation of lowercase into a more generic strings processor (influxdata#3890)
1 parent 6e245b5 commit e714e10

File tree

4 files changed

+480
-0
lines changed

4 files changed

+480
-0
lines changed

plugins/processors/all/all.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ import (
77
_ "github.com/influxdata/telegraf/plugins/processors/printer"
88
_ "github.com/influxdata/telegraf/plugins/processors/regex"
99
_ "github.com/influxdata/telegraf/plugins/processors/topk"
10+
_ "github.com/influxdata/telegraf/plugins/processors/strings"
1011
)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Strings Processor Plugin
2+
3+
The `strings` plugin maps certain go string functions onto tag and field values. If `result_key` parameter is present, it can produce new tags and fields from existing ones.
4+
5+
Implemented functions are: Lowercase, Uppercase, Trim, TrimPrefix, TrimSuffix, TrimRight, TrimLeft
6+
7+
Please note that in this implementation these are processed in the order that they appear above.
8+
9+
Specify the `tag` or `field` that you want processed in each section and optionally a `result_key` if you want the result stored in a new tag or field. You can specify lots of transformations on data with a single strings processor. Certain functions require an `argument` field to specify how they should process their throughput.
10+
11+
Functions that require an `argument` are: Trim, TrimPrefix, TrimSuffix, TrimRight, TrimLeft
12+
13+
### Configuration:
14+
15+
```toml
16+
[[processors.strings]]
17+
namepass = ["uri_stem"]
18+
19+
# Tag and field conversions defined in a separate sub-tables
20+
[[processors.strings.lowercase]]
21+
## Tag to change
22+
tag = "uri_stem"
23+
24+
[[processors.strings.lowercase]]
25+
## Multiple tags or fields may be defined
26+
tag = "method"
27+
28+
[[processors.strings.uppercase]]
29+
key = "cs-host"
30+
result_key = "cs-host_normalised"
31+
32+
[[processors.strings.trimprefix]]
33+
tag = "uri_stem"
34+
argument = "/api/"
35+
```
36+
37+
### Tags:
38+
39+
No tags are applied by this processor.
40+
41+
### Example Input:
42+
```
43+
iis_log,method=get,uri_stem=/API/HealthCheck cs-host="MIXEDCASE_host",referrer="-",ident="-",http_version=1.1,agent="UserAgent",resp_bytes=270i 1519652321000000000
44+
```
45+
### Example Output:
46+
```
47+
iis_log,method=get,uri_stem=healthcheck cs-host="MIXEDCASE_host",cs-host_normalised="MIXEDCASE_HOST",referrer="-",ident="-",http_version=1.1,agent="UserAgent",resp_bytes=270i 1519652321000000000
48+
```
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package strings
2+
3+
import (
4+
"strings"
5+
6+
"github.com/influxdata/telegraf"
7+
"github.com/influxdata/telegraf/plugins/processors"
8+
)
9+
10+
type Strings struct {
11+
Lowercase []converter
12+
Uppercase []converter
13+
Trim []converter
14+
TrimLeft []converter
15+
TrimRight []converter
16+
TrimPrefix []converter
17+
TrimSuffix []converter
18+
}
19+
20+
type converter struct {
21+
Tag string
22+
Field string
23+
ResultKey string
24+
Argument string
25+
}
26+
27+
const sampleConfig = `
28+
## Tag and field conversions defined in a separate sub-tables
29+
30+
# [[processors.strings.uppercase]]
31+
# tag = "method"
32+
33+
# [[processors.strings.lowercase]]
34+
# field = "uri_stem"
35+
# result_key = "uri_stem_normalised"
36+
`
37+
38+
func (r *Strings) SampleConfig() string {
39+
return sampleConfig
40+
}
41+
42+
func (r *Strings) Description() string {
43+
return "Transforms tag and field values to lower case"
44+
}
45+
46+
func ApplyFunction(
47+
metric telegraf.Metric,
48+
c converter,
49+
fn func(string) string) {
50+
51+
if value, ok := metric.Tags()[c.Tag]; ok {
52+
metric.AddTag(
53+
getKey(c),
54+
fn(value),
55+
)
56+
} else if value, ok := metric.Fields()[c.Field]; ok {
57+
switch value := value.(type) {
58+
case string:
59+
metric.AddField(
60+
getKey(c),
61+
fn(value),
62+
)
63+
}
64+
}
65+
}
66+
67+
func (r *Strings) Apply(in ...telegraf.Metric) []telegraf.Metric {
68+
for _, metric := range in {
69+
for _, converter := range r.Lowercase {
70+
ApplyFunction(metric, converter, strings.ToLower)
71+
}
72+
for _, converter := range r.Uppercase {
73+
ApplyFunction(metric, converter, strings.ToUpper)
74+
}
75+
for _, converter := range r.Trim {
76+
ApplyFunction(metric, converter,
77+
func(s string) string { return strings.Trim(s, converter.Argument) })
78+
}
79+
for _, converter := range r.TrimPrefix {
80+
ApplyFunction(metric, converter,
81+
func(s string) string { return strings.TrimPrefix(s, converter.Argument) })
82+
}
83+
for _, converter := range r.TrimSuffix{
84+
ApplyFunction(metric, converter,
85+
func(s string) string { return strings.TrimSuffix(s, converter.Argument) })
86+
}
87+
for _, converter := range r.TrimRight {
88+
ApplyFunction(metric, converter,
89+
func(s string) string { return strings.TrimRight(s, converter.Argument) })
90+
}
91+
for _, converter := range r.TrimLeft {
92+
ApplyFunction(metric, converter,
93+
func(s string) string { return strings.TrimLeft(s, converter.Argument) })
94+
}
95+
}
96+
97+
return in
98+
}
99+
100+
func getKey(c converter) string {
101+
if c.ResultKey != "" {
102+
return c.ResultKey
103+
} else if c.Field != "" {
104+
return c.Field
105+
} else {
106+
return c.Tag
107+
}
108+
}
109+
110+
func init() {
111+
processors.Add("strings", func() telegraf.Processor {
112+
return &Strings{}
113+
})
114+
}

0 commit comments

Comments
 (0)