summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-10 19:25:51 +0200
committerPaul Buetow <paul@buetow.org>2026-03-10 19:25:51 +0200
commitc43932b6eee8b8a964b9be7c21c42057f05456ba (patch)
tree94a5a7ebeefdc79c106060c004b561985df69970
parent70acff73c8d103ec68c575d3cac1bdd87c189cf0 (diff)
task 434: unify trace filter plumbing
-rw-r--r--internal/eventfilter.go78
-rw-r--r--internal/eventloop.go33
-rw-r--r--internal/eventloop_constructor_test.go23
-rw-r--r--internal/eventloop_error_handling_test.go7
-rw-r--r--internal/eventloop_filter_test.go31
-rw-r--r--internal/globalfilter/pair.go5
-rw-r--r--internal/globalfilter/trace.go81
-rw-r--r--internal/globalfilter/trace_test.go47
-rw-r--r--internal/ior.go38
-rw-r--r--internal/ior_mode_test.go14
10 files changed, 219 insertions, 138 deletions
diff --git a/internal/eventfilter.go b/internal/eventfilter.go
deleted file mode 100644
index 43a8f51..0000000
--- a/internal/eventfilter.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package internal
-
-import (
- "bytes"
- "fmt"
- "strings"
-
- "ior/internal/event"
- "ior/internal/types"
-)
-
-type eventFilter struct {
- commFilterEnable bool
- commFilter string
- commFilterBytes []byte
- pathFilterEnable bool
- pathFilter string
- pathFilterBytes []byte
-}
-
-func newEventFilter(commFilter, pathFilter string) (*eventFilter, error) {
- var ef eventFilter
-
- if commFilter != "" {
- if len(commFilter) > types.MAX_PROGNAME_LENGTH {
- return nil, fmt.Errorf("comm filter max size is %d (got %d)", types.MAX_PROGNAME_LENGTH, len(commFilter))
- }
- ef.commFilterEnable = true
- ef.commFilter = commFilter
- ef.commFilterBytes = []byte(commFilter)
- }
-
- if pathFilter != "" {
- if len(pathFilter) > types.MAX_FILENAME_LENGTH {
- return nil, fmt.Errorf("path filter max size is %d (got %d)", types.MAX_FILENAME_LENGTH, len(pathFilter))
- }
- ef.pathFilterEnable = true
- ef.pathFilter = pathFilter
- ef.pathFilterBytes = []byte(pathFilter)
- }
-
- return &ef, nil
-}
-
-func (ef *eventFilter) eventPair(ev *event.Pair) bool {
- if ef.commFilterEnable && !strings.Contains(ev.Comm, ef.commFilter) {
- return false
- }
- if ef.pathFilterEnable && (ev.File == nil || !strings.Contains(ev.File.Name(), ef.pathFilter)) {
- return false
- }
- return true
-}
-
-func (ef *eventFilter) openEvent(ev *types.OpenEvent) (*types.OpenEvent, bool) {
- if ef.commFilterEnable && !bytes.Contains(ev.Comm[:], ef.commFilterBytes) {
- return ev, false
- }
-
- if ef.pathFilterEnable && !bytes.Contains(ev.Filename[:], ef.pathFilterBytes) {
- return ev, false
- }
- return ev, true
-}
-
-func (ef *eventFilter) pathEvent(ev *types.PathEvent) (*types.PathEvent, bool) {
- if ef.pathFilterEnable {
- return ev, bytes.Contains(ev.Pathname[:], ef.pathFilterBytes)
- }
- return ev, true
-}
-
-func (ef *eventFilter) nameEvent(ev *types.NameEvent) (*types.NameEvent, bool) {
- if ef.pathFilterEnable {
- return ev, bytes.Contains(ev.Oldname[:], ef.pathFilterBytes) || bytes.Contains(ev.Newname[:], ef.pathFilterBytes)
- }
- return ev, true
-}
diff --git a/internal/eventloop.go b/internal/eventloop.go
index 278387f..6eba594 100644
--- a/internal/eventloop.go
+++ b/internal/eventloop.go
@@ -14,6 +14,7 @@ import (
"ior/internal/event"
"ior/internal/file"
+ "ior/internal/globalfilter"
"ior/internal/types"
)
@@ -26,8 +27,7 @@ const (
type eventLoopConfig struct {
pidFilter int
- commFilter string
- pathFilter string
+ filter globalfilter.Filter
collapsedFields []string
countField string
pprofEnable bool
@@ -241,7 +241,7 @@ type rawEventHandler func(raw []byte, ch chan<- *event.Pair)
type tracepointExitHandler func(ep *event.Pair) bool
type eventLoop struct {
- filter *eventFilter
+ filter globalfilter.Filter
enterEvs map[uint32]*event.Pair // Temp. store of sys_enter tracepoints per Tid.
pendingHandles map[uint32]string // map of TID to pathname from name_to_handle_at
fdTracker *fdTracker
@@ -266,13 +266,12 @@ type eventLoop struct {
func newEventLoop(cfg eventLoopConfig) (*eventLoop, error) {
fdState := configuredFDTracker(cfg.fdTracker)
commState := configuredCommResolver(cfg.commResolver)
- filter, err := newEventFilter(cfg.commFilter, cfg.pathFilter)
- if err != nil {
+ if err := cfg.filter.ValidateTracepointFields(); err != nil {
return nil, fmt.Errorf("create event filter: %w", err)
}
el := &eventLoop{
- filter: filter,
+ filter: cfg.filter.Clone(),
enterEvs: make(map[uint32]*event.Pair),
pendingHandles: make(map[uint32]string),
fdTracker: fdState,
@@ -480,8 +479,8 @@ func (e *eventLoop) initRawHandlers() {
e.dropMalformedRawEvent(types.ENTER_OPEN_EVENT, raw)
return
}
- if ev, ok := e.filter.openEvent(openEv); ok {
- e.tracepointEntered(ev)
+ if e.filter.MatchOpenEvent(openEv) {
+ e.tracepointEntered(openEv)
}
}
e.rawHandlers[types.EXIT_OPEN_EVENT] = func(raw []byte, ch chan<- *event.Pair) {
@@ -538,8 +537,8 @@ func (e *eventLoop) initRawHandlers() {
e.dropMalformedRawEvent(types.ENTER_NAME_EVENT, raw)
return
}
- if ev, ok := e.filter.nameEvent(nameEv); ok {
- e.tracepointEntered(ev)
+ if e.filter.MatchNameEvent(nameEv) {
+ e.tracepointEntered(nameEv)
}
}
e.rawHandlers[types.ENTER_PATH_EVENT] = func(raw []byte, _ chan<- *event.Pair) {
@@ -548,8 +547,8 @@ func (e *eventLoop) initRawHandlers() {
e.dropMalformedRawEvent(types.ENTER_PATH_EVENT, raw)
return
}
- if ev, ok := e.filter.pathEvent(pathEv); ok {
- e.tracepointEntered(ev)
+ if e.filter.MatchPathEvent(pathEv) {
+ e.tracepointEntered(pathEv)
}
}
e.rawHandlers[types.ENTER_FCNTL_EVENT] = func(raw []byte, _ chan<- *event.Pair) {
@@ -582,7 +581,7 @@ func (e *eventLoop) tracepointEntered(enterEv event.Event) {
tid := enterEv.GetTid()
// Schedule comm lookup as early as possible to reduce races for short-lived processes.
e.queueCommLookup(tid)
- if !e.filter.commFilterEnable {
+ if !e.filter.UsesCommFilter() {
e.enterEvs[tid] = event.NewPair(enterEv)
return
}
@@ -797,7 +796,7 @@ func (e *eventLoop) handleFdExit(ep *event.Pair, fdEv *types.FdEvent) bool {
}
}
ep.Comm = e.comm(fdEv.GetTid())
- if !e.filter.eventPair(ep) {
+ if !e.filter.MatchPair(ep) {
ep.Recycle()
return false
}
@@ -838,7 +837,7 @@ func (e *eventLoop) handleDup3Exit(ep *event.Pair, dup3Ev *types.Dup3Event) bool
fd := int32(dup3Ev.Fd)
ep.File = e.resolveFdFile(fd, dup3Ev.Pid)
ep.Comm = e.comm(dup3Ev.GetTid())
- if !e.filter.eventPair(ep) {
+ if !e.filter.MatchPair(ep) {
ep.Recycle()
return false
}
@@ -914,7 +913,7 @@ func (e *eventLoop) handleNullExit(ep *event.Pair, nullEv *types.NullEvent) bool
}
}
ep.Comm = e.comm(nullEv.GetTid())
- if !e.filter.eventPair(ep) {
+ if !e.filter.MatchPair(ep) {
ep.Recycle()
return false
}
@@ -925,7 +924,7 @@ func (e *eventLoop) handleFcntlExit(ep *event.Pair, fcntlEv *types.FcntlEvent) b
ep.Comm = e.comm(fcntlEv.GetTid())
fd := int32(fcntlEv.Fd)
ep.File = e.resolveFdFile(fd, fcntlEv.Pid)
- if !e.filter.eventPair(ep) {
+ if !e.filter.MatchPair(ep) {
ep.Recycle()
return false
}
diff --git a/internal/eventloop_constructor_test.go b/internal/eventloop_constructor_test.go
index 6636838..94b723e 100644
--- a/internal/eventloop_constructor_test.go
+++ b/internal/eventloop_constructor_test.go
@@ -4,6 +4,7 @@ import (
"strings"
"testing"
+ "ior/internal/globalfilter"
"ior/internal/types"
)
@@ -19,17 +20,25 @@ func mustNewEventLoop(tb testing.TB, cfg eventLoopConfig) *eventLoop {
return el
}
-func TestNewEventFilterRejectsTooLongCommFilter(t *testing.T) {
+func TestNewEventLoopRejectsTooLongCommFilter(t *testing.T) {
tooLong := strings.Repeat("a", types.MAX_PROGNAME_LENGTH+1)
- _, err := newEventFilter(tooLong, "")
+ _, err := newEventLoop(eventLoopConfig{
+ filter: globalfilter.Filter{
+ Comm: &globalfilter.StringFilter{Pattern: tooLong},
+ },
+ })
if err == nil {
t.Fatalf("expected error for comm filter longer than %d", types.MAX_PROGNAME_LENGTH)
}
}
-func TestNewEventFilterRejectsTooLongPathFilter(t *testing.T) {
+func TestNewEventLoopRejectsTooLongPathFilter(t *testing.T) {
tooLong := strings.Repeat("a", types.MAX_FILENAME_LENGTH+1)
- _, err := newEventFilter("", tooLong)
+ _, err := newEventLoop(eventLoopConfig{
+ filter: globalfilter.Filter{
+ File: &globalfilter.StringFilter{Pattern: tooLong},
+ },
+ })
if err == nil {
t.Fatalf("expected error for path filter longer than %d", types.MAX_FILENAME_LENGTH)
}
@@ -37,7 +46,11 @@ func TestNewEventFilterRejectsTooLongPathFilter(t *testing.T) {
func TestNewEventLoopPropagatesFilterError(t *testing.T) {
tooLong := strings.Repeat("a", types.MAX_PROGNAME_LENGTH+1)
- _, err := newEventLoop(eventLoopConfig{commFilter: tooLong})
+ _, err := newEventLoop(eventLoopConfig{
+ filter: globalfilter.Filter{
+ Comm: &globalfilter.StringFilter{Pattern: tooLong},
+ },
+ })
if err == nil {
t.Fatalf("expected newEventLoop to propagate invalid filter error")
}
diff --git a/internal/eventloop_error_handling_test.go b/internal/eventloop_error_handling_test.go
index e025343..b5add72 100644
--- a/internal/eventloop_error_handling_test.go
+++ b/internal/eventloop_error_handling_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"ior/internal/event"
+ "ior/internal/globalfilter"
"ior/internal/types"
)
@@ -146,7 +147,11 @@ func TestProcessRawEventMalformedKnownTypeDoesNotPanicAndNotifies(t *testing.T)
}
func TestTracepointEnteredMissingCommWithCommFilterNotifies(t *testing.T) {
- el := mustNewEventLoop(t, eventLoopConfig{commFilter: "system"})
+ el := mustNewEventLoop(t, eventLoopConfig{
+ filter: globalfilter.Filter{
+ Comm: &globalfilter.StringFilter{Pattern: "system"},
+ },
+ })
warnings := make(chan string, 1)
el.warningCb = func(message string) { warnings <- message }
diff --git a/internal/eventloop_filter_test.go b/internal/eventloop_filter_test.go
index b31f39c..ec8e75b 100644
--- a/internal/eventloop_filter_test.go
+++ b/internal/eventloop_filter_test.go
@@ -8,6 +8,7 @@ import (
"ior/internal/event"
"ior/internal/file"
+ "ior/internal/globalfilter"
"ior/internal/types"
)
@@ -449,9 +450,7 @@ func TestCommFilterToggle(t *testing.T) {
// Create eventloop without comm filter
el := &eventLoop{
- filter: &eventFilter{
- commFilterEnable: false,
- },
+ filter: globalfilter.Filter{},
enterEvs: make(map[uint32]*event.Pair),
fdTracker: newFDTracker(make(map[int32]file.File)),
commResolver: newCommResolver(make(map[uint32]string)),
@@ -493,10 +492,8 @@ func TestCommFilterToggle(t *testing.T) {
// Create eventloop with comm filter enabled
el := &eventLoop{
- filter: &eventFilter{
- commFilterEnable: true,
- commFilter: "test",
- commFilterBytes: []byte("test"),
+ filter: globalfilter.Filter{
+ Comm: &globalfilter.StringFilter{Pattern: "test"},
},
enterEvs: make(map[uint32]*event.Pair),
fdTracker: newFDTracker(make(map[int32]file.File)),
@@ -532,14 +529,7 @@ func TestCommFilterToggle(t *testing.T) {
func newEventLoopWithFilter(commFilter, pathFilter string) *eventLoop {
el := &eventLoop{
- filter: &eventFilter{
- commFilterEnable: commFilter != "",
- commFilter: commFilter,
- commFilterBytes: []byte(commFilter),
- pathFilterEnable: pathFilter != "",
- pathFilter: pathFilter,
- pathFilterBytes: []byte(pathFilter),
- },
+ filter: testFilter(commFilter, pathFilter),
enterEvs: make(map[uint32]*event.Pair),
fdTracker: newFDTracker(make(map[int32]file.File)),
commResolver: newCommResolver(make(map[uint32]string)),
@@ -550,3 +540,14 @@ func newEventLoopWithFilter(commFilter, pathFilter string) *eventLoop {
}
return el
}
+
+func testFilter(commFilter, pathFilter string) globalfilter.Filter {
+ filter := globalfilter.Filter{}
+ if commFilter != "" {
+ filter.Comm = &globalfilter.StringFilter{Pattern: commFilter}
+ }
+ if pathFilter != "" {
+ filter.File = &globalfilter.StringFilter{Pattern: pathFilter}
+ }
+ return filter
+}
diff --git a/internal/globalfilter/pair.go b/internal/globalfilter/pair.go
index 4215120..7aca331 100644
--- a/internal/globalfilter/pair.go
+++ b/internal/globalfilter/pair.go
@@ -6,10 +6,7 @@ import (
)
func MatchPair(filter Filter, pair *event.Pair) bool {
- if pair == nil {
- return false
- }
- return filter.Matches(pairCandidate{pair: pair})
+ return filter.MatchPair(pair)
}
type pairCandidate struct {
diff --git a/internal/globalfilter/trace.go b/internal/globalfilter/trace.go
new file mode 100644
index 0000000..b1e3fde
--- /dev/null
+++ b/internal/globalfilter/trace.go
@@ -0,0 +1,81 @@
+package globalfilter
+
+import (
+ "fmt"
+ "strings"
+
+ "ior/internal/event"
+ "ior/internal/types"
+)
+
+// ValidateTracepointFields checks string filters that are applied against
+// fixed-size kernel event fields before pair reconstruction.
+func (f Filter) ValidateTracepointFields() error {
+ if err := validateTraceStringFilter("comm", f.Comm, types.MAX_PROGNAME_LENGTH); err != nil {
+ return err
+ }
+ if err := validateTraceStringFilter("path", f.File, types.MAX_FILENAME_LENGTH); err != nil {
+ return err
+ }
+ return nil
+}
+
+// UsesCommFilter reports whether the filter needs command-name matching.
+func (f Filter) UsesCommFilter() bool {
+ return hasStringPattern(f.Comm)
+}
+
+// MatchPair reports whether a completed syscall pair satisfies the filter.
+func (f Filter) MatchPair(pair *event.Pair) bool {
+ if pair == nil {
+ return false
+ }
+ return f.Matches(pairCandidate{pair: pair})
+}
+
+// MatchOpenEvent applies the subset of the filter that can be evaluated on raw
+// open events before exit pairing.
+func (f Filter) MatchOpenEvent(ev *types.OpenEvent) bool {
+ if ev == nil {
+ return false
+ }
+ if !matchString(f.Comm, types.StringValue(ev.Comm[:])) {
+ return false
+ }
+ return matchString(f.File, types.StringValue(ev.Filename[:]))
+}
+
+// MatchPathEvent applies the path-related subset of the filter to raw path events.
+func (f Filter) MatchPathEvent(ev *types.PathEvent) bool {
+ if ev == nil {
+ return false
+ }
+ return matchString(f.File, types.StringValue(ev.Pathname[:]))
+}
+
+// MatchNameEvent applies the path-related subset of the filter to raw rename-like events.
+func (f Filter) MatchNameEvent(ev *types.NameEvent) bool {
+ if ev == nil {
+ return false
+ }
+ if !hasStringPattern(f.File) {
+ return true
+ }
+ return matchString(f.File, types.StringValue(ev.Oldname[:])) ||
+ matchString(f.File, types.StringValue(ev.Newname[:]))
+}
+
+func hasStringPattern(filter *StringFilter) bool {
+ return filter != nil && strings.TrimSpace(filter.Pattern) != ""
+}
+
+func validateTraceStringFilter(name string, filter *StringFilter, maxLen int) error {
+ if !hasStringPattern(filter) {
+ return nil
+ }
+ pattern := strings.TrimSpace(filter.Pattern)
+ if len(pattern) > maxLen {
+ return fmt.Errorf("%s filter max size is %d (got %d)", name, maxLen, len(pattern))
+ }
+ return nil
+}
diff --git a/internal/globalfilter/trace_test.go b/internal/globalfilter/trace_test.go
new file mode 100644
index 0000000..cd5736a
--- /dev/null
+++ b/internal/globalfilter/trace_test.go
@@ -0,0 +1,47 @@
+package globalfilter
+
+import (
+ "strings"
+ "testing"
+
+ "ior/internal/types"
+)
+
+func TestValidateTracepointFieldsRejectsOversizedPatterns(t *testing.T) {
+ tooLongComm := strings.Repeat("a", types.MAX_PROGNAME_LENGTH+1)
+ if err := (Filter{Comm: &StringFilter{Pattern: tooLongComm}}).ValidateTracepointFields(); err == nil {
+ t.Fatalf("expected oversized comm pattern to fail validation")
+ }
+
+ tooLongPath := strings.Repeat("b", types.MAX_FILENAME_LENGTH+1)
+ if err := (Filter{File: &StringFilter{Pattern: tooLongPath}}).ValidateTracepointFields(); err == nil {
+ t.Fatalf("expected oversized path pattern to fail validation")
+ }
+}
+
+func TestTracepointHelpersMatchRawEvents(t *testing.T) {
+ filter := Filter{
+ Comm: &StringFilter{Pattern: "^nginx"},
+ File: &StringFilter{Pattern: "access.log$"},
+ }
+
+ open := &types.OpenEvent{}
+ copy(open.Comm[:], "nginx-worker")
+ copy(open.Filename[:], "/var/log/nginx/access.log")
+ if !filter.MatchOpenEvent(open) {
+ t.Fatalf("expected open event to match comm and file filters")
+ }
+
+ path := &types.PathEvent{}
+ copy(path.Pathname[:], "/var/log/nginx/access.log")
+ if !filter.MatchPathEvent(path) {
+ t.Fatalf("expected path event to match file filter")
+ }
+
+ name := &types.NameEvent{}
+ copy(name.Oldname[:], "/tmp/old.log")
+ copy(name.Newname[:], "/var/log/nginx/access.log")
+ if !filter.MatchNameEvent(name) {
+ t.Fatalf("expected rename event to match file filter via newname")
+ }
+}
diff --git a/internal/ior.go b/internal/ior.go
index 668dda1..7b8f68a 100644
--- a/internal/ior.go
+++ b/internal/ior.go
@@ -177,7 +177,7 @@ func tuiTraceStarterFromRunTrace(
cfg := baseCfg
if filter, ok := tui.TraceFiltersFromContext(ctx); ok {
cfg.GlobalFilter = filter.Clone()
- applyTraceFilterConfig(&cfg, filter)
+ applyTraceScopeFromGlobalFilter(&cfg, filter)
}
engine := statsengine.NewEngine(64)
streamBuf := eventstream.NewRingBuffer()
@@ -243,24 +243,15 @@ func shouldIngestTracePair(filter globalfilter.Filter, pair *event.Pair) bool {
if !filter.IsActive() {
return true
}
- return globalfilter.MatchPair(filter, pair)
+ return filter.MatchPair(pair)
}
-func applyTraceFilterConfig(cfg *flags.Config, filter globalfilter.Filter) {
+func applyTraceScopeFromGlobalFilter(cfg *flags.Config, filter globalfilter.Filter) {
if cfg == nil {
return
}
- cfg.CommFilter = ""
- cfg.PathFilter = ""
cfg.PidFilter = -1
cfg.TidFilter = -1
-
- if filter.Comm != nil {
- cfg.CommFilter = filter.Comm.Pattern
- }
- if filter.File != nil {
- cfg.PathFilter = filter.File.Pattern
- }
if pid, ok := eqFilterValue(filter.PID); ok {
cfg.PidFilter = pid
}
@@ -285,8 +276,7 @@ func newEventLoopConfig(cfg flags.Config) eventLoopConfig {
copy(fields, cfg.CollapsedFields)
return eventLoopConfig{
pidFilter: cfg.PidFilter,
- commFilter: cfg.CommFilter,
- pathFilter: cfg.PathFilter,
+ filter: traceFilterFromConfig(cfg),
collapsedFields: fields,
countField: cfg.CountField,
pprofEnable: cfg.PprofEnable,
@@ -294,6 +284,26 @@ func newEventLoopConfig(cfg flags.Config) eventLoopConfig {
}
}
+func traceFilterFromConfig(cfg flags.Config) globalfilter.Filter {
+ filter := cfg.GlobalFilter.Clone()
+ if filter.IsActive() {
+ return filter
+ }
+ if cfg.CommFilter != "" {
+ filter.Comm = &globalfilter.StringFilter{Pattern: cfg.CommFilter}
+ }
+ if cfg.PathFilter != "" {
+ filter.File = &globalfilter.StringFilter{Pattern: cfg.PathFilter}
+ }
+ if cfg.PidFilter > 0 {
+ filter.PID = &globalfilter.NumericFilter{Op: globalfilter.OpEq, Value: int64(cfg.PidFilter)}
+ }
+ if cfg.TidFilter > 0 {
+ filter.TID = &globalfilter.NumericFilter{Op: globalfilter.OpEq, Value: int64(cfg.TidFilter)}
+ }
+ return filter
+}
+
type profilingControl struct {
done chan struct{}
enabled bool
diff --git a/internal/ior_mode_test.go b/internal/ior_mode_test.go
index 4140485..8fbc79c 100644
--- a/internal/ior_mode_test.go
+++ b/internal/ior_mode_test.go
@@ -461,11 +461,17 @@ func TestTuiTraceStarterFromRunTraceUsesContextFilters(t *testing.T) {
if gotCfg.TidFilter != 3333 {
t.Fatalf("expected tid filter from context, got %d", gotCfg.TidFilter)
}
- if gotCfg.CommFilter != "nginx" {
- t.Fatalf("expected comm filter from context, got %q", gotCfg.CommFilter)
+ if gotCfg.CommFilter != "" {
+ t.Fatalf("expected legacy comm filter to remain unused, got %q", gotCfg.CommFilter)
}
- if gotCfg.PathFilter != "/var/log" {
- t.Fatalf("expected path filter from context, got %q", gotCfg.PathFilter)
+ if gotCfg.PathFilter != "" {
+ t.Fatalf("expected legacy path filter to remain unused, got %q", gotCfg.PathFilter)
+ }
+ if gotCfg.GlobalFilter.Comm == nil || gotCfg.GlobalFilter.Comm.Pattern != "nginx" {
+ t.Fatalf("expected comm preserved in global filter payload, got %+v", gotCfg.GlobalFilter.Comm)
+ }
+ if gotCfg.GlobalFilter.File == nil || gotCfg.GlobalFilter.File.Pattern != "/var/log" {
+ t.Fatalf("expected file preserved in global filter payload, got %+v", gotCfg.GlobalFilter.File)
}
if gotCfg.GlobalFilter.Syscall == nil || gotCfg.GlobalFilter.Syscall.Pattern != "read" {
t.Fatalf("expected syscall preserved in global filter payload, got %+v", gotCfg.GlobalFilter.Syscall)