From b0e4b234cb835b60157dd92d0ee04904a3f9f6c5 Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Sun, 6 Dec 2020 11:59:13 +0200 Subject: [PATCH] lib/protoparser/influx: allow multiple whitespace chars between measurement, fields and timestamp in Influx line protocol --- docs/CHANGELOG.md | 4 ++++ lib/protoparser/influx/parser.go | 11 ++++++++-- lib/protoparser/influx/parser_test.go | 30 +++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d81781eb6..4e0c99124 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,10 @@ # tip +* FEATURE: allow multiple whitespace chars between measurements, fields and timestamp when parsing InfluxDB line protocol. + Though [InfluxDB line protocol](https://docs.influxdata.com/influxdb/v1.8/write_protocols/line_protocol_tutorial/) denies multiple whitespace chars between these entities, + some apps improperly put multiple whitespace chars. This workaround allows accepting data from such apps. + # [v1.49.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.49.0) diff --git a/lib/protoparser/influx/parser.go b/lib/protoparser/influx/parser.go index e08d42ee2..0e8680697 100644 --- a/lib/protoparser/influx/parser.go +++ b/lib/protoparser/influx/parser.go @@ -69,7 +69,7 @@ func (r *Row) unmarshal(s string, tagsPool []Tag, fieldsPool []Field, noEscapeCh return tagsPool, fieldsPool, fmt.Errorf("cannot find Whitespace I in %q", s) } measurementTags := s[:n] - s = s[n+1:] + s = stripLeadingWhitespace(s[n+1:]) // Parse measurement and tags var err error @@ -110,7 +110,7 @@ func (r *Row) unmarshal(s string, tagsPool []Tag, fieldsPool []Field, noEscapeCh return tagsPool, fieldsPool, err } r.Fields = fieldsPool[fieldsStart:] - s = s[n+1:] + s = stripLeadingWhitespace(s[n+1:]) // Parse timestamp timestamp, err := fastfloat.ParseInt64(s) @@ -409,3 +409,10 @@ func isInQuote(s string, noEscapeChars bool) bool { s = s[n+1:] } } + +func stripLeadingWhitespace(s string) string { + for len(s) > 0 && s[0] == ' ' { + s = s[1:] + } + return s +} diff --git a/lib/protoparser/influx/parser_test.go b/lib/protoparser/influx/parser_test.go index 6d75d04c0..50c625b9f 100644 --- a/lib/protoparser/influx/parser_test.go +++ b/lib/protoparser/influx/parser_test.go @@ -468,6 +468,36 @@ func TestRowsUnmarshalSuccess(t *testing.T) { }, }) + // Superfluous whitespace between tags, fields and timestamps. + f(`cpu_utilization,host=mnsbook-pro.local value=119.8 1607222595591`, &Rows{ + Rows: []Row{{ + Measurement: "cpu_utilization", + Tags: []Tag{{ + Key: "host", + Value: "mnsbook-pro.local", + }}, + Fields: []Field{{ + Key: "value", + Value: 119.8, + }}, + Timestamp: 1607222595591, + }}, + }) + f(`cpu_utilization,host=mnsbook-pro.local value=119.8 1607222595591`, &Rows{ + Rows: []Row{{ + Measurement: "cpu_utilization", + Tags: []Tag{{ + Key: "host", + Value: "mnsbook-pro.local", + }}, + Fields: []Field{{ + Key: "value", + Value: 119.8, + }}, + Timestamp: 1607222595591, + }}, + }) + f("x,y=z,g=p:\\ \\ 5432\\,\\ gp\\ mon\\ [lol]\\ con10\\ cmd5\\ SELECT f=1", &Rows{ Rows: []Row{{ Measurement: "x",