Ctrl K
ComunidadGuías…

src/node/prom-instruments.ts

Rama develop · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Prometheus instruments referenced from the hot path (PadMessageHandler).
//
// Defined in a separate file so that PadMessageHandler can import the
// recording helpers without creating a circular import with prometheus.ts
// (which already requires PadMessageHandler to read sessioninfos).
//
// The metrics themselves are added to the central Registry by prometheus.ts.
//
// Everything here is gated behind settings.scalingDiveMetrics (default false).
// When the flag is off the recording helpers short-circuit to no-ops and the
// metrics are never registered, so production deployments don't pay for
// instrumentation they don't use.

import client from 'prom-client';
import settings from './utils/Settings';

export const enabled = (): boolean => settings.scalingDiveMetrics === true;

export const changesetApplyDuration = new client.Histogram({
  name: 'etherpad_changeset_apply_duration_seconds',
  help: 'Time spent applying an incoming USER_CHANGES message on the server (apply path only, excludes fan-out to other clients)',
  buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 5],
});

export const socketEmitsTotal = new client.Counter({
  name: 'etherpad_socket_emits_total',
  help: 'Number of socket.io broadcast emits, bucketed by message type',
  labelNames: ['type'],
});

export const padUsersGauge = new client.Gauge({
  name: 'etherpad_pad_users',
  help: 'Active users connected to a pad, keyed by padId',
  labelNames: ['padId'],
});

// Allowlist of message-type label values. Anything outside this set is rolled
// into 'other' so a misbehaving plugin or HTTP-API caller passing a
// user-controlled msgString cannot explode prom-client's internal label-cardinality
// state.
const KNOWN_TYPES = new Set([
  'NEW_CHANGES',
  'ACCEPT_COMMIT',
  'CHAT_MESSAGE',
  'CLIENT_VARS',
  'CLIENT_MESSAGE',
  'CUSTOM',
  'USER_NEWINFO',
  'USERINFO_UPDATE',
  'USER_LEAVE',
]);

/** Start a timer for the changeset apply path. Call the returned function when done.
 *  Returns a no-op stopper when the feature flag is off. */
export const recordChangesetApply = (): (() => void) => {
  if (!enabled()) return () => {};
  return changesetApplyDuration.startTimer();
};

/** Increment the socket-emit counter for the given message type.
 *  No-op when the feature flag is off. Unknown/missing types are bucketed as
 *  'other' to keep label cardinality bounded. */
export const recordSocketEmit = (type: string | undefined): void => {
  if (!enabled()) return;
  const label = type && KNOWN_TYPES.has(type) ? type : 'other';
  socketEmitsTotal.labels(label).inc();
};