Skip to content

Commit

Permalink
Improve equals check (#22778)
Browse files Browse the repository at this point in the history
  • Loading branch information
newly12 authored Dec 7, 2020
1 parent 37ecba1 commit 5f3d8ac
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 37 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Add support for ephemeral containers in kubernetes autodiscover and `add_kubernetes_metadata`. {pull}22389[22389] {pull}22439[22439]
- Added support for wildcard fields and keyword fallback in beats setup commands. {pull}22521[22521]
- Fix polling node when it is not ready and monitor by hostname {pull}22666[22666]
- Improve equals check. {pull}22778[22778]

*Auditbeat*

Expand Down
77 changes: 40 additions & 37 deletions libbeat/conditions/equals.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,64 @@ import (
"github.com/elastic/beats/v7/libbeat/logp"
)

type equalsValue struct {
Int uint64
Str string
Bool bool
}

// Equals is a Condition for testing string equality.
type Equals map[string]equalsValue

type equalsValue func(interface{}) bool

func equalsIntValue(i uint64) equalsValue {
logger := logp.L().Named(logName)
return func(value interface{}) bool {
if sValue, err := ExtractInt(value); err == nil {
return sValue == i
}
logger.Warnf("expected int but got type %T in equals condition.", value)
return false
}
}

func equalsStringValue(s string) equalsValue {
logger := logp.L().Named(logName)
return func(value interface{}) bool {
if sValue, err := ExtractString(value); err == nil {
return sValue == s
}
logger.Warnf("expected string but got type %T in equals condition.", value)
return false
}
}

func equalsBoolValue(b bool) equalsValue {
logger := logp.L().Named(logName)
return func(value interface{}) bool {
if sValue, err := ExtractBool(value); err == nil {
return sValue == b
}
logger.Warnf("expected bool but got type %T in equals condition.", value)
return false
}
}

// NewEqualsCondition builds a new Equals using the given configuration of string equality checks.
func NewEqualsCondition(fields map[string]interface{}) (c Equals, err error) {
c = Equals{}

for field, value := range fields {
uintValue, err := ExtractInt(value)
if err == nil {
c[field] = equalsValue{Int: uintValue}
c[field] = equalsIntValue(uintValue)
continue
}

sValue, err := ExtractString(value)
if err == nil {
c[field] = equalsValue{Str: sValue}
c[field] = equalsStringValue(sValue)
continue
}

bValue, err := ExtractBool(value)
if err == nil {
c[field] = equalsValue{Bool: bValue}
c[field] = equalsBoolValue(bValue)
continue
}

Expand All @@ -70,35 +99,9 @@ func (c Equals) Check(event ValuesMap) bool {
return false
}

intValue, err := ExtractInt(value)
if err == nil {
if intValue != equalValue.Int {
return false
}

continue
}

sValue, err := ExtractString(value)
if err == nil {
if sValue != equalValue.Str {
return false
}

continue
}

bValue, err := ExtractBool(value)
if err == nil {
if bValue != equalValue.Bool {
return false
}

continue
if !equalValue(value) {
return false
}

logp.L().Named(logName).Warnf("unexpected type %T in equals condition as it accepts only integers, strings, or booleans.", value)
return false
}

return true
Expand Down
43 changes: 43 additions & 0 deletions libbeat/conditions/equals_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package conditions

import (
"runtime"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -58,3 +59,45 @@ func TestEqualsMultiFieldAndTypePositiveMatch(t *testing.T) {
}},
})
}

func BenchmarkEquals(b *testing.B) {
cases := map[string]map[string]interface{}{
"1 condition": {
"type": "process",
},
"3 conditions": {
"type": "process",
"proc.pid": 305,
"final": false,
},
"5 conditions": {
"type": "process",
"proc.pid": 305,
"final": false,
"tags": "error path",
"non-existing-key": "",
},
"7 conditions": {
"type": "process",
"proc.pid": 305,
"final": false,
"tags": "error path",
"non-existing-key": "",
"proc.cmdline": "/usr/libexec/secd",
"proc.cpu.start_time": 10,
},
}

for name, config := range cases {
b.Run(name, func(b *testing.B) {
e, err := NewEqualsCondition(config)
assert.NoError(b, err)

runtime.GC()
b.ResetTimer()
for i := 0; i < b.N; i++ {
e.Check(secdTestEvent)
}
})
}
}

0 comments on commit 5f3d8ac

Please sign in to comment.