diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/eventfilter.go | 14 | ||||
| -rw-r--r-- | internal/eventloop.go | 20 | ||||
| -rw-r--r-- | internal/flags/flags.go | 41 | ||||
| -rw-r--r-- | internal/flamegraph/flamegraph.go | 4 | ||||
| -rw-r--r-- | internal/flamegraph/iordata.go | 15 | ||||
| -rw-r--r-- | internal/ior.go | 20 |
6 files changed, 58 insertions, 56 deletions
diff --git a/internal/eventfilter.go b/internal/eventfilter.go index 71995b1..0b3f121 100644 --- a/internal/eventfilter.go +++ b/internal/eventfilter.go @@ -15,23 +15,23 @@ type eventFilter struct { pathFilter string } -func newEventFilter(flags flags.Flags) *eventFilter { +func newEventFilter() *eventFilter { var ef eventFilter - if flags.CommFilter != "" { - if len(flags.CommFilter) > types.MAX_FILENAME_LENGTH { + if flags.Get().CommFilter != "" { + if len(flags.Get().CommFilter) > types.MAX_FILENAME_LENGTH { panic(fmt.Sprintf("Comm filter's max size is %d", types.MAX_PROGNAME_LENGTH)) } ef.commFilterEnable = true - ef.commFilter = flags.CommFilter + ef.commFilter = flags.Get().CommFilter } - if flags.PathFilter != "" { - if len(flags.PathFilter) > types.MAX_FILENAME_LENGTH { + if flags.Get().PathFilter != "" { + if len(flags.Get().PathFilter) > types.MAX_FILENAME_LENGTH { panic(fmt.Sprintf("Path filter's max size is %d", types.MAX_FILENAME_LENGTH)) } ef.pathFilterEnable = true - ef.pathFilter = flags.PathFilter + ef.pathFilter = flags.Get().PathFilter } return &ef diff --git a/internal/eventloop.go b/internal/eventloop.go index 4e9a3cb..f52274d 100644 --- a/internal/eventloop.go +++ b/internal/eventloop.go @@ -20,7 +20,6 @@ import ( // TOOD: read and write syscalls: can also collect amount of bytes! type eventLoop struct { - flags flags.Flags filter *eventFilter enterEvs map[uint32]*event.Pair // Temp. store of sys_enter tracepoints per Tid. files map[int32]file.File // Track all open files by file descriptor.. @@ -37,15 +36,14 @@ type eventLoop struct { done chan struct{} } -func newEventLoop(flags flags.Flags) *eventLoop { +func newEventLoop() *eventLoop { return &eventLoop{ - flags: flags, - filter: newEventFilter(flags), + filter: newEventFilter(), enterEvs: make(map[uint32]*event.Pair), files: make(map[int32]file.File), comms: make(map[uint32]string), prevPairTimes: make(map[uint32]uint64), - flamegraph: flamegraph.New(flags), + flamegraph: flamegraph.New(), done: make(chan struct{}), } } @@ -73,23 +71,23 @@ func (e *eventLoop) stats() string { func (e *eventLoop) run(ctx context.Context, rawCh <-chan []byte) { defer close(e.done) - if e.flags.FlamegraphEnable { + if flags.Get().FlamegraphEnable { fmt.Println("Collecting flame graph stats, press Ctrl+C to stop") e.flamegraph.Start(ctx) } - if e.flags.PprofEnable { + if flags.Get().PprofEnable { fmt.Println("Profiling, press Ctrl+C to stop") } - if !e.flags.FlamegraphEnable && !e.flags.PprofEnable { + if !flags.Get().FlamegraphEnable && !flags.Get().PprofEnable { fmt.Println(event.EventStreamHeader) } e.startTime = time.Now() for ev := range e.events(ctx, rawCh) { switch { - case e.flags.FlamegraphEnable: + case flags.Get().FlamegraphEnable: e.flamegraph.Ch <- ev - case e.flags.PprofEnable: + case flags.Get().PprofEnable: ev.Recycle() default: fmt.Println(ev.String()) @@ -98,7 +96,7 @@ func (e *eventLoop) run(ctx context.Context, rawCh <-chan []byte) { e.numSyscallsAfterFilter++ } - if e.flags.FlamegraphEnable { + if flags.Get().FlamegraphEnable { fmt.Println("Waiting for flamegraph") <-e.flamegraph.Done } diff --git a/internal/flags/flags.go b/internal/flags/flags.go index a85c838..c971335 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -6,10 +6,18 @@ import ( "os" "regexp" "strings" + "sync" bpf "github.com/aquasecurity/libbpfgo" ) +var singleton Flags +var once sync.Once + +func Get() Flags { + return singleton +} + type Flags struct { PidFilter int TidFilter int @@ -28,29 +36,32 @@ type Flags struct { FlamegraphName string // If set, enables new style iorData output, TODO: remove comment once old style collapsed format is retired } -func New() (flags Flags) { - flag.IntVar(&flags.PidFilter, "pid", -1, "Filter for processes ID") - flag.IntVar(&flags.TidFilter, "tid", -1, "Filter for thread ID") - flag.IntVar(&flags.EventMapSize, "mapSize", 4096*16, "BPF FD event ring buffer map size") - flag.IntVar(&flags.Duration, "duration", 60, "Probe duration in seconds") +func Parse() { + once.Do(func() { + parse() + }) +} - flag.StringVar(&flags.CommFilter, "comm", "", "Command to filter for") - flag.StringVar(&flags.PathFilter, "path", "", "Path to filter for") +func parse() { + flag.IntVar(&singleton.PidFilter, "pid", -1, "Filter for processes ID") + flag.IntVar(&singleton.TidFilter, "tid", -1, "Filter for thread ID") + flag.IntVar(&singleton.EventMapSize, "mapSize", 4096*16, "BPF FD event ring buffer map size") + flag.IntVar(&singleton.Duration, "duration", 60, "Probe duration in seconds") - flag.BoolVar(&flags.PprofEnable, "pprof", false, "Enable profiling") + flag.StringVar(&singleton.CommFilter, "comm", "", "Command to filter for") + flag.StringVar(&singleton.PathFilter, "path", "", "Path to filter for") + + flag.BoolVar(&singleton.PprofEnable, "pprof", false, "Enable profiling") tracepointsToAttach := flag.String("tps", "", "Comma separated list regexes for tracepoints to load") tracepointsToExclude := flag.String("tpsExclude", "", "Comma separated list regexes for tracepoints to exclude") - flag.BoolVar(&flags.FlamegraphEnable, "flamegraph", false, "Enable flamegraph builder") - flag.StringVar(&flags.FlamegraphName, "name", "", "Name of the flamegraph data output") - + flag.BoolVar(&singleton.FlamegraphEnable, "flamegraph", false, "Enable flamegraph builder") + flag.StringVar(&singleton.FlamegraphName, "name", "", "Name of the flamegraph data output") flag.Parse() - flags.TracepointsToAttach = extractTracepointFlags(*tracepointsToAttach) - flags.TracepointsToExclude = extractTracepointFlags(*tracepointsToExclude) - - return flags + singleton.TracepointsToAttach = extractTracepointFlags(*tracepointsToAttach) + singleton.TracepointsToExclude = extractTracepointFlags(*tracepointsToExclude) } func extractTracepointFlags(tracepoints string) (regexes []*regexp.Regexp) { diff --git a/internal/flamegraph/flamegraph.go b/internal/flamegraph/flamegraph.go index 9e1e14b..aeb5143 100644 --- a/internal/flamegraph/flamegraph.go +++ b/internal/flamegraph/flamegraph.go @@ -18,7 +18,7 @@ type Flamegraph struct { workers []worker } -func New(flags flags.Flags) Flamegraph { +func New() Flamegraph { f := Flamegraph{ Ch: make(chan *event.Pair, 4096), Done: make(chan struct{}), @@ -41,7 +41,7 @@ func (f Flamegraph) Start(ctx context.Context) { for i, worker := range f.workers { fmt.Println("Starting flamegraph worker", i) - if f.flags.FlamegraphName == "" { // Empty string means: old style collapsed + if flags.Get().FlamegraphName == "" { // Empty string means: old style collapsed go worker.runCollapsed(ctx, &wg, f.Ch) } else { go worker.run(ctx, &wg, f.Ch) diff --git a/internal/flamegraph/iordata.go b/internal/flamegraph/iordata.go index c167f22..b6bb197 100644 --- a/internal/flamegraph/iordata.go +++ b/internal/flamegraph/iordata.go @@ -21,7 +21,6 @@ type flagsType = string type pathMap map[pathType]map[traceIdType]map[commType]map[pidType]map[tidType]map[flagsType]counter type iorData struct { - flags flags.Flags paths pathMap } @@ -29,11 +28,8 @@ type iorData struct { // TODO: Name flag for iorData (outfile format: hostname-name-timestamp.ior.zst) // TODO: Output path for iorData flag // TODO: Add helper to convert .ior data file to collapsed format -func newIorData(flags flags.Flags) iorData { - return iorData{ - flags: flags, - paths: make(pathMap), - } +func newIorData() iorData { + return iorData{paths: make(pathMap)} } // TODO: Unit test @@ -100,7 +96,7 @@ func (iod iorData) commit() error { panic(err) } - filename := fmt.Sprintf("%s-%s-%s.ior.zst", hostname, iod.flags.FlamegraphName, + filename := fmt.Sprintf("%s-%s-%s.ior.zst", hostname, flags.Get().FlamegraphName, time.Now().Format("2006-01-02_15:04:05")) file, err := os.Create(filename) if err != nil { @@ -108,10 +104,7 @@ func (iod iorData) commit() error { } defer file.Close() - encoder, err := zstd.NewWriter(file) - if err != nil { - return err - } + encoder := zstd.NewWriter(file) defer encoder.Close() jsonEncoder := json.NewEncoder(encoder) diff --git a/internal/ior.go b/internal/ior.go index 7bf96bc..3d6fd1e 100644 --- a/internal/ior.go +++ b/internal/ior.go @@ -19,9 +19,9 @@ import ( // TODO: Generally, write unit tests // TODO: Integration tests, write C or Cgo code to simulate I/O? -func attachTracepoints(flags flags.Flags, bpfModule *bpf.Module) error { +func attachTracepoints(bpfModule *bpf.Module) error { for _, name := range tracepoints.List { - if !flags.ShouldIAttachTracepoint(name) { + if !flags.Get().ShouldIAttachTracepoint(name) { continue } fmt.Println("Attaching tracepoint", name) @@ -43,18 +43,18 @@ func attachTracepoints(flags flags.Flags, bpfModule *bpf.Module) error { return nil } -func Run(flags flags.Flags) { +func Run() { bpfModule, err := bpf.NewModuleFromFile("ior.bpf.o") if err != nil { panic(err) } defer bpfModule.Close() - if err := flags.ResizeBPFMaps(bpfModule); err != nil { + if err := flags.Get().ResizeBPFMaps(bpfModule); err != nil { panic(err) } - if err := flags.SetBPF(bpfModule); err != nil { + if err := flags.Get().SetBPF(bpfModule); err != nil { panic(err) } @@ -62,7 +62,7 @@ func Run(flags flags.Flags) { panic(err) } - if err := attachTracepoints(flags, bpfModule); err != nil { + if err := attachTracepoints(bpfModule); err != nil { panic(err) } @@ -76,7 +76,7 @@ func Run(flags flags.Flags) { pprofDone := make(chan struct{}) var cpuProfile, memProfile *os.File - if flags.PprofEnable { + if flags.Get().PprofEnable { if cpuProfile, err = os.Create("ior.cpuprofile"); err != nil { panic(err) } @@ -88,8 +88,8 @@ func Run(flags flags.Flags) { close(pprofDone) } - loop := newEventLoop(flags) - duration := time.Duration(flags.Duration) * time.Second + loop := newEventLoop() + duration := time.Duration(flags.Get().Duration) * time.Second fmt.Println("Probing for", duration) ctx, cancel := context.WithTimeout(context.Background(), duration) @@ -105,7 +105,7 @@ func Run(flags flags.Flags) { go func() { <-ctx.Done() fmt.Println(loop.stats()) - if flags.PprofEnable { + if flags.Get().PprofEnable { fmt.Println("Stoppig profiling, writing ior.cpuprofile and ior.memprofile") pprof.StopCPUProfile() pprof.WriteHeapProfile(memProfile) |
