fix: sanitize stasd names (#10466)
This commit is contained in:
parent
d99e8d49fc
commit
39e065fd78
|
|
@ -75,6 +75,14 @@
|
||||||
|
|
||||||
## Max duration (TTL) for each metric to stay cached/reported without being updated.
|
## Max duration (TTL) for each metric to stay cached/reported without being updated.
|
||||||
# max_ttl = "10h"
|
# max_ttl = "10h"
|
||||||
|
|
||||||
|
## Sanitize name method
|
||||||
|
## By default, telegraf will pass names directly as they are received.
|
||||||
|
## However, upstream statsd now does sanitization of names which can be
|
||||||
|
## enabled by using the "upstream" method option. This option will a) replace
|
||||||
|
## white space with '_', replace '/' with '-', and remove charachters not
|
||||||
|
## matching 'a-zA-Z_\-0-9\.;='.
|
||||||
|
#sanitize_name_method = ""
|
||||||
```
|
```
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -98,6 +99,8 @@ type Statsd struct {
|
||||||
|
|
||||||
ReadBufferSize int `toml:"read_buffer_size"`
|
ReadBufferSize int `toml:"read_buffer_size"`
|
||||||
|
|
||||||
|
SanitizeNamesMethod string `toml:"sanitize_name_method"`
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
// Lock for preventing a data race during resource cleanup
|
// Lock for preventing a data race during resource cleanup
|
||||||
cleanup sync.Mutex
|
cleanup sync.Mutex
|
||||||
|
|
@ -284,6 +287,14 @@ const sampleConfig = `
|
||||||
|
|
||||||
## Max duration (TTL) for each metric to stay cached/reported without being updated.
|
## Max duration (TTL) for each metric to stay cached/reported without being updated.
|
||||||
#max_ttl = "1000h"
|
#max_ttl = "1000h"
|
||||||
|
|
||||||
|
## Sanitize name method
|
||||||
|
## By default, telegraf will pass names directly as they are received.
|
||||||
|
## However, upstream statsd now does sanitization of names which can be
|
||||||
|
## enabled by using the "upstream" method option. This option will a) replace
|
||||||
|
## white space with '_', replace '/' with '-', and remove charachters not
|
||||||
|
## matching 'a-zA-Z_\-0-9\.;='.
|
||||||
|
#sanitize_name_method = ""
|
||||||
`
|
`
|
||||||
|
|
||||||
func (s *Statsd) SampleConfig() string {
|
func (s *Statsd) SampleConfig() string {
|
||||||
|
|
@ -763,6 +774,17 @@ func (s *Statsd) parseName(bucket string) (name string, field string, tags map[s
|
||||||
}
|
}
|
||||||
|
|
||||||
name = bucketparts[0]
|
name = bucketparts[0]
|
||||||
|
switch s.SanitizeNamesMethod {
|
||||||
|
case "":
|
||||||
|
case "upstream":
|
||||||
|
whitespace := regexp.MustCompile(`\s+`)
|
||||||
|
name = whitespace.ReplaceAllString(name, "_")
|
||||||
|
name = strings.ReplaceAll(name, "/", "-")
|
||||||
|
allowedChars := regexp.MustCompile(`[^a-zA-Z_\-0-9\.;=]`)
|
||||||
|
name = allowedChars.ReplaceAllString(name, "")
|
||||||
|
default:
|
||||||
|
s.Log.Errorf("Unknown sanitizae name method: %s", s.SanitizeNamesMethod)
|
||||||
|
}
|
||||||
|
|
||||||
p := s.graphiteParser
|
p := s.graphiteParser
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -1089,6 +1111,7 @@ func init() {
|
||||||
DeleteGauges: true,
|
DeleteGauges: true,
|
||||||
DeleteSets: true,
|
DeleteSets: true,
|
||||||
DeleteTimings: true,
|
DeleteTimings: true,
|
||||||
|
SanitizeNamesMethod: "",
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1701,3 +1701,67 @@ func TestParse_KeyValue(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseSanitize(t *testing.T) {
|
||||||
|
s := NewTestStatsd()
|
||||||
|
s.SanitizeNamesMethod = "upstream"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
inName string
|
||||||
|
outName string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"regex.ARP flood stats",
|
||||||
|
"regex_ARP_flood_stats",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regex./dev/null",
|
||||||
|
"regex_-dev-null",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regex.wow!!!",
|
||||||
|
"regex_wow",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regex.all*things",
|
||||||
|
"regex_allthings",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
name, _, _ := s.parseName(test.inName)
|
||||||
|
require.Equalf(t, name, test.outName, "Expected: %s, got %s", test.outName, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseNoSanitize(t *testing.T) {
|
||||||
|
s := NewTestStatsd()
|
||||||
|
s.SanitizeNamesMethod = ""
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
inName string
|
||||||
|
outName string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"regex.ARP flood stats",
|
||||||
|
"regex_ARP",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regex./dev/null",
|
||||||
|
"regex_/dev/null",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regex.wow!!!",
|
||||||
|
"regex_wow!!!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regex.all*things",
|
||||||
|
"regex_all*things",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
name, _, _ := s.parseName(test.inName)
|
||||||
|
require.Equalf(t, name, test.outName, "Expected: %s, got %s", test.outName, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue