diff --git a/.golangci.yml b/.golangci.yml index c044903d0f2..544cebbac6a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -3,7 +3,7 @@ linters-settings: cyclop: # lower this after refactoring - max-complexity: 48 + max-complexity: 45 gci: sections: @@ -18,11 +18,11 @@ linters-settings: gocognit: # lower this after refactoring - min-complexity: 145 + min-complexity: 128 gocyclo: # lower this after refactoring - min-complexity: 48 + min-complexity: 45 funlen: # Checks the number of lines in a function. @@ -55,7 +55,7 @@ linters-settings: nestif: # lower this after refactoring - min-complexity: 28 + min-complexity: 24 nlreturn: block-size: 5 diff --git a/pkg/dumps/parser_dump.go b/pkg/dumps/parser_dump.go index 227f96315d4..7d4e09ecf1a 100644 --- a/pkg/dumps/parser_dump.go +++ b/pkg/dumps/parser_dump.go @@ -92,40 +92,59 @@ func LoadParserDump(filepath string) (*ParserResults, error) { return &pdump, nil } -func DumpTree(parserResults ParserResults, bucketPour BucketPourInfo, opts DumpOpts) { +type tree struct { // note : we can use line -> time as the unique identifier (of acquisition) - state := make(map[time.Time]map[string]map[string]ParserResult) - assoc := make(map[time.Time]string, 0) - parser_order := make(map[string][]string) + state map[time.Time]map[string]map[string]ParserResult + assoc map[time.Time]string + parserOrder map[string][]string +} + +func newTree() *tree { + return &tree{ + state: make(map[time.Time]map[string]map[string]ParserResult), + assoc: make(map[time.Time]string), + parserOrder: make(map[string][]string), + } +} +func DumpTree(parserResults ParserResults, bucketPour BucketPourInfo, opts DumpOpts) { + t := newTree() + t.processEvents(parserResults) + t.processBuckets(bucketPour) + t.displayResults(opts) +} + +func (t *tree) processEvents(parserResults ParserResults) { for stage, parsers := range parserResults { // let's process parsers in the order according to idx - parser_order[stage] = make([]string, len(parsers)) + t.parserOrder[stage] = make([]string, len(parsers)) for pname, parser := range parsers { if len(parser) > 0 { - parser_order[stage][parser[0].Idx-1] = pname + t.parserOrder[stage][parser[0].Idx-1] = pname } } - for _, parser := range parser_order[stage] { + for _, parser := range t.parserOrder[stage] { results := parsers[parser] for _, parserRes := range results { evt := parserRes.Evt - if _, ok := state[evt.Line.Time]; !ok { - state[evt.Line.Time] = make(map[string]map[string]ParserResult) - assoc[evt.Line.Time] = evt.Line.Raw + if _, ok := t.state[evt.Line.Time]; !ok { + t.state[evt.Line.Time] = make(map[string]map[string]ParserResult) + t.assoc[evt.Line.Time] = evt.Line.Raw } - if _, ok := state[evt.Line.Time][stage]; !ok { - state[evt.Line.Time][stage] = make(map[string]ParserResult) + if _, ok := t.state[evt.Line.Time][stage]; !ok { + t.state[evt.Line.Time][stage] = make(map[string]ParserResult) } - state[evt.Line.Time][stage][parser] = ParserResult{Evt: evt, Success: parserRes.Success} + t.state[evt.Line.Time][stage][parser] = ParserResult{Evt: evt, Success: parserRes.Success} } } } +} +func (t *tree) processBuckets(bucketPour BucketPourInfo) { for bname, evtlist := range bucketPour { for _, evt := range evtlist { if evt.Line.Raw == "" { @@ -133,38 +152,41 @@ func DumpTree(parserResults ParserResults, bucketPour BucketPourInfo, opts DumpO } // it might be bucket overflow being reprocessed, skip this - if _, ok := state[evt.Line.Time]; !ok { - state[evt.Line.Time] = make(map[string]map[string]ParserResult) - assoc[evt.Line.Time] = evt.Line.Raw + if _, ok := t.state[evt.Line.Time]; !ok { + t.state[evt.Line.Time] = make(map[string]map[string]ParserResult) + t.assoc[evt.Line.Time] = evt.Line.Raw } // there is a trick : to know if an event successfully exit the parsers, we check if it reached the pour() phase // we thus use a fake stage "buckets" and a fake parser "OK" to know if it entered - if _, ok := state[evt.Line.Time]["buckets"]; !ok { - state[evt.Line.Time]["buckets"] = make(map[string]ParserResult) + if _, ok := t.state[evt.Line.Time]["buckets"]; !ok { + t.state[evt.Line.Time]["buckets"] = make(map[string]ParserResult) } - state[evt.Line.Time]["buckets"][bname] = ParserResult{Success: true} + t.state[evt.Line.Time]["buckets"][bname] = ParserResult{Success: true} } } +} +func (t *tree) displayResults(opts DumpOpts) { yellow := color.New(color.FgYellow).SprintFunc() red := color.New(color.FgRed).SprintFunc() green := color.New(color.FgGreen).SprintFunc() whitelistReason := "" + // get each line - for tstamp, rawstr := range assoc { + for tstamp, rawstr := range t.assoc { if opts.SkipOk { - if _, ok := state[tstamp]["buckets"]["OK"]; ok { + if _, ok := t.state[tstamp]["buckets"]["OK"]; ok { continue } } fmt.Printf("line: %s\n", rawstr) - skeys := make([]string, 0, len(state[tstamp])) + skeys := make([]string, 0, len(t.state[tstamp])) - for k := range state[tstamp] { + for k := range t.state[tstamp] { // there is a trick : to know if an event successfully exit the parsers, we check if it reached the pour() phase // we thus use a fake stage "buckets" and a fake parser "OK" to know if it entered if k == "buckets" { @@ -180,18 +202,18 @@ func DumpTree(parserResults ParserResults, bucketPour BucketPourInfo, opts DumpO var prevItem types.Event for _, stage := range skeys { - parsers := state[tstamp][stage] + parsers := t.state[tstamp][stage] sep := "├" presep := "|" fmt.Printf("\t%s %s\n", sep, stage) - for idx, parser := range parser_order[stage] { + for idx, parser := range t.parserOrder[stage] { res := parsers[parser].Success sep := "├" - if idx == len(parser_order[stage])-1 { + if idx == len(t.parserOrder[stage])-1 { sep = "└" } @@ -278,12 +300,12 @@ func DumpTree(parserResults ParserResults, bucketPour BucketPourInfo, opts DumpO sep := "└" - if len(state[tstamp]["buckets"]) > 0 { + if len(t.state[tstamp]["buckets"]) > 0 { sep = "├" } // did the event enter the bucket pour phase ? - if _, ok := state[tstamp]["buckets"]["OK"]; ok { + if _, ok := t.state[tstamp]["buckets"]["OK"]; ok { fmt.Printf("\t%s-------- parser success %s\n", sep, emoji.GreenCircle) } else if whitelistReason != "" { fmt.Printf("\t%s-------- parser success, ignored by whitelist (%s) %s\n", sep, whitelistReason, emoji.GreenCircle) @@ -292,13 +314,13 @@ func DumpTree(parserResults ParserResults, bucketPour BucketPourInfo, opts DumpO } // now print bucket info - if len(state[tstamp]["buckets"]) > 0 { + if len(t.state[tstamp]["buckets"]) > 0 { fmt.Printf("\t├ Scenarios\n") } - bnames := make([]string, 0, len(state[tstamp]["buckets"])) + bnames := make([]string, 0, len(t.state[tstamp]["buckets"])) - for k := range state[tstamp]["buckets"] { + for k := range t.state[tstamp]["buckets"] { // there is a trick : to know if an event successfully exit the parsers, we check if it reached the pour() phase // we thus use a fake stage "buckets" and a fake parser "OK" to know if it entered if k == "OK" {