summaryrefslogtreecommitdiff
path: root/internal/export
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-13 20:04:48 +0300
committerPaul Buetow <paul@buetow.org>2026-05-13 20:04:48 +0300
commit251894cf3375812564ecf28392179b395cdda9c7 (patch)
tree83c3609ab591702e29a375923670e7622a33b5c7 /internal/export
parent78ea9e22e596255c5e23ce445d80641870674ca9 (diff)
refactor: break down functions exceeding 50 lines into smaller helpers
Split 22 production files across the codebase — event loop, TUI models, probe manager, dashboard, export, flag parsing, code generation, and ioworkload scenarios — so that no function body exceeds 50 lines. Each extracted helper carries its own comment explaining its role. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/export')
-rw-r--r--internal/export/snapshot_csv.go114
1 files changed, 69 insertions, 45 deletions
diff --git a/internal/export/snapshot_csv.go b/internal/export/snapshot_csv.go
index 591bd67..6f7312a 100644
--- a/internal/export/snapshot_csv.go
+++ b/internal/export/snapshot_csv.go
@@ -24,65 +24,89 @@ func SnapshotCSV(snap *statsengine.Snapshot) (filename string, retErr error) {
}()
w := csv.NewWriter(f)
+ if err := writeSnapshotRows(w, snap); err != nil {
+ return "", err
+ }
+ w.Flush()
+ if err := w.Error(); err != nil {
+ return "", err
+ }
+ return filename, nil
+}
- rows := [][]string{
+// writeSnapshotRows writes all CSV sections to w in order:
+// header, summary, per-syscall stats, file stats, process stats, histograms.
+func writeSnapshotRows(w *csv.Writer, snap *statsengine.Snapshot) error {
+ summaryRows := [][]string{
{"section", "name", "value1", "value2", "value3"},
- {"summary", "totals", fmt.Sprint(snapValue(snap, func(s *statsengine.Snapshot) uint64 { return s.TotalSyscalls })), fmt.Sprint(snapValue(snap, func(s *statsengine.Snapshot) uint64 { return s.TotalErrors })), fmt.Sprint(snapValue(snap, func(s *statsengine.Snapshot) uint64 { return s.TotalBytes }))},
- {"summary", "rates_per_sec", fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.SyscallRatePerSec })), fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.ReadBytesPerSec })), fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.WriteBytesPerSec }))},
- {"summary", "latency_gap_mean_ns", fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.LatencyMeanNs })), fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.GapMeanNs })), ""},
- {"summary", "trend", trendSummary(snap, func(s *statsengine.Snapshot) statsengine.Trend { return s.LatencyTrend }), trendSummary(snap, func(s *statsengine.Snapshot) statsengine.Trend { return s.GapTrend }), trendSummary(snap, func(s *statsengine.Snapshot) statsengine.Trend { return s.ThroughputTrend })},
+ {"summary", "totals",
+ fmt.Sprint(snapValue(snap, func(s *statsengine.Snapshot) uint64 { return s.TotalSyscalls })),
+ fmt.Sprint(snapValue(snap, func(s *statsengine.Snapshot) uint64 { return s.TotalErrors })),
+ fmt.Sprint(snapValue(snap, func(s *statsengine.Snapshot) uint64 { return s.TotalBytes }))},
+ {"summary", "rates_per_sec",
+ fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.SyscallRatePerSec })),
+ fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.ReadBytesPerSec })),
+ fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.WriteBytesPerSec }))},
+ {"summary", "latency_gap_mean_ns",
+ fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.LatencyMeanNs })),
+ fmt.Sprintf("%.2f", snapValueF(snap, func(s *statsengine.Snapshot) float64 { return s.GapMeanNs })), ""},
+ {"summary", "trend",
+ trendSummary(snap, func(s *statsengine.Snapshot) statsengine.Trend { return s.LatencyTrend }),
+ trendSummary(snap, func(s *statsengine.Snapshot) statsengine.Trend { return s.GapTrend }),
+ trendSummary(snap, func(s *statsengine.Snapshot) statsengine.Trend { return s.ThroughputTrend })},
}
- for _, row := range rows {
+ for _, row := range summaryRows {
if err := w.Write(row); err != nil {
- return "", err
+ return err
}
}
+ if snap == nil {
+ return nil
+ }
+ return writeSnapshotDetailRows(w, snap)
+}
- if snap != nil {
- for _, s := range snap.Syscalls() {
- if err := w.Write([]string{"syscall", s.Name, fmt.Sprint(s.Count), fmt.Sprintf("%.2f", s.RatePerSec), fmt.Sprint(s.Bytes)}); err != nil {
- return "", err
- }
- if err := w.Write([]string{"syscall_latency_ns", s.Name, fmt.Sprintf("%.2f", s.LatencyMeanNs), fmt.Sprint(s.LatencyMinNs), fmt.Sprint(s.LatencyMaxNs)}); err != nil {
- return "", err
- }
- if err := w.Write([]string{"syscall_percentiles_ns", s.Name, fmt.Sprint(s.LatencyP50Ns), fmt.Sprint(s.LatencyP95Ns), fmt.Sprint(s.LatencyP99Ns)}); err != nil {
- return "", err
- }
+// writeSnapshotDetailRows writes per-item rows for syscalls, files, processes,
+// and histograms. It is called only when snap is non-nil.
+func writeSnapshotDetailRows(w *csv.Writer, snap *statsengine.Snapshot) error {
+ for _, s := range snap.Syscalls() {
+ if err := w.Write([]string{"syscall", s.Name, fmt.Sprint(s.Count), fmt.Sprintf("%.2f", s.RatePerSec), fmt.Sprint(s.Bytes)}); err != nil {
+ return err
}
- for _, r := range snap.Files() {
- if err := w.Write([]string{"file", r.Path, fmt.Sprint(r.Accesses), fmt.Sprint(r.BytesRead), fmt.Sprint(r.BytesWritten)}); err != nil {
- return "", err
- }
- if err := w.Write([]string{"file_latency_ns", r.Path, fmt.Sprintf("%.2f", r.AvgLatencyNs), fmt.Sprint(r.MaxLatencyNs), ""}); err != nil {
- return "", err
- }
+ if err := w.Write([]string{"syscall_latency_ns", s.Name, fmt.Sprintf("%.2f", s.LatencyMeanNs), fmt.Sprint(s.LatencyMinNs), fmt.Sprint(s.LatencyMaxNs)}); err != nil {
+ return err
}
- for _, p := range snap.Processes() {
- if err := w.Write([]string{"process", fmt.Sprint(p.PID), fmt.Sprint(p.Syscalls), fmt.Sprintf("%.2f", p.RatePerSec), fmt.Sprint(p.Bytes)}); err != nil {
- return "", err
- }
- if err := w.Write([]string{"process_latency_ns", fmt.Sprint(p.PID), fmt.Sprintf("%.2f", p.AvgLatencyNs), "", ""}); err != nil {
- return "", err
- }
+ if err := w.Write([]string{"syscall_percentiles_ns", s.Name, fmt.Sprint(s.LatencyP50Ns), fmt.Sprint(s.LatencyP95Ns), fmt.Sprint(s.LatencyP99Ns)}); err != nil {
+ return err
}
- for _, b := range snap.LatencyHistogram.Buckets() {
- if err := w.Write([]string{"latency_hist", b.Label, fmt.Sprint(b.Count), fmt.Sprint(b.LowerNs), fmt.Sprint(b.UpperNs)}); err != nil {
- return "", err
- }
+ }
+ for _, r := range snap.Files() {
+ if err := w.Write([]string{"file", r.Path, fmt.Sprint(r.Accesses), fmt.Sprint(r.BytesRead), fmt.Sprint(r.BytesWritten)}); err != nil {
+ return err
}
- for _, b := range snap.GapHistogram.Buckets() {
- if err := w.Write([]string{"gap_hist", b.Label, fmt.Sprint(b.Count), fmt.Sprint(b.LowerNs), fmt.Sprint(b.UpperNs)}); err != nil {
- return "", err
- }
+ if err := w.Write([]string{"file_latency_ns", r.Path, fmt.Sprintf("%.2f", r.AvgLatencyNs), fmt.Sprint(r.MaxLatencyNs), ""}); err != nil {
+ return err
}
}
-
- w.Flush()
- if err := w.Error(); err != nil {
- return "", err
+ for _, p := range snap.Processes() {
+ if err := w.Write([]string{"process", fmt.Sprint(p.PID), fmt.Sprint(p.Syscalls), fmt.Sprintf("%.2f", p.RatePerSec), fmt.Sprint(p.Bytes)}); err != nil {
+ return err
+ }
+ if err := w.Write([]string{"process_latency_ns", fmt.Sprint(p.PID), fmt.Sprintf("%.2f", p.AvgLatencyNs), "", ""}); err != nil {
+ return err
+ }
}
- return filename, nil
+ for _, b := range snap.LatencyHistogram.Buckets() {
+ if err := w.Write([]string{"latency_hist", b.Label, fmt.Sprint(b.Count), fmt.Sprint(b.LowerNs), fmt.Sprint(b.UpperNs)}); err != nil {
+ return err
+ }
+ }
+ for _, b := range snap.GapHistogram.Buckets() {
+ if err := w.Write([]string{"gap_hist", b.Label, fmt.Sprint(b.Count), fmt.Sprint(b.LowerNs), fmt.Sprint(b.UpperNs)}); err != nil {
+ return err
+ }
+ }
+ return nil
}
func snapValue(snap *statsengine.Snapshot, get func(*statsengine.Snapshot) uint64) uint64 {