diff --git a/README.md b/README.md index e51ff50a2..2d4862af7 100644 --- a/README.md +++ b/README.md @@ -223,7 +223,7 @@ VictoriaMetrics maps Influx data using the following rules: unless `db` tag exists in the Influx line. * Field names are mapped to time series names prefixed with `{measurement}{separator}` value, where `{separator}` equals to `_` by default. It can be changed with `-influxMeasurementFieldSeparator` command-line flag. - See also `-influxSkipSingleField` command-line flag. + See also `-influxSkipSingleField` command-line flag. If `{measurement}` is empty, then time series names correspond to field names. * Field values are mapped to time series values. * Tags are mapped to Prometheus labels as-is. @@ -251,7 +251,7 @@ An arbitrary number of lines delimited by '\n' may be sent in a single request. After that the data may be read via [/api/v1/export](#how-to-export-time-series) endpoint: ``` -curl -G 'http://localhost:8428/api/v1/export' -d 'match={__name__!=""}' +curl -G 'http://localhost:8428/api/v1/export' -d 'match={__name__=~"measurement_.*"}' ``` The `/api/v1/export` endpoint should return the following response: @@ -289,7 +289,7 @@ An arbitrary number of lines delimited by `\n` may be sent in one go. After that the data may be read via [/api/v1/export](#how-to-export-time-series) endpoint: ``` -curl -G 'http://localhost:8428/api/v1/export' -d 'match={__name__!=""}' +curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz' ``` The `/api/v1/export` endpoint should return the following response: @@ -334,7 +334,7 @@ An arbitrary number of lines delimited by `\n` may be sent in one go. After that the data may be read via [/api/v1/export](#how-to-export-time-series) endpoint: ``` -curl -G 'http://localhost:8428/api/v1/export' -d 'match={__name__!=""}' +curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz' ``` The `/api/v1/export` endpoint should return the following response: diff --git a/app/vminsert/influx/parser.go b/app/vminsert/influx/parser.go index ae586adad..df1709fe9 100644 --- a/app/vminsert/influx/parser.go +++ b/app/vminsert/influx/parser.go @@ -85,9 +85,7 @@ func (r *Row) unmarshal(s string, tagsPool []Tag, fieldsPool []Field, noEscapeCh measurementTags = measurementTags[:n] } r.Measurement = unescapeTagValue(measurementTags, noEscapeChars) - if len(r.Measurement) == 0 { - return tagsPool, fieldsPool, fmt.Errorf("measurement cannot be empty. measurementTags=%q", s) - } + // Allow empty r.Measurement. In this case metric name is constructed directly from field keys. // Parse fields fieldsStart := len(fieldsPool) diff --git a/app/vminsert/influx/parser_test.go b/app/vminsert/influx/parser_test.go index 207ea35c9..cf9180a66 100644 --- a/app/vminsert/influx/parser_test.go +++ b/app/vminsert/influx/parser_test.go @@ -86,9 +86,6 @@ func TestRowsUnmarshalFailure(t *testing.T) { } } - // Missing measurement - f(",foo=bar baz=123") - // No fields f("foo") f("foo,bar=baz 1234") @@ -147,6 +144,30 @@ func TestRowsUnmarshalSuccess(t *testing.T) { f("#foobar baz", &Rows{}) f("#foobar baz\n#sss", &Rows{}) + // Missing measurement + f(" baz=123", &Rows{ + Rows: []Row{{ + Measurement: "", + Fields: []Field{{ + Key: "baz", + Value: 123, + }}, + }}, + }) + f(",foo=bar baz=123", &Rows{ + Rows: []Row{{ + Measurement: "", + Tags: []Tag{{ + Key: "foo", + Value: "bar", + }}, + Fields: []Field{{ + Key: "baz", + Value: 123, + }}, + }}, + }) + // Minimal line without tags and timestamp f("foo bar=123", &Rows{ Rows: []Row{{ diff --git a/app/vminsert/influx/request_handler.go b/app/vminsert/influx/request_handler.go index e0bfbe85d..3e60ea35b 100644 --- a/app/vminsert/influx/request_handler.go +++ b/app/vminsert/influx/request_handler.go @@ -104,7 +104,7 @@ func (ctx *pushCtx) InsertRows(db string) error { ctx.metricNameBuf = storage.MarshalMetricNameRaw(ctx.metricNameBuf[:0], ic.Labels) ctx.metricGroupBuf = append(ctx.metricGroupBuf[:0], r.Measurement...) skipFieldKey := len(r.Fields) == 1 && *skipSingleField - if !skipFieldKey { + if len(ctx.metricGroupBuf) > 0 && !skipFieldKey { ctx.metricGroupBuf = append(ctx.metricGroupBuf, *measurementFieldSeparator...) } metricGroupPrefixLen := len(ctx.metricGroupBuf) diff --git a/docs/Single-server-VictoriaMetrics.md b/docs/Single-server-VictoriaMetrics.md index 564d0a683..5419ef7db 100644 --- a/docs/Single-server-VictoriaMetrics.md +++ b/docs/Single-server-VictoriaMetrics.md @@ -214,7 +214,7 @@ VictoriaMetrics maps Influx data using the following rules: unless `db` tag exists in the Influx line. * Field names are mapped to time series names prefixed with `{measurement}{separator}` value, where `{separator}` equals to `_` by default. It can be changed with `-influxMeasurementFieldSeparator` command-line flag. - See also `-influxSkipSingleField` command-line flag. + See also `-influxSkipSingleField` command-line flag. If `{measurement}` is empty, then time series names correspond to field names. * Field values are mapped to time series values. * Tags are mapped to Prometheus labels as-is. @@ -242,7 +242,7 @@ An arbitrary number of lines delimited by '\n' may be sent in a single request. After that the data may be read via [/api/v1/export](#how-to-export-time-series) endpoint: ``` -curl -G 'http://localhost:8428/api/v1/export' -d 'match={__name__!=""}' +curl -G 'http://localhost:8428/api/v1/export' -d 'match={__name__=~"measurement_.*"}' ``` The `/api/v1/export` endpoint should return the following response: @@ -280,7 +280,7 @@ An arbitrary number of lines delimited by `\n` may be sent in one go. After that the data may be read via [/api/v1/export](#how-to-export-time-series) endpoint: ``` -curl -G 'http://localhost:8428/api/v1/export' -d 'match={__name__!=""}' +curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz' ``` The `/api/v1/export` endpoint should return the following response: @@ -325,7 +325,7 @@ An arbitrary number of lines delimited by `\n` may be sent in one go. After that the data may be read via [/api/v1/export](#how-to-export-time-series) endpoint: ``` -curl -G 'http://localhost:8428/api/v1/export' -d 'match={__name__!=""}' +curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz' ``` The `/api/v1/export` endpoint should return the following response: