Skip to content

Commit 3ddbd6a

Browse files
committed
feat(config): add telemetry and metrics configuration options
- Introduce new environment variables for telemetry and Prometheus metrics in .env.example - Create example configuration files for Prometheus and Grafana dashboards - Update main application to utilize new configuration settings for Sentry, audio converter, and proxy - Enhance channel services to support audio conversion API integration - Implement middleware for metrics IP whitelisting and basic authentication in routes
1 parent 81a991a commit 3ddbd6a

File tree

16 files changed

+538
-44
lines changed

16 files changed

+538
-44
lines changed

.env.example

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@ SSL_CONF_FULLCHAIN=/path/to/cert.crt
99

1010
SENTRY_DSN=
1111

12+
# Telemetry - Set to false to disable telemetry
13+
TELEMETRY_ENABLED=true
14+
TELEMETRY_URL=
15+
16+
# Prometheus metrics - Set to true to enable Prometheus metrics
17+
PROMETHEUS_METRICS=false
18+
METRICS_AUTH_REQUIRED=true
19+
METRICS_USER=prometheus
20+
METRICS_PASSWORD=secure_random_password_here
21+
METRICS_ALLOWED_IPS=127.0.0.1,10.0.0.100,192.168.1.50
22+
23+
# Proxy configuration (optional)
24+
PROXY_HOST=
25+
PROXY_PORT=
26+
PROXY_PROTOCOL=
27+
PROXY_USERNAME=
28+
PROXY_PASSWORD=
29+
30+
# Audio converter API (optional)
31+
API_AUDIO_CONVERTER=
32+
API_AUDIO_CONVERTER_KEY=
33+
1234
# Cors - * for all or set separate by commas - ex.: 'yourdomain1.com, yourdomain2.com'
1335
CORS_ORIGIN=*
1436
CORS_METHODS=GET,POST,PUT,DELETE

grafana-dashboard.json.example

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
{
2+
"dashboard": {
3+
"id": null,
4+
"title": "Evolution API Monitoring",
5+
"tags": ["evolution-api", "whatsapp", "monitoring"],
6+
"style": "dark",
7+
"timezone": "browser",
8+
"panels": [
9+
{
10+
"id": 1,
11+
"title": "API Status",
12+
"type": "stat",
13+
"targets": [
14+
{
15+
"expr": "up{job=\"evolution-api\"}",
16+
"legendFormat": "API Status"
17+
}
18+
],
19+
"fieldConfig": {
20+
"defaults": {
21+
"mappings": [
22+
{
23+
"options": {
24+
"0": {
25+
"text": "DOWN",
26+
"color": "red"
27+
},
28+
"1": {
29+
"text": "UP",
30+
"color": "green"
31+
}
32+
},
33+
"type": "value"
34+
}
35+
]
36+
}
37+
},
38+
"gridPos": {
39+
"h": 8,
40+
"w": 12,
41+
"x": 0,
42+
"y": 0
43+
}
44+
},
45+
{
46+
"id": 2,
47+
"title": "Total Instances",
48+
"type": "stat",
49+
"targets": [
50+
{
51+
"expr": "evolution_instances_total",
52+
"legendFormat": "Total Instances"
53+
}
54+
],
55+
"gridPos": {
56+
"h": 8,
57+
"w": 12,
58+
"x": 12,
59+
"y": 0
60+
}
61+
},
62+
{
63+
"id": 3,
64+
"title": "Instance Status Overview",
65+
"type": "piechart",
66+
"targets": [
67+
{
68+
"expr": "sum by (state) (evolution_instance_state)",
69+
"legendFormat": "{{ state }}"
70+
}
71+
],
72+
"gridPos": {
73+
"h": 9,
74+
"w": 12,
75+
"x": 0,
76+
"y": 8
77+
}
78+
},
79+
{
80+
"id": 4,
81+
"title": "Instances by Integration Type",
82+
"type": "piechart",
83+
"targets": [
84+
{
85+
"expr": "sum by (integration) (evolution_instance_up)",
86+
"legendFormat": "{{ integration }}"
87+
}
88+
],
89+
"gridPos": {
90+
"h": 9,
91+
"w": 12,
92+
"x": 12,
93+
"y": 8
94+
}
95+
},
96+
{
97+
"id": 5,
98+
"title": "Instance Uptime",
99+
"type": "table",
100+
"targets": [
101+
{
102+
"expr": "evolution_instance_up",
103+
"format": "table",
104+
"instant": true
105+
}
106+
],
107+
"transformations": [
108+
{
109+
"id": "organize",
110+
"options": {
111+
"excludeByName": {
112+
"Time": true,
113+
"__name__": true
114+
},
115+
"renameByName": {
116+
"instance": "Instance Name",
117+
"integration": "Integration Type",
118+
"Value": "Status"
119+
}
120+
}
121+
}
122+
],
123+
"fieldConfig": {
124+
"overrides": [
125+
{
126+
"matcher": {
127+
"id": "byName",
128+
"options": "Status"
129+
},
130+
"properties": [
131+
{
132+
"id": "mappings",
133+
"value": [
134+
{
135+
"options": {
136+
"0": {
137+
"text": "DOWN",
138+
"color": "red"
139+
},
140+
"1": {
141+
"text": "UP",
142+
"color": "green"
143+
}
144+
},
145+
"type": "value"
146+
}
147+
]
148+
}
149+
]
150+
}
151+
]
152+
},
153+
"gridPos": {
154+
"h": 9,
155+
"w": 24,
156+
"x": 0,
157+
"y": 17
158+
}
159+
},
160+
{
161+
"id": 6,
162+
"title": "Instance Status Timeline",
163+
"type": "timeseries",
164+
"targets": [
165+
{
166+
"expr": "evolution_instance_up",
167+
"legendFormat": "{{ instance }} ({{ integration }})"
168+
}
169+
],
170+
"fieldConfig": {
171+
"defaults": {
172+
"custom": {
173+
"drawStyle": "line",
174+
"lineInterpolation": "stepAfter",
175+
"lineWidth": 2,
176+
"fillOpacity": 10,
177+
"gradientMode": "none",
178+
"spanNulls": false,
179+
"insertNulls": false,
180+
"showPoints": "never",
181+
"pointSize": 5,
182+
"stacking": {
183+
"mode": "none",
184+
"group": "A"
185+
},
186+
"axisPlacement": "auto",
187+
"axisLabel": "",
188+
"scaleDistribution": {
189+
"type": "linear"
190+
},
191+
"hideFrom": {
192+
"legend": false,
193+
"tooltip": false,
194+
"vis": false
195+
},
196+
"thresholdsStyle": {
197+
"mode": "off"
198+
}
199+
},
200+
"min": 0,
201+
"max": 1
202+
}
203+
},
204+
"gridPos": {
205+
"h": 8,
206+
"w": 24,
207+
"x": 0,
208+
"y": 26
209+
}
210+
}
211+
],
212+
"time": {
213+
"from": "now-1h",
214+
"to": "now"
215+
},
216+
"timepicker": {},
217+
"templating": {
218+
"list": []
219+
},
220+
"annotations": {
221+
"list": [
222+
{
223+
"builtIn": 1,
224+
"datasource": "-- Grafana --",
225+
"enable": true,
226+
"hide": true,
227+
"iconColor": "rgba(0, 211, 255, 1)",
228+
"name": "Annotations & Alerts",
229+
"type": "dashboard"
230+
}
231+
]
232+
},
233+
"refresh": "30s",
234+
"schemaVersion": 27,
235+
"version": 0,
236+
"links": []
237+
}
238+
}

prometheus.yml.example

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Prometheus configuration example for Evolution API
2+
# Copy this file to prometheus.yml and adjust the settings
3+
4+
global:
5+
scrape_interval: 15s
6+
evaluation_interval: 15s
7+
8+
rule_files:
9+
# - "first_rules.yml"
10+
# - "second_rules.yml"
11+
12+
scrape_configs:
13+
# Evolution API metrics
14+
- job_name: 'evolution-api'
15+
static_configs:
16+
- targets: ['localhost:8080'] # Adjust to your Evolution API URL
17+
18+
# Metrics endpoint path
19+
metrics_path: '/metrics'
20+
21+
# Scrape interval for this job
22+
scrape_interval: 30s
23+
24+
# Basic authentication (if METRICS_AUTH_REQUIRED=true)
25+
basic_auth:
26+
username: 'prometheus' # Should match METRICS_USER
27+
password: 'secure_random_password_here' # Should match METRICS_PASSWORD
28+
29+
# Optional: Add custom labels
30+
relabel_configs:
31+
- source_labels: [__address__]
32+
target_label: __param_target
33+
- source_labels: [__param_target]
34+
target_label: instance
35+
- target_label: __address__
36+
replacement: localhost:8080 # Evolution API address
37+
38+
# Alerting configuration (optional)
39+
alerting:
40+
alertmanagers:
41+
- static_configs:
42+
- targets:
43+
# - alertmanager:9093
44+
45+
# Example alert rules for Evolution API
46+
# Create a file called evolution_alerts.yml with these rules:
47+
#
48+
# groups:
49+
# - name: evolution-api
50+
# rules:
51+
# - alert: EvolutionAPIDown
52+
# expr: up{job="evolution-api"} == 0
53+
# for: 1m
54+
# labels:
55+
# severity: critical
56+
# annotations:
57+
# summary: "Evolution API is down"
58+
# description: "Evolution API has been down for more than 1 minute."
59+
#
60+
# - alert: EvolutionInstanceDown
61+
# expr: evolution_instance_up == 0
62+
# for: 2m
63+
# labels:
64+
# severity: warning
65+
# annotations:
66+
# summary: "Evolution instance {{ $labels.instance }} is down"
67+
# description: "Instance {{ $labels.instance }} has been down for more than 2 minutes."
68+
#
69+
# - alert: HighInstanceCount
70+
# expr: evolution_instances_total > 100
71+
# for: 5m
72+
# labels:
73+
# severity: warning
74+
# annotations:
75+
# summary: "High number of Evolution instances"
76+
# description: "Evolution API is managing {{ $value }} instances."

src/api/integrations/channel/evolution/evolution.channel.service.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { chatbotController } from '@api/server.module';
1313
import { CacheService } from '@api/services/cache.service';
1414
import { ChannelStartupService } from '@api/services/channel.service';
1515
import { Events, wa } from '@api/types/wa.types';
16-
import { Chatwoot, ConfigService, Openai, S3 } from '@config/env.config';
16+
import { AudioConverter, Chatwoot, ConfigService, Openai, S3 } from '@config/env.config';
1717
import { BadRequestException, InternalServerErrorException } from '@exceptions';
1818
import { createJid } from '@utils/createJid';
1919
import axios from 'axios';
@@ -622,7 +622,8 @@ export class EvolutionStartupService extends ChannelStartupService {
622622
number = number.replace(/\D/g, '');
623623
const hash = `${number}-${new Date().getTime()}`;
624624

625-
if (process.env.API_AUDIO_CONVERTER) {
625+
const audioConverterConfig = this.configService.get<AudioConverter>('AUDIO_CONVERTER');
626+
if (audioConverterConfig.API_URL) {
626627
try {
627628
this.logger.verbose('Using audio converter API');
628629
const formData = new FormData();
@@ -640,10 +641,10 @@ export class EvolutionStartupService extends ChannelStartupService {
640641

641642
formData.append('format', 'mp4');
642643

643-
const response = await axios.post(process.env.API_AUDIO_CONVERTER, formData, {
644+
const response = await axios.post(audioConverterConfig.API_URL, formData, {
644645
headers: {
645646
...formData.getHeaders(),
646-
apikey: process.env.API_AUDIO_CONVERTER_KEY,
647+
apikey: audioConverterConfig.API_KEY,
647648
},
648649
});
649650

0 commit comments

Comments
 (0)