Skip to content

Commit

Permalink
tags: validate tag values. (#42)
Browse files Browse the repository at this point in the history
This makes sure that | and : are not sent in as tag values, which causes
statsd parse errors, since | and : are delimiters in the statsd format.

This is the most conservative approach in validation, and I think it
makes sense because people tend to send unchecked input in as tag
values. There are stricter rules for metric names and tag keys (at least
in wavefront[1]) but rather than silently changing those, we should let
them fail and cause alerts as they currently do.

[1] https://docs.wavefront.com/wavefront_data_format.html
  • Loading branch information
diegs authored and James Sedgwick committed Aug 15, 2018
1 parent f60c0ca commit 1fc908d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
10 changes: 8 additions & 2 deletions tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ package stats
import (
"bytes"
"fmt"
"regexp"
"sort"
)

const (
tagPrefix = ".__"
tagSep = "="
tagPrefix = ".__"
tagSep = "="
tagFailsafe = "_"
)

// illegalTagValueChars are loosely set to ensure we don't have statsd parse errors.
var illegalTagValueChars = regexp.MustCompile(`[:|]`)

type tagPair struct {
dimension string
value string
Expand All @@ -25,6 +30,7 @@ func (t tagSet) Less(i, j int) bool { return t[i].dimension < t[j].dimension }
func serializeTags(tags map[string]string) string {
tagPairs := make([]tagPair, 0, len(tags))
for tagKey, tagValue := range tags {
tagValue = illegalTagValueChars.ReplaceAllLiteralString(tagValue, tagFailsafe)
tagPairs = append(tagPairs, tagPair{tagKey, tagValue})
}
sort.Sort(tagSet(tagPairs))
Expand Down
8 changes: 8 additions & 0 deletions tags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ func TestSerializeWithPerInstanceFlag(t *testing.T) {
t.Errorf("Serialized output (%s) didn't match expected output", serialized)
}
}

func TestSerializeIllegalTags(t *testing.T) {
tags := map[string]string{"foo": "b|a:r", "q": "p"}
serialized := serializeTags(tags)
if serialized != ".__foo=b_a_r.__q=p" {
t.Errorf("Serialized output (%s) didn't match expected output", serialized)
}
}

0 comments on commit 1fc908d

Please sign in to comment.