summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-01 23:17:56 +0200
committerPaul Buetow <paul@buetow.org>2026-03-01 23:17:56 +0200
commit9391ec7fb056b1006cdf36f21e3e37c0fa8071bb (patch)
treec484f4a7bb4fa029796702419e000530efbefe5a /internal
parent4a9848af6fb83ffec682737e9046fd6db6d05ead (diff)
eventloop: inject runtime config instead of flags singleton (task 315)
Diffstat (limited to 'internal')
-rw-r--r--internal/eventloop.go37
-rw-r--r--internal/eventloop_filter_test.go2
-rw-r--r--internal/eventloop_seed_test.go22
-rw-r--r--internal/eventloop_test.go2
-rw-r--r--internal/ior.go29
5 files changed, 55 insertions, 37 deletions
diff --git a/internal/eventloop.go b/internal/eventloop.go
index 29e0918..8433159 100644
--- a/internal/eventloop.go
+++ b/internal/eventloop.go
@@ -12,7 +12,6 @@ import (
"ior/internal/event"
"ior/internal/file"
- "ior/internal/flags"
"ior/internal/flamegraph"
"ior/internal/types"
. "ior/internal/types"
@@ -20,6 +19,17 @@ import (
const sysEnterNameToHandleAtName = "name_to_handle_at"
+type eventLoopConfig struct {
+ pidFilter int
+ liveFlamegraph bool
+ liveInterval time.Duration
+ collapsedFields []string
+ countField string
+ flamegraphEnable bool
+ pprofEnable bool
+ plainMode bool
+}
+
type eventLoop struct {
filter *eventFilter
enterEvs map[uint32]*event.Pair // Temp. store of sys_enter tracepoints per Tid.
@@ -30,6 +40,7 @@ type eventLoop struct {
flamegraph flamegraph.IorDataCollector // Storing all paths in a map structure for analysis
liveTrie *flamegraph.LiveTrie
printCb func(ep *event.Pair) // Callback to print the event
+ cfg eventLoopConfig
// Statistics
numTracepoints uint
@@ -40,8 +51,7 @@ type eventLoop struct {
done chan struct{}
}
-func newEventLoop() *eventLoop {
- cfg := flags.Get()
+func newEventLoop(cfg eventLoopConfig) *eventLoop {
el := &eventLoop{
filter: newEventFilter(),
enterEvs: make(map[uint32]*event.Pair),
@@ -51,17 +61,18 @@ func newEventLoop() *eventLoop {
prevPairTimes: make(map[uint32]uint64),
printCb: func(ep *event.Pair) { fmt.Println(ep); ep.Recycle() },
flamegraph: flamegraph.New(),
+ cfg: cfg,
done: make(chan struct{}),
}
- if cfg.LiveFlamegraph {
- el.liveTrie = flamegraph.NewLiveTrie(cfg.CollapsedFields, cfg.CountField)
+ if cfg.liveFlamegraph {
+ el.liveTrie = flamegraph.NewLiveTrie(cfg.collapsedFields, cfg.countField)
}
el.seedTrackedPidComm()
return el
}
func (e *eventLoop) seedTrackedPidComm() {
- pid := flags.Get().PidFilter
+ pid := e.cfg.pidFilter
if pid <= 0 {
return
}
@@ -94,31 +105,31 @@ func (e *eventLoop) run(ctx context.Context, rawCh <-chan []byte) {
if e.liveTrie != nil {
fmt.Println("Starting live flamegraph server")
go func() {
- if err := flamegraph.ServeLive(ctx, e.liveTrie, flags.Get().LiveInterval); err != nil && ctx.Err() == nil {
+ if err := flamegraph.ServeLive(ctx, e.liveTrie, e.cfg.liveInterval); err != nil && ctx.Err() == nil {
fmt.Println("Live flamegraph server error:", err)
}
}()
}
- if flags.Get().FlamegraphEnable {
+ if e.cfg.flamegraphEnable {
fmt.Println("Collecting flame graph stats, press Ctrl+C to stop")
e.flamegraph.Start(ctx)
}
- if flags.Get().PprofEnable {
+ if e.cfg.pprofEnable {
fmt.Println("Profiling, press Ctrl+C to stop")
}
- if flags.Get().PlainMode && !flags.Get().FlamegraphEnable && !flags.Get().PprofEnable {
+ if e.cfg.plainMode && !e.cfg.flamegraphEnable && !e.cfg.pprofEnable {
fmt.Println(event.EventStreamHeader)
}
e.startTime = time.Now()
for ep := range e.events(ctx, rawCh) {
switch {
- case flags.Get().FlamegraphEnable:
+ case e.cfg.flamegraphEnable:
e.flamegraph.Ch <- ep
case e.liveTrie != nil:
e.liveTrie.Ingest(ep)
- case flags.Get().PprofEnable:
+ case e.cfg.pprofEnable:
ep.Recycle()
default:
e.printCb(ep)
@@ -126,7 +137,7 @@ func (e *eventLoop) run(ctx context.Context, rawCh <-chan []byte) {
e.numSyscallsAfterFilter++
}
- if flags.Get().FlamegraphEnable {
+ if e.cfg.flamegraphEnable {
fmt.Println("Waiting for flamegraph")
<-e.flamegraph.Done
}
diff --git a/internal/eventloop_filter_test.go b/internal/eventloop_filter_test.go
index 9a47429..c3eef1f 100644
--- a/internal/eventloop_filter_test.go
+++ b/internal/eventloop_filter_test.go
@@ -21,7 +21,7 @@ func TestCommPropagation(t *testing.T) {
inCh := make(chan []byte)
outCh := make(chan *event.Pair)
- el := newEventLoop()
+ el := newEventLoop(eventLoopConfig{})
el.printCb = func(ev *event.Pair) { outCh <- ev }
go el.run(ctx, inCh)
diff --git a/internal/eventloop_seed_test.go b/internal/eventloop_seed_test.go
index f8e631a..2b3574a 100644
--- a/internal/eventloop_seed_test.go
+++ b/internal/eventloop_seed_test.go
@@ -3,22 +3,17 @@ package internal
import (
"os"
"testing"
-
- "ior/internal/flags"
)
func TestSeedTrackedPidCommCachesTrackedPidComm(t *testing.T) {
- oldPID := flags.Get().PidFilter
- flags.SetPidFilter(os.Getpid())
- t.Cleanup(func() {
- flags.SetPidFilter(oldPID)
- })
-
+ pid := uint32(os.Getpid())
el := &eventLoop{
+ cfg: eventLoopConfig{
+ pidFilter: int(pid),
+ },
comms: make(map[uint32]string),
}
- pid := uint32(os.Getpid())
want := el.comm(pid)
if want == "" {
t.Fatalf("expected comm for pid %d", pid)
@@ -33,13 +28,10 @@ func TestSeedTrackedPidCommCachesTrackedPidComm(t *testing.T) {
}
func TestSeedTrackedPidCommSkipsWhenPidFilterDisabled(t *testing.T) {
- oldPID := flags.Get().PidFilter
- flags.SetPidFilter(-1)
- t.Cleanup(func() {
- flags.SetPidFilter(oldPID)
- })
-
el := &eventLoop{
+ cfg: eventLoopConfig{
+ pidFilter: -1,
+ },
comms: make(map[uint32]string),
}
diff --git a/internal/eventloop_test.go b/internal/eventloop_test.go
index 9c26372..49ba3e8 100644
--- a/internal/eventloop_test.go
+++ b/internal/eventloop_test.go
@@ -96,7 +96,7 @@ func TestEventloop(t *testing.T) {
inCh := make(chan []byte)
outCh := make(chan *event.Pair)
- el := newEventLoop()
+ el := newEventLoop(eventLoopConfig{})
el.printCb = func(ev *event.Pair) { outCh <- ev }
go el.run(ctx, inCh)
diff --git a/internal/ior.go b/internal/ior.go
index cdddc24..7642b21 100644
--- a/internal/ior.go
+++ b/internal/ior.go
@@ -215,6 +215,21 @@ func runTrace() error {
return runTraceWithContext(context.Background(), nil, nil)
}
+func newEventLoopConfig(cfg flags.Flags) eventLoopConfig {
+ fields := make([]string, len(cfg.CollapsedFields))
+ copy(fields, cfg.CollapsedFields)
+ return eventLoopConfig{
+ pidFilter: cfg.PidFilter,
+ liveFlamegraph: cfg.LiveFlamegraph,
+ liveInterval: cfg.LiveInterval,
+ collapsedFields: fields,
+ countField: cfg.CountField,
+ flamegraphEnable: cfg.FlamegraphEnable,
+ pprofEnable: cfg.PprofEnable,
+ plainMode: cfg.PlainMode,
+ }
+}
+
func runTraceWithContext(parentCtx context.Context, started chan<- struct{}, configure func(*eventLoop)) error {
if getEUID() != 0 {
return errRootPrivilegesRequired
@@ -225,6 +240,7 @@ func runTraceWithContext(parentCtx context.Context, started chan<- struct{}, con
if verbose {
logln = func(args ...any) { _, _ = fmt.Println(args...) }
}
+ cfg := flags.Get()
bpfModule, err := bpf.NewModuleFromFile("ior.bpf.o")
if err != nil {
@@ -232,11 +248,11 @@ func runTraceWithContext(parentCtx context.Context, started chan<- struct{}, con
}
defer bpfModule.Close()
- if err := flags.Get().ResizeBPFMaps(bpfModule); err != nil {
+ if err := cfg.ResizeBPFMaps(bpfModule); err != nil {
return err
}
- if err := flags.Get().SetBPF(bpfModule); err != nil {
+ if err := cfg.SetBPF(bpfModule); err != nil {
return err
}
@@ -246,7 +262,7 @@ func runTraceWithContext(parentCtx context.Context, started chan<- struct{}, con
mgr := probemanager.NewManager(libbpfTracepointModule{module: bpfModule})
defer mgr.Close()
- if err := mgr.AttachAll(flags.Get().ShouldIAttachTracepoint, tracepoints.List); err != nil {
+ if err := mgr.AttachAll(cfg.ShouldIAttachTracepoint, tracepoints.List); err != nil {
return err
}
tui.SetProbeManager(mgr)
@@ -262,7 +278,7 @@ func runTraceWithContext(parentCtx context.Context, started chan<- struct{}, con
pprofDone := make(chan struct{})
var cpuProfile, memProfile *os.File
- if flags.Get().PprofEnable {
+ if cfg.PprofEnable {
if cpuProfile, err = os.Create("ior.cpuprofile"); err != nil {
return err
}
@@ -276,7 +292,7 @@ func runTraceWithContext(parentCtx context.Context, started chan<- struct{}, con
signalTraceStarted(started)
- el := newEventLoop()
+ el := newEventLoop(newEventLoopConfig(cfg))
if configure != nil {
configure(el)
}
@@ -290,7 +306,6 @@ func runTraceWithContext(parentCtx context.Context, started chan<- struct{}, con
origPrintCb(ep)
}
}
- cfg := flags.Get()
ctx := parentCtx
cancel := func() {}
if shouldAutoStopByDuration(cfg) {
@@ -322,7 +337,7 @@ func runTraceWithContext(parentCtx context.Context, started chan<- struct{}, con
if verbose {
fmt.Println(el.stats())
}
- if flags.Get().PprofEnable {
+ if cfg.PprofEnable {
logln("Stoppig profiling, writing ior.cpuprofile and ior.memprofile")
pprof.StopCPUProfile()
pprof.WriteHeapProfile(memProfile)