WeKan and FerretDB on one machine can drive CPU high enough to starve other
software. Add a monitor, a governor, and a report. Design: docs/Features/CPU/CPU.md.
Monitor (server/lib/cpuMonitor.js): samples system-wide CPU% from os.cpus()
idle/total deltas on an interval (so it includes WeKan, FerretDB and every other
process). A pure, hysteresis state machine (models/lib/cpuHighTracker.js) turns
the samples into ONLY the START and END of each sustained high-CPU period — two
rows per episode, never a flood. Enters high after 3 consecutive samples >= 85%,
leaves after 3 consecutive < 70%. Each row carries duration, peak, system load,
and what WeKan was doing (setActivity label). Recorded to a new 'cpu' event
stream (server/lib/cpuLog.js).
Governor: cpuMonitor exports isHighCpu() and pauseIfBusy(), so long batch
operations await a short pause and yield the CPU only while the system is busy
(no cost when idle). Wired into the existing-file extension corrector. Tunable
via WEKAN_CPU_* env vars.
Report: 'cpu' added to EVENT_STREAMS; reuses the generic eventStreamReport
(stream="cpu") with search + pagination; a "CPU usage" item is added to the
Admin Panel / Problems side menu (cpuReportTitle i18n).
Tests: cpuHighTracker unit (start/end, duration/peak, no-flap hysteresis;
positive + negative) and cpuMonitorWiring source guards. CHANGELOG + design doc.
The Admin Panel → Problems → Cards report already paginates (limit/skip), but it
sorted by { boardId:1, sort:1 } which has NO index, so every page load full-sorted
all cards in memory — the spinner on a site with 11761 cards. Switched both the
cardsReport publication and the client mirror sort to { boardId:1, createdAt:-1 },
the existing index (server/models/cards.js), so one page is a bounded index scan.
Also added a { stream:1, at:-1 } index on the eventlog collection (and { stream:1 }
on eventlogAcks) so the Security/Speed/Tests report pages stay an index scan as the
log grows, instead of a full scan + in-memory sort.
Guarded in tests/adminReportsPagination.test.cjs.
Thanks to xet7 !
The Admin Panel → Problems detail methods eventLogCount/eventLogPage awaited
requireAdmin() BEFORE check()ing their arguments. When requireAdmin throws (a
non-admin call, or before admin status resolves on the client), Meteor's
audit-argument-checks runs and throws "Did not check() all arguments during call
to '<method>'", masking the real error and spamming the server log. Moved the
check() calls to the top of both methods, before any await/throw — matching
acknowledgeEventLog, which was already correct. Guarded in
tests/securityLog.test.cjs (check() must precede requireAdmin in every
argument-taking method).
Thanks to xet7 !
- 2nd header bar: add a Problems button (warning icon) to the RIGHT of the Info
(version) button; it turns red when there are new problems (settingHeader.js
polls eventLogProblemAreas). Remove the old Reports button; the Admin Panel
still opens on Settings.
- The former Reports page is now the Problems page: left menu Summary / Security /
Speed / Tests, then a separator, then the moved Broken Cards/Files/Rules/Boards/
Cards/Impersonation items.
- Summary (problemsSummary, renamed from the removed top banner): the checkbox
list + one Acknowledge button — the ONLY place to acknowledge.
- Security/Speed/Tests: read-only, paginated, searchable event tables via new
admin-only eventLogPage/eventLogCount methods; acknowledgeEventLog now takes a
stream or array.
- i18n keys + CSS + source-guard tests + design doc updated.
Change the top problem banner from a per-area button to a checkbox list of
problem areas with a single Acknowledge button that acknowledges every checked
area in one call. acknowledgeEventLog now accepts a stream or an array of
streams. Acknowledging happens ONLY at the top banner; the Reports pages are
read-only (noted in the design doc).
Like the Announcement banner, the Admin Panel top now shows, for each problem
area with unacknowledged events, its menu path (Admin Panel -> Reports ->
Security/Speed/Tests) and the count of NEW problems. Each area has an Acknowledge
button that marks the newest problems seen, zeroing the count and removing the
info from the top.
- models/eventLog.js: add the eventlogAcks collection and admin-only methods
eventLogProblemAreas() (count of events newer than each stream ack) and
acknowledgeEventLog(stream) (upsert ack = now).
- client adminProblemBanner.{jade,js}: poll the counts, render path/count/button,
acknowledge on click; included in settingHeaderBar (top of every admin page).
- i18n keys (securityReportTitle/speedReportTitle/testsReportTitle/new-problems/
acknowledge) + banner CSS. Source-guard tests added.
Per correction: use only the existing WeKan database via Meteor JavaScript
queries (works on FerretDB and MongoDB); do not create files/DBs under
WRITABLE_PATH; and have FerretDB report problems to WeKan rather than writing
itself.
- models/eventLog.js: one `eventlog` collection (stream: security|speed|tests).
- server/lib/{securityLog,speedLog,testLog}.js: thin wrappers that insert one
document via EventLog.insertAsync (fire-and-forget, never throw).
- models/lib/securityLogFormat.js slimmed to just sanitizeDetail; remove the
node:sqlite event store (server/lib/eventStore.js) and all file/path/schema
helpers.
- Add a Tests stream: log anything that would fail an existing WeKan test.
- Design docs (WeKan.md, FerretDB.md) rewritten: DB-collection storage, grouped
counts for the summary, Admin Reports read the collection, and FerretDB reports
problems to WeKan which records them (no FerretDB DB/file writes).
- tests/securityLog.test.cjs updated (sanitizer + catalog + collection wiring +
no-filesystem guards); verified via Python mirror.