Service Monitor - Documentación Completa
Fecha: 2025-12-08
Versión: 1.2
Lenguaje: Zig 0.15.2
Repositorio: https://git.reugenio.com/reugenio/service-monitor
Descripción
Monitor de servicios HTTP y TCP para verificar disponibilidad del servidor Hetzner (Simba). Notifica por desktop, email y Telegram cuando hay servicios caídos.
Características Implementadas
| Feature |
Estado |
Descripción |
| Verificación HTTP/HTTPS |
✅ |
GET + status 200 + tiempo respuesta |
| Verificación TCP |
✅ |
Conexión a puerto + DNS resolution |
| Modo watch |
✅ |
Loop continuo con intervalo configurable |
| Modo daemon |
✅ |
Background con fork() + setsid() |
| Log a archivo |
✅ |
Append mode, timestamps ISO |
| Config externo |
✅ |
Archivo CSV simple |
| Notificación desktop |
✅ |
notify-send (Linux) |
| Notificación email |
✅ |
SMTP con STARTTLS via curl |
| Notificación Telegram |
✅ |
Bot API via curl |
Estructura del Proyecto
service-monitor/
├── build.zig # Sistema de build Zig
├── CLAUDE.md # Especificación del proyecto
├── services.conf # Configuración activa
├── services.conf.example # Ejemplo documentado
├── service-monitor # Binario compilado
├── service-monitor.log # Log de ejecución
├── service-monitor.pid # PID en modo daemon
│
├── src/
│ ├── main.zig # Entry point + CLI + lógica principal (317 líneas)
│ ├── http.zig # Cliente HTTP/HTTPS (77 líneas)
│ ├── tcp.zig # Verificación TCP (68 líneas)
│ ├── config.zig # Parser de configuración (233 líneas)
│ ├── notify.zig # Notificaciones desktop (77 líneas)
│ ├── daemon.zig # Daemonización (101 líneas)
│ ├── smtp.zig # Cliente SMTP (260 líneas)
│ └── telegram.zig # Cliente Telegram (107 líneas)
│
└── docs/
├── DIARIO_DESARROLLO.md
└── PROYECTO_COMPLETO.md # Este archivo
Uso
Comandos Básicos
# Compilar
zig build
# Verificar una vez
./service-monitor
# Modo watch (cada 60 segundos)
./service-monitor --watch
# Modo watch cada 30 segundos
./service-monitor -w -i 30
# Con log a archivo
./service-monitor -w -l
# Con notificaciones desktop
./service-monitor -w -n
# Daemon en background
./service-monitor -w -d
# Todo junto
./service-monitor -w -i 60 -d -l -n
# Config personalizado
./service-monitor -c /ruta/config.conf
# Ayuda
./service-monitor --help
Opciones CLI
| Opción |
Corto |
Descripción |
Default |
--watch |
-w |
Modo continuo |
false |
--interval |
-i |
Segundos entre checks |
60 |
--log |
-l |
Log a archivo |
service-monitor.log |
--notify |
-n |
Notificaciones desktop |
false |
--daemon |
-d |
Ejecutar en background |
false |
--config |
-c |
Archivo de configuración |
services.conf |
--help |
-h |
Mostrar ayuda |
- |
Gestión del Daemon
# Iniciar daemon
./service-monitor -w -d -l -n
# Ver PID
cat service-monitor.pid
# Ver logs
tail -f service-monitor.log
# Detener daemon
kill $(cat service-monitor.pid)
Archivo de Configuración
Formato
# Comentarios con #
# tipo,parámetros...
# Servicios HTTP
http,Nombre Servicio,https://url.com
# Servicios TCP
tcp,Nombre Servicio,hostname,puerto
# Email (destinatarios)
email,destinatario@ejemplo.com
# Email (servidor SMTP)
email_smtp,smtp.servidor.com,puerto,usuario,password,from@email.com
# Telegram
telegram,bot_token,chat_id
Ejemplo Real (services.conf)
# Servicios HTTP
http,Forgejo (HTTP),https://git.reugenio.com
http,Simifactu API,https://simifactu.com
http,Mundisofa,https://mundisofa.com
http,Menzuri,https://menzuri.com
# Servicios TCP
tcp,Forgejo (SSH),git.reugenio.com,2222
# Telegram
telegram,8158165444:AAFxUjLChsuusgFD5B1gt2svt8NflvAm1M8,1481345275
Servicios Monitoreados (Servidor Simba)
| Servicio |
Tipo |
Endpoint |
Puerto |
| Forgejo HTTP |
HTTPS |
git.reugenio.com |
443 |
| Forgejo SSH |
TCP |
git.reugenio.com |
2222 |
| Simifactu |
HTTPS |
simifactu.com |
443 |
| Mundisofa |
HTTPS |
mundisofa.com |
443 |
| Menzuri |
HTTPS |
menzuri.com |
443 |
Output
Terminal (con colores)
[2025-12-07 20:53:24]
✓ Forgejo (HTTP) - OK (768ms)
✓ Forgejo (SSH) - OK (63ms)
✓ Simifactu API - OK (481ms)
✓ Mundisofa - OK (444ms)
✓ Menzuri - OK (456ms)
Log (sin colores)
[2025-12-07 20:53:24]
OK Forgejo (HTTP) (768ms)
OK Forgejo (SSH) (63ms)
OK Simifactu API (481ms)
OK Mundisofa (444ms)
OK Menzuri (456ms)
Telegram (cuando hay errores)
⚠️ ALERTA: Servicios caídos
- Nombre Servicio 1
- Nombre Servicio 2
Detalles Técnicos por Módulo
main.zig
- Entry point de la aplicación
- Parser de argumentos CLI
- Lógica de loop watch/daemon
- Coordinación de todos los módulos
- Gestión de timestamps (UTC)
http.zig
- Cliente HTTP usando
std.http.Client
- Soporte HTTPS con TLS automático
- Buffer de headers: 8192 bytes
- Medición de tiempo de respuesta
- Errores tipados: DnsResolutionFailed, ConnectionFailed, Timeout, UnexpectedStatus
tcp.zig
- Conexión TCP con
std.net.tcpConnectToHost
- Resolución DNS automática
- Medición de tiempo de conexión
- Errores tipados: DnsResolutionFailed, ConnectionRefused, Timeout
config.zig
- Parser CSV simple
- Soporte para comentarios (#)
- Estructuras: Service, SmtpConfig, TelegramConfig, Config
- Fallback a config por defecto si no existe archivo
- Gestión de memoria con allocator
notify.zig
- Wrapper sobre
notify-send
- Niveles de urgencia: low, normal, critical
- Funciones: send(), sendError(), sendRecovery()
daemon.zig
- Double fork para daemonización correcta
- Syscall directo para setsid() (no disponible en std.posix Zig 0.13)
- Redirección de stdin/stdout/stderr a /dev/null
- Escritura de PID file
- Cambio a directorio raíz
smtp.zig
- Implementación SMTP usando curl como subprocess
- Soporte completo STARTTLS (puerto 587)
- Curl maneja TLS de forma transparente
- Autenticación con usuario/contraseña
- Compatible con Gmail, Mailbox.org, Outlook, etc.
telegram.zig
- Bot API via curl (más fiable que std.http para POST)
- Funciones: sendMessage(), sendAlert()
- Formato de mensaje con lista de servicios
Consumo de Recursos
| Recurso |
Valor |
| RAM |
~2-5 MB |
| CPU (idle) |
~0% |
| CPU (check) |
<1% por ~2s |
| Binario |
~8.4 MB (debug) |
| Red |
~10KB por ciclo |
Commits Históricos
| Hash |
Descripción |
e2e19da |
Fase 1: Monitor básico HTTP/TCP |
3946f83 |
Fase 2: Modo watch + CLI + timestamps |
dfcfd31 |
Log a archivo |
5a17d74 |
Fase 3: Notificaciones desktop |
655dcb8 |
Daemon mode + config externo |
a011d9e |
SMTP y Telegram |
f31ce95 |
Migración a Zig 0.15.2 |
4a9d0e6 |
SMTP con STARTTLS via curl |
Pendiente
Notas de Migración a Zig 0.15
La migración a Zig 0.15.2 requirió los siguientes cambios:
| Cambio |
Antes (0.13) |
Después (0.15) |
| Build.zig |
root_source_file |
root_module con b.createModule() |
| stdout |
std.io.getStdOut().writer() |
std.fs.File.stdout().deprecatedWriter() |
| ArrayList |
std.ArrayList(T).init(alloc) |
std.array_list.Managed(T).init(alloc) |
| file.reader() |
sin args |
requiere buffer, usar deprecatedReader() |
| HTTP Client |
client.open() + send() + wait() |
client.fetch() |
| sleep |
std.time.sleep() |
std.Thread.sleep() |
Notas de Implementación SMTP con STARTTLS
La implementación nativa de TLS en Zig 0.15 resultó compleja debido a cambios en la API de I/O.
Se optó por usar curl como subprocess, que ofrece:
- Simplicidad: curl maneja STARTTLS transparentemente con
--ssl-reqd
- Fiabilidad: curl es estable y bien probado
- Compatibilidad: Funciona con cualquier servidor SMTP moderno
- Consistencia: Mismo enfoque que Telegram (también usa curl)
# Equivalente manual:
echo -e "From: user@mailbox.org\r\nTo: dest@example.com\r\nSubject: Test\r\n\r\nBody" | \
curl -s --url "smtp://smtp.mailbox.org:587" --ssl-reqd \
-u "user@mailbox.org:password" \
--mail-from "<user@mailbox.org>" \
--mail-rcpt "<dest@example.com>" -T -
Configuración SMTP Actual
| Parámetro |
Valor |
| Servidor |
smtp.mailbox.org |
| Puerto |
587 (STARTTLS) |
| Usuario |
reugenio@mailbox.org |
| Tipo password |
App password (solo envío) |
Nota: Credenciales completas en teamdocs/INFRASTRUCTURE/NOTIFICACIONES.md
Referencias