From 169b84421227a4a2cab1c680863df958862bc615 Mon Sep 17 00:00:00 2001 From: "Thibault \"bui\" Koechlin" Date: Mon, 27 Mar 2023 16:01:42 +0200 Subject: [PATCH] fix awkward stacktrace in conditional filter (#2145) --- pkg/leakybucket/conditional.go | 35 ++++++++++++++++++++++++--------- pkg/leakybucket/manager_load.go | 13 ++++-------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/pkg/leakybucket/conditional.go b/pkg/leakybucket/conditional.go index fecba9c69..f55df04ae 100644 --- a/pkg/leakybucket/conditional.go +++ b/pkg/leakybucket/conditional.go @@ -2,6 +2,7 @@ package leakybucket import ( "fmt" + "sync" "time" "github.com/antonmedv/expr" @@ -10,24 +11,40 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/types" ) +var conditionalExprCache map[string]vm.Program +var conditionalExprCacheLock sync.Mutex + type ConditionalOverflow struct { ConditionalFilter string ConditionalFilterRuntime *vm.Program DumbProcessor } -func NewConditionalOverflow(g *BucketFactory) (*ConditionalOverflow, error) { +func (c *ConditionalOverflow) OnBucketInit(g *BucketFactory) error { var err error + var compiledExpr *vm.Program - c := ConditionalOverflow{} - c.ConditionalFilter = g.ConditionalOverflow - c.ConditionalFilterRuntime, err = expr.Compile(c.ConditionalFilter, expr.Env(exprhelpers.GetExprEnv(map[string]interface{}{ - "queue": &Queue{}, "leaky": &Leaky{}}))) - if err != nil { - g.logger.Errorf("Unable to compile condition expression for conditional bucket : %s", err) - return nil, fmt.Errorf("unable to compile condition expression for conditional bucket : %v", err) + if conditionalExprCache == nil { + conditionalExprCache = make(map[string]vm.Program) } - return &c, nil + conditionalExprCacheLock.Lock() + if compiled, ok := conditionalExprCache[g.ConditionalOverflow]; ok { + conditionalExprCacheLock.Unlock() + c.ConditionalFilterRuntime = &compiled + } else { + conditionalExprCacheLock.Unlock() + //release the lock during compile + compiledExpr, err = expr.Compile(g.ConditionalOverflow, expr.Env(exprhelpers.GetExprEnv(map[string]interface{}{ + "queue": &Queue{}, "leaky": &Leaky{}, "evt": &types.Event{}}))) + if err != nil { + return fmt.Errorf("conditional compile error : %w", err) + } + c.ConditionalFilterRuntime = compiledExpr + conditionalExprCacheLock.Lock() + conditionalExprCache[g.ConditionalOverflow] = *compiledExpr + conditionalExprCacheLock.Unlock() + } + return err } func (c *ConditionalOverflow) AfterBucketPour(b *BucketFactory) func(types.Event, *Leaky) *types.Event { diff --git a/pkg/leakybucket/manager_load.go b/pkg/leakybucket/manager_load.go index 37cac5762..520a6a7be 100644 --- a/pkg/leakybucket/manager_load.go +++ b/pkg/leakybucket/manager_load.go @@ -321,12 +321,12 @@ func LoadBucket(bucketFactory *BucketFactory, tomb *tomb.Tomb) error { } if bucketFactory.Distinct != "" { - bucketFactory.logger.Tracef("Adding a non duplicate filter on %s.", bucketFactory.Name) + bucketFactory.logger.Tracef("Adding a non duplicate filter") bucketFactory.processors = append(bucketFactory.processors, &Uniq{}) } if bucketFactory.CancelOnFilter != "" { - bucketFactory.logger.Tracef("Adding a cancel_on filter on %s.", bucketFactory.Name) + bucketFactory.logger.Tracef("Adding a cancel_on filter") bucketFactory.processors = append(bucketFactory.processors, &CancelOnFilter{}) } @@ -351,13 +351,8 @@ func LoadBucket(bucketFactory *BucketFactory, tomb *tomb.Tomb) error { } if bucketFactory.ConditionalOverflow != "" { - bucketFactory.logger.Tracef("Adding conditional overflow.") - condovflw, err := NewConditionalOverflow(bucketFactory) - if err != nil { - bucketFactory.logger.Errorf("Error creating conditional overflow : %s", err) - return fmt.Errorf("error creating conditional overflow : %s", err) - } - bucketFactory.processors = append(bucketFactory.processors, condovflw) + bucketFactory.logger.Tracef("Adding conditional overflow") + bucketFactory.processors = append(bucketFactory.processors, &ConditionalOverflow{}) } if len(bucketFactory.Data) > 0 {