From 18d7adf731811eb673f4e67a8c2764ca13f16d6c Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Sun, 29 Aug 2021 11:49:21 +0300 Subject: [PATCH] lib/protoparser/opentsdb: follow-up after 8ee75ca45ac6f71e92fb2ebce2862ea4b84a90a3 --- docs/CHANGELOG.md | 1 + lib/protoparser/opentsdb/parser.go | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 59daf63d85..0cbe2e621e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -21,6 +21,7 @@ sort: 15 * BUGFIX: improve the detection of the needed free space for background merge operation. This should prevent from possible out of disk space crashes during big merges. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1560). * BUGFIX: vmauth: remove trailing slash from the full url before requesting it from the backend. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1554). * BUGFIX: [vmbackupmanager](https://docs.victoriametrics.com/vmbackupmanager.html): fix timeout error when snapshot takes longer than 10 seconds. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1571). +* BUGFIX: properly parse OpenTSDB `put` messages with multiple spaces between message elements. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1574). Thanks to @envzhu for the fix. ## [v1.64.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.64.1) diff --git a/lib/protoparser/opentsdb/parser.go b/lib/protoparser/opentsdb/parser.go index 54d0d9da9d..a63ccda30b 100644 --- a/lib/protoparser/opentsdb/parser.go +++ b/lib/protoparser/opentsdb/parser.go @@ -57,11 +57,12 @@ func (r *Row) reset() { func (r *Row) unmarshal(s string, tagsPool []Tag) ([]Tag, error) { r.reset() - s = strings.TrimSpace(s) + s = trimLeadingSpaces(s) if !strings.HasPrefix(s, "put ") { return tagsPool, fmt.Errorf("missing `put ` prefix in %q", s) } - s = strings.TrimSpace(s[len("put "):]) + s = s[len("put "):] + s = trimLeadingSpaces(s) n := strings.IndexByte(s, ' ') if n < 0 { return tagsPool, fmt.Errorf("cannot find whitespace between metric and timestamp in %q", s) @@ -70,7 +71,7 @@ func (r *Row) unmarshal(s string, tagsPool []Tag) ([]Tag, error) { if len(r.Metric) == 0 { return tagsPool, fmt.Errorf("metric cannot be empty") } - tail := strings.TrimSpace(s[n+1:]) + tail := trimLeadingSpaces(s[n+1:]) n = strings.IndexByte(tail, ' ') if n < 0 { return tagsPool, fmt.Errorf("cannot find whitespace between timestamp and value in %q", s) @@ -80,7 +81,7 @@ func (r *Row) unmarshal(s string, tagsPool []Tag) ([]Tag, error) { return tagsPool, fmt.Errorf("cannot parse timestamp from %q: %w", tail[:n], err) } r.Timestamp = int64(timestamp) - tail = strings.TrimSpace(tail[n+1:]) + 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) @@ -142,6 +143,10 @@ var invalidLines = metrics.NewCounter(`vm_rows_invalid_total{type="opentsdb"}`) func unmarshalTags(dst []Tag, s string) ([]Tag, error) { for { + s = trimLeadingSpaces(s) + if len(s) == 0 { + return dst, nil + } if cap(dst) > len(dst) { dst = dst[:len(dst)+1] } else { @@ -149,7 +154,6 @@ func unmarshalTags(dst []Tag, s string) ([]Tag, error) { } tag := &dst[len(dst)-1] - s = strings.TrimSpace(s) n := strings.IndexByte(s, ' ') if n < 0 { // The last tag found @@ -194,3 +198,10 @@ func (t *Tag) unmarshal(s string) error { t.Value = s[n+1:] return nil } + +func trimLeadingSpaces(s string) string { + for len(s) > 0 && s[0] == ' ' { + s = s[1:] + } + return s +}