-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rework MapStr.walkMap to support dotted keys (#6406)
Currently if a dotted key is passed to walkmap it is split up in it's part and the map is traversed for each part. In case an event has a dotted key inside walkMap does not return the expected value. For the Event `{"a.b": 1}` the method `GetValue("a.b")` has previously returned `ErrKeyNotExists` but now returns 0. With this change all processors which rely on Get/Put functionalities of MapStr can now also work with events containing dotted keys. **Changes** * The walkMap function was rewritten to a recursive function. This made adding the new functionality easier. * Add tests for GetValue to make possible usages more clear * Add Benchmark tests for walkMap use cases **Limitations** When using `walkMap` with a Key, either the full key has to be dotted or the last part. `GetValue("a.b.c")` on an event `{"a.b":{"c":17}}` does not work as only the first part of the key or the full key are checked against the map. Benchmark old to new walkMap: ``` go test -bench=BenchmarkWalkMap -run=BenchmarkWalkMap ``` Recursive ``` BenchmarkWalkMap/Get-4 1000000 1334 ns/op 432 B/op 7 allocs/op BenchmarkWalkMap/Put-4 1000000 1273 ns/op 1120 B/op 10 allocs/op BenchmarkWalkMap/HasKey-4 2000000 690 ns/op 160 B/op 5 allocs/op BenchmarkWalkMap/HasKeyFirst-4 50000000 28.8 ns/op 0 B/op 0 allocs/op BenchmarkWalkMap/Delete-4 1000000 1431 ns/op 1120 B/op 10 allocs/op ``` Iterative ``` BenchmarkWalkMap/Get-4 500000 2577 ns/op 824 B/op 13 allocs/op BenchmarkWalkMap/Put-4 1000000 1052 ns/op 1072 B/op 8 allocs/op BenchmarkWalkMap/HasKey-4 5000000 381 ns/op 96 B/op 2 allocs/op BenchmarkWalkMap/HasKeyFirst-4 20000000 89.6 ns/op 16 B/op 1 allocs/op BenchmarkWalkMap/Delete-4 1000000 1083 ns/op 1072 B/op 8 allocs/op ``` The benchmark show a difference in the code before and after. The `GetValue` function has become quite a bit more efficient. The `HasKey` is now less efficient. I still need to investigate in detail where the differences come from but the assumption is it comes from the additional functionality. This change was initially triggered by #5916 but is split out into a separate PR because it has usage in multiple places.
- Loading branch information
1 parent
1d7e325
commit a4bddd8
Showing
3 changed files
with
262 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package actions | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
"github.com/elastic/beats/libbeat/beat" | ||
"github.com/elastic/beats/libbeat/common" | ||
) | ||
|
||
func TestIncludeFields(t *testing.T) { | ||
|
||
var tests = []struct { | ||
Fields []string | ||
Input common.MapStr | ||
Output common.MapStr | ||
}{ | ||
{ | ||
Fields: []string{"test"}, | ||
Input: common.MapStr{ | ||
"hello": "world", | ||
"test": 17, | ||
}, | ||
Output: common.MapStr{ | ||
"test": 17, | ||
}, | ||
}, | ||
{ | ||
Fields: []string{"test", "a.b"}, | ||
Input: common.MapStr{ | ||
"a.b": "b", | ||
"a.c": "c", | ||
"test": 17, | ||
}, | ||
Output: common.MapStr{ | ||
"test": 17, | ||
"a": common.MapStr{ | ||
"b": "b", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
p := includeFields{ | ||
Fields: test.Fields, | ||
} | ||
|
||
event := &beat.Event{ | ||
Fields: test.Input, | ||
} | ||
|
||
newEvent, err := p.Run(event) | ||
assert.NoError(t, err) | ||
|
||
assert.Equal(t, test.Output, newEvent.Fields) | ||
} | ||
} |