From 4b0e361f1e77e16f2680a3aa3c453204ee9f114b Mon Sep 17 00:00:00 2001 From: Roman Khavronenko Date: Wed, 9 Nov 2022 14:32:47 +0100 Subject: [PATCH] protoparser/opentsdb: allow lines without tags (#3303) According to http://opentsdb.net/docs/build/html/api_telnet/put.html "At least one tag pair must be present". However, in VictoriaMetrics datamodel tags aren't required. This could be confusing for users. Allowing accept lines without tags seems to do no harm. https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3290 Signed-off-by: hagen1778 Signed-off-by: hagen1778 --- lib/protoparser/opentsdb/parser.go | 18 +++++++++++------- lib/protoparser/opentsdb/parser_test.go | 11 ++++++++--- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/lib/protoparser/opentsdb/parser.go b/lib/protoparser/opentsdb/parser.go index a63ccda30..7f8a43f8e 100644 --- a/lib/protoparser/opentsdb/parser.go +++ b/lib/protoparser/opentsdb/parser.go @@ -84,20 +84,24 @@ func (r *Row) unmarshal(s string, tagsPool []Tag) ([]Tag, error) { tail = trimLeadingSpaces(tail[n+1:]) n = strings.IndexByte(tail, ' ') if n < 0 { - return tagsPool, fmt.Errorf("cannot find whitespace between value and the first tag in %q", s) + // see https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3290 + n = len(tail) } v, err := fastfloat.Parse(tail[:n]) if err != nil { return tagsPool, fmt.Errorf("cannot parse value from %q: %w", tail[:n], err) } r.Value = v - tagsStart := len(tagsPool) - tagsPool, err = unmarshalTags(tagsPool, tail[n+1:]) - if err != nil { - return tagsPool, fmt.Errorf("cannot unmarshal tags in %q: %w", s, err) + if len(tail) > n { + tagsStart := len(tagsPool) + tagsPool, err = unmarshalTags(tagsPool, tail[n+1:]) + if err != nil { + return tagsPool, fmt.Errorf("cannot unmarshal tags in %q: %w", s, err) + } + tags := tagsPool[tagsStart:] + r.Tags = tags[:len(tags):len(tags)] } - tags := tagsPool[tagsStart:] - r.Tags = tags[:len(tags):len(tags)] + return tagsPool, nil } diff --git a/lib/protoparser/opentsdb/parser_test.go b/lib/protoparser/opentsdb/parser_test.go index d2e739f90..7e7c435c9 100644 --- a/lib/protoparser/opentsdb/parser_test.go +++ b/lib/protoparser/opentsdb/parser_test.go @@ -37,9 +37,6 @@ func TestRowsUnmarshalFailure(t *testing.T) { f("put aaa timestamp") f("put foobar 3df4 -123456 a=b") - // Missing first tag - f("put aaa 123 43") - // Invalid value f("put aaa 123 invalid-value") f("put foobar 789 -123foo456 a=b") @@ -104,6 +101,14 @@ func TestRowsUnmarshalSuccess(t *testing.T) { }, }}, }) + // No tags + f("put foobar 789 -123.456", &Rows{ + Rows: []Row{{ + Metric: "foobar", + Value: -123.456, + Timestamp: 789, + }}, + }) // Fractional timestamp that is supported by Akumuli. f("put foobar 789.4 -123.456 a=b", &Rows{ Rows: []Row{{