151 lines
3.3 KiB
Go
151 lines
3.3 KiB
Go
|
// Licensed to Elasticsearch B.V. under one or more contributor
|
||
|
// license agreements. See the NOTICE file distributed with
|
||
|
// this work for additional information regarding copyright
|
||
|
// ownership. Elasticsearch B.V. licenses this file to you under
|
||
|
// the Apache License, Version 2.0 (the "License"); you may
|
||
|
// not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing,
|
||
|
// software distributed under the License is distributed on an
|
||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
|
// KIND, either express or implied. See the License for the
|
||
|
// specific language governing permissions and limitations
|
||
|
// under the License.
|
||
|
|
||
|
package conditions
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/elastic/beats/libbeat/common"
|
||
|
"github.com/elastic/beats/libbeat/logp"
|
||
|
)
|
||
|
|
||
|
type rangeValue struct {
|
||
|
gte *float64
|
||
|
gt *float64
|
||
|
lte *float64
|
||
|
lt *float64
|
||
|
}
|
||
|
|
||
|
// Range is a Condition type for checking against ranges.
|
||
|
type Range map[string]rangeValue
|
||
|
|
||
|
// NewRangeCondition builds a new Range from a map of ranges.
|
||
|
func NewRangeCondition(config map[string]interface{}) (c Range, err error) {
|
||
|
c = Range{}
|
||
|
|
||
|
updateRangeValue := func(key string, op string, value float64) error {
|
||
|
field := strings.TrimSuffix(key, "."+op)
|
||
|
_, exists := c[field]
|
||
|
if !exists {
|
||
|
c[field] = rangeValue{}
|
||
|
}
|
||
|
rv := c[field]
|
||
|
switch op {
|
||
|
case "gte":
|
||
|
rv.gte = &value
|
||
|
case "gt":
|
||
|
rv.gt = &value
|
||
|
case "lt":
|
||
|
rv.lt = &value
|
||
|
case "lte":
|
||
|
rv.lte = &value
|
||
|
default:
|
||
|
return fmt.Errorf("unexpected field %s", op)
|
||
|
}
|
||
|
c[field] = rv
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
for key, value := range config {
|
||
|
|
||
|
floatValue, err := ExtractFloat(value)
|
||
|
if err != nil {
|
||
|
return c, err
|
||
|
}
|
||
|
|
||
|
list := strings.Split(key, ".")
|
||
|
err = updateRangeValue(key, list[len(list)-1], floatValue)
|
||
|
if err != nil {
|
||
|
return c, err
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
// Check determines whether the given event matches this condition.
|
||
|
func (c Range) Check(event ValuesMap) bool {
|
||
|
checkValue := func(value float64, rangeValue rangeValue) bool {
|
||
|
if rangeValue.gte != nil {
|
||
|
if value < *rangeValue.gte {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
if rangeValue.gt != nil {
|
||
|
if value <= *rangeValue.gt {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
if rangeValue.lte != nil {
|
||
|
if value > *rangeValue.lte {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
if rangeValue.lt != nil {
|
||
|
if value >= *rangeValue.lt {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
for field, rangeValue := range c {
|
||
|
|
||
|
value, err := event.GetValue(field)
|
||
|
if err != nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch value.(type) {
|
||
|
case int, int8, int16, int32, int64:
|
||
|
intValue := reflect.ValueOf(value).Int()
|
||
|
|
||
|
if !checkValue(float64(intValue), rangeValue) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
case uint, uint8, uint16, uint32, uint64:
|
||
|
uintValue := reflect.ValueOf(value).Uint()
|
||
|
|
||
|
if !checkValue(float64(uintValue), rangeValue) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
case float64, float32, common.Float:
|
||
|
floatValue := reflect.ValueOf(value).Float()
|
||
|
|
||
|
if !checkValue(floatValue, rangeValue) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
logp.Warn("unexpected type %T in range condition. ", value)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func (c Range) String() string {
|
||
|
return fmt.Sprintf("range: %v", map[string]rangeValue(c))
|
||
|
}
|