Formatos y fuentes de datos 4 min de lectura

Parseo de logs: analizar registros de servidores y aplicaciones con ejemplos

Parseo de logs de servidores y aplicaciones: formatos de los registros de acceso y de errores, expresiones regulares, herramientas listas y ejemplos de análisis.

EW
Equipo Web-Scraping.es
Recopilación de datos para las necesidades del negocio
Publicado: 22 marzo 2025

Los logs son los registros de eventos de servidores, aplicaciones y servicios: cada petición a un sitio, cada error y cada acción del usuario dejan en ellos una línea. El parseo de logs sirve para analizar el tráfico, localizar errores, investigar incidentes de seguridad y monitorizar sistemas. Formalmente, los logs son archivos de texto, y las técnicas generales para analizarlos son las mismas; pero tienen la suficiente especificidad propia como para dedicarles un artículo aparte dentro de nuestro panorama del parseo de documentos.

En qué se diferencian los logs del texto corriente

La particularidad principal es que, dentro de una misma fuente, el formato de la línea es estrictamente estable. El servidor web escribe cada línea con la misma plantilla, lo que permite analizar millones de líneas con una única expresión regular. Pero también hay complicaciones. Los logs pueden ser enormes (gigabytes al día), así que no se pueden leer enteros en memoria, solo en flujo. Rotan: los archivos antiguos se renombran y se comprimen en .gz, y el parser debe saber leer los archivos comprimidos. Y contienen entradas multilínea: por ejemplo, la traza de una excepción (stack trace) ocupa decenas de líneas que pertenecen a un mismo evento.

Formatos estándar de los logs web

Lo más habitual es analizar los access logs de Nginx y Apache en formato «combined». Una línea tiene este aspecto:

code
192.168.1.10 - - [01/Jun/2026:13:55:36 +0200] "GET /product/101 HTTP/1.1" 200 4523 "https://example.com/" "Mozilla/5.0 ..."

Por orden: dirección IP, fecha y hora, método y ruta de la petición, código de respuesta, tamaño de la respuesta, referer y User-Agent. Como el formato es fijo, resulta cómodo procesarlo con una única expresión regular con grupos con nombre.

Python

El enfoque básico y más flexible: una expresión regular más lectura en flujo. Los grupos con nombre hacen legible el resultado.

python
import re
import gzip

LOG_RE = re.compile(
    r'(?P<ip>\S+) \S+ \S+ \[(?P<time>[^\]]+)\] '
    r'"(?P<method>\S+) (?P<path>\S+) [^"]*" '
    r'(?P<status>\d{3}) (?P<size>\S+) '
    r'"(?P<referer>[^"]*)" "(?P<agent>[^"]*)"'
)

def open_log(path):
    # lee de forma transparente tanto archivos normales como comprimidos
    return gzip.open(path, "rt") if path.endswith(".gz") else open(path, "r")

with open_log("access.log") as f:
    for line in f:
        m = LOG_RE.match(line)
        if not m:
            continue
        row = m.groupdict()
        if row["status"] != "200":
            print(row["status"], row["method"], row["path"], row["ip"])

Cuando no basta con parsear y hay que analizar (contar el top de páginas, la distribución de códigos de respuesta, el tráfico por horas), lo cómodo es volcar las líneas ya parseadas en pandas y trabajar con ellas como con una tabla.

python
import pandas as pd

records = [m.groupdict() for line in open_log("access.log")
           if (m := LOG_RE.match(line))]
df = pd.DataFrame(records)

# top 10 de páginas más solicitadas
print(df["path"].value_counts().head(10))

# proporción de errores 5xx
errors = df[df["status"].str.startswith("5")]
print(len(errors) / len(df))

Desde aquí, el resultado se exporta fácilmente a CSV o Excel para un informe.

Línea de comandos: análisis rápido sin código

Para una tarea puntual, lo más rápido suele ser recurrir a las utilidades de Unix. awk divide la línea en campos y calcula al vuelo.

bash
# top 10 de IP por número de peticiones
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head

# todas las peticiones que acabaron en error 404
awk '$9 == 404 {print $7}' access.log | sort | uniq -c | sort -rn

# volumen total de tráfico servido (el campo 10 es el tamaño)
awk '{sum += $10} END {print sum/1024/1024 " MB"}' access.log

La combinación grep + awk + sort + uniq resuelve la mayoría de las preguntas ad hoc sobre los logs sin escribir nada.

Analizadores listos para usar

Si la tarea es la analítica general del tráfico web, y no extraer campos concretos, no hace falta inventar un parser. GoAccess lee los access logs de Nginx/Apache y construye un informe interactivo en el terminal o en el navegador en tiempo real. Para pipelines complejos con fuentes heterogéneas se emplea el stack basado en Logstash, con sus conjuntos de plantillas grok: en esencia, una biblioteca de expresiones regulares con nombre ya preparadas para los formatos de log más populares.

Logs estructurados (logs en JSON)

Las aplicaciones modernas escriben cada vez más sus logs no como líneas de texto libre, sino en JSON: un objeto por línea (formato JSON Lines). Un log así se analiza de forma mucho más simple y fiable: no hacen falta expresiones regulares frágiles, cada línea simplemente se deserializa.

python
import json

with open("app.log") as f:
    for line in f:
        event = json.loads(line)
        if event.get("level") == "ERROR":
            print(event["timestamp"], event["message"])

Si puede influir en cómo se escriben los logs, pasar a JSON Lines simplifica radicalmente su análisis posterior: merece la pena preverlo en el proyecto desde el principio.

Dónde aparecen las complicaciones

Los problemas más frecuentes son el formato de la fecha y la hora (los logs de sistemas distintos usan zonas horarias y plantillas de fecha diferentes que hay que unificar), los errores multilínea (el stack trace rompe el análisis línea a línea y las entradas deben «pegarse» detectando el inicio de cada registro nuevo) y el volumen (analizar un log diario de gigabytes exige procesamiento en flujo y filtrado al vuelo, no cargarlo entero en memoria).

Si necesita analizar con regularidad los logs de varios servidores, consolidarlos en una analítica única o monitorizar errores y actividad sospechosa, configuramos la recogida y el parseo de logs adaptados a sus formatos, con la exportación de las métricas al sistema que le resulte cómodo. Las técnicas generales de trabajo con texto arbitrario sobre las que se apoya todo esto están en el artículo sobre el parseo de TXT.