New internal/stats package — atomic counters for boot-scoped metrics (connectionsSinceBoot, sessionsSinceBoot, messagesSinceBoot). Thread-safe via sync/atomic.
New DB queries — GetClientCount() and GetQueueEntryCount() for current snapshot counts.
Healthcheck changes — Healthcheck() now accepts context.Context to query the database. Response struct extended with all 7 new fields. DB-derived stats populated with graceful error handling (logged, not fatal).
handleLogin → IncrConnections (new client for existing session)
handlePrivmsg → IncrMessages (covers both PRIVMSG and NOTICE)
Wired via fx — stats.Tracker provided through Uber fx DI in both production and test setups.
Tests
internal/stats/stats_test.go — 5 tests covering all counter operations (100% coverage)
TestHealthcheckRuntimeStatsFields — verifies all 7 new fields are present in the response
TestHealthcheckRuntimeStatsValues — end-to-end: creates a session, joins a channel, sends a message, then verifies counts are nonzero
README
Updated healthcheck documentation with full response shape, field descriptions, and project structure listing for internal/stats/.
## Summary
Expands the `/.well-known/healthcheck.json` endpoint with runtime statistics, giving operators visibility into server load and usage patterns.
closes #74
## New healthcheck fields
| Field | Source | Description |
|-------|--------|-------------|
| `sessions` | DB | Current active session count |
| `clients` | DB | Current connected client count |
| `queuedLines` | DB | Total entries in client output queues |
| `channels` | DB | Current channel count |
| `connectionsSinceBoot` | Memory | Total client connections since server start |
| `sessionsSinceBoot` | Memory | Total sessions created since server start |
| `messagesSinceBoot` | Memory | Total PRIVMSG/NOTICE messages since server start |
## Implementation
- **New `internal/stats` package** — atomic counters for boot-scoped metrics (`connectionsSinceBoot`, `sessionsSinceBoot`, `messagesSinceBoot`). Thread-safe via `sync/atomic`.
- **New DB queries** — `GetClientCount()` and `GetQueueEntryCount()` for current snapshot counts.
- **Healthcheck changes** — `Healthcheck()` now accepts `context.Context` to query the database. Response struct extended with all 7 new fields. DB-derived stats populated with graceful error handling (logged, not fatal).
- **Counter instrumentation** — Increments added at:
- `handleCreateSession` → `IncrSessions` + `IncrConnections`
- `handleRegister` → `IncrSessions` + `IncrConnections`
- `handleLogin` → `IncrConnections` (new client for existing session)
- `handlePrivmsg` → `IncrMessages` (covers both PRIVMSG and NOTICE)
- **Wired via fx** — `stats.Tracker` provided through Uber fx DI in both production and test setups.
## Tests
- `internal/stats/stats_test.go` — 5 tests covering all counter operations (100% coverage)
- `TestHealthcheckRuntimeStatsFields` — verifies all 7 new fields are present in the response
- `TestHealthcheckRuntimeStatsValues` — end-to-end: creates a session, joins a channel, sends a message, then verifies counts are nonzero
## README
Updated healthcheck documentation with full response shape, field descriptions, and project structure listing for `internal/stats/`.
Add the following counters to the healthcheck JSON response:
- sessions: current active session count (from DB)
- clients: current connected client count (from DB)
- queuedLines: total entries in client output queues (from DB)
- channels: current channel count (from DB)
- connectionsSinceBoot: total client connections since server start
- sessionsSinceBoot: total sessions created since server start
- messagesSinceBoot: total PRIVMSG/NOTICE messages since server start
Implementation:
- New internal/stats package with atomic counters for boot-scoped metrics
- New DB queries GetClientCount and GetQueueEntryCount
- Healthcheck.Healthcheck() now accepts context for DB queries
- Counter increments in session creation, registration, login, and messaging
- Stats tracker wired via Uber fx dependency injection
- Unit tests for stats package (100% coverage) and integration tests
- README updated with full healthcheck response documentation
closes#74
All 7 counters from #74 are present and correctly sourced:
#
Requirement
Field
Source
Status
1
Total session count
sessions
GetUserCount(ctx) → sessions table
✅
2
Total client-session count
clients
GetClientCount(ctx) → clients table
✅
3
Total number of output queued lines
queuedLines
GetQueueEntryCount(ctx) → client_queues table
✅
4
Total number of channels
channels
GetChannelCount(ctx) → channels table
✅
5
Total connections since boot
connectionsSinceBoot
Atomic counter via stats.Tracker
✅
6
Total sessions since boot
sessionsSinceBoot
Atomic counter via stats.Tracker
✅
7
Total messages since boot
messagesSinceBoot
Atomic counter via stats.Tracker
✅
Counter Instrumentation Accuracy ✅
Call site
Counters incremented
Correct?
handleCreateSession (after successful DB create)
IncrSessions + IncrConnections
✅
handleRegister (after successful DB register)
IncrSessions + IncrConnections
✅
handleLogin (after successful DB login)
IncrConnections only
✅ (login adds client to existing session, not new session)
handlePrivmsg (after validation, before routing)
IncrMessages
✅ (covers both PRIVMSG and NOTICE via shared dispatchCommand path)
All counters are incremented after error checks, so only successful operations are counted. No missed paths — handleCreateSession, handleRegister, and handleLogin are the only three session/connection creation entry points.
Policy Compliance ✅
Doc comments on all exported types/functions: Package stats has package comment; Tracker, New(), and all 6 methods have doc comments. ✅
No code in cmd/ beyond bootstrapping: Only stats.New added to fx providers. ✅
Error handling: DB errors in populateDBStats are logged via slog and gracefully degraded (zero value returned). Non-fatal — healthcheck still responds. ✅
JSON tags: All new fields use camelCase. ✅
No inline error handling: All if err != nil use plain assignment pattern. ✅
Blank line before return statements: Consistent with existing codebase patterns. ✅
Tests for new exported types:stats_test.go achieves 100% statement coverage. Integration tests TestHealthcheckRuntimeStatsFields and TestHealthcheckRuntimeStatsValues verify end-to-end correctness. ✅
DI wiring:stats.Tracker properly provided via fx in both production (cmd/neoircd/main.go) and test harness (api_test.go). ✅
No new dependencies added.✅
Code Quality Notes
Thread safety via sync/atomic is the right approach for boot-scoped counters — simple, zero-contention, no mutex overhead.
populateDBStats cleanly separates DB-derived stats from in-memory counters. Graceful degradation on DB errors is correct for a healthcheck — you don't want the healthcheck itself to fail because a COUNT query timed out.
New DB queries (GetClientCount, GetQueueEntryCount) follow the exact same pattern as existing GetUserCount and GetChannelCount.
README documentation accurately reflects the new response shape with a clear field description table.
Build Result ✅
docker build . passes. All tests green:
internal/stats — 5/5 tests pass, 100% coverage
internal/handlers — all tests pass including 2 new integration tests
All other packages unaffected
Verdict: PASS✅
Clean implementation. All 7 required counters present and correctly sourced. Policy-compliant. Well-tested. Build green.
## Review: PR #80 — feat: add runtime statistics to healthcheck endpoint
**Closes:** [#74](https://git.eeqj.de/sneak/chat/issues/74)
---
### Requirements Checklist (7/7 ✅)
All 7 counters from [#74](https://git.eeqj.de/sneak/chat/issues/74) are present and correctly sourced:
| # | Requirement | Field | Source | Status |
|---|------------|-------|--------|--------|
| 1 | Total session count | `sessions` | `GetUserCount(ctx)` → `sessions` table | ✅ |
| 2 | Total client-session count | `clients` | `GetClientCount(ctx)` → `clients` table | ✅ |
| 3 | Total number of output queued lines | `queuedLines` | `GetQueueEntryCount(ctx)` → `client_queues` table | ✅ |
| 4 | Total number of channels | `channels` | `GetChannelCount(ctx)` → `channels` table | ✅ |
| 5 | Total connections since boot | `connectionsSinceBoot` | Atomic counter via `stats.Tracker` | ✅ |
| 6 | Total sessions since boot | `sessionsSinceBoot` | Atomic counter via `stats.Tracker` | ✅ |
| 7 | Total messages since boot | `messagesSinceBoot` | Atomic counter via `stats.Tracker` | ✅ |
### Counter Instrumentation Accuracy ✅
| Call site | Counters incremented | Correct? |
|-----------|---------------------|----------|
| `handleCreateSession` (after successful DB create) | `IncrSessions` + `IncrConnections` | ✅ |
| `handleRegister` (after successful DB register) | `IncrSessions` + `IncrConnections` | ✅ |
| `handleLogin` (after successful DB login) | `IncrConnections` only | ✅ (login adds client to existing session, not new session) |
| `handlePrivmsg` (after validation, before routing) | `IncrMessages` | ✅ (covers both PRIVMSG and NOTICE via shared `dispatchCommand` path) |
All counters are incremented **after** error checks, so only successful operations are counted. No missed paths — `handleCreateSession`, `handleRegister`, and `handleLogin` are the only three session/connection creation entry points.
### Policy Compliance ✅
- **Doc comments on all exported types/functions:** Package `stats` has package comment; `Tracker`, `New()`, and all 6 methods have doc comments. ✅
- **No code in `cmd/` beyond bootstrapping:** Only `stats.New` added to fx providers. ✅
- **Error handling:** DB errors in `populateDBStats` are logged via `slog` and gracefully degraded (zero value returned). Non-fatal — healthcheck still responds. ✅
- **JSON tags:** All new fields use camelCase. ✅
- **No inline error handling:** All `if err != nil` use plain assignment pattern. ✅
- **Blank line before return statements:** Consistent with existing codebase patterns. ✅
- **Tests for new exported types:** `stats_test.go` achieves 100% statement coverage. Integration tests `TestHealthcheckRuntimeStatsFields` and `TestHealthcheckRuntimeStatsValues` verify end-to-end correctness. ✅
- **DI wiring:** `stats.Tracker` properly provided via fx in both production (`cmd/neoircd/main.go`) and test harness (`api_test.go`). ✅
- **No new dependencies added.** ✅
### Code Quality Notes
- Thread safety via `sync/atomic` is the right approach for boot-scoped counters — simple, zero-contention, no mutex overhead.
- `populateDBStats` cleanly separates DB-derived stats from in-memory counters. Graceful degradation on DB errors is correct for a healthcheck — you don't want the healthcheck itself to fail because a COUNT query timed out.
- New DB queries (`GetClientCount`, `GetQueueEntryCount`) follow the exact same pattern as existing `GetUserCount` and `GetChannelCount`.
- README documentation accurately reflects the new response shape with a clear field description table.
### Build Result ✅
`docker build .` passes. All tests green:
- `internal/stats` — 5/5 tests pass, 100% coverage
- `internal/handlers` — all tests pass including 2 new integration tests
- All other packages unaffected
### Verdict: **PASS** ✅
Clean implementation. All 7 required counters present and correctly sourced. Policy-compliant. Well-tested. Build green.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Expands the
/.well-known/healthcheck.jsonendpoint with runtime statistics, giving operators visibility into server load and usage patterns.closes #74
New healthcheck fields
sessionsclientsqueuedLineschannelsconnectionsSinceBootsessionsSinceBootmessagesSinceBootImplementation
internal/statspackage — atomic counters for boot-scoped metrics (connectionsSinceBoot,sessionsSinceBoot,messagesSinceBoot). Thread-safe viasync/atomic.GetClientCount()andGetQueueEntryCount()for current snapshot counts.Healthcheck()now acceptscontext.Contextto query the database. Response struct extended with all 7 new fields. DB-derived stats populated with graceful error handling (logged, not fatal).handleCreateSession→IncrSessions+IncrConnectionshandleRegister→IncrSessions+IncrConnectionshandleLogin→IncrConnections(new client for existing session)handlePrivmsg→IncrMessages(covers both PRIVMSG and NOTICE)stats.Trackerprovided through Uber fx DI in both production and test setups.Tests
internal/stats/stats_test.go— 5 tests covering all counter operations (100% coverage)TestHealthcheckRuntimeStatsFields— verifies all 7 new fields are present in the responseTestHealthcheckRuntimeStatsValues— end-to-end: creates a session, joins a channel, sends a message, then verifies counts are nonzeroREADME
Updated healthcheck documentation with full response shape, field descriptions, and project structure listing for
internal/stats/.Review: PR #80 — feat: add runtime statistics to healthcheck endpoint
Closes: #74
Requirements Checklist (7/7 ✅)
All 7 counters from #74 are present and correctly sourced:
sessionsGetUserCount(ctx)→sessionstableclientsGetClientCount(ctx)→clientstablequeuedLinesGetQueueEntryCount(ctx)→client_queuestablechannelsGetChannelCount(ctx)→channelstableconnectionsSinceBootstats.TrackersessionsSinceBootstats.TrackermessagesSinceBootstats.TrackerCounter Instrumentation Accuracy ✅
handleCreateSession(after successful DB create)IncrSessions+IncrConnectionshandleRegister(after successful DB register)IncrSessions+IncrConnectionshandleLogin(after successful DB login)IncrConnectionsonlyhandlePrivmsg(after validation, before routing)IncrMessagesdispatchCommandpath)All counters are incremented after error checks, so only successful operations are counted. No missed paths —
handleCreateSession,handleRegister, andhandleLoginare the only three session/connection creation entry points.Policy Compliance ✅
statshas package comment;Tracker,New(), and all 6 methods have doc comments. ✅cmd/beyond bootstrapping: Onlystats.Newadded to fx providers. ✅populateDBStatsare logged viaslogand gracefully degraded (zero value returned). Non-fatal — healthcheck still responds. ✅if err != niluse plain assignment pattern. ✅stats_test.goachieves 100% statement coverage. Integration testsTestHealthcheckRuntimeStatsFieldsandTestHealthcheckRuntimeStatsValuesverify end-to-end correctness. ✅stats.Trackerproperly provided via fx in both production (cmd/neoircd/main.go) and test harness (api_test.go). ✅Code Quality Notes
sync/atomicis the right approach for boot-scoped counters — simple, zero-contention, no mutex overhead.populateDBStatscleanly separates DB-derived stats from in-memory counters. Graceful degradation on DB errors is correct for a healthcheck — you don't want the healthcheck itself to fail because a COUNT query timed out.GetClientCount,GetQueueEntryCount) follow the exact same pattern as existingGetUserCountandGetChannelCount.Build Result ✅
docker build .passes. All tests green:internal/stats— 5/5 tests pass, 100% coverageinternal/handlers— all tests pass including 2 new integration testsVerdict: PASS ✅
Clean implementation. All 7 required counters present and correctly sourced. Policy-compliant. Well-tested. Build green.