diff options
Diffstat (limited to 'internal/tracepoints/selector.go')
| -rw-r--r-- | internal/tracepoints/selector.go | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/internal/tracepoints/selector.go b/internal/tracepoints/selector.go new file mode 100644 index 0000000..af2f39e --- /dev/null +++ b/internal/tracepoints/selector.go @@ -0,0 +1,85 @@ +package tracepoints + +import ( + "fmt" + "regexp" + "slices" + "strings" +) + +// Selector holds compiled include and exclude regexes for choosing which +// tracepoints to attach at BPF probe registration time. It is the single +// authoritative home for tracepoint-selection logic, keeping that concern +// out of the top-level flags.Config. +type Selector struct { + // Attach is the list of compiled regexes that select which tracepoints to + // load. An empty list means "attach all non-excluded tracepoints". + Attach []*regexp.Regexp + // Exclude is the list of compiled regexes that suppress specific + // tracepoints even when they match the Attach list. + Exclude []*regexp.Regexp +} + +// ParseSelector parses the comma-separated regex strings for the -tps and +// -tpsExclude CLI flags into a Selector. Either string may be empty, which +// leaves the corresponding list nil (i.e. "match all" for Attach, "exclude +// nothing" for Exclude). An error is returned if any regex fails to compile. +func ParseSelector(attach, exclude string) (Selector, error) { + attachRegexes, err := parseRegexList(attach) + if err != nil { + return Selector{}, err + } + excludeRegexes, err := parseRegexList(exclude) + if err != nil { + return Selector{}, err + } + return Selector{Attach: attachRegexes, Exclude: excludeRegexes}, nil +} + +// parseRegexList splits a comma-separated string of regex patterns and +// compiles each one. Returns nil (not an error) when the input is empty. +func parseRegexList(patterns string) ([]*regexp.Regexp, error) { + if len(patterns) == 0 { + return nil, nil + } + var regexes []*regexp.Regexp + for _, pattern := range strings.Split(patterns, ",") { + re, err := regexp.Compile(pattern) + if err != nil { + return nil, fmt.Errorf("unable to compile regex %q: %w", pattern, err) + } + regexes = append(regexes, re) + } + return regexes, nil +} + +// ShouldAttach reports whether the given tracepoint name passes the +// selector's 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 (s Selector) ShouldAttach(tracepointName string) bool { + for _, re := range s.Exclude { + if re.MatchString(tracepointName) { + return false + } + } + if len(s.Attach) == 0 { + return true + } + for _, re := range s.Attach { + if re.MatchString(tracepointName) { + return true + } + } + return false +} + +// Clone returns a deep copy of the Selector so that modifications to the +// copy's slices do not affect the original. +func (s Selector) Clone() Selector { + return Selector{ + Attach: slices.Clone(s.Attach), + Exclude: slices.Clone(s.Exclude), + } +} |
