diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-07 09:47:05 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-07 09:47:05 +0300 |
| commit | ed04ccd8e2297458ec97381806a05dea13090f0f (patch) | |
| tree | 99b707441b6990686bbd2773c177bdc3b8bf3313 /internal | |
| parent | ac05beabdbaa90597ed0cfcea781d5ab44d123ba (diff) | |
update docs and ascii banner
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/flags/flags.go | 4 | ||||
| -rw-r--r-- | internal/flags/version.go | 13 | ||||
| -rw-r--r-- | internal/ior.go | 5 | ||||
| -rw-r--r-- | internal/ior_mode_test.go | 12 |
4 files changed, 29 insertions, 5 deletions
diff --git a/internal/flags/flags.go b/internal/flags/flags.go index 9b1c3cf..5d00b74 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -42,6 +42,9 @@ type Config struct { CollapsedFields []string CountField string GlobalFilter globalfilter.Filter + + // ShowVersion prints the banner plus version and exits without running. + ShowVersion bool } var ( @@ -177,6 +180,7 @@ func parse() error { flag.BoolVar(&cfg.TestLiveFlames, "testliveflames", false, "Run TUI with continuously-updating synthetic flamegraph data for live keyboard-navigation testing") flag.DurationVar(&cfg.LiveInterval, "live-interval", cfg.LiveInterval, "Synthetic live flamegraph refresh interval for --testliveflames") flag.BoolVar(&cfg.TUIExportEnable, "tuiExport", cfg.TUIExportEnable, "Enable TUI CSV snapshot export files (separate from Parquet recording)") + flag.BoolVar(&cfg.ShowVersion, "version", false, "Print version banner and exit") fields := flag.String("fields", "", fmt.Sprintf("Comma separated list of fields to collapse, valid are: %v", validFields)) flag.StringVar(&cfg.CountField, "count", cfg.CountField, diff --git a/internal/flags/version.go b/internal/flags/version.go index 3db0b9f..583d19b 100644 --- a/internal/flags/version.go +++ b/internal/flags/version.go @@ -5,11 +5,14 @@ import "fmt" // Version is the current application version. const Version = "v0.0.1" -const asciiBannerTemplate = ` ___ _____ ___ _ _ -|_ _| / / _ \ | _ (_)___| |_ - | | / / (_) | | / / _ \ _| -|___/_/ \___/ |_|_\_\___/\__| NG - %s` +const asciiBannerTemplate = ` ██╗ ██╗ ██████╗ ██████╗ ██╗ ██████╗ ████████╗ + ██║ ██╔╝ ██╔═══██╗ ██╔══██╗ ██║ ██╔═══██╗ ╚══██╔══╝ + ██║ ██╔╝ ██║ ██║ ██████╔╝ ██║ ██║ ██║ ██║ + ██║ ██╔╝ ██║ ██║ ██╔══██╗ ██║ ██║ ██║ ██║ + ██║██╔╝ ╚██████╔╝ ██║ ██║ ██║ ╚██████╔╝ ██║ + ╚═╝╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ + ⚡ Next-Generation BPF I/O Syscall Tracer ⚡ + %s` // PrintVersion prints the banner with the current version. func PrintVersion() { diff --git a/internal/ior.go b/internal/ior.go index e6e7233..63da223 100644 --- a/internal/ior.go +++ b/internal/ior.go @@ -57,6 +57,11 @@ func dispatchRun(cfg flags.Config) error { if cfg.TestLiveFlames { return runTUITestLiveFlamesFn(cfg, tuiTestLiveFlamesStarter(cfg)) } + // All remaining modes require tracing, which needs root. Fail fast here so + // the TUI never starts (and hangs) when we already know it cannot trace. + if getEUID() != 0 { + return errRootPrivilegesRequired + } if isHeadlessParquetMode(cfg) { return runParquetFn(cfg) } diff --git a/internal/ior_mode_test.go b/internal/ior_mode_test.go index a7fcab1..ab0466d 100644 --- a/internal/ior_mode_test.go +++ b/internal/ior_mode_test.go @@ -95,13 +95,16 @@ func TestDispatchRunUsesTraceModeWhenRequested(t *testing.T) { origRunTUI := runTUIFn origRunTUITestFlames := runTUITestFlamesFn origRunTUITestLiveFlames := runTUITestLiveFlamesFn + origGetEUID := getEUID defer func() { runTraceFn = origRunTrace runParquetFn = origRunParquet runTUIFn = origRunTUI runTUITestFlamesFn = origRunTUITestFlames runTUITestLiveFlamesFn = origRunTUITestLiveFlames + getEUID = origGetEUID }() + getEUID = func() int { return 0 } traceCalled := false tuiCalled := false @@ -144,13 +147,16 @@ func TestDispatchRunUsesHeadlessParquetModeWhenRequested(t *testing.T) { origRunTUI := runTUIFn origRunTUITestFlames := runTUITestFlamesFn origRunTUITestLiveFlames := runTUITestLiveFlamesFn + origGetEUID := getEUID defer func() { runTraceFn = origRunTrace runParquetFn = origRunParquet runTUIFn = origRunTUI runTUITestFlamesFn = origRunTUITestFlames runTUITestLiveFlamesFn = origRunTUITestLiveFlames + getEUID = origGetEUID }() + getEUID = func() int { return 0 } traceCalled := false parquetCalled := false @@ -196,12 +202,15 @@ func TestDispatchRunUsesTUIWhenOnlyPprofEnabled(t *testing.T) { origRunTUI := runTUIFn origRunTUITestFlames := runTUITestFlamesFn origRunTUITestLiveFlames := runTUITestLiveFlamesFn + origGetEUID := getEUID defer func() { runTraceFn = origRunTrace runTUIFn = origRunTUI runTUITestFlamesFn = origRunTUITestFlames runTUITestLiveFlamesFn = origRunTUITestLiveFlames + getEUID = origGetEUID }() + getEUID = func() int { return 0 } traceCalled := false tuiCalled := false @@ -239,12 +248,15 @@ func TestDispatchRunUsesTUIStarterWhenNotPlain(t *testing.T) { origRunTUI := runTUIFn origRunTUITestFlames := runTUITestFlamesFn origRunTUITestLiveFlames := runTUITestLiveFlamesFn + origGetEUID := getEUID defer func() { runTraceWithContextFn = origRunTraceWithContext runTUIFn = origRunTUI runTUITestFlamesFn = origRunTUITestFlames runTUITestLiveFlamesFn = origRunTUITestLiveFlames + getEUID = origGetEUID }() + getEUID = func() int { return 0 } traceDone := make(chan struct{}, 1) runTraceWithContextFn = func(_ context.Context, _ flags.Config, started chan<- struct{}, configure func(*eventLoop)) error { |
