diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-13 19:35:02 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-13 19:35:02 +0300 |
| commit | f4a814df4e39ff5547a88d4f5d37ae6fe159cc76 (patch) | |
| tree | 24410b41efdabbf037d0efc4ee8cb577252faf9c /internal/flags | |
| parent | e6b85dd4222eb1660b591f5dbf6e2b58dfae3bfa (diff) | |
refactor: move TraceFilter and tracepoint selector logic out of flags.Config
- Add tracepoints.Selector type with ShouldAttach method and ParseSelector
constructor, replacing the raw TracepointsToAttach/TracepointsToExclude
regex slices on flags.Config.
- Add flags.BuildTraceFilter as a standalone function replacing the
Config.TraceFilter() method, keeping filter-building logic out of the
config struct.
- Remove stale ShouldIAttachTracepoint noise-filter entry from Magefile.
- Add selector_test.go with full coverage of ParseSelector and ShouldAttach.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/flags')
| -rw-r--r-- | internal/flags/flags.go | 90 | ||||
| -rw-r--r-- | internal/flags/tracefilter.go | 33 |
2 files changed, 46 insertions, 77 deletions
diff --git a/internal/flags/flags.go b/internal/flags/flags.go index dc87e89..2544007 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -4,7 +4,6 @@ import ( "flag" "fmt" "os" - "regexp" "slices" "strings" "time" @@ -12,6 +11,7 @@ import ( "ior/internal/collapse" appconfig "ior/internal/config" "ior/internal/globalfilter" + "ior/internal/tracepoints" ) // Config captures runtime configuration parsed from CLI flags. @@ -31,12 +31,10 @@ type Config struct { // Duration is the maximum tracing duration in seconds. Duration int - // TracepointsToAttach is the list of compiled regexes that select which - // tracepoints to load; an empty list means attach all tracepoints. - TracepointsToAttach []*regexp.Regexp - // TracepointsToExclude is the list of compiled regexes that suppress - // specific tracepoints even when they match TracepointsToAttach. - TracepointsToExclude []*regexp.Regexp + // TracepointSelector holds the compiled include/exclude regexes that + // decide which BPF tracepoints to attach. The selection logic lives in + // tracepoints.Selector.ShouldAttach rather than on Config itself. + TracepointSelector tracepoints.Selector // PlainMode disables the TUI and writes raw CSV rows to stdout. PlainMode bool @@ -65,6 +63,7 @@ type Config struct { CountField string // GlobalFilter is the structured event filter applied across all dashboards // and output modes; takes precedence over the individual CLI filter flags. + // Use BuildTraceFilter(cfg) to obtain a resolved globalfilter.Filter. GlobalFilter globalfilter.Filter // ResetTimer is the interval at which aggregate dashboard state (flamegraph // trie and stats engine) is automatically cleared; 0 disables auto-reset. @@ -114,8 +113,7 @@ func (f Config) GetTUIExportEnable() bool { // fields so that modifications to the copy do not affect the original. func (f Config) Clone() Config { out := f - out.TracepointsToAttach = slices.Clone(f.TracepointsToAttach) - out.TracepointsToExclude = slices.Clone(f.TracepointsToExclude) + out.TracepointSelector = f.TracepointSelector.Clone() out.CollapsedFields = slices.Clone(f.CollapsedFields) out.GlobalFilter = f.GlobalFilter.Clone() return out @@ -146,8 +144,8 @@ func parseFromFlagSet(fs *flag.FlagSet, args []string) (Config, error) { fs.BoolVar(&cfg.PprofEnable, "pprof", false, "Enable profiling") - tracepointsToAttach := fs.String("tps", "", "Comma separated list regexes for tracepoints to load") - tracepointsToExclude := fs.String("tpsExclude", "", "Comma separated list regexes for tracepoints to exclude") + tpsAttach := fs.String("tps", "", "Comma separated list regexes for tracepoints to load") + tpsExclude := fs.String("tpsExclude", "", "Comma separated list regexes for tracepoints to exclude") fs.BoolVar(&cfg.PlainMode, "plain", false, "Enable plain CSV output mode (disable TUI)") fs.BoolVar(&cfg.FlamegraphOutput, "flamegraph", false, "Write aggregated .ior.zst output for trace/integration workflows") @@ -169,15 +167,13 @@ func parseFromFlagSet(fs *flag.FlagSet, args []string) (Config, error) { return Config{}, err } - var err error - cfg.TracepointsToAttach, err = extractTracepointFlags(*tracepointsToAttach) - if err != nil { - return Config{}, err - } - cfg.TracepointsToExclude, err = extractTracepointFlags(*tracepointsToExclude) + // Parse the tracepoint include/exclude regex lists into a Selector. + // The Selector owns all matching logic; Config is purely a data carrier. + sel, err := tracepoints.ParseSelector(*tpsAttach, *tpsExclude) if err != nil { return Config{}, err } + cfg.TracepointSelector = sel // Keep this list empty by default. // As of February 23, 2026, open_by_handle_at and name_to_handle_at were @@ -221,63 +217,3 @@ func parseFromFlagSet(fs *flag.FlagSet, args []string) (Config, error) { return cfg, nil } - -func extractTracepointFlags(tracepoints string) (regexes []*regexp.Regexp, err error) { - if len(tracepoints) == 0 { - return regexes, nil - } - for _, name := range strings.Split(tracepoints, ",") { - re, err := regexp.Compile(name) - if err != nil { - return nil, fmt.Errorf("unable to compile regex %q: %w", name, err) - } - regexes = append(regexes, re) - } - return regexes, nil -} - -// TraceFilter builds a globalfilter.Filter from the config's filter fields. -// If GlobalFilter is already active, it is returned as-is. Otherwise, -// individual CLI-level filters (CommFilter, PathFilter, PidFilter, TidFilter) -// are merged into a new filter. -func (cfg Config) TraceFilter() 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.NewEqFilter(int64(cfg.PidFilter)) - } - if cfg.TidFilter > 0 { - filter.TID = globalfilter.NewEqFilter(int64(cfg.TidFilter)) - } - return filter -} - -// ShouldIAttachTracepoint reports whether the given tracepoint name passes the -// attach/exclude regex filters. Exclusions are checked first; if the name -// matches any exclude pattern it is rejected regardless of the attach list. -// When the attach list is empty, all non-excluded tracepoints are accepted. -func (f Config) ShouldIAttachTracepoint(tracepointName string) bool { - for _, re := range f.TracepointsToExclude { - if re.MatchString(tracepointName) { - return false - } - } - if len(f.TracepointsToAttach) == 0 { - return true - } - for _, re := range f.TracepointsToAttach { - if re.MatchString(tracepointName) { - return true - } - } - - return false -} diff --git a/internal/flags/tracefilter.go b/internal/flags/tracefilter.go new file mode 100644 index 0000000..90ac609 --- /dev/null +++ b/internal/flags/tracefilter.go @@ -0,0 +1,33 @@ +package flags + +import "ior/internal/globalfilter" + +// BuildTraceFilter constructs a globalfilter.Filter from the CLI-level filter +// fields stored in cfg. If a GlobalFilter is already active it is returned +// as-is (cloned), because the structured filter supersedes all individual CLI +// flags. Otherwise the per-field flags (CommFilter, PathFilter, PidFilter, +// TidFilter) are merged into a new filter. +// +// This function is the single authoritative place for turning a flags.Config +// into the globalfilter.Filter used by event ingestion. It replaces the +// former Config.TraceFilter() method so that filter-building logic lives in a +// dedicated function rather than on the configuration struct itself. +func BuildTraceFilter(cfg 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.NewEqFilter(int64(cfg.PidFilter)) + } + if cfg.TidFilter > 0 { + filter.TID = globalfilter.NewEqFilter(int64(cfg.TidFilter)) + } + return filter +} |
