Merge pull request #1947 from elizandropacheco/feat/prometheus-metrics

Feat/prometheus metrics
This commit is contained in:
Davidson Gomes
2025-09-17 14:25:22 -03:00
committed by GitHub
3 changed files with 80 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ import { ChannelRouter } from '@api/integrations/channel/channel.router';
import { ChatbotRouter } from '@api/integrations/chatbot/chatbot.router';
import { EventRouter } from '@api/integrations/event/event.router';
import { StorageRouter } from '@api/integrations/storage/storage.router';
import { waMonitor } from '@api/server.module';
import { configService } from '@config/env.config';
import { fetchLatestWaWebVersion } from '@utils/fetchLatestWaWebVersion';
import { Router } from 'express';
@@ -42,6 +43,65 @@ const telemetry = new Telemetry();
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
// Expose Prometheus metrics when enabled by env flag
if (process.env.PROMETHEUS_METRICS === 'true') {
router.get('/metrics', async (req, res) => {
res.set('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');
res.set('Cache-Control', 'no-cache, no-store, must-revalidate');
const escapeLabel = (value: unknown) =>
String(value ?? '')
.replace(/\\/g, '\\\\')
.replace(/\n/g, '\\n')
.replace(/"/g, '\\"');
const lines: string[] = [];
const clientName = process.env.DATABASE_CONNECTION_CLIENT_NAME || 'unknown';
const serverUrl = serverConfig.URL || '';
// environment info
lines.push('# HELP evolution_environment_info Environment information');
lines.push('# TYPE evolution_environment_info gauge');
lines.push(
`evolution_environment_info{version="${escapeLabel(packageJson.version)}",clientName="${escapeLabel(
clientName,
)}",serverUrl="${escapeLabel(serverUrl)}"} 1`,
);
const instances = (waMonitor && waMonitor.waInstances) || {};
const instanceEntries = Object.entries(instances);
// total instances
lines.push('# HELP evolution_instances_total Total number of instances');
lines.push('# TYPE evolution_instances_total gauge');
lines.push(`evolution_instances_total ${instanceEntries.length}`);
// per-instance status
lines.push('# HELP evolution_instance_up 1 if instance state is open, else 0');
lines.push('# TYPE evolution_instance_up gauge');
lines.push('# HELP evolution_instance_state Instance state as a labelled metric');
lines.push('# TYPE evolution_instance_state gauge');
for (const [name, instance] of instanceEntries) {
const state = instance?.connectionStatus?.state || 'unknown';
const integration = instance?.integration || '';
const up = state === 'open' ? 1 : 0;
lines.push(
`evolution_instance_up{instance="${escapeLabel(name)}",integration="${escapeLabel(integration)}"} ${up}`,
);
lines.push(
`evolution_instance_state{instance="${escapeLabel(name)}",integration="${escapeLabel(
integration,
)}",state="${escapeLabel(state)}"} 1`,
);
}
res.send(lines.join('\n') + '\n');
});
}
if (!serverConfig.DISABLE_MANAGER) router.use('/manager', new ViewsRouter().router);
router.get('/assets/*', (req, res) => {