diff --git a/plugins/parsers/wavefront/element.go b/plugins/parsers/wavefront/element.go index 4e40238e7..859eab1f2 100644 --- a/plugins/parsers/wavefront/element.go +++ b/plugins/parsers/wavefront/element.go @@ -37,7 +37,10 @@ type LiteralParser struct { func (ep *NameParser) parse(p *PointParser, pt *Point) error { //Valid characters are: a-z, A-Z, 0-9, hyphen ("-"), underscore ("_"), dot ("."). // Forward slash ("/") and comma (",") are allowed if metricName is enclosed in double quotes. + // Delta (U+2206) is allowed as the first characeter of the + // metricName name, err := parseLiteral(p) + if err != nil { return err } @@ -225,6 +228,9 @@ func parseLiteral(p *PointParser) (string, error) { for tok != EOF && tok > literal_beg && tok < literal_end { p.writeBuf.WriteString(lit) tok, lit = p.scan() + if tok == DELTA { + return "", errors.New("found delta inside metric name") + } } if tok == QUOTES { return "", errors.New("found quote inside unquoted literal") diff --git a/plugins/parsers/wavefront/parser_test.go b/plugins/parsers/wavefront/parser_test.go index 85367fa1a..e7d427dd8 100644 --- a/plugins/parsers/wavefront/parser_test.go +++ b/plugins/parsers/wavefront/parser_test.go @@ -19,6 +19,26 @@ func TestParse(t *testing.T) { assert.Equal(t, parsedMetrics[0].Name(), testMetric.Name()) assert.Equal(t, parsedMetrics[0].Fields(), testMetric.Fields()) + parsedMetrics, err = parser.Parse([]byte("\u2206test.delta 1 1530939936")) + assert.NoError(t, err) + testMetric, err = metric.New("\u2206test.delta", map[string]string{}, + map[string]interface{}{"value": 1.}, time.Unix(1530939936, 0)) + assert.NoError(t, err) + assert.EqualValues(t, parsedMetrics[0], testMetric) + + parsedMetrics, err = parser.Parse([]byte("\u0394test.delta 1 1530939936")) + assert.NoError(t, err) + testMetric, err = metric.New("\u0394test.delta", map[string]string{}, + map[string]interface{}{"value": 1.}, time.Unix(1530939936, 0)) + assert.NoError(t, err) + assert.EqualValues(t, parsedMetrics[0], testMetric) + + parsedMetrics, err = parser.Parse([]byte("\u0394test.delta 1.234 1530939936 source=\"mysource\" tag2=value2")) + assert.NoError(t, err) + testMetric, err = metric.New("\u0394test.delta", map[string]string{"source": "mysource", "tag2": "value2"}, map[string]interface{}{"value": 1.234}, time.Unix(1530939936, 0)) + assert.NoError(t, err) + assert.EqualValues(t, parsedMetrics[0], testMetric) + parsedMetrics, err = parser.Parse([]byte("test.metric 1 1530939936")) assert.NoError(t, err) testMetric, err = metric.New("test.metric", map[string]string{}, map[string]interface{}{"value": 1.}, time.Unix(1530939936, 0)) @@ -166,6 +186,9 @@ func TestParseInvalid(t *testing.T) { _, err = parser.Parse([]byte("test.metric 1 string")) assert.Error(t, err) + _, err = parser.Parse([]byte("test.\u2206delta 1")) + assert.Error(t, err) + _, err = parser.Parse([]byte("test.metric 1 1530939936 tag_no_pair")) assert.Error(t, err) diff --git a/plugins/parsers/wavefront/scanner.go b/plugins/parsers/wavefront/scanner.go index e64516f54..a528f72ee 100644 --- a/plugins/parsers/wavefront/scanner.go +++ b/plugins/parsers/wavefront/scanner.go @@ -40,6 +40,8 @@ func (s *PointScanner) Scan() (Token, string) { return LETTER, string(ch) } else if isNumber(ch) { return NUMBER, string(ch) + } else if isDelta(ch) { + return DELTA, string(ch) } // Otherwise read the individual character. diff --git a/plugins/parsers/wavefront/token.go b/plugins/parsers/wavefront/token.go index bbcbf4e76..5b77d0cdb 100644 --- a/plugins/parsers/wavefront/token.go +++ b/plugins/parsers/wavefront/token.go @@ -18,6 +18,7 @@ const ( SLASH BACKSLASH COMMA + DELTA literal_end // Misc characters @@ -38,4 +39,8 @@ func isNumber(ch rune) bool { return ch >= '0' && ch <= '9' } +func isDelta(ch rune) bool { + return ch == '\u2206' || ch == '\u0394' +} + var eof = rune(0)