Skip to content

dashboard: a Keeper members panel — role, Raft log position and snapshot settings per member - #58

Merged
CamiloSierraH merged 4 commits into
mainfrom
cami/keeper-members-panel
Oct 20, 2026
Merged

CamiloSierraH merged 4 commits into
mainfrom
cami/keeper-members-panel

Conversation

@CamiloSierraH

@CamiloSierraH CamiloSierraH commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Why

PR #56 collects what each Keeper member reports about itself (role, Raft log position, snapshot size and settings), and the pre-pass draws its HC-3.18–3.20 findings from it. Only the skill could see those findings. A customer opening dashboard.html saw nothing of them: not the member that fell behind the leader's retained log, and not the 2 GiB snapshot sent unchunked.

Builds on #56 (merged). It reads the keeper/ files #56 introduced. Main has been merged in, so the diff is now only this PR's own 7 files.

What changed

The dashboard's Keeper section gains a Keeper members table, one row per member:

member · ensemble · state · role · version · Raft log first → last · committed / leader · latest snapshot · chunk size · snapshot format · on disk (snapshots / log)

  • Marks (⛔ / ⚠, the reason on hover) follow the pre-pass's checks:
    • not serving, or probe failed (HC-3.18);
    • behind the leader's retained log, needs a full snapshot (HC-3.19, only against exactly one observed leader in the same ensemble; with none, or two mid-election, there is no verdict). The row turns red;
    • an unchunked snapshot over 2 GiB (critical) or over 1 GiB (warning) (HC-3.20);
    • snapshot format below 7, judged against the member's own version (HC-3.20).
  • A banner appears when no member of an ensemble in the bundle is serving. It says that members outside the bundle may still hold a quorum, because the bundle does not prove voting membership. Apache ZooKeeper's "This ZooKeeper instance is not currently serving requests" counts like Keeper's wording.
  • Its own visibility. The table is shown whenever keeper/ is in the bundle, even without metric_log. It is absent, not empty, without the files: older bundles, cloud by default, -keeper-mntr off. The existing metric-driven parts of the section keep their behaviour.

internal/keeper.ReadMembers ports the pre-pass's rules to Go. A truncated reply is not evidence, members are grouped by ensemble, and the leader is required for the snapshot verdict. Versions drop mntr's build suffix.

The rules now exist twice, Python and Go, so a test keeps them together. It runs the pre-pass and ReadMembers on the same fixtures (incident, leaderless, growing snapshot during a rolling upgrade, no leader, two ensembles) and requires the same verdict per member. On the incident fixture it compares 8 verdicts, and changing only the Go side fails it.

Verification

  • Reader tests: the incident shape, a healthy ensemble with no marks, no leader means no verdict, a truncated reply, two ensembles, a member without the ensemble line, the format per member's version, the version suffix and Leaderless. Each rule fails its test when reverted.
  • Template and page data: the panel has its own switch and escapes every file value. It adds nothing to the page without keeper/.
  • Lab, real run: a healthy 3-member ensemble shows three members serving and no marks, only ℹ for format 6, the default on 26.7. On the incident-shaped demo bundle, the lagging member's row is red with "needs a full snapshot", and the 2.24 GiB unchunked snapshot is marked on the leader and the follower.
  • Review round: ZooKeeper's not-serving wording (collector, both readers), two leaders mid-election and the banner's caveat. The consistency test gains a ZooKeeper and a two-leader fixture; both caught the readers disagreeing before the fix.
  • gofmt, go vet (also GOOS=windows) and make test are green: 305 passed.

🤖 Generated with Claude Code

…hot settings per member

The Keeper section gains a table with one row per Keeper member, read from
the keeper/<member>.txt files PR #56 collects: ensemble, state, role,
version, Raft log first → last, committed vs leader-committed, latest
snapshot, snapshot_transfer_chunk_size, snapshot format, bytes on disk.
Marks follow the pre-pass's HC-3.18-3.20 (a member behind the leader's
retained log needs a full snapshot; an unchunked snapshot over 2 GiB; the
format judged against the member's own version; not serving / probe
failed), with a banner when no member of an ensemble is serving. The panel
has its own visibility — shown whenever keeper/ is in the bundle, even
without metric_log — and is absent without the files.

internal/keeper.ReadMembers ports the pre-pass's rules to Go (a truncated
reply is not evidence, cross-member checks within one ensemble and only
against an observed leader). Because the rules now exist twice, a test runs
the pre-pass and ReadMembers on the same fixtures and requires the same
verdict per member: 8 on the incident fixture, and a change to one side
fails it. Versions drop mntr's build suffix.

Checked on the lab: a healthy 3-member ensemble shows three members serving
with no marks; the incident-shaped demo shows the lagging member's row red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved classification and leader-selection errors can produce misleading health verdicts, and the outage banner overstates incomplete evidence.

3 open issues
What changed in this PR

Adds a Keeper members panel to the diagnostic dashboard, building on #56’s collection of member-level Raft and snapshot information.

Changes:

  • Displays member status, log positions, snapshot settings, and health marks independently of hourly metrics.
  • Adds Go reader logic and Python/Go consistency tests.
  • Expands Keeper collection and documents the diagnostic checks.
File Description
skills/​clickhouse-diagnostic/​scripts/​inspect_bundle.py Adds Keeper parsing and health checks.
skills/​clickhouse-diagnostic/​references/​running-the-tool.md Updates Keeper collection guidance.
skills/​clickhouse-diagnostic/​references/​known-patterns.md Documents snapshot-transfer failure patterns.
skills/​clickhouse-diagnostic/​references/​health-checks.md Defines HC-3.18–3.20.
skills/​clickhouse-diagnostic/​references/​file-guide.md Explains member evidence and dashboard marks.
skills/​clickhouse-diagnostic/​references/​bundle-layout.md Documents expanded Keeper files.
README.md Describes collection and the new panel.
internal/​keeper/​members.go Parses members and computes verdicts.
internal/​keeper/​members_test.go Tests member parsing and verdicts.
internal/​keeper/​fourletter.go Expands parallel collection and gov filtering.
internal/​keeper/​fourletter_test.go Tests collector behavior and isolation.
internal/​dashboard/​generator.go Adds panel data and rendering.
internal/​dashboard/​alerts_panel_test.go Tests panel structure and data.
cmd/​prepass_keeper_test.go Tests Python Keeper checks.
cmd/​main.go Updates collection messaging.
cmd/​keeper_consistency_test.go Compares Python and Go verdicts.

Review effort: Balanced

Comment thread internal/keeper/members.go
Comment thread internal/dashboard/generator.go Outdated
Comment thread internal/keeper/fourletter.go Outdated
CamiloSierraH added a commit that referenced this pull request Oct 19, 2026
…dict with two leaders

Apache ZooKeeper answers "This ZooKeeper instance is not currently serving
requests". Only Keeper's exact sentence was recognised, so a ZooKeeper
member that was not serving came out "ok" in the collector and "serving"
in the pre-pass — hiding HC-3.18. Both wordings are recognised now.

Mid-election a bundle can hold two members reporting leader. The pre-pass
took the first in file order, so the HC-3.19 verdict depended on which file
sorted first. A "behind the leader's log" verdict now needs exactly one
serving leader; with two there is none — the same reasoning as no leader.
Found reviewing #58, which reads these files with the same rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CamiloSierraH and others added 2 commits October 19, 2026 15:06
… keeper-members-panel

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eader, and its banner claims only what the bundle shows

- Apache ZooKeeper answers "This ZooKeeper instance is not currently
  serving requests"; the Go reader matched only Keeper's sentence and
  showed such a member as serving. Both wordings count (shared
  keeper.IsNotServing, fixed in the collector and the pre-pass on #56).
- With two members reporting leader mid-election, the Go reader took the
  last and the pre-pass the first, so the two could disagree on HC-3.19.
  Both now require exactly one serving leader, and give no "behind the
  leader" verdict otherwise.
- The banner said the ensemble had no leader and writes fail. Two members
  not serving can sit next to voters this server does not know that hold a
  quorum; it now says no member in the bundle is serving, and that members
  outside it may still hold a quorum — the pre-pass's qualification.

The consistency test gains a ZooKeeper and a two-leader fixture; both
caught the readers disagreeing before the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…' dashboard tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CamiloSierraH
CamiloSierraH merged commit 4c3c8d7 into main Oct 20, 2026
2 checks 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.

3 participants