En 2019, un de nos serveurs IRC a subi un memory leak progressif pendant trois semaines. Personne ne s'en est rendu compte jusqu'a ce que le serveur OOM-kill le processus a 3h du matin. Les utilisateurs se sont reconnectes sur un autre noeud, mais nous avons perdu les logs et la configuration du runtime. Apres cet incident, j'ai installe Prometheus et Grafana. Depuis, je vois venir les problemes avant qu'ils n'arrivent. Le monitoring, c'est la difference entre reagir a une crise et la prevenir.
Pourquoi monitorer IRC
Un serveur IRC a l'air simple — un processus, quelques connexions, du texte. En realite, un IRCd en production genere des dizaines de metriques qu'il faut surveiller :
- Connexions : Nombre d'utilisateurs connectes, taux de connexion/deconnexion, connexions par IP.
- Canaux : Nombre de canaux actifs, taille des canaux, activite par canal.
- Reseau : Bande passante entrante/sortante, latence entre serveurs links, netsplits.
- Ressources : CPU, memoire, file descriptors, taille des send queues.
- Securite : Tentatives de connexion echouees, K-lines et G-lines actives, connexions depuis des DNSBLs.
Sans monitoring, vous decouvrez les problemes quand les utilisateurs se plaignent. Avec Prometheus et Grafana, vous voyez les tendances, detectez les anomalies, et recevez des alertes avant que la situation ne degenere.
Pour les organisations qui gerent plusieurs services — IRC, web, bases de donnees — la mise en place d'un monitoring unifie est un investissement qui se rentabilise au premier incident evite. Des prestataires comme PowerITi peuvent deployer et configurer une stack d'observabilite complete (Prometheus, Grafana, Alertmanager) adaptee a votre infrastructure specifique.
Architecture de monitoring
# Architecture typique :
#
# [IRCd] --> [Exporter IRC] <-- [Prometheus] --> [Grafana]
# |
# [Alertmanager]
# |
# [Email/Slack/IRC]
# Composants :
# 1. Exporter IRC : collecte les metriques de l'IRCd
# et les expose au format Prometheus (HTTP /metrics)
# 2. Prometheus : scrape les metriques periodiquement,
# les stocke, et evalue les regles d'alerte
# 3. Grafana : visualise les metriques avec des dashboards
# 4. Alertmanager : route les alertes vers les canaux
# de notification (email, Slack, ou meme IRC)
# Installation rapide (Docker Compose) :
# docker-compose.yml
version: '3'
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
alertmanager:
image: prom/alertmanager
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
ports:
- "9093:9093"
# prometheus.yml :
scrape_configs:
- job_name: 'irc-exporter'
scrape_interval: 30s
static_configs:
- targets: ['irc-exporter:9100']
Ecrire un exporter IRC
Il n'existe pas d'exporter Prometheus officiel pour IRC. Mais en ecrire un est simple — l'exporter se connecte a l'IRCd comme un operateur et collecte les statistiques via les commandes d'administration.
# Exporter IRC en Python
# (exporter_irc.py)
import time
import ssl
import socket
import re
from prometheus_client import start_http_server, Gauge, Counter
# Metriques Prometheus
USERS_TOTAL = Gauge('irc_users_total', 'Total connected users')
CHANNELS_TOTAL = Gauge('irc_channels_total', 'Total active channels')
SERVERS_TOTAL = Gauge('irc_servers_total', 'Total linked servers')
MEMORY_BYTES = Gauge('irc_memory_bytes', 'IRCd memory usage')
UPTIME_SECONDS = Gauge('irc_uptime_seconds', 'IRCd uptime')
CONNECTIONS = Counter('irc_connections_total', 'Total connections')
SEND_QUEUE = Gauge('irc_sendq_bytes', 'Send queue size')
class IRCExporter:
def __init__(self, host, port, nick, oper_user, oper_pass):
self.host = host
self.port = port
self.nick = nick
self.oper_user = oper_user
self.oper_pass = oper_pass
self.sock = None
def connect(self):
raw = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock = ssl.wrap_socket(raw)
self.sock.connect((self.host, self.port))
self.send(f"NICK {self.nick}")
self.send(f"USER exporter 0 * :IRC Exporter")
time.sleep(2)
self.send(f"OPER {self.oper_user} {self.oper_pass}")
def send(self, msg):
self.sock.send(f"{msg}\r\n".encode())
def recv(self, timeout=5):
self.sock.settimeout(timeout)
data = b""
try:
while True:
chunk = self.sock.recv(4096)
if not chunk:
break
data += chunk
except socket.timeout:
pass
return data.decode('utf-8', errors='replace')
def collect_stats(self):
# LUSERS retourne les stats globales
self.send("LUSERS")
response = self.recv()
# Parser les reponses numeriques
for line in response.split('\n'):
# 251: users and invisible
m = re.search(r':There are (\d+) users', line)
if m:
USERS_TOTAL.set(int(m.group(1)))
# 254: channels
m = re.search(r'(\d+) :channels formed', line)
if m:
CHANNELS_TOTAL.set(int(m.group(1)))
# 252: operators
m = re.search(r'(\d+) :operator', line)
if m:
pass # operator count metric
def run(self, interval=30):
self.connect()
while True:
self.collect_stats()
time.sleep(interval)
if __name__ == '__main__':
# Demarrer le serveur HTTP Prometheus
start_http_server(9100)
exporter = IRCExporter(
host='127.0.0.1',
port=6697,
nick='prometheus-exporter',
oper_user='exporter',
oper_pass='motdepasse'
)
exporter.run()
/STATS fournit des metriques detaillees. STATS u donne l'uptime, STATS m les compteurs de commandes, STATS z les statistiques memoire. Pour InspIRCd, les modules m_httpd et m_httpd_stats exposent des statistiques en HTTP/JSON — plus simple a parser qu'un client IRC.Metriques essentielles
# Metriques a collecter absolument :
# Utilisateurs
irc_users_total # Nombre total de connectes
irc_users_local # Connectes sur ce serveur
irc_users_invisible # Avec mode +i
irc_operators_online # Opers connectes
# Canaux
irc_channels_total # Canaux actifs
irc_channels_by_size # Distribution par taille
# Reseau
irc_servers_linked # Serveurs dans le reseau
irc_messages_per_second # Debit de messages
irc_bytes_sent_total # Bande passante sortante
irc_bytes_received_total # Bande passante entrante
# Ressources systeme (via node_exporter)
process_resident_memory_bytes # Memoire RSS
process_cpu_seconds_total # Temps CPU
process_open_fds # File descriptors
# Securite
irc_kline_count # K-lines actives
irc_gline_count # G-lines actives
irc_connection_rejected_total # Connexions refusees
irc_dnsbl_hits_total # Hits DNSBL
# Send queue (critique)
irc_sendq_max_bytes # Plus grande send queue
# Si la send queue atteint le maximum, le client
# est deconnecte. Une send queue qui croit indique
# un client lent ou un flood.
Requetes PromQL
# Utilisateurs connectes sur 24h :
irc_users_total
# Taux de connexions par minute :
rate(irc_connections_total[5m]) * 60
# Memoire utilisee vs disponible :
process_resident_memory_bytes / 1024 / 1024 # En Mo
# Ratio messages/utilisateurs :
rate(irc_messages_per_second[5m]) / irc_users_total
# Croissance des canaux sur une semaine :
irc_channels_total - irc_channels_total offset 7d
# Alertes de send queue :
irc_sendq_max_bytes > 500000
# Si une send queue depasse 500 Ko, un client a un
# probleme de debit.
# Detection de netsplit :
changes(irc_servers_linked[5m]) > 0
# Si le nombre de serveurs change, c'est un split
# ou un rejoin.
# Anomalie de connexions (deviation) :
irc_users_total < (avg_over_time(irc_users_total[7d]) * 0.5)
# Si le nombre d'utilisateurs chute de 50% par rapport
# a la moyenne hebdomadaire, quelque chose ne va pas.
Alertes
# Fichier de regles Prometheus :
# /etc/prometheus/rules/irc_alerts.yml
groups:
- name: irc
rules:
- alert: IRCdDown
expr: up{job="irc-exporter"} == 0
for: 2m
labels:
severity: critical
annotations:
summary: "IRCd is down"
description: "L'exporter IRC ne repond plus depuis 2 min"
- alert: IRCdHighMemory
expr: process_resident_memory_bytes{job="irc-exporter"} > 500 * 1024 * 1024
for: 10m
labels:
severity: warning
annotations:
summary: "IRCd uses more than 500 MB RAM"
description: "Memoire: {{ $value | humanize1024 }}"
- alert: IRCdNetsplit
expr: changes(irc_servers_linked[5m]) > 0
labels:
severity: warning
annotations:
summary: "Netsplit detected"
- alert: IRCdUserDrop
expr: irc_users_total < (avg_over_time(irc_users_total[7d]) * 0.5)
for: 5m
labels:
severity: warning
annotations:
summary: "User count dropped 50% below weekly average"
# Configuration Alertmanager :
# alertmanager.yml
route:
receiver: 'irc-ops'
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: 'irc-ops'
webhook_configs:
# Webhook vers un bot IRC qui poste dans #ops
- url: 'http://localhost:8080/alert'
email_configs:
- to: 'ops@votredomaine.com'
from: 'prometheus@votredomaine.com'
smarthost: 'smtp.votredomaine.com:587'
for (duree minimale) raisonnable. Sans for, un pic momentane declenche une alerte immediatement. Avec for: 5m, la condition doit persister 5 minutes avant de declencher. Trop d'alertes inutiles = alerte fatigue = alertes ignorees.Dashboards Grafana
Un bon dashboard IRC a trois niveaux :
- Vue d'ensemble : Un panneau unique avec les metriques cles. Utilisateurs, canaux, serveurs, uptime. C'est ce que vous regardez en premier pour savoir si tout va bien.
- Tendances : Graphiques sur 24h, 7j, 30j. Croissance des utilisateurs, evolution de la memoire, bande passante. Les tendances revelent les problemes avant qu'ils ne deviennent critiques.
- Debug : Metriques detaillees. Distribution des send queues, repartition par serveur, logs d'evenements. Utilise quand un probleme est identifie et que vous cherchez la cause.
# Panneaux recommandes pour le dashboard principal :
# Panneau 1 : Stat (nombre actuel)
# Titre : "Utilisateurs connectes"
# Query : irc_users_total
# Panneau 2 : Graph (historique)
# Titre : "Utilisateurs sur 24h"
# Query : irc_users_total
# Time range : 24h
# Panneau 3 : Graph (memoire)
# Titre : "Memoire IRCd"
# Query : process_resident_memory_bytes / 1024 / 1024
# Unit : MB
# Panneau 4 : Graph (messages)
# Titre : "Messages par seconde"
# Query : rate(irc_messages_per_second[5m])
# Panneau 5 : Stat (uptime)
# Titre : "Uptime"
# Query : irc_uptime_seconds
# Unit : duration (seconds)
# Panneau 6 : Table (serveurs)
# Titre : "Serveurs links"
# Query : irc_servers_linked
# Exporter le dashboard en JSON pour versioning :
# Dashboard Settings -> JSON Model -> Copier dans un fichier
# Versionner dans git avec la config Prometheus
Questions frequentes
Prometheus ou Nagios pour IRC ?
Prometheus. Nagios est concu pour le monitoring a base de checks (est-ce que le service repond ? oui/non). Prometheus est concu pour les metriques continues (combien de memoire, combien d'utilisateurs, quelle tendance). Pour IRC, les metriques continues sont bien plus utiles que les checks binaires.
L'exporter impacte-t-il les performances de l'IRCd ?
Marginalement. L'exporter envoie une commande LUSERS et STATS toutes les 30 secondes. C'est moins de charge qu'un utilisateur qui tape activement. Le seul risque est si l'exporter floode les commandes STATS — respectez un intervalle de scrape minimum de 15 secondes.
Combien de temps conserver les metriques ?
15 jours en resolution maximale et 1 an en resolution reduite (downsampling) est un bon compromis. Prometheus peut etre configure avec une retention de 15 jours, et Thanos ou Cortex pour le stockage longue duree. Pour un reseau IRC modeste, 15 jours suffisent generalement.