Skip to content

Commit

Permalink
fix: sanitize stasd names (#10466)
Browse files Browse the repository at this point in the history
  • Loading branch information
powersj authored Mar 1, 2022
1 parent d99e8d4 commit 39e065f
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
8 changes: 8 additions & 0 deletions plugins/inputs/statsd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions plugins/inputs/statsd/statsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bytes"
"fmt"
"net"
"regexp"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1089,6 +1111,7 @@ func init() {
DeleteGauges: true,
DeleteSets: true,
DeleteTimings: true,
SanitizeNamesMethod: "",
}
})
}
64 changes: 64 additions & 0 deletions plugins/inputs/statsd/statsd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

0 comments on commit 39e065f

Please sign in to comment.