etherpad-lite/src/node/utils
John McLear 986f139a61
feat(metrics): 3 Prometheus counters for scaling dive (#7756) (#7762)
* feat(metrics): expose 3 Prometheus counters for the scaling dive

Per the spec section 6 of #7756: enables the load-test harness to
attribute *where* time goes on the server, not just the gauge headline
(CPU / event-loop / memory) the dive doc starts from.

New /stats/prometheus rows:

- etherpad_pad_users{padId} — gauge, derived from sessioninfos on
  each scrape. Lets the harness confirm the pad it points at actually
  has the expected concurrency.

- etherpad_changeset_apply_duration_seconds — histogram observed
  inside handleUserChanges. Separates "apply path is slow" from
  "fan-out is slow" when latency rises.

- etherpad_socket_emits_total{type} — counter at the broadcast
  emit sites (handleCustomObjectMessage, handleCustomMessage,
  sendChatMessageToPadClients) and inside the NEW_CHANGES per-socket
  loop in updatePadClients. Bucketed by message type so the harness
  can measure the amplification factor of each lever (especially the
  fan-out batching lever).

Metric handles live in a new prom-instruments.ts module rather than
in prometheus.ts itself, so PadMessageHandler can import the
recording helpers without creating a circular dependency
(prometheus.ts already requires PadMessageHandler).

Tests: smoke test verifies recordSocketEmit + recordChangesetApply
move the underlying counters/histogram.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(metrics): address Qodo review — flag-gate, scope histogram, bound label cardinality

Three issues raised on the initial PR:

1. **Feature flag.** Per project compliance rule, new features must
   be behind a flag and disabled by default. Adds
   `settings.scalingDiveMetrics` (default `false`). When off,
   recordSocketEmit() / recordChangesetApply() short-circuit to
   no-ops and the metrics are never even registered with the
   Prometheus register. Enable only when running the
   ether/etherpad-load-test scaling-dive harness.

2. **Histogram scope.** Previously the
   etherpad_changeset_apply_duration_seconds timer wrapped the
   whole handleUserChanges() body — including
   `await exports.updatePadClients(pad)` — so the histogram
   measured apply+fan-out, defeating its stated purpose. Now
   stopped immediately after the apply work (`assert.equal(...rev,
   r)`), before the ACCEPT_COMMIT socket emit and the
   updatePadClients call. Failed applies deliberately don't observe
   so the success-path distribution stays clean.

3. **Label cardinality.** handleCustomMessage was passing the
   user-supplied msgString (an HTTP-API param) directly as the
   `type` label value. A misbehaving API caller could grow
   prom-client's internal label map until OOM. Now bucketed against
   a known-types allowlist; anything outside it lands in `other`.

Tests updated: 5/5 — covers happy path, "other" bucketing of
unknown/unsafe labels, and that the flag-disabled state is a true
no-op.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 19:54:42 +01:00
..
AbsolutePaths.ts chore: migrated settings to esm6 (#7062) 2025-08-04 22:42:50 +02:00
anonymizeIp.ts feat(gdpr): IP/privacy audit (PR2 of #6701) (#7547) 2026-05-01 13:47:40 +01:00
checkValidRev.ts Added typescript to etherpad 2024-02-05 21:13:02 +01:00
Cleanup.ts chore: moved first files to esm (#7061) 2025-08-04 19:59:28 +02:00
Cli.ts chore: use args from cmd (#7112) 2025-09-03 21:01:20 +02:00
customError.ts Added typescript to etherpad 2024-02-05 21:13:02 +01:00
ensureAuthorTokenCookie.ts feat(gdpr): HttpOnly author-token cookie (PR3 of #6701) (#7548) 2026-05-03 05:56:56 +01:00
ExportEtherpad.ts fix(export): /export/etherpad honors the :rev URL segment (#7566) 2026-04-26 10:29:02 +02:00
ExportHelper.ts Feat/changeset ts (#6594) 2024-08-18 12:14:24 +02:00
ExportHtml.ts fix(editor): preserve U+00A0 non-breaking space (#3037) (#7585) 2026-04-23 08:57:30 +01:00
ExportPdfNative.ts feat(export): native DOCX export via html-to-docx (opt-in) (#7568) 2026-05-08 18:33:50 +01:00
ExportSanitizeHtml.ts feat(export): native DOCX export via html-to-docx (opt-in) (#7568) 2026-05-08 18:33:50 +01:00
ExportTxt.ts feat!: replace Abiword with LibreOffice and add DOCX export (#7539) 2026-04-19 09:08:22 +01:00
ImportDocxNative.ts feat(export): native DOCX export via html-to-docx (opt-in) (#7568) 2026-05-08 18:33:50 +01:00
ImportEtherpad.ts Moved to ts (#6593) 2024-08-17 20:14:36 +02:00
ImportHtml.ts Feat/changeset ts (#6594) 2024-08-18 12:14:24 +02:00
LibreOffice.ts chore: migrated settings to esm6 (#7062) 2025-08-04 22:42:50 +02:00
Minify.ts chore: migrated settings to esm6 (#7062) 2025-08-04 22:42:50 +02:00
MinifyWorker.ts Feat/frontend vitest (#6469) 2024-08-16 22:55:42 +02:00
NodeVersion.ts chore: moved first files to esm (#7061) 2025-08-04 19:59:28 +02:00
padDiff.ts fix: createDiffHTML API fails with "Not a changeset: undefined" (#7445) 2026-04-04 08:25:26 +01:00
path_exists.ts Moved path_exists and promises to es6 2024-08-18 19:52:21 +02:00
PluginCapabilities.ts feat(padOptions): pass plugin-namespaced ep_* keys through applyPadSettings (#7698) 2026-05-07 17:17:05 +01:00
promises.ts Moved path_exists and promises to es6 2024-08-18 19:52:21 +02:00
randomstring.ts chore: moved first files to esm (#7061) 2025-08-04 19:59:28 +02:00
run_cmd.ts feat(packaging): add Debian (.deb) build via nfpm with systemd unit (v2) (#7583) 2026-04-27 10:33:30 +01:00
sanitizePathname.ts Feat/frontend vitest (#6469) 2024-08-16 22:55:42 +02:00
Settings.ts feat(metrics): 3 Prometheus counters for scaling dive (#7756) (#7762) 2026-05-15 19:54:42 +01:00
SettingsTree.ts Enforce 2-space indentation across codebase (#7426) 2026-04-01 19:48:45 +01:00
SkinColors.ts fix(7606): sync theme-color meta with client-side dark-mode switch (#7690) 2026-05-07 10:43:29 +01:00
socialMeta.ts fix(socialMeta): coerced numeric/boolean override silently dropped (#7692) 2026-05-07 18:38:17 +08:00
Stream.ts Added typescript to etherpad 2024-02-05 21:13:02 +01:00
tar.json Changeset: New API to simplify attribute processing 2021-11-21 04:11:41 -05:00
toolbar.ts Fix ESM/CJS interop for Settings module breaking plugin compatibility (#7421) 2026-04-01 11:39:40 +01:00
UpdateCheck.ts chore: removed axios (#7685) 2026-05-06 22:06:04 +02:00