snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
6
apps/meteor/server/lib/metrics/index.ts
Normal file
6
apps/meteor/server/lib/metrics/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { metrics } from './lib/metrics';
|
||||
import StatsTracker from './lib/statsTracker';
|
||||
|
||||
import './lib/collectMetrics';
|
||||
|
||||
export { metrics, StatsTracker };
|
||||
213
apps/meteor/server/lib/metrics/lib/collectMetrics.ts
Normal file
213
apps/meteor/server/lib/metrics/lib/collectMetrics.ts
Normal file
@@ -0,0 +1,213 @@
|
||||
import http from 'node:http';
|
||||
|
||||
import { Statistics } from '@rocket.chat/models';
|
||||
import { tracerSpan } from '@rocket.chat/tracing';
|
||||
import connect from 'connect';
|
||||
import { Facts } from 'meteor/facts-base';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import client from 'prom-client';
|
||||
import gcStats from 'prometheus-gc-stats';
|
||||
import _ from 'underscore';
|
||||
|
||||
import { metrics } from './metrics';
|
||||
import { Info } from '../../../../app/utils/rocketchat.info';
|
||||
import { settings } from '../../../settings';
|
||||
import { SystemLogger } from '../../logger/system';
|
||||
import { getControl } from '../../migrations';
|
||||
import { getAppsStatistics } from '../../statistics/lib/getAppsStatistics';
|
||||
|
||||
Facts.incrementServerFact = function (pkg: 'pkg' | 'fact', fact: string | number, increment: number): void {
|
||||
metrics.meteorFacts.inc({ pkg, fact }, increment);
|
||||
};
|
||||
|
||||
const setPrometheusData = async (): Promise<void> => {
|
||||
metrics.info.set(
|
||||
{
|
||||
version: Info.version,
|
||||
unique_id: settings.get<string>('uniqueID'),
|
||||
site_url: settings.get<string>('Site_Url'),
|
||||
},
|
||||
1,
|
||||
);
|
||||
|
||||
const sessions = Array.from<{ userId: string }>(Meteor.server.sessions.values());
|
||||
const authenticatedSessions = sessions.filter((s) => s.userId);
|
||||
metrics.ddpSessions.set(Meteor.server.sessions.size);
|
||||
metrics.ddpAuthenticatedSessions.set(authenticatedSessions.length);
|
||||
metrics.ddpConnectedUsers.set(_.unique(authenticatedSessions.map((s) => s.userId)).length);
|
||||
|
||||
// Apps metrics
|
||||
const { totalInstalled, totalActive, totalFailed } = await getAppsStatistics();
|
||||
|
||||
metrics.totalAppsInstalled.set(totalInstalled || 0);
|
||||
metrics.totalAppsEnabled.set(totalActive || 0);
|
||||
metrics.totalAppsFailed.set(totalFailed || 0);
|
||||
|
||||
const statistics = await Statistics.findLast();
|
||||
if (!statistics) {
|
||||
return;
|
||||
}
|
||||
|
||||
metrics.version.set({ version: statistics.version }, 1);
|
||||
metrics.migration.set((await getControl()).version);
|
||||
metrics.instanceCount.set(statistics.instanceCount);
|
||||
|
||||
// User statistics
|
||||
metrics.totalUsers.set(statistics.totalUsers);
|
||||
metrics.activeUsers.set(statistics.activeUsers);
|
||||
metrics.nonActiveUsers.set(statistics.nonActiveUsers);
|
||||
metrics.onlineUsers.set(statistics.onlineUsers);
|
||||
metrics.awayUsers.set(statistics.awayUsers);
|
||||
metrics.offlineUsers.set(statistics.offlineUsers);
|
||||
|
||||
// Room statistics
|
||||
metrics.totalRooms.set(statistics.totalRooms);
|
||||
metrics.totalChannels.set(statistics.totalChannels);
|
||||
metrics.totalPrivateGroups.set(statistics.totalPrivateGroups);
|
||||
metrics.totalDirect.set(statistics.totalDirect);
|
||||
metrics.totalLivechat.set(statistics.totalLivechat);
|
||||
|
||||
// Message statistics
|
||||
metrics.totalMessages.set(statistics.totalMessages);
|
||||
metrics.totalChannelMessages.set(statistics.totalChannelMessages);
|
||||
metrics.totalPrivateGroupMessages.set(statistics.totalPrivateGroupMessages);
|
||||
metrics.totalDirectMessages.set(statistics.totalDirectMessages);
|
||||
metrics.totalLivechatMessages.set(statistics.totalLivechatMessages);
|
||||
|
||||
// Livechat stats
|
||||
metrics.totalLivechatVisitors.set(statistics.totalLivechatVisitors);
|
||||
metrics.totalLivechatAgents.set(statistics.totalLivechatAgents);
|
||||
|
||||
metrics.pushQueue.set(statistics.pushQueue || 0);
|
||||
};
|
||||
|
||||
const app = connect();
|
||||
|
||||
// const compression = require('compression');
|
||||
// app.use(compression());
|
||||
|
||||
app.use('/metrics', (_req, res) => {
|
||||
res.setHeader('Content-Type', 'text/plain');
|
||||
client.register
|
||||
.metrics()
|
||||
.then((data) => {
|
||||
metrics.metricsRequests.inc();
|
||||
metrics.metricsRequestsTotal.inc();
|
||||
metrics.metricsSize.set(data.length);
|
||||
|
||||
res.end(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
SystemLogger.error({ msg: 'Error while collecting metrics', err });
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
|
||||
app.use('/', (_req, res) => {
|
||||
const html = `<html>
|
||||
<head>
|
||||
<title>Rocket.Chat Prometheus Exporter</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Rocket.Chat Prometheus Exporter</h1>
|
||||
<p><a href="/metrics">Metrics</a></p>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
res.write(html);
|
||||
res.end();
|
||||
});
|
||||
|
||||
const server = http.createServer(app);
|
||||
|
||||
let timer: NodeJS.Timeout;
|
||||
let resetTimer: NodeJS.Timeout;
|
||||
let defaultMetricsInitiated = false;
|
||||
let gcStatsInitiated = false;
|
||||
const was = {
|
||||
enabled: false,
|
||||
port: 9458,
|
||||
resetInterval: 0,
|
||||
collectGC: false,
|
||||
};
|
||||
const updatePrometheusConfig = async (): Promise<void> => {
|
||||
const is = {
|
||||
port: process.env.PROMETHEUS_PORT || settings.get('Prometheus_Port'),
|
||||
enabled: settings.get<boolean>('Prometheus_Enabled'),
|
||||
resetInterval: settings.get<number>('Prometheus_Reset_Interval'),
|
||||
collectGC: settings.get<boolean>('Prometheus_Garbage_Collector'),
|
||||
};
|
||||
|
||||
if (Object.values(is).some((s) => s == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Object.entries(is).every(([k, v]) => v === was[k as keyof typeof was])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is.enabled) {
|
||||
if (was.enabled) {
|
||||
SystemLogger.info('Disabling Prometheus');
|
||||
server.close();
|
||||
clearInterval(timer);
|
||||
}
|
||||
Object.assign(was, is);
|
||||
return;
|
||||
}
|
||||
|
||||
SystemLogger.debug({ msg: 'Configuring Prometheus', is });
|
||||
|
||||
if (!was.enabled) {
|
||||
server.listen({
|
||||
port: is.port,
|
||||
host: process.env.BIND_IP || '0.0.0.0',
|
||||
});
|
||||
|
||||
timer = setInterval(async () => {
|
||||
void tracerSpan(
|
||||
'setPrometheusData',
|
||||
{
|
||||
attributes: {
|
||||
port: is.port,
|
||||
host: process.env.BIND_IP || '0.0.0.0',
|
||||
},
|
||||
},
|
||||
() => {
|
||||
void setPrometheusData();
|
||||
},
|
||||
);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
clearInterval(resetTimer);
|
||||
if (is.resetInterval) {
|
||||
resetTimer = setInterval(() => {
|
||||
client.register.getMetricsAsArray().forEach((metric) => {
|
||||
// @ts-expect-error Property 'hashMap' does not exist on type 'metric'.
|
||||
metric.hashMap = {};
|
||||
});
|
||||
}, is.resetInterval);
|
||||
}
|
||||
|
||||
// Prevent exceptions on calling those methods twice since
|
||||
// it's not possible to stop them to be able to restart
|
||||
try {
|
||||
if (defaultMetricsInitiated === false) {
|
||||
defaultMetricsInitiated = true;
|
||||
client.collectDefaultMetrics();
|
||||
}
|
||||
if (is.collectGC && gcStatsInitiated === false) {
|
||||
gcStatsInitiated = true;
|
||||
gcStats(client.register)();
|
||||
}
|
||||
} catch (error) {
|
||||
SystemLogger.error({ err: error });
|
||||
}
|
||||
|
||||
Object.assign(was, is);
|
||||
};
|
||||
|
||||
Meteor.startup(async () => {
|
||||
settings.watchByRegex(/^Prometheus_.+/, updatePrometheusConfig);
|
||||
});
|
||||
340
apps/meteor/server/lib/metrics/lib/metrics.ts
Normal file
340
apps/meteor/server/lib/metrics/lib/metrics.ts
Normal file
@@ -0,0 +1,340 @@
|
||||
import { performance } from 'node:perf_hooks';
|
||||
|
||||
import client from 'prom-client';
|
||||
|
||||
const percentiles = [0.01, 0.1, 0.5, 0.9, 0.95, 0.99, 1];
|
||||
|
||||
const latencyBuckets = [0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0];
|
||||
const queueWaitBuckets = [1, 5, 10, 30, 60, 120, 300, 600, 900, 1800, 3600];
|
||||
|
||||
export const metrics = {
|
||||
deprecations: new client.Counter({
|
||||
name: 'rocketchat_deprecations',
|
||||
labelNames: ['type', 'kind', 'name', 'params'],
|
||||
help: 'cumulated number of deprecations being used',
|
||||
}),
|
||||
deprecationsTotal: new client.Counter({
|
||||
name: 'rocketchat_deprecations_total',
|
||||
labelNames: ['type', 'kind', 'name', 'params'],
|
||||
help: 'cumulated number of deprecations being used',
|
||||
}),
|
||||
metricsRequests: new client.Counter({
|
||||
name: 'rocketchat_metrics_requests',
|
||||
labelNames: ['notification_type'],
|
||||
help: 'cumulated number of calls to the metrics endpoint',
|
||||
}),
|
||||
metricsRequestsTotal: new client.Counter({
|
||||
name: 'rocketchat_metrics_requests_total',
|
||||
labelNames: ['notification_type'],
|
||||
help: 'cumulated number of calls to the metrics endpoint',
|
||||
}),
|
||||
metricsSize: new client.Gauge({
|
||||
name: 'rocketchat_metrics_size',
|
||||
help: 'size of the metrics response in chars',
|
||||
}),
|
||||
info: new client.Gauge({
|
||||
name: 'rocketchat_info',
|
||||
labelNames: ['version', 'unique_id', 'site_url'],
|
||||
help: 'Rocket.Chat info',
|
||||
}),
|
||||
meteorMethods: new client.Summary({
|
||||
name: 'rocketchat_meteor_methods',
|
||||
help: 'summary of meteor methods count and time',
|
||||
labelNames: ['method', 'has_connection', 'has_user'],
|
||||
percentiles,
|
||||
}),
|
||||
meteorMethodsSeconds: new client.Histogram({
|
||||
name: 'rocketchat_meteor_methods_seconds',
|
||||
help: 'histogram of meteor methods count and time in seconds',
|
||||
labelNames: ['method', 'has_connection', 'has_user'],
|
||||
buckets: latencyBuckets,
|
||||
}),
|
||||
rocketchatCallbacks: new client.Summary({
|
||||
name: 'rocketchat_callbacks',
|
||||
help: 'summary of rocketchat callbacks count and time',
|
||||
labelNames: ['hook', 'callback'],
|
||||
percentiles,
|
||||
}),
|
||||
rocketchatCallbacksSeconds: new client.Histogram({
|
||||
name: 'rocketchat_callbacks_seconds',
|
||||
help: 'histogram of rocketchat callbacks count and time in seconds',
|
||||
labelNames: ['hook', 'callback'],
|
||||
buckets: latencyBuckets,
|
||||
}),
|
||||
rocketchatHooks: new client.Summary({
|
||||
name: 'rocketchat_hooks',
|
||||
help: 'summary of rocketchat hooks count and time',
|
||||
labelNames: ['hook', 'callbacks_length'],
|
||||
percentiles,
|
||||
}),
|
||||
rocketchatHooksSeconds: new client.Histogram({
|
||||
name: 'rocketchat_hooks_seconds',
|
||||
help: 'histogram of rocketchat hooks count and time in seconds',
|
||||
labelNames: ['hook', 'callbacks_length'],
|
||||
buckets: latencyBuckets,
|
||||
}),
|
||||
rocketchatRestApi: new client.Summary({
|
||||
name: 'rocketchat_rest_api',
|
||||
help: 'summary of rocketchat rest api count and time',
|
||||
labelNames: ['method', 'entrypoint', 'user_agent', 'status', 'version'],
|
||||
percentiles,
|
||||
}),
|
||||
rocketchatRestApiSeconds: new client.Histogram({
|
||||
name: 'rocketchat_rest_api_seconds',
|
||||
help: 'histogram of rocketchat rest api count and time in seconds',
|
||||
labelNames: ['method', 'entrypoint', 'status', 'version'],
|
||||
buckets: latencyBuckets,
|
||||
}),
|
||||
rocketchatRestApiResponseSizeBytes: new client.Histogram({
|
||||
name: 'rocketchat_rest_api_response_size_bytes',
|
||||
help: 'histogram of rocketchat rest api response sizes in bytes',
|
||||
labelNames: ['method', 'entrypoint', 'status', 'version'],
|
||||
buckets: [0, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000],
|
||||
}),
|
||||
rocketchatRestApiActiveRequests: new client.Gauge({
|
||||
name: 'rocketchat_rest_api_active_requests',
|
||||
help: 'number of currently active rest api requests',
|
||||
labelNames: ['method'],
|
||||
}),
|
||||
|
||||
meteorSubscriptions: new client.Summary({
|
||||
name: 'rocketchat_meteor_subscriptions',
|
||||
help: 'summary of meteor subscriptions count and time',
|
||||
labelNames: ['subscription'],
|
||||
percentiles,
|
||||
}),
|
||||
meteorSubscriptionsSeconds: new client.Histogram({
|
||||
name: 'rocketchat_meteor_subscriptions_seconds',
|
||||
help: 'histogram of meteor subscriptions count and time in seconds',
|
||||
labelNames: ['subscription'],
|
||||
buckets: latencyBuckets,
|
||||
}),
|
||||
|
||||
messagesSent: new client.Counter({
|
||||
name: 'rocketchat_message_sent',
|
||||
help: 'cumulated number of messages sent',
|
||||
}),
|
||||
messagesSentTotal: new client.Counter({
|
||||
name: 'rocketchat_messages_sent_total',
|
||||
help: 'cumulated number of messages sent',
|
||||
}),
|
||||
notificationsSent: new client.Counter({
|
||||
name: 'rocketchat_notification_sent',
|
||||
labelNames: ['notification_type'],
|
||||
help: 'cumulated number of notifications sent',
|
||||
}),
|
||||
notificationsSentTotal: new client.Counter({
|
||||
name: 'rocketchat_notifications_sent_total',
|
||||
labelNames: ['notification_type'],
|
||||
help: 'cumulated number of notifications sent',
|
||||
}),
|
||||
messageRoundtripTime: new client.Summary({
|
||||
name: 'rocketchat_messages_roundtrip_time_summary',
|
||||
help: 'time spent by a message from save to receive back',
|
||||
percentiles,
|
||||
maxAgeSeconds: 60,
|
||||
ageBuckets: 5,
|
||||
// pruneAgedBuckets: true, // Type not added to prom-client on 14.2 https://github.com/siimon/prom-client/pull/558
|
||||
}),
|
||||
messageRoundtripTimeSeconds: new client.Histogram({
|
||||
name: 'rocketchat_messages_roundtrip_time_seconds',
|
||||
help: 'time in seconds spent by a message from save to receive back',
|
||||
buckets: latencyBuckets,
|
||||
}),
|
||||
|
||||
ddpSessions: new client.Gauge({
|
||||
name: 'rocketchat_ddp_sessions_count',
|
||||
help: 'number of open ddp sessions',
|
||||
}),
|
||||
ddpAuthenticatedSessions: new client.Gauge({
|
||||
name: 'rocketchat_ddp_sessions_auth',
|
||||
help: 'number of authenticated open ddp sessions',
|
||||
}),
|
||||
ddpConnectedUsers: new client.Gauge({
|
||||
name: 'rocketchat_ddp_connected_users',
|
||||
help: 'number of unique connected users',
|
||||
}),
|
||||
ddpRateLimitExceeded: new client.Counter({
|
||||
name: 'rocketchat_ddp_rate_limit_exceeded',
|
||||
labelNames: ['limit_name', 'user_id', 'client_address', 'type', 'name', 'connection_id'],
|
||||
help: 'number of times a ddp rate limiter was exceeded',
|
||||
}),
|
||||
ddpRateLimitExceededTotal: new client.Counter({
|
||||
name: 'rocketchat_ddp_rate_limit_exceeded_total',
|
||||
labelNames: ['limit_name', 'user_id', 'client_address', 'type', 'name', 'connection_id'],
|
||||
help: 'number of times a ddp rate limiter was exceeded',
|
||||
}),
|
||||
|
||||
version: new client.Gauge({
|
||||
name: 'rocketchat_version',
|
||||
labelNames: ['version'],
|
||||
help: 'Rocket.Chat version',
|
||||
}),
|
||||
migration: new client.Gauge({ name: 'rocketchat_migration', help: 'migration versoin' }),
|
||||
instanceCount: new client.Gauge({
|
||||
name: 'rocketchat_instance_count',
|
||||
help: 'instances running',
|
||||
}),
|
||||
pushQueue: new client.Gauge({
|
||||
name: 'rocketchat_push_queue',
|
||||
labelNames: ['queue'],
|
||||
help: 'push queue',
|
||||
}),
|
||||
|
||||
// User statistics
|
||||
totalUsers: new client.Gauge({ name: 'rocketchat_users_total', help: 'total of users' }),
|
||||
activeUsers: new client.Gauge({
|
||||
name: 'rocketchat_users_active',
|
||||
help: 'total of active users',
|
||||
}),
|
||||
nonActiveUsers: new client.Gauge({
|
||||
name: 'rocketchat_users_non_active',
|
||||
help: 'total of non active users',
|
||||
}),
|
||||
onlineUsers: new client.Gauge({
|
||||
name: 'rocketchat_users_online',
|
||||
help: 'total of users online',
|
||||
}),
|
||||
awayUsers: new client.Gauge({
|
||||
name: 'rocketchat_users_away',
|
||||
help: 'total of users away',
|
||||
}),
|
||||
offlineUsers: new client.Gauge({
|
||||
name: 'rocketchat_users_offline',
|
||||
help: 'total of users offline',
|
||||
}),
|
||||
|
||||
// Room statistics
|
||||
totalRooms: new client.Gauge({ name: 'rocketchat_rooms_total', help: 'total of rooms' }),
|
||||
totalChannels: new client.Gauge({
|
||||
name: 'rocketchat_channels_total',
|
||||
help: 'total of public rooms/channels',
|
||||
}),
|
||||
totalPrivateGroups: new client.Gauge({
|
||||
name: 'rocketchat_private_groups_total',
|
||||
help: 'total of private rooms',
|
||||
}),
|
||||
totalDirect: new client.Gauge({
|
||||
name: 'rocketchat_direct_total',
|
||||
help: 'total of direct rooms',
|
||||
}),
|
||||
totalLivechat: new client.Gauge({
|
||||
name: 'rocketchat_livechat_total',
|
||||
help: 'total of livechat rooms',
|
||||
}),
|
||||
|
||||
// Message statistics
|
||||
totalMessages: new client.Gauge({
|
||||
name: 'rocketchat_messages_total',
|
||||
help: 'total of messages',
|
||||
}),
|
||||
totalChannelMessages: new client.Gauge({
|
||||
name: 'rocketchat_channel_messages_total',
|
||||
help: 'total of messages in public rooms',
|
||||
}),
|
||||
totalPrivateGroupMessages: new client.Gauge({
|
||||
name: 'rocketchat_private_group_messages_total',
|
||||
help: 'total of messages in private rooms',
|
||||
}),
|
||||
totalDirectMessages: new client.Gauge({
|
||||
name: 'rocketchat_direct_messages_total',
|
||||
help: 'total of messages in direct rooms',
|
||||
}),
|
||||
totalLivechatMessages: new client.Gauge({
|
||||
name: 'rocketchat_livechat_messages_total',
|
||||
help: 'total of messages in livechat rooms',
|
||||
}),
|
||||
|
||||
// Apps metrics
|
||||
totalAppsInstalled: new client.Gauge({
|
||||
name: 'rocketchat_apps_installed',
|
||||
help: 'total apps installed',
|
||||
}),
|
||||
totalAppsEnabled: new client.Gauge({
|
||||
name: 'rocketchat_apps_enabled',
|
||||
help: 'total apps enabled',
|
||||
}),
|
||||
totalAppsFailed: new client.Gauge({
|
||||
name: 'rocketchat_apps_failed',
|
||||
help: 'total apps that failed to load',
|
||||
}),
|
||||
appBridgeMethods: new client.Summary({
|
||||
name: 'rocketchat_apps_bridge_methods',
|
||||
help: 'summary of app bridge method calls count and time',
|
||||
labelNames: ['bridge', 'method', 'app_id'],
|
||||
percentiles,
|
||||
}),
|
||||
appBridgeMethodsSeconds: new client.Histogram({
|
||||
name: 'rocketchat_apps_bridge_methods_seconds',
|
||||
help: 'histogram of app bridge method calls count and time in seconds',
|
||||
labelNames: ['bridge', 'method', 'app_id'],
|
||||
buckets: latencyBuckets,
|
||||
}),
|
||||
|
||||
// Meteor Facts
|
||||
meteorFacts: new client.Gauge({
|
||||
name: 'rocketchat_meteor_facts',
|
||||
labelNames: ['pkg', 'fact'],
|
||||
help: 'internal meteor facts',
|
||||
}),
|
||||
|
||||
// Livechat metrics
|
||||
totalLivechatVisitors: new client.Gauge({ name: 'rocketchat_visitors_total', help: 'total of visitors' }),
|
||||
totalLivechatAgents: new client.Gauge({ name: 'rocketchat_agents_total', help: 'total of agents' }),
|
||||
totalLivechatWebhooksSuccess: new client.Counter({
|
||||
name: 'rocketchat_livechat_webhooks_success',
|
||||
help: 'successful livechat webhooks',
|
||||
}),
|
||||
totalLivechatWebhooksSuccessTotal: new client.Counter({
|
||||
name: 'rocketchat_livechat_webhooks_success_total',
|
||||
help: 'successful livechat webhooks',
|
||||
}),
|
||||
totalLivechatWebhooksFailures: new client.Counter({
|
||||
name: 'rocketchat_livechat_webhooks_failures',
|
||||
help: 'failed livechat webhooks',
|
||||
}),
|
||||
totalLivechatWebhooksFailuresTotal: new client.Counter({
|
||||
name: 'rocketchat_livechat_webhooks_failures_total',
|
||||
help: 'failed livechat webhooks',
|
||||
}),
|
||||
|
||||
totalItemsProcessedByQueue: new client.Counter({
|
||||
name: 'rocketchat_queue_items_processed_total',
|
||||
labelNames: ['queue'],
|
||||
help: 'Total number of items processed by Rocket.Chat Omni queues',
|
||||
}),
|
||||
totalItemsFailedByQueue: new client.Counter({
|
||||
name: 'rocketchat_queue_items_failed_total',
|
||||
labelNames: ['queue'],
|
||||
help: 'Total number of items failed by Rocket.Chat Omni queues',
|
||||
}),
|
||||
totalItemsProcessedByReconciliationQueue: new client.Counter({
|
||||
name: 'rocketchat_reconciliation_queue_items_processed_total',
|
||||
labelNames: ['queue', 'action'],
|
||||
help: 'Total number of items processed by the Omnichannel queue that were reconciled before processing',
|
||||
}),
|
||||
timeToQueueProcessingByQueue: new client.Summary({
|
||||
name: 'rocketchat_queue_wait_time_seconds',
|
||||
labelNames: ['queue'],
|
||||
help: 'Time taken in seconds for an item to be processed for the first time by Omni queues',
|
||||
percentiles,
|
||||
}),
|
||||
timeToQueueProcessingByQueueHistogram: new client.Histogram({
|
||||
name: 'rocketchat_queue_wait_duration_seconds',
|
||||
labelNames: ['queue'],
|
||||
help: 'Histogram of time taken in seconds for an item to be processed for the first time by Omni queues',
|
||||
buckets: queueWaitBuckets,
|
||||
}),
|
||||
};
|
||||
|
||||
// Metrics
|
||||
let eluBase = performance.eventLoopUtilization();
|
||||
|
||||
new client.Gauge({
|
||||
name: 'nodejs_event_loop_utilization_ratio',
|
||||
help: 'Event Loop Utilization (ELU) as reported by NodeJS',
|
||||
collect() {
|
||||
this.set(performance.eventLoopUtilization(eluBase).utilization);
|
||||
eluBase = performance.eventLoopUtilization();
|
||||
},
|
||||
});
|
||||
47
apps/meteor/server/lib/metrics/lib/statsTracker.js
Normal file
47
apps/meteor/server/lib/metrics/lib/statsTracker.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import { StatsD } from 'node-dogstatsd';
|
||||
|
||||
class StatsTracker {
|
||||
constructor() {
|
||||
this.StatsD = StatsD;
|
||||
this.dogstatsd = new this.StatsD();
|
||||
}
|
||||
|
||||
track(type, stats, ...args) {
|
||||
this.dogstatsd[type](`RocketChat.${stats}`, ...args);
|
||||
}
|
||||
|
||||
now() {
|
||||
const hrtime = process.hrtime();
|
||||
return hrtime[0] * 1000000 + hrtime[1] / 1000;
|
||||
}
|
||||
|
||||
timing(stats, time, tags) {
|
||||
this.track('timing', stats, time, tags);
|
||||
}
|
||||
|
||||
increment(stats, time, tags) {
|
||||
this.track('increment', stats, time, tags);
|
||||
}
|
||||
|
||||
decrement(stats, time, tags) {
|
||||
this.track('decrement', stats, time, tags);
|
||||
}
|
||||
|
||||
histogram(stats, time, tags) {
|
||||
this.track('histogram', stats, time, tags);
|
||||
}
|
||||
|
||||
gauge(stats, time, tags) {
|
||||
this.track('gauge', stats, time, tags);
|
||||
}
|
||||
|
||||
unique(stats, time, tags) {
|
||||
this.track('unique', stats, time, tags);
|
||||
}
|
||||
|
||||
set(stats, time, tags) {
|
||||
this.track('set', stats, time, tags);
|
||||
}
|
||||
}
|
||||
|
||||
export default new StatsTracker();
|
||||
Reference in New Issue
Block a user