lib/storage: properly handle series selector matching multiple metric names plus a negative filter

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2238

This is a follow-up for 00cbb099b6
This commit is contained in:
Aliaksandr Valialkin 2022-02-24 12:10:44 +02:00
parent 1967b9c211
commit 02a922b53f
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
3 changed files with 8 additions and 18 deletions

View file

@ -33,6 +33,7 @@ This rule is equivalent to less clear traditional one:
* FEATURE: reduce memory usage for various caches under [high churn rate](https://docs.victoriametrics.com/FAQ.html#what-is-high-churn-rate). * FEATURE: reduce memory usage for various caches under [high churn rate](https://docs.victoriametrics.com/FAQ.html#what-is-high-churn-rate).
* BUGFIX: properly handle [series selector](https://prometheus.io/docs/prometheus/latest/querying/basics/#time-series-selectors) containing a filter for multiple metric names plus a negative filter. For example, `{__name__=~"foo|bar",job!="baz"}` . Previously VictoriaMetrics could return series with `foo` or `bar` names and with `job="baz"`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2238).
* BUGFIX: [vmgateway](https://docs.victoriametrics.com/vmgateway.html): properly parse JWT tokens if they are encoded with [URL-safe base64 encoding](https://datatracker.ietf.org/doc/html/rfc4648#section-5). * BUGFIX: [vmgateway](https://docs.victoriametrics.com/vmgateway.html): properly parse JWT tokens if they are encoded with [URL-safe base64 encoding](https://datatracker.ietf.org/doc/html/rfc4648#section-5).

View file

@ -50,7 +50,10 @@ func convertToCompositeTagFilters(tfs *TagFilters) []*TagFilters {
hasPositiveFilter = true hasPositiveFilter = true
} }
} }
if len(names) == 0 { // If tfs have no filters on __name__ or have no non-negative filters,
// then it is impossible to construct composite tag filter.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2238
if len(names) == 0 || !hasPositiveFilter {
atomic.AddUint64(&compositeFilterMissingConversions, 1) atomic.AddUint64(&compositeFilterMissingConversions, 1)
return []*TagFilters{tfs} return []*TagFilters{tfs}
} }
@ -62,7 +65,7 @@ func convertToCompositeTagFilters(tfs *TagFilters) []*TagFilters {
tfsNew := make([]tagFilter, 0, len(tfs.tfs)) tfsNew := make([]tagFilter, 0, len(tfs.tfs))
for _, tf := range tfs.tfs { for _, tf := range tfs.tfs {
if len(tf.key) == 0 { if len(tf.key) == 0 {
if !hasPositiveFilter || tf.isNegative { if tf.isNegative {
// Negative filters on metric name cannot be used for building composite filter, so leave them as is. // Negative filters on metric name cannot be used for building composite filter, so leave them as is.
tfsNew = append(tfsNew, tf) tfsNew = append(tfsNew, tf)
continue continue

View file

@ -193,7 +193,7 @@ func TestConvertToCompositeTagFilters(t *testing.T) {
IsRegexp: false, IsRegexp: false,
}, },
{ {
Key: []byte("\xfe\x03barfoo"), Key: []byte("foo"),
Value: []byte("abc"), Value: []byte("abc"),
IsNegative: true, IsNegative: true,
IsRegexp: false, IsRegexp: false,
@ -596,21 +596,7 @@ func TestConvertToCompositeTagFilters(t *testing.T) {
IsRegexp: true, IsRegexp: true,
}, },
{ {
Key: []byte("\xfe\x03barfoo"), Key: []byte("foo"),
Value: []byte("abc"),
IsNegative: true,
IsRegexp: false,
},
},
{
{
Key: nil,
Value: []byte("bar|foo"),
IsNegative: false,
IsRegexp: true,
},
{
Key: []byte("\xfe\x03foofoo"),
Value: []byte("abc"), Value: []byte("abc"),
IsNegative: true, IsNegative: true,
IsRegexp: false, IsRegexp: false,