@@ -32,7 +32,6 @@ import (
3232 "github.com/rabbitstack/fibratus/pkg/event"
3333 "github.com/rabbitstack/fibratus/pkg/filter/fields"
3434 "github.com/rabbitstack/fibratus/pkg/filter/ql"
35- "github.com/rabbitstack/fibratus/pkg/util/hashers"
3635)
3736
3837var (
@@ -207,12 +206,17 @@ func (f *filter) Compile() error {
207206 ql .WalkFunc (f .expr , walk )
208207 } else {
209208 if f .seq .By != nil {
210- f .addField (f .seq .By )
209+ for _ , fld := range f .seq .By .Fields {
210+ f .addField (fld )
211+ }
211212 }
212213 for _ , expr := range f .seq .Expressions {
213214 ql .WalkFunc (expr .Expr , walk )
214- if expr .By != nil {
215- f .addField (expr .By )
215+ if expr .By == nil {
216+ continue
217+ }
218+ for _ , fld := range expr .By .Fields {
219+ f .addField (fld )
216220 }
217221 }
218222 }
@@ -302,23 +306,67 @@ func (f *filter) evalBoundSequence(
302306 // evaluate the expression with the current valuer state
303307 if ql .Eval (expr .Expr , valuer , f .hasFunctions ) {
304308 // compute sequence key hash to stich events
305- hash := make ([]byte , 0 )
309+ values := make ([]any , 0 )
306310 for _ , fld := range flds {
307311 if ! strings .HasPrefix (fld .BoundVar , "$" ) {
308312 continue
309313 }
310- hash = appendHash ( hash , valuer [fld .Value ])
314+ values = append ( values , valuer [fld .Value ])
311315 }
312- fnv := hashers . FnvUint64 ( hash )
313- e .AddSequenceLink (fnv )
314- evt .AddSequenceLink (fnv )
316+ hash := hashFields ( values )
317+ e .AddSequenceLink (hash )
318+ evt .AddSequenceLink (hash )
315319 return true
316320 }
317321 }
318322
319323 return false
320324}
321325
326+ // evalSequence evaluates the sequence with one, multiple or
327+ // no join links. The sequence link is first consulted for the
328+ // global sequence definition, and if it is not defined then
329+ // the expression sequence link is used.
330+ func (f * filter ) evalSequence (
331+ e * event.Event ,
332+ seqID int ,
333+ expr * ql.SequenceExpr ,
334+ partials map [int ][]* event.Event ,
335+ valuer ql.MapValuer ,
336+ ) bool {
337+ // top-level sequence link is defined
338+ by := f .seq .By
339+ if by == nil {
340+ // otherwise, use the expression link
341+ by = expr .By
342+ }
343+
344+ var match bool
345+ if seqID >= 1 && by != nil {
346+ linkID := makeSequenceLinkID (valuer , by )
347+ // traverse upstream partials for join equality
348+ joins := make ([]bool , seqID )
349+ outer:
350+ for i := range seqID {
351+ for _ , p := range partials [i ] {
352+ if CompareSeqLink (linkID , p .SequenceLinks ()) {
353+ joins [i ] = true
354+ continue outer
355+ }
356+ }
357+ }
358+ match = joinsEqual (joins ) && ql .Eval (expr .Expr , valuer , f .hasFunctions )
359+ } else {
360+ match = ql .Eval (expr .Expr , valuer , f .hasFunctions )
361+ }
362+
363+ if match && by != nil {
364+ e .AddSequenceLink (makeSequenceLinkID (valuer , by ))
365+ }
366+
367+ return match
368+ }
369+
322370func (f * filter ) RunSequence (e * event.Event , seqID int , partials map [int ][]* event.Event , rawMatch bool ) bool {
323371 if f .seq == nil {
324372 return false
@@ -343,45 +391,10 @@ func (f *filter) RunSequence(e *event.Event, seqID int, partials map[int][]*even
343391 match = f .evalBoundSequence (e , seqID , & expr , partials , valuer )
344392 } else {
345393 // evaluate constrained/unconstrained sequences
346- by := f .seq .By
347- if by == nil {
348- by = expr .By
349- }
350-
351- if seqID >= 1 && by != nil {
352- // traverse upstream partials for join equality
353- joins := make ([]bool , seqID )
354- joinID := valuer [by .Value ]
355- outer:
356- for i := range seqID {
357- for _ , p := range partials [i ] {
358- if CompareSeqLink (joinID , p .SequenceLinks ()) {
359- joins [i ] = true
360- continue outer
361- }
362- }
363- }
364- match = joinsEqual (joins ) && ql .Eval (expr .Expr , valuer , f .hasFunctions )
365- } else {
366- match = ql .Eval (expr .Expr , valuer , f .hasFunctions )
367- }
368-
369- if match && by != nil {
370- if v := valuer [by .Value ]; v != nil {
371- e .AddSequenceLink (v )
372- }
373- }
394+ match = f .evalSequence (e , seqID , & expr , partials , valuer )
374395 }
375- return match
376- }
377396
378- func joinsEqual (joins []bool ) bool {
379- for _ , j := range joins {
380- if ! j {
381- return false
382- }
383- }
384- return true
397+ return match
385398}
386399
387400func (f * filter ) GetStringFields () map [fields.Field ][]string { return f .stringFields }
@@ -564,3 +577,14 @@ func (f *filter) checkBoundRefs() error {
564577
565578 return nil
566579}
580+
581+ func makeSequenceLinkID (valuer ql.MapValuer , link * ql.SequenceLink ) any {
582+ if ! link .IsCompound () {
583+ return valuer [link .First ()]
584+ }
585+ values := make ([]any , 0 , len (link .Fields ))
586+ for _ , fld := range link .Fields {
587+ values = append (values , valuer [fld .Value ])
588+ }
589+ return hashFields (values )
590+ }
0 commit comments