fix: sanitize stasd names (#10466)

This commit is contained in:
Joshua Powers 2022-03-01 15:01:08 -07:00 committed by GitHub
parent d99e8d49fc
commit 39e065fd78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 0 deletions

View File

@ -75,6 +75,14 @@
## Max duration (TTL) for each metric to stay cached/reported without being updated.
# 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

View File

@ -5,6 +5,7 @@ import (
"bytes"
"fmt"
"net"
"regexp"
"sort"
"strconv"
"strings"
@ -98,6 +99,8 @@ type Statsd struct {
ReadBufferSize int `toml:"read_buffer_size"`
SanitizeNamesMethod string `toml:"sanitize_name_method"`
sync.Mutex
// Lock for preventing a data race during resource cleanup
cleanup sync.Mutex
@ -284,6 +287,14 @@ const sampleConfig = `
## Max duration (TTL) for each metric to stay cached/reported without being updated.
#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 {
@ -763,6 +774,17 @@ func (s *Statsd) parseName(bucket string) (name string, field string, tags map[s
}
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
var err error
@ -1089,6 +1111,7 @@ func init() {
DeleteGauges: true,
DeleteSets: true,
DeleteTimings: true,
SanitizeNamesMethod: "",
}
})
}

View File

@ -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)
}
}