summaryrefslogtreecommitdiff
path: root/internal/tracepoints/selector.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/tracepoints/selector.go')
-rw-r--r--internal/tracepoints/selector.go85
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),
+ }
+}