diff --git a/src/metrics/filters/filter.go b/src/metrics/filters/filter.go index a57ddd08a3..69ecfe80b3 100644 --- a/src/metrics/filters/filter.go +++ b/src/metrics/filters/filter.go @@ -585,14 +585,43 @@ func (f *multiCharSequenceFilter) matches(val []byte) ([]byte, bool) { return nil, false } + var matchIndex int + var bestPattern []byte for _, pattern := range f.patterns { - if f.backwards && bytes.HasSuffix(val, pattern) { - return val[:len(val)-len(pattern)], true + if len(pattern) > len(val) { + continue } - if !f.backwards && bytes.HasPrefix(val, pattern) { - return val[len(pattern):], true + if f.backwards { + if bytes.HasSuffix(val, pattern) { + if len(pattern) > len(bestPattern) { + bestPattern = pattern + matchIndex = len(val) - len(pattern) + // No need to continue searching through remaining patterns if a complete match is found + if len(bestPattern) == len(val) { + break + } + } + } + } else { + if bytes.HasPrefix(val, pattern) { + if len(pattern) > len(bestPattern) { + bestPattern = pattern + matchIndex = len(pattern) + // No need to continue searching through remaining patterns if a complete match is found + if len(bestPattern) == len(val) { + break + } + } + } + } + } + + if bestPattern != nil { + if f.backwards { + return val[:matchIndex], true } + return val[matchIndex:], true } return nil, false diff --git a/src/metrics/filters/filter_benchmark_test.go b/src/metrics/filters/filter_benchmark_test.go index aa2dc01271..c79dfa75ef 100644 --- a/src/metrics/filters/filter_benchmark_test.go +++ b/src/metrics/filters/filter_benchmark_test.go @@ -125,6 +125,16 @@ func BenchmarkRangeFilterRangeMatchNegation(b *testing.B) { benchRangeFilterRange(b, []byte("!a-z"), []byte("p"), false) } +func BenchmarkMultiRangeFilterPrefixCollision(b *testing.B) { + benchMultiRangeFilter(b, []byte("test_1,test_1_suffix,extra_unused_pattern"), + false, [][]byte{[]byte("test_1"), []byte("test_1_suffix")}) +} + +func BenchmarkMultiRangeFilterSuffixCollision(b *testing.B) { + benchMultiRangeFilter(b, []byte("test_1,prefix_test_1,extra_unused_pattern"), + true, [][]byte{[]byte("test_1"), []byte("prefix_test_1")}) +} + func BenchmarkMultiRangeFilterTwo(b *testing.B) { benchMultiRangeFilter(b, []byte("test_1,test_2"), false, [][]byte{[]byte("test_1"), []byte("fake_1")}) } diff --git a/src/metrics/filters/filter_test.go b/src/metrics/filters/filter_test.go index 0cdc75595b..e7216cbf77 100644 --- a/src/metrics/filters/filter_test.go +++ b/src/metrics/filters/filter_test.go @@ -349,6 +349,16 @@ func TestMultiCharSequenceFilter(t *testing.T) { validateLookup(t, f, "12test", true, "12") validateLookup(t, f, "12test2", true, "12") validateLookup(t, f, "123book", true, "123") + + f, err = newMultiCharSequenceFilter([]byte("test,test_post,extra_unused_filter"), false) + require.NoError(t, err) + validateLookup(t, f, "test", true, "") + validateLookup(t, f, "test_post", true, "") + + f, err = newMultiCharSequenceFilter([]byte("test,pre_test,extra_unused_filter"), true) + require.NoError(t, err) + validateLookup(t, f, "test", true, "") + validateLookup(t, f, "pre_test", true, "") } func validateLookup(t *testing.T, f chainFilter, val string, expectedMatch bool, expectedRemainder string) {