| Age | Commit message (Collapse) | Author |
|
setupEventChannel now returns the *bpf.RingBuffer handle alongside the
event channel. Both callers (runTraceWithContext, runHeadlessParquet)
defer rb.Stop() so the libbpfgo polling goroutine and C ring_buffer
struct are released promptly when the trace context is cancelled,
rather than waiting for bpfModule.Close() to eventually call rb.Close().
rb.Stop() and rb.Close() are both idempotent, so the double-call from
the defer and from bpfModule.Close() is safe.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Add tracepoints.Selector type with ShouldAttach method and ParseSelector
constructor, replacing the raw TracepointsToAttach/TracepointsToExclude
regex slices on flags.Config.
- Add flags.BuildTraceFilter as a standalone function replacing the
Config.TraceFilter() method, keeping filter-building logic out of the
config struct.
- Remove stale ShouldIAttachTracepoint noise-filter entry from Magefile.
- Add selector_test.go with full coverage of ParseSelector and ShouldAttach.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
The testRace and goBuildRace targets already existed in Magefile.go
(added in commit 70acff7) but were missing from the build/test command
reference in AGENTS.md. Add the testRace entry so contributors know
how to run the full test suite under Go's race detector.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Four near-identical sorted-rows functions (sortedFileSnapshots,
sortedDirSnapshots, sortedSyscallSnapshots, sortedProcessTableRows)
each repeated the same guard-clone-sort-tiebreak-apply pattern.
Replace them with a single generic sortedWithState[T,K] in sort.go
that accepts per-tab byKey and tiebreak comparators as parameters.
Remove now-unused slices imports from syscalls.go and processes.go.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
fileRankHeap Len/Less/Swap converted to pointer receivers to match
Push/Pop; bubbleChart HasNodes and AnimationState Settled converted
to pointer receivers to match all other methods on their types.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace sync.WaitGroup with errgroup.Group in buildSubSnapshots so errors from
sub-builders (buildSyscallSnapshots, buildFileSnapshots, buildProcessSnapshots,
buildHistogramSnapshot) are captured and propagated rather than silently dropped.
Change Engine.Snapshot() to return (*Snapshot, error), update runtime.SnapshotSource
and dashboard.SnapshotSource interfaces accordingly, and adjust all callers in
tui.go, dashboard/model.go, and the test helpers.
Each sub-builder now returns (result, error); the error return is currently
always nil but establishes the contract for future validation. The per-type
Snapshot() convenience methods (histogram, syscall, file, process) panic on
error since they are internal helpers where failure would be a programming bug.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
paths
Swap out ad-hoc += string concatenation in the flamegraph toolbar/status
lines, dashboard filter summary, bubble/treemap status lines, eventstream
view, processes tab, and probes list for strings.Builder, eliminating
redundant allocations on every render tick. Also update dashboard/model_test.go
fake SnapshotSource implementations to match the updated interface signature.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduce kindregistry.go with a kindMeta struct (structName, enterAccepted)
and a kindRegistry map keyed by TracepointKind. Replace the switch in
isEnterRejected (codegen.go) and the switch in eventStructName (bpfhandler.go)
with lookupKind registry lookups. Adding a new TracepointKind now only
requires a single registry entry — no switch statements need to be touched.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace three time.Sleep usages in tests with channel-based and
happens-before reasoning:
- internal/ior_mode_test.go: waitForStreamRows no longer polls with
time.Sleep(1ms); starter() only returns after the trace goroutine
closes the started channel, which happens after all printCb pushes,
forming a happens-before edge that guarantees the rows are visible.
- internal/probemanager/manager_test.go: the intermediate attach-count
assertions (enter==1, exit==0) are now checked immediately after
<-enterBlocked, which is itself a happens-before edge, rather than
after a 50ms sleep. The concurrent goroutine 2 is started afterwards;
the final count assertions after both goroutines complete verify the
serialization invariant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Wrap processRawEvent calls in a new processRawEventSafe() helper that
uses defer/recover to catch any panic from a callback and convert it into
a warning notification via warningCb, preventing a single bad event from
crashing the whole process. Added TestEventsPanicInCallbackIsRecoveredAndNotified
to verify the recovery behaviour end-to-end.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Extract the per-pid goroutine body from scanAllThreadsFrom into a named
scanThreadsWorker function. This removes both defer statements from the
anonymous closure that was spawned inside a for loop: the semaphore
release is now an explicit <-sem call immediately after I/O completes,
and wg.Done() is called directly after scanThreadsWorker returns.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
EqValue() previously returned int, silently truncating int64 values that
exceed math.MaxInt32 on 32-bit architectures. Change the return type to
int64 and update callers (ior.go, filterstack.go) with explicit int()
casts that are safe because Linux PID/TID values never exceed 4194304.
Add TestEqValueReturnsInt64PreservesLargeValues to guard the fix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Extend the var _ Interface = (*Concrete)(nil) coverage started in j3 to
cover the remaining public types not yet guarded:
- *file.FdFile → file.File (file/file.go)
- streamrow.Row → globalfilter.Candidate (streamrow/row.go; adds
globalfilter import — no cycle since globalfilter does not import streamrow)
- *streamrow.RingBuffer → eventstream.Source
(tui/eventstream/ringbuffer.go; already a type alias for streamrow.RingBuffer)
- *probemanager.Manager → tui/probes.Manager (tui/probes/model.go)
- All 9 generated *types.*Event types → event.Event in the new file
internal/event/interface_assertions.go (non-generated, lives in the event
package which already imports types, so no new import cycle)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
pidpicker, tui/export
Before: probes=30%, tui/common=41%, export=0%, streamrow=25%, pidpicker=59%, tui/export=45%
After: probes=89%, tui/common=97%, export=77%, streamrow=100%, pidpicker=73%, tui/export=99%
New test files cover RingBuffer push/wrap/reset, Row accessor methods, nil
Sequencer safety, SnapshotCSV nil and data paths, helper functions snapValue /
snapValueF / trendSummary, all table navigation keys, VisibleTableWindow/
ClampTableCol edge cases, RenderTableHeader/Row, PickerShortHelp, probe modal
navigation/search/toggle/view/error paths, truncateText/sanitizeOneLine,
export modal View rendering, key navigation, status messages, scanAllThreadsFrom,
readThreadInfo guards, formatProcess variants, and clamp helper.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Extract GetTraceId/GetPid/GetTid into EventIdentity (routing and
aggregation concerns) and Recycle into EventLifecycle (pool memory
management). Event embeds both and retains String, GetTime, Equals.
All existing implementations satisfy the composed interface unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Run gofmt -w on 9 files that had minor alignment/whitespace drift
(pair.go, filter.go, ior_mode_registry.go, ior_mode_test.go,
runtime.go, engine.go, dashboard/model.go, flamegraph/model.go,
flamegraph/renderer.go).
Add two new Mage targets to Magefile.go:
- `mage fmt` – rewrites all .go files in-place via go/format
- `mage fmtCheck` – dry-run check; fails with a list of offending
files, suitable as a CI gate
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
startTraceCmdWithTimeout
Per Go convention, context.Context must always be the first parameter. Updated
both function signatures and all call sites in tracelifecycle.go and tui_test.go.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace the buffered errCh (capacity 1) with an unbuffered channel plus a
dedicated done channel that is closed via defer when the outer function
returns for any reason (ctx cancellation, startedCh signal, or startup
error). The trace goroutine selects on both errCh and done when delivering
its result, guaranteeing it can always exit and is never left blocked
waiting on a channel that nobody will drain.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
User-supplied filenames are now sanitised through filepath.Base before
being joined with exportDir, so inputs like "../../etc/passwd" can no
longer write files outside the intended export directory. Pure directory
references ("..") are rejected outright. Two new tests cover both the
unit-level sanitisation and the end-to-end exportRowsToCSV path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Adds maxFilterHistory=50 and evicts the oldest entry from both the
history and label-stack slices in filterStack.push whenever the cap is
exceeded. Covers the fix with a new table-driven unit test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
paths with spaces
Replace strings.Fields with a new shellSplit function that implements
POSIX-like quoting rules (single-quotes, double-quotes, backslash escapes),
so EDITOR values such as '/My Editor/hx' or "/path/with spaces/hx" --wait
are correctly parsed rather than mangled into multiple path components.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
A negative or zero -duration was silently accepted, causing the trace
context to be cancelled immediately (time.Duration(N) * time.Second with
N <= 0 yields a non-positive timeout), so no events were ever captured.
parseFromFlagSet now returns an error for Duration <= 0, matching the
existing pattern used for -resetTimer validation.
Three new tests cover the negative, zero, and valid positive cases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
BPF timestamps can be non-monotonic across CPUs (NTP step, TSC skew).
When exit < enter or enter < prevPairTime the uint64 subtraction wraps
to a huge value, corrupting latency histograms and flamegraph weights.
Clamp both Duration and DurationToPrev to 0 instead of underflowing.
Add TestPairCalculateDurationsNegativeDelta to cover this case.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
indefinite blocking
Frozen cgroup entries in /proc could stall a lookup worker goroutine
forever, preventing clean shutdown because shutdown() waits on
workersWG.Wait(). Changed resolveFn signature to accept context.Context
and wrap each call in context.WithTimeout(1s) in both lookupWorker and
seedTrackedPidComm. Added TestCommResolverLookupWorkerRespectsTimeout
to verify the pending entry is cleared after a timeout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Wrap the bare `defer mgr.Close()` calls in runTraceWithContext (ior.go)
and runHeadlessParquet (ior_parquet_sink.go) in a closure that checks
the returned error and logs it via logln, so BPF probe-detach failures
and map-cleanup errors are no longer silently discarded.
bpfModule.Close() has no return value and is unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Raw errors from GetMap and SetMaxEntries gave no indication of which BPF
map failed. Wrap both with fmt.Errorf including the map name (and target
size for SetMaxEntries) so callers can immediately identify the offending
map. Also simplify resizeBPFMaps to return directly since resizeBPFMap
now carries full context, removing the redundant outer wrap.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
BPF attach failure
If kernel lock contention or another issue causes BPF probe attachment to
stall, the TUI previously remained in the 'Attaching tracepoints...' spinner
state forever. startTraceCmdWithTimeout now races the starter goroutine against
a configurable deadline (defaultStartupTimeout = 30s) and returns a
TracingErrorMsg with a clear message when the deadline expires. The stuck
goroutine is cleaned up when the caller cancels the trace context on the next
user action (e.g. traceLifecycle.stop). Two new tests cover the timeout and
context-cancel paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Silent disk-full or permission-denied failures when writing the heap
profile are now surfaced via logln so the operator can diagnose them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Panics in non-setup code violate the AGENTS.md convention. Replace all
three panic(err) calls with fmt.Fprintf(os.Stderr, ...) + os.Exit(1) so
the process exits cleanly with a human-readable message instead of a
stack trace.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
On serialization failure the deferred close was called but its error
silently discarded, potentially masking filesystem issues such as a
full-disk condition detected only at close time. Capture the close
error and join it with the existing retErr via errors.Join so callers
see the full picture.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
This reverts commit 66956756ba018ed32a455aa57f04517af2c7357f.
|
|
The libbpfgo RingBuffer.Poll() previously launched a background goroutine
that could fail with a fatal C-level errno (e.g. EBADF, EPERM) and silently
exit, causing BPF events to stop flowing with no diagnostic.
Changes:
- Patch ../libbpfgo (replace directive) so RingBuffer.Poll() returns a
buffered <-chan error that the background goroutine sends to on failure.
- In setupEventChannel, capture the error channel and spawn a monitoring
goroutine that logs any poll error to stderr.
- Update go.mod with the replace directive and drop the now-unused remote
checksum entries from go.sum.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Move ParseDurationNs to globalfilter/parser and move CompareOpSymbol,
AppendStringSummary, AppendNumericSummary, FilterSummary to
globalfilter/presenter. The domain Filter type retains only matching,
equality, clone, and active-predicate logic. All callers updated;
tests for the new sub-packages added.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Remove the global atomic.Pointer[Config], sync.Once, and parseErr fields
from the flags package. Parse() now returns (Config, error) directly,
eliminating all global-state accessors (Get, SetPidFilter, SetTidFilter,
SetTUIExportEnable, setCurrent, updateCurrent). The internal parse logic
is factored into parseFromFlagSet so tests can inject a fresh FlagSet
without touching os.Args or package-level state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduce runnerDeps struct to bundle all injectable function dependencies
(getEUID, runTrace, runParquet, runTraceWithContext, runTUI*) that were
previously package-level vars overridden in tests. The modeRegistry now
carries a runnerDeps instance and passes it to each handler's run() method,
eliminating global state mutation in tests.
- Add runnerDeps struct and defaultRunnerDeps() constructor in ior_mode_registry.go
- Convert modeRegistry from a []modeHandler slice type to a struct with
handlers + deps fields; add newModeRegistry(deps) constructor
- Update modeHandler.run() signature to accept runnerDeps; handlers call
deps.getEUID / deps.runTrace etc. instead of globals
- Update SetTUIRunners to write into defaultRegistry.deps instead of
package-level vars
- Add dispatchRunWithDeps helper for test isolation without global mutation
- Remove root-privilege check from runTraceWithContext and runHeadlessParquet;
each mode handler owns the EUID gate via deps.getEUID
- Rewrite ior_mode_test.go: replace save/restore patterns with stubDeps()
helper and dispatchRunWithDeps; add three new root-privilege tests
replacing the removed TestRunTraceWithContextRequiresRoot
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Export AppendStringSummary and AppendNumericSummary from globalfilter so
filterstack.go can delegate to the canonical token-formatting logic instead
of reimplementing fmt.Sprintf("%s~%s") and fmt.Sprintf("%sOP%s") in
appendStringFilterChange / appendNumericFilterChange. Drop the now-unused
fmt, strconv, and time imports from filterstack.go.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace three near-identical trimOldest* functions with a single generic
trimLRU[K comparable, V any] helper; the three wrappers now delegate to it,
with trimOldestPendingPairs passing a cleanup callback for Recycle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
values
Introduces statsengine.DefaultTopN = 64 as the canonical named constant for
the top-N capacity used when constructing an Engine. Removes the local
defaultEngineCapacity constant from runtime_builder.go and updates all
call sites to reference statsengine.DefaultTopN instead of bare 64.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Add var _ Interface = (*ConcreteType)(nil) assertions for:
- *flamegraph.LiveTrie → runtime.{Snapshotter,Configurator,LiveTrieSource}
and tui/flamegraph.{Snapshotter,Configurator,LiveTrieSource}
- *probemanager.Manager → runtime.ProbeManager
- *statsengine.Engine → runtime.SnapshotSource
- *streamrow.RingBuffer → runtime.EventSink
- *runtimeBindings (tui) → runtime.TraceRuntimeBindings
- *lateBoundDashboardSource → dashboard.SnapshotSource
- libbpfTracepointProgram/Module → probemanager.{Program,Attacher}
Assertions are grouped close to their interface definitions to avoid
introducing new import cycles (runtime already imports all affected
packages; tui/flamegraph already imports coreflamegraph).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
The receiver name flags shadowed the package name flags, making the
package inaccessible inside the method body. Rename to f to match all
other receivers in flags.go and add a doc comment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Document every exported field in Config (flags package) and Filter,
NumericFilter, StringFilter (globalfilter package) with a concise one-line
doc comment describing its purpose and behaviour.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Applies the Interface Segregation Principle to LiveTrieSource in both
internal/runtime and internal/tui/flamegraph. The monolithic interface is
replaced by two focused sub-interfaces — Snapshotter (read-only: Version,
SnapshotJSON, SnapshotTree) and Configurator (mutating: Fields, CountField,
Reconfigure, SetCountField, Reset) — which LiveTrieSource then embeds so all
existing consumers continue to compile unchanged. The buildSnapshotMsg helper
is narrowed to Snapshotter since it only reads snapshot data, preventing
accidental mutation from the background goroutine.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduce tabDescriptor struct and tabDescriptors map in new
tabregistry.go. Each tab registers its name, short name, ordered
position, allowed viz modes, render function, scroll handler, and
optional init tick command. Adding a new tab now requires only a
single registry entry — no existing switch/if chains need editing.
Key changes:
- Tab.String() and tabLabel() use lookupTab() instead of a switch
- renderActiveTabContent() dispatches via d.Render (replaces renderActiveTab switch)
- handleScrollKey() dispatches via d.HandleScroll (replaces tab switch)
- Init() and postKeyTransitionCmd() use d.InitCmd (replaces stream/flame tab checks)
- allowedVizModes() delegates to tabAllowedVizModes() from registry
- orderedTabs() replaces hardcoded allTabs slice, derived from Position field
- bubbleChartFor() helper eliminates 5 repeated switch-on-tab for chart ops
- toggleBubbleMetric, tickActiveBubbleChart, moveBubbleSelection,
activeBubbleChartHasNodes all use bubbleChartFor()
- refreshBubbleData split into two focused functions under 50 lines
- Two pre-existing test functions over 50 lines refactored
All tests pass; go build ./internal/tui/... clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduce a ModeRegistry pattern so new execution modes can be added
without modifying the dispatch or validation switch/if chains. Each mode
is a self-contained modeHandler (match + validate + run); the ordered
defaultRegistry replaces the open if-chains in dispatchRun and
validateRunConfig, which become thin wrappers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Split the 1389-line tui.go Model into three focused sub-controllers
that each own a single concern:
- filterstack.go (filterStack): owns the filter chain, undo history,
and label stack; provides push/pop/rebindProcessFilters API so the
Model never manipulates filter slices directly.
- tracelifecycle.go (traceLifecycle): owns trace start/stop and the
active context.CancelFunc; provides beginCmd/stop API; also houses
the recorder helpers (recorderStart/Stop/Active/Status) and the
auto-reset cycle logic (nextAutoResetInterval, autoResetCycle).
- screenrouter.go (screenRouter): owns the picker-return bookmark
(pickerReturn) and the applyWindowSizeToPicker helper so screen
transition code in tui.go delegates to it.
The Model.Update switch is split into dispatchTypedMsg (framework
messages) and dispatchAppMsg (app messages) to keep each helper
under the 50-line limit. View is split into viewPickerScreen and
viewDashboardScreen for the same reason.
All functions are ≤50 lines. go test ./internal/tui/... passes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
RuntimeBuilder encapsulates allocation of per-trace-session components
(statsengine.Engine, streamrow.RingBuffer, Sequencer, flamegraph.LiveTrie);
buildTUIRuntime, buildTestFlamesRuntime, and buildTestLiveFlamesRuntime now
delegate construction to RuntimeBuilder.Build() and focus only on wiring.
wireRuntimeBindings is extracted to isolate the context-binding wiring step.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Break the god-class Model in internal/tui/flamegraph/model.go into four
focused sub-controllers that each own a single concern:
- ZoomNavigator : zoom path, stack, root node, and reset/undo logic
- SelectionManager: selected frame index, clamp, traversal, navigation
- FrameAnimator : spring animation, frame layout swap, ancestry index
- SearchController: search query, match indices, filter-visible set
All four are embedded in Model so existing field access (m.selectedIdx,
m.zoomPath, etc.) is promoted unchanged, keeping tests and callers intact.
Model methods now delegate to the sub-controllers rather than holding all
logic inline.
Also split RenderTerminalView (88 lines) into computeRenderParams,
buildToolbar, buildFilteredStatus, and buildNormalStatus helpers, and
extracted buildSnapshotMsg from RefreshFromLiveTrieCmd.
All functions are now ≤ 50 lines. All tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduce internal/runtime as a neutral contract package that both the
core engine (internal) and the TUI layer (internal/tui) depend on.
- internal/runtime: defines TraceStarter, StreamSource, EventSink,
LiveTrieSource, SnapshotSource, ProbeManager, RuntimePublisher,
RuntimeState, TraceRuntimeBindings, and all context key/helper
functions (RuntimeBindingsFromContext, RuntimePublisherFromContext,
ContextWithRuntimeBindings, ContextWithTraceFilters,
TraceFiltersFromContext). These were previously defined in
internal/tui, forcing the core package to import the TUI layer.
- internal/streamrow: add RingBuffer (moved from internal/tui/eventstream)
so the core tracing engine can use the ring buffer without importing
the TUI layer.
- internal/tui/eventstream/ringbuffer.go: change to a thin re-export of
streamrow.RingBuffer via a type alias, preserving the existing API for
all callers within the TUI layer.
- internal/tui/tui.go: replace locally-defined interface declarations
(TraceStarter, SnapshotSource, ProbeManager, RuntimePublisher,
RuntimeState, TraceRuntimeBindings) with type aliases from
internal/runtime. Delegate all context helper functions to runtime.
- internal/ior.go, internal/ior_bpfsetup.go: remove imports of
internal/tui and internal/tui/eventstream; use internal/runtime and
internal/streamrow instead. Add SetTUIRunners injection point so the
concrete TUI runner functions are wired in by cmd/ior/main.go.
- cmd/ior/main.go: call internal.SetTUIRunners with the concrete TUI
runner functions before internal.Run, completing the wiring without
creating a cycle.
- Test files (internal/ior_mode_test.go, internal/bench_pipeline_test.go):
updated to use runtime.* and streamrow.* types in place of tui.* and
eventstream.* types.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Extract renderActiveContentViz (treemap/icicle/bubble dispatch) and
renderActiveContentTable (table-with-sort dispatch) from the original
56-line renderActiveContent, reducing it to 15 lines of code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
50-line limit
Extract buildTUIRuntime and makeTUIEventLoopConfigurer from the monolithic
tuiTraceStarterFromRunTrace closure, and extract maybePrependFlamegraphConfigure
and finaliseTrace from runTraceWithContext. All functions are now <= 50 lines.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|