Skip to content

feat: procpidstat record/report support (003)#138

Merged
lesovsky merged 37 commits into
masterfrom
develop
May 19, 2026
Merged

feat: procpidstat record/report support (003)#138
lesovsky merged 37 commits into
masterfrom
develop

Conversation

@lesovsky
Copy link
Copy Markdown
Owner

Summary

  • Adds pgcenter record / pgcenter report -N support for the per-process system stats screen (Shift+S, procpidstat). Closes tech-debt [002].
  • MVC split of buildProcPidResultbuildProcPidResultRaw + formatProcPidResultForDisplay; exports BuildProcPidResult, ReadProcPidStat, ReadProcPidIO, GetSysticksLocal, SysInfo
  • tarRecorder is now stateful: prev/curr ProcPidStat/ProcPidIO maps, sysinfo.TIMESTAMP.json written per tick, local/remote gate via db.Local
  • pgcenter report -N (--proc-stats): reads recorded procpidstat data with full formatting support (-s, -e, -o, -g, -l, -t)

Also includes feature 002 (per-process iodelay columns, iodelay_total,s + %iodelay in Shift+S screen).

Test plan

  • make test — all green
  • make lint — clean
  • make build && pgcenter record -c 3 -i 1s -f /tmp/test.tar && pgcenter report -N -f /tmp/test.tar — non-empty output with timestamps
  • pgcenter report -N -f report/testdata/pgcenter.stat.golden.tar — INFO "no procpidstat data", exit 0
  • pgcenter top → Shift+S — 19 columns, no panic (manual)

🤖 Generated with Claude Code

Alexey Lesovsky and others added 30 commits May 18, 2026 21:17
New TUI screen showing PostgreSQL backend CPU and IO utilization
from procfs — user-spec, interview, and validation reports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Column names now follow pgcenter convention: name,unit / %name
  (all_total,s / %all / read,KiB/s etc.)
- UX section corrected: ↑/↓ change column width, / sets filter
- Update all in-text column references to match new names
- Add Q21/Q22 to interview capturing iodelay and record/report scope decisions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Architecture: procpidstat view + Collector enrichment pattern.
8 implementation tasks across 3 waves + Final Wave.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use CollectExtra int on View (not string name detection)
- IOAvailable bool via view.View channel (not inaccessible Collector field)
- record/stat.go → record/record.go (correct file)
- Fix QueryAgeThresh template syntax (ne "", not gt)
- First tick rate = 0 explicitly (not approximation)
- Add stale PID cleanup to prevent memory growth
- PID integer validation via strconv.Atoi before path construction
- Isolate dialogChangeAge guard from compound dialog guard
- Merge Tasks 6+7 (both modify top/config_view.go, wave conflict)
- Add itv=0 division-by-zero guard
- Specify ticks source (Collector.config.ticks)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- viewSwitchHandler: manual view patching (load→patch→send) instead of wrong API usage
- CPU % formula: direct Δjiffies/(refresh_s*ticks)*100/cpuCount, not sValue
- IO rate: ΔBytes/refresh_s/1024 directly
- itv source: float64(int(refresh/time.Second)) from Update() top-level
- QueryAgeThresh: always-embedded convention (no conditional guard)
- Add Filters: map[int]*regexp.Regexp{} to view entry (nil map panic prevention)
- CollectExtra change-detection in collectStat() to trigger Reset() on view switch
- Add top/stat.go to modified files (collectStat change-detection)
- Add dev-security-auditor to Tasks 4, 5, 6
- Column widths: query gets remaining width via align.SetAlign()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 validation rounds, all 5 validators approved.
Minor cleanup: Task 2/4 descriptions trimmed of impl details;
dev-security-auditor added to Task 2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wave 1: tasks 01 (procfs parsers), 02 (SQL query) — independent
Wave 2: tasks 03 (result builder), 04 (view registration) — depends on W1
Wave 3: tasks 05 (collector), 06 (hotkey + guards) — depends on W2
Final:  task 07 (pre-deploy QA) — depends on W3

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CollectProcPidStat = 6 (not 5) — iota offset from pgProcUptimeQuery string const
- Task 03 depends_on: ["01", "02"] — wave completion precondition
- All tasks: add decisions.md and overview.md to Context Files
- Task 04: update record_test.go expected counts, fix 21 views (not 20)
- Task 05: itv type float64 consistent with buildProcPidResult signature
- Task 06: fix TDD Anchor (TUI callbacks not unit-testable), fix line number
- Task 01: fix misleading utime/stime index description

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CheckIOAvailable() exported (stat→top cross-package call requires export)
- Task 05: itv is int, pass float64(itv) at buildProcPidResult call site
- Task 05: CollectProcPidStat = 6 in all references
- Tech-spec: CheckIOAvailable() exported form

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Task 03: buildProcPidResult signature itv float64 (not int)
- Task 03: CheckIOAvailable() (exported) in all references
- Task 05: float64(itv) cast documented at call site
- Task 05: postgres.NewTestConnect() correct helper name

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 validation rounds. 7 tasks across 3 waves ready for implementation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New TUI screen (Shift+S) showing PostgreSQL backend CPU and IO utilization
from Linux procfs alongside pg_stat_activity columns. 17 columns: pid,
datname, usename, state, wait_etype, wait_event, accumulated CPU (HH:MM:SS),
accumulated IO (KiB), CPU rates (%), IO rates (KiB/s), query.

Features:
- Local mode only (procfs not available for remote connections)
- Graceful degradation when /proc/[pid]/io is inaccessible (EACCES)
- I/A filters work same as activity screen
- pgcenter record skips procpidstat (NotRecordable)
- Panic-safe: 17-col guarantee prevents issue #99 class errors

New packages: internal/stat/procpidstat.go
New views: procpidstat in internal/view/view.go
New query: internal/query/procpidstat.go
Collector: internal/stat/stat.go (CollectExtra mechanism)
TUI: top/config_view.go, top/keybindings.go, top/dialog.go, top/help.go
Docs: features-catalog.md, decisions-log.md, tech-debt.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…column narrative, build gap, task descriptions
…elay-procpidstat)

Add two new columns to the S-screen (Shift+S):
- iodelay_total,s — accumulated IO wait time (HH:MM:SS) from /proc/[pid]/stat field 42
- %iodelay — fraction of time spent in D-state between ticks (%)

Availability probe reads /proc/sys/kernel/task_delayacct at screen-open time.
When disabled: both columns render as "" + warning in cmdline area.
Combined warning when both IO and delay accounting are unavailable.

%iodelay is not normalized by cpuCount (wall-clock blocked time, not CPU utilization).
Resolves tech debt [001]. Supersedes ADR deferring iodelay to Netlink taskstats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…alog, ADR log, tech debt, archive

- architecture.md: update procpidstat section (17→19 cols, add iodelay source, both probes)
- patterns.md: extend printCmdline mutual exclusion note (4-branch pattern)
- user-spec: add Post-implementation section (2 divergences, 2 added, 1 deferred)
- metrics: finalize and copy to docs/metrics/
- archive: move docs/features/002-feat-iodelay-procpidstat/ → archive/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, PID validation, test file coverage, Task02 trim

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…04 security reviewer, AC formula clarification

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Alexey Lesovsky and others added 7 commits May 19, 2026 18:36
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…port (003)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…st ownership, Task05 details

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… export call sites, loop placement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rt (003)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds pgcenter record/report support for per-process system stats (procpidstat, Shift+S).
Closes tech-debt [002].

- MVC split of buildProcPidResult (buildProcPidResultRaw + formatProcPidResultForDisplay)
- Exports: BuildProcPidResult, ReadProcPidStat, ReadProcPidIO, GetSysticksLocal, SysInfo
- tarRecorder stateful: prev/curr ProcPidStat/ProcPidIO maps, sysinfo.TIMESTAMP.json per tick
- Local/remote gate via db.Local in app.setup()
- pgcenter report -N flag; sysinfo merge into metadata; WARNING/INFO detection
- 18 review JSON reports, QA passed 10/11 AC (AC11 TUI requires manual check)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lesovsky lesovsky merged commit 83f95cd into master May 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant