Skip to content

Commit

Permalink
Advanced match_fields (#537)
Browse files Browse the repository at this point in the history
* Add do_if checker and update docs
  • Loading branch information
HeadHunter483 authored Nov 27, 2023
1 parent 54cf379 commit 86db123
Show file tree
Hide file tree
Showing 13 changed files with 2,337 additions and 3 deletions.
6 changes: 6 additions & 0 deletions Insanedocfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ extractors:
config-params: '"config-params" /json:\"([a-z_]+)\"/ #2 /default:\"([^"]+)\"/ /(required):\"true\"/ /options:\"([^"]+)\"/'
fn-list: '"fn-list" #4 /Plugin\)\s(.+)\s{/'
match-modes: '"match-modes" /MatchMode(.*),/ /\"(.*)\"/'
do-if-node: '"do-if-node" /DoIfNode(\w+)\s/'
do-if-field-op: '"do-if-field-op" /doIfField(\w+)OpBytes\s/'
do-if-logical-op: '"do-if-logical-op" /doIfLogical(\w+)Bytes\s/'
decorators:
config-params: '_ _ /*`%s`* / /*`default=%s`* / /*`%s`* / /*`options=%s`* /'
fn-list: '_ _ /`%s`/'
match-modes: '_ /%s/ /`match_mode: %s`/'
do-if-node: '_ /%s/'
do-if-field-op: '_ /%s/'
do-if-logical-op: '_ /%s/'
templates:
- template: docs/*.idoc.md
files: ["../pipeline/*.go"]
Expand Down
4 changes: 4 additions & 0 deletions _sidebar.idoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
- Output
@global-contents-table-plugin-output|links-list

- **Pipeline**
- [Match modes](pipeline/README.md#match-modes)
- [Experimental: Do If rules](pipeline/README.md#experimental-do-if-rules)

- **Other**
- [Contributing](/docs/contributing.md)
- [License](/docs/license.md)
4 changes: 4 additions & 0 deletions _sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
- [stdout](plugin/output/stdout/README.md)


- **Pipeline**
- [Match modes](pipeline/README.md#match-modes)
- [Experimental: Do If rules](pipeline/README.md#experimental-do-if-rules)

- **Other**
- [Contributing](/docs/contributing.md)
- [License](/docs/license.md)
6 changes: 6 additions & 0 deletions fd/file.d.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ func (f *FileD) setupAction(p *pipeline.Pipeline, index int, t string, actionJSO
logger.Infof("creating action with type %q for pipeline %q", t, p.Name)
info := f.plugins.GetActionByType(t)

doIfChecker, err := extractDoIfChecker(actionJSON.Get("do_if"))
if err != nil {
logger.Fatalf(`failed to extract "do_if" conditions for action %d/%s in pipeline %q: %s`, index, t, p.Name, err.Error())
}

matchMode := extractMatchMode(actionJSON)
if matchMode == pipeline.MatchModeUnknown {
logger.Fatalf("unknown match_mode value for action %d/%s in pipeline %q", index, t, p.Name)
Expand Down Expand Up @@ -191,6 +196,7 @@ func (f *FileD) setupAction(p *pipeline.Pipeline, index int, t string, actionJSO
MetricLabels: metricLabels,
MetricSkipStatus: skipStatus,
MatchInvert: matchInvert,
DoIfChecker: doIfChecker,
})
}

Expand Down
91 changes: 91 additions & 0 deletions fd/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fd
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"time"

Expand Down Expand Up @@ -180,6 +181,95 @@ func extractMetrics(actionJSON *simplejson.Json) (string, []string, bool) {
return metricName, metricLabels, skipStatus
}

var (
doIfLogicalOpNodes = map[string]struct{}{
"and": struct{}{},
"not": struct{}{},
"or": struct{}{},
}
doIfFieldOpNodes = map[string]struct{}{
"equal": struct{}{},
"contains": struct{}{},
"prefix": struct{}{},
"suffix": struct{}{},
"regex": struct{}{},
}
)

func extractFieldOpNode(opName string, jsonNode *simplejson.Json) (pipeline.DoIfNode, error) {
var result pipeline.DoIfNode
var err error
fieldPath := jsonNode.Get("field").MustString()
caseSensitiveNode, has := jsonNode.CheckGet("case_sensitive")
caseSensitive := true
if has {
caseSensitive = caseSensitiveNode.MustBool()
}
values := jsonNode.Get("values")
vals := make([][]byte, 0)
for i := range values.MustArray() {
curValue := values.GetIndex(i).Interface()
if curValue == nil {
vals = append(vals, nil)
} else {
vals = append(vals, []byte(curValue.(string)))
}
}
result, err = pipeline.NewFieldOpNode(opName, fieldPath, caseSensitive, vals)
if err != nil {
return nil, fmt.Errorf("failed to init field op: %w", err)
}

return result, nil
}

func extractLogicalOpNode(opName string, jsonNode *simplejson.Json) (pipeline.DoIfNode, error) {
var result, operand pipeline.DoIfNode
var err error
operands := jsonNode.Get("operands")
operandsList := make([]pipeline.DoIfNode, 0)
for i := range operands.MustArray() {
opNode := operands.GetIndex(i)
operand, err = extractDoIfNode(opNode)
if err != nil {
return nil, fmt.Errorf("failed to extract operand node for logical op %q", opName)
}
operandsList = append(operandsList, operand)
}
result, err = pipeline.NewLogicalNode(opName, operandsList)
if err != nil {
return nil, fmt.Errorf("failed to init logical node: %w", err)
}
return result, nil
}

func extractDoIfNode(jsonNode *simplejson.Json) (pipeline.DoIfNode, error) {
opNameNode, has := jsonNode.CheckGet("op")
if !has {
return nil, errors.New(`"op" field not found`)
}
opName := opNameNode.MustString()
if _, has := doIfLogicalOpNodes[opName]; has {
return extractLogicalOpNode(opName, jsonNode)
} else if _, has := doIfFieldOpNodes[opName]; has {
return extractFieldOpNode(opName, jsonNode)
}
return nil, fmt.Errorf("unknown op %q", opName)
}

func extractDoIfChecker(actionJSON *simplejson.Json) (*pipeline.DoIfChecker, error) {
if actionJSON.MustMap() == nil {
return nil, nil
}

root, err := extractDoIfNode(actionJSON)
if err != nil {
return nil, fmt.Errorf("failed to extract nodes: %w", err)
}
result := pipeline.NewDoIfChecker(root)
return result, nil
}

func makeActionJSON(actionJSON *simplejson.Json) []byte {
actionJSON.Del("type")
actionJSON.Del("match_fields")
Expand All @@ -188,6 +278,7 @@ func makeActionJSON(actionJSON *simplejson.Json) []byte {
actionJSON.Del("metric_labels")
actionJSON.Del("metric_skip_status")
actionJSON.Del("match_invert")
actionJSON.Del("do_if")
configJson, err := actionJSON.Encode()
if err != nil {
logger.Panicf("can't create action json")
Expand Down
Loading

0 comments on commit 86db123

Please sign in to comment.