mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-12-11 02:49:36 -06:00
Merge pull request #1947 from elizandropacheco/feat/prometheus-metrics
Feat/prometheus metrics
This commit is contained in:
commit
e75dae38ee
19
Dockerfile.metrics
Normal file
19
Dockerfile.metrics
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
FROM evoapicloud/evolution-api:latest AS base
|
||||||
|
WORKDIR /evolution
|
||||||
|
|
||||||
|
# Copiamos apenas o necessário para recompilar o dist com as mudanças locais
|
||||||
|
COPY tsconfig.json tsup.config.ts package.json ./
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# Recompila usando os node_modules já presentes na imagem base
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Runtime final: reaproveita a imagem oficial e apenas sobrepõe o dist
|
||||||
|
FROM evoapicloud/evolution-api:latest AS final
|
||||||
|
WORKDIR /evolution
|
||||||
|
COPY --from=base /evolution/dist ./dist
|
||||||
|
|
||||||
|
ENV PROMETHEUS_METRICS=true
|
||||||
|
|
||||||
|
# Entrada original da imagem oficial já sobe o app em /evolution
|
||||||
|
|
||||||
@ -3,7 +3,7 @@ version: "3.8"
|
|||||||
services:
|
services:
|
||||||
api:
|
api:
|
||||||
container_name: evolution_api
|
container_name: evolution_api
|
||||||
image: evoapicloud/evolution-api:latest
|
image: evolution/api:metrics
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { ChannelRouter } from '@api/integrations/channel/channel.router';
|
|||||||
import { ChatbotRouter } from '@api/integrations/chatbot/chatbot.router';
|
import { ChatbotRouter } from '@api/integrations/chatbot/chatbot.router';
|
||||||
import { EventRouter } from '@api/integrations/event/event.router';
|
import { EventRouter } from '@api/integrations/event/event.router';
|
||||||
import { StorageRouter } from '@api/integrations/storage/storage.router';
|
import { StorageRouter } from '@api/integrations/storage/storage.router';
|
||||||
|
import { waMonitor } from '@api/server.module';
|
||||||
import { configService } from '@config/env.config';
|
import { configService } from '@config/env.config';
|
||||||
import { fetchLatestWaWebVersion } from '@utils/fetchLatestWaWebVersion';
|
import { fetchLatestWaWebVersion } from '@utils/fetchLatestWaWebVersion';
|
||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
@ -42,6 +43,65 @@ const telemetry = new Telemetry();
|
|||||||
|
|
||||||
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
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);
|
if (!serverConfig.DISABLE_MANAGER) router.use('/manager', new ViewsRouter().router);
|
||||||
|
|
||||||
router.get('/assets/*', (req, res) => {
|
router.get('/assets/*', (req, res) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user