Migración a Zig 0.15.2
Cambios principales: - build.zig: root_source_file → root_module con b.createModule() - stdout: std.io.getStdOut() → std.fs.File.stdout().deprecatedWriter() - ArrayList: std.ArrayList → std.array_list.Managed - file.reader(): deprecatedReader() para compatibilidad - HTTP Client: client.open/send/wait → client.fetch() - sleep: std.time.sleep → std.Thread.sleep Código funciona correctamente con Zig 0.15.2. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a011d9e552
commit
f31ce95afe
6 changed files with 333 additions and 31 deletions
|
|
@ -1,12 +1,12 @@
|
||||||
# service-monitor - Monitor de Servicios en Zig
|
# service-monitor - Monitor de Servicios en Zig
|
||||||
|
|
||||||
> **Última actualización**: 2025-12-07
|
> **Última actualización**: 2025-12-08
|
||||||
|
|
||||||
## Descripción del Proyecto
|
## Descripción del Proyecto
|
||||||
|
|
||||||
Monitor que verifica periódicamente que los servicios en nuestro servidor Hetzner (Simba) estén funcionando correctamente, con notificaciones si algo falla.
|
Monitor que verifica periódicamente que los servicios en nuestro servidor Hetzner (Simba) estén funcionando correctamente, con notificaciones si algo falla.
|
||||||
|
|
||||||
**Lenguaje**: Zig 0.13.0
|
**Lenguaje**: Zig 0.15.2
|
||||||
|
|
||||||
**Objetivo**: Herramienta de monitoreo simple y ligera, sin dependencias de servicios externos como UptimeRobot.
|
**Objetivo**: Herramienta de monitoreo simple y ligera, sin dependencias de servicios externos como UptimeRobot.
|
||||||
|
|
||||||
|
|
|
||||||
16
build.zig
16
build.zig
|
|
@ -6,9 +6,11 @@ pub fn build(b: *std.Build) void {
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "service-monitor",
|
.name = "service-monitor",
|
||||||
.root_source_file = b.path("src/main.zig"),
|
.root_module = b.createModule(.{
|
||||||
.target = target,
|
.root_source_file = b.path("src/main.zig"),
|
||||||
.optimize = optimize,
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Instalar en carpeta raíz del proyecto (no en zig-out/)
|
// Instalar en carpeta raíz del proyecto (no en zig-out/)
|
||||||
|
|
@ -29,9 +31,11 @@ pub fn build(b: *std.Build) void {
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
const unit_tests = b.addTest(.{
|
const unit_tests = b.addTest(.{
|
||||||
.root_source_file = b.path("src/main.zig"),
|
.root_module = b.createModule(.{
|
||||||
.target = target,
|
.root_source_file = b.path("src/main.zig"),
|
||||||
.optimize = optimize,
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const run_unit_tests = b.addRunArtifact(unit_tests);
|
const run_unit_tests = b.addRunArtifact(unit_tests);
|
||||||
|
|
|
||||||
308
docs/PROYECTO_COMPLETO.md
Normal file
308
docs/PROYECTO_COMPLETO.md
Normal file
|
|
@ -0,0 +1,308 @@
|
||||||
|
# Service Monitor - Documentación Completa
|
||||||
|
|
||||||
|
> **Fecha**: 2025-12-08
|
||||||
|
> **Versión**: 1.1
|
||||||
|
> **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 AUTH LOGIN (sin TLS) |
|
||||||
|
| 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
|
||||||
|
- Protocolo SMTP completo (RFC 5321)
|
||||||
|
- Comandos: EHLO, AUTH LOGIN, MAIL FROM, RCPT TO, DATA, QUIT
|
||||||
|
- Autenticación Base64
|
||||||
|
- Múltiples destinatarios
|
||||||
|
- **Limitación**: No soporta STARTTLS (usar puerto 25 o servidores sin TLS)
|
||||||
|
|
||||||
|
### 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 |
|
||||||
|
|
||||||
|
## Pendiente
|
||||||
|
|
||||||
|
- [ ] SMTP con STARTTLS (para Gmail/Outlook)
|
||||||
|
- [x] ~~Migración a Zig 0.15~~ (completado 2025-12-08)
|
||||||
|
- [ ] Notificación de recuperación (servicio vuelve a funcionar)
|
||||||
|
- [ ] Rate limiting de notificaciones (evitar spam)
|
||||||
|
- [ ] Métricas/estadísticas de uptime
|
||||||
|
|
||||||
|
## 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()` |
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- Zig 0.15 stdlib: https://ziglang.org/documentation/0.15.0/std/
|
||||||
|
- SMTP RFC 5321: https://tools.ietf.org/html/rfc5321
|
||||||
|
- Telegram Bot API: https://core.telegram.org/bots/api
|
||||||
|
- Guía Zig 0.15: /mnt/cello2/arno/re/recode/TEAM_STANDARDS/INFRASTRUCTURE/ZIG_0.15_GUIA.md
|
||||||
|
|
@ -113,12 +113,12 @@ pub fn loadFromFile(allocator: std.mem.Allocator, path: []const u8) !Config {
|
||||||
|
|
||||||
/// Parsea el contenido de un archivo de configuración.
|
/// Parsea el contenido de un archivo de configuración.
|
||||||
fn parseConfigFile(allocator: std.mem.Allocator, file: std.fs.File) !Config {
|
fn parseConfigFile(allocator: std.mem.Allocator, file: std.fs.File) !Config {
|
||||||
var services = std.ArrayList(Service).init(allocator);
|
var services = std.array_list.Managed(Service).init(allocator);
|
||||||
var emails = std.ArrayList([]const u8).init(allocator);
|
var emails = std.array_list.Managed([]const u8).init(allocator);
|
||||||
var smtp = SmtpConfig{};
|
var smtp = SmtpConfig{};
|
||||||
var telegram = TelegramConfig{};
|
var telegram = TelegramConfig{};
|
||||||
|
|
||||||
const reader = file.reader();
|
const reader = file.deprecatedReader();
|
||||||
var buf: [1024]u8 = undefined;
|
var buf: [1024]u8 = undefined;
|
||||||
|
|
||||||
while (reader.readUntilDelimiterOrEof(&buf, '\n')) |maybe_line| {
|
while (reader.readUntilDelimiterOrEof(&buf, '\n')) |maybe_line| {
|
||||||
|
|
|
||||||
22
src/http.zig
22
src/http.zig
|
|
@ -44,27 +44,17 @@ pub const HttpCheckError = error{
|
||||||
pub fn check(allocator: std.mem.Allocator, url: []const u8) HttpCheckError!u64 {
|
pub fn check(allocator: std.mem.Allocator, url: []const u8) HttpCheckError!u64 {
|
||||||
var timer = std.time.Timer.start() catch return HttpCheckError.NetworkError;
|
var timer = std.time.Timer.start() catch return HttpCheckError.NetworkError;
|
||||||
|
|
||||||
// Parsear la URL
|
// Crear cliente HTTP (Zig 0.15 API)
|
||||||
const uri = std.Uri.parse(url) catch return HttpCheckError.InvalidResponse;
|
var client: std.http.Client = .{ .allocator = allocator };
|
||||||
|
|
||||||
// Crear cliente HTTP
|
|
||||||
var client = std.http.Client{ .allocator = allocator };
|
|
||||||
defer client.deinit();
|
defer client.deinit();
|
||||||
|
|
||||||
// Buffer para headers de respuesta (requerido en Zig 0.13)
|
// Realizar la petición usando fetch() - API Zig 0.15
|
||||||
var header_buffer: [8192]u8 = undefined;
|
const result = client.fetch(.{
|
||||||
|
.location = .{ .url = url },
|
||||||
// Realizar la petición - API Zig 0.13
|
|
||||||
var request = client.open(.GET, uri, .{
|
|
||||||
.server_header_buffer = &header_buffer,
|
|
||||||
}) catch return HttpCheckError.ConnectionFailed;
|
}) catch return HttpCheckError.ConnectionFailed;
|
||||||
defer request.deinit();
|
|
||||||
|
|
||||||
request.send() catch return HttpCheckError.NetworkError;
|
|
||||||
request.wait() catch return HttpCheckError.Timeout;
|
|
||||||
|
|
||||||
// Verificar status
|
// Verificar status
|
||||||
if (request.response.status != .ok) {
|
if (result.status != .ok) {
|
||||||
return HttpCheckError.UnexpectedStatus;
|
return HttpCheckError.UnexpectedStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ pub fn main() !void {
|
||||||
defer _ = gpa.deinit();
|
defer _ = gpa.deinit();
|
||||||
const allocator = gpa.allocator();
|
const allocator = gpa.allocator();
|
||||||
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
const stdout = std.fs.File.stdout().deprecatedWriter();
|
||||||
|
|
||||||
// Parsear argumentos
|
// Parsear argumentos
|
||||||
const options = parseArgs() catch |err| {
|
const options = parseArgs() catch |err| {
|
||||||
|
|
@ -131,7 +131,7 @@ pub fn main() !void {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
_ = try runChecks(allocator, output_writer, log_file, options.notify, &cfg);
|
_ = try runChecks(allocator, output_writer, log_file, options.notify, &cfg);
|
||||||
std.time.sleep(@as(u64, options.interval_seconds) * std.time.ns_per_s);
|
std.Thread.sleep(@as(u64, options.interval_seconds) * std.time.ns_per_s);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try stdout.print("\n=== Service Monitor ===\n\n", .{});
|
try stdout.print("\n=== Service Monitor ===\n\n", .{});
|
||||||
|
|
@ -146,7 +146,7 @@ pub fn main() !void {
|
||||||
/// Ejecuta verificación de todos los servicios.
|
/// Ejecuta verificación de todos los servicios.
|
||||||
fn runChecks(
|
fn runChecks(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
stdout: ?std.fs.File.Writer,
|
stdout: ?std.fs.File.DeprecatedWriter,
|
||||||
log_file: ?std.fs.File,
|
log_file: ?std.fs.File,
|
||||||
notify_enabled: bool,
|
notify_enabled: bool,
|
||||||
cfg: *const config.Config,
|
cfg: *const config.Config,
|
||||||
|
|
@ -181,7 +181,7 @@ fn runChecks(
|
||||||
try out.print(timestamp_str ++ "\n", timestamp_args);
|
try out.print(timestamp_str ++ "\n", timestamp_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
const log_writer = if (log_file) |f| f.writer() else null;
|
const log_writer = if (log_file) |f| f.deprecatedWriter() else null;
|
||||||
if (log_writer) |lw| {
|
if (log_writer) |lw| {
|
||||||
try lw.print(timestamp_str ++ "\n", timestamp_args);
|
try lw.print(timestamp_str ++ "\n", timestamp_args);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue