From 04b0e4e7bf96b2ba432b8ed1f0589a79fb0a843f 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{{