SolveConPython

Python Reto #21 — Parsear logs y extraer métricas

Nivel: Intermedio+
Tema: Parsing de texto, manejo de archivos, validación robusta, agregaciones, tests con pytest
Objetivo: Leer un archivo de logs (texto), parsear líneas con formato consistente y generar métricas útiles, ignorando líneas inválidas sin romper el proceso.

Enunciado

Crea una función llamada metricas_logs(ruta_log) que:

  1. Reciba ruta_log (string) a un archivo .log o .txt.
  2. Si ruta_log es None o no es str, lance TypeError.
  3. Si el archivo no existe, lance FileNotFoundError.
  4. Lea el archivo línea por línea y procese entradas con este formato:

YYYY-MM-DD HH:MM:SS | LEVEL | mensaje

Donde:

  • LEVEL puede ser: INFO, WARNING, ERROR

Ejemplo de líneas válidas:

2026-01-10 09:00:00 | INFO | Inicio del servicio
2026-01-10 09:01:02 | WARNING | Respuesta lenta
2026-01-10 09:02:10 | ERROR | Fallo al conectar a la base de datos

5. Debe ignorar cualquier línea inválida (por ejemplo, formato incorrecto, campos faltantes, LEVEL desconocido).

6. Debe devolver un diccionario con esta estructura:

{
"total": int,
"por_level": {"INFO": int, "WARNING": int, "ERROR": int},
"primer_timestamp": "YYYY-MM-DD HH:MM:SS" | None,
"ultimo_timestamp": "YYYY-MM-DD HH:MM:SS" | None,
}

Notas:

  • total cuenta solo líneas válidas.
  • primer_timestamp y ultimo_timestamp se calculan sobre líneas válidas.
  • Si no hay líneas válidas, ambos timestamps deben ser None.

Ejemplos

Si el log contiene 2 INFO, 1 WARNING y 3 ERROR válidos:

  • total → 6
  • por_level["ERROR"] → 3

Pistas

  1. Divide cada línea por "|" y luego aplica strip() para limpiar espacios.
  2. Valida que existan exactamente 3 partes: timestamp, level, mensaje.
  3. Para validar el timestamp sin complicarte, usa datetime.strptime.
  4. Si falla el parseo, esa línea es inválida → se ignora.

Solución explicada (paso a paso)

  1. Validar tipos y existencia del archivo.
  2. Inicializar contadores: total y por nivel.
  3. Recorrer el archivo línea por línea:
    • limpiar \n y espacios
    • separar por |
    • validar estructura y level permitido
    • validar timestamp con datetime.strptime
    • si todo OK: contar y actualizar primer/último timestamp
  4. Construir el diccionario final y devolverlo.

Ejecuta:

  • pytest -q

Variantes para subir de nivel (opcional)

  1. Top N mensajes de ERROR (por frecuencia)
  2. Métricas por hora (conteos agrupados por YYYY-MM-DD HH)
  3. Exportar resumen a CSV/JSON
  4. Soportar múltiples formatos de log (configurable)
  5. Streaming (procesar logs enormes sin cargar todo)

Lo que aprendiste

  • Parsing robusto con validación real
  • Ignorar errores sin ocultar fallos críticos (archivo inexistente)
  • Agregaciones útiles para observabilidad básica
  • Tests con archivos temporales

Accede al código completo y a los tests en GitHub para ejecutar y modificar la solución localmente.

Si quieres seguir en esta línea “muy real”, el próximo reto recomendado es:
Reto #22 — Resumir un CSV por grupo (group-by sin pandas) (agrupación + métricas + archivos).