Fix template pattern partial wildcard matching (#6135)
This commit is contained in:
parent
5c9923a20a
commit
77b1a43539
|
@ -3,6 +3,7 @@ package templating
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -20,3 +21,57 @@ func TestEngineAlternateSeparator(t *testing.T) {
|
|||
}, tags)
|
||||
require.Equal(t, "", field)
|
||||
}
|
||||
|
||||
func TestEngineWithWildcardTemplate(t *testing.T) {
|
||||
var (
|
||||
defaultTmpl, err = NewDefaultTemplateWithPattern("measurement*")
|
||||
templates = []string{
|
||||
"taskmanagerTask.alarm-detector.Assign.alarmDefinitionId metricsType.process.nodeId.x.alarmDefinitionId.measurement.field rule=1",
|
||||
"taskmanagerTask.*.*.*.* metricsType.process.nodeId.measurement rule=2",
|
||||
}
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
engine, err := NewEngine(".", defaultTmpl, templates)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, testCase := range []struct {
|
||||
line string
|
||||
measurement string
|
||||
field string
|
||||
tags map[string]string
|
||||
}{
|
||||
{
|
||||
line: "taskmanagerTask.alarm-detector.Assign.alarmDefinitionId.timeout_errors.duration.p75",
|
||||
measurement: "duration",
|
||||
field: "p75",
|
||||
tags: map[string]string{
|
||||
"metricsType": "taskmanagerTask",
|
||||
"process": "alarm-detector",
|
||||
"nodeId": "Assign",
|
||||
"x": "alarmDefinitionId",
|
||||
"alarmDefinitionId": "timeout_errors",
|
||||
"rule": "1",
|
||||
},
|
||||
},
|
||||
{
|
||||
line: "taskmanagerTask.alarm-detector.Assign.numRecordsInPerSecond.m5_rate",
|
||||
measurement: "numRecordsInPerSecond",
|
||||
tags: map[string]string{
|
||||
"metricsType": "taskmanagerTask",
|
||||
"process": "alarm-detector",
|
||||
"nodeId": "Assign",
|
||||
"rule": "2",
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(testCase.line, func(t *testing.T) {
|
||||
measurement, tags, field, err := engine.Apply(testCase.line)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, testCase.measurement, measurement)
|
||||
assert.Equal(t, testCase.field, field)
|
||||
assert.Equal(t, testCase.tags, tags)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,32 +55,44 @@ func (n *node) search(line string) *Template {
|
|||
|
||||
// recursiveSearch performs the actual recursive search
|
||||
func (n *node) recursiveSearch(lineParts []string) *Template {
|
||||
// Nothing to search
|
||||
// nothing to search
|
||||
if len(lineParts) == 0 || len(n.children) == 0 {
|
||||
return n.template
|
||||
}
|
||||
|
||||
// If last element is a wildcard, don't include it in this search since it's sorted
|
||||
// to the end but lexicographically it would not always be and sort.Search assumes
|
||||
// the slice is sorted.
|
||||
length := len(n.children)
|
||||
if n.children[length-1].value == "*" {
|
||||
var (
|
||||
hasWildcard bool
|
||||
length = len(n.children)
|
||||
)
|
||||
|
||||
// exclude last child from search if it is a wildcard. sort.Search expects
|
||||
// a lexicographically sorted set of children and we have artificially sorted
|
||||
// wildcards to the end of the child set
|
||||
// wildcards will be searched seperately if no exact match is found
|
||||
if hasWildcard = n.children[length-1].value == "*"; hasWildcard {
|
||||
length--
|
||||
}
|
||||
|
||||
// Find the index of child with an exact match
|
||||
i := sort.Search(length, func(i int) bool {
|
||||
return n.children[i].value >= lineParts[0]
|
||||
})
|
||||
|
||||
// Found an exact match, so search that child sub-tree
|
||||
if i < len(n.children) && n.children[i].value == lineParts[0] {
|
||||
return n.children[i].recursiveSearch(lineParts[1:])
|
||||
// given an exact match is found within children set
|
||||
if i < length && n.children[i].value == lineParts[0] {
|
||||
// decend into the matching node
|
||||
if tmpl := n.children[i].recursiveSearch(lineParts[1:]); tmpl != nil {
|
||||
// given a template is found return it
|
||||
return tmpl
|
||||
}
|
||||
}
|
||||
// Not an exact match, see if we have a wildcard child to search
|
||||
if n.children[len(n.children)-1].value == "*" {
|
||||
return n.children[len(n.children)-1].recursiveSearch(lineParts[1:])
|
||||
|
||||
// given no template is found and the last child is a wildcard
|
||||
if hasWildcard {
|
||||
// also search the wildcard child node
|
||||
return n.children[length].recursiveSearch(lineParts[1:])
|
||||
}
|
||||
|
||||
// fallback to returning template at this node
|
||||
return n.template
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue