Tutoriales
Parseando Timestamps de Logs: Guía Práctica con Ejemplos
Introducción
Los archivos de log contienen timestamps en muchos formatos diferentes. Saber cómo parsearlos correctamente es esencial para análisis de logs, monitoreo y debugging.
Lo que Aprenderás
- ✅ Formatos comunes de timestamps en logs
- ✅ Expresiones regulares para cada formato
- ✅ Código de parsing en Python y JavaScript
- ✅ Normalización a formato estándar
- ✅ Manejo de zonas horarias
Formatos Comunes de Log
1. Apache/Nginx (CLF - Common Log Format)
[01/Dec/2024:10:15:30 +0000]
Regex:
regex
\[(\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4})\]
Python:
from datetime import datetime
def parse_apache(timestamp_str):
# Ejemplo: "01/Dec/2024:10:15:30 +0000"
return datetime.strptime(
timestamp_str,
"%d/%b/%Y:%H:%M:%S %z"
)
log_line = '[01/Dec/2024:10:15:30 +0000] "GET / HTTP/1.1" 200'
match = re.search(r'\[([^\]]+)\]', log_line)
if match:
dt = parse_apache(match.group(1))
print(dt.isoformat())
2. ISO 8601 / RFC 3339
2024-12-01T10:15:30Z
2024-12-01T10:15:30+01:00
Regex:
regex
\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})
JavaScript:
function parseIso8601(timestampStr) {
return new Date(timestampStr);
}
// Ejemplo
const dt = parseIso8601("2024-12-01T10:15:30Z");
console.log(dt.toISOString());
3. Syslog (RFC 3164)
Dec 1 10:15:30 hostname app[123]: mensaje
Nota: Este formato NO incluye año ni zona horaria.
Python:
from datetime import datetime
def parse_syslog(timestamp_str, year=None):
# Ejemplo: "Dec 1 10:15:30"
if year is None:
year = datetime.now().year
dt = datetime.strptime(timestamp_str, "%b %d %H:%M:%S")
return dt.replace(year=year)
# Extraer del log
import re
log_line = "Dec 1 10:15:30 servidor app[123]: error"
match = re.match(r'^(\w{3}\s+\d{1,2}\s\d{2}:\d{2}:\d{2})', log_line)
if match:
dt = parse_syslog(match.group(1), year=2024)
4. Unix Timestamp
1701425730
1701425730000
JavaScript:
function parseUnixTimestamp(raw) {
const str = String(raw);
if (str.length === 10) {
return new Date(Number(raw) * 1000);
} else if (str.length === 13) {
return new Date(Number(raw));
}
throw new Error('Formato desconocido');
}
Parser Universal
Python
from datetime import datetime, timezone
from dateutil import parser as dateutil_parser
import re
def parse_log_timestamp(raw: str) -> datetime:
"""Parser universal para timestamps de logs"""
s = raw.strip()
# 1. Intentar ISO 8601 / RFC 3339
try:
dt = dateutil_parser.isoparse(s)
if dt.tzinfo is None:
dt = dt.replace(tzinfo=timezone.utc)
return dt
except:
pass
# 2. Apache/Nginx: [01/Dec/2024:10:15:30 +0000]
if s.startswith('[') and s.endswith(']'):
inner = s[1:-1]
dt = datetime.strptime(inner, "%d/%b/%Y:%H:%M:%S %z")
return dt
# 3. Unix timestamp numérico
if s.isdigit():
n = len(s)
if n == 10:
return datetime.fromtimestamp(int(s), tz=timezone.utc)
if n == 13:
return datetime.fromtimestamp(int(s)/1000, tz=timezone.utc)
raise ValueError(f"Formato no reconocido: {raw}")
JavaScript
import { DateTime } from 'luxon';
function parseLogTimestamp(raw) {
const s = raw.trim();
// 1. ISO 8601
const iso = DateTime.fromISO(s, { setZone: true });
if (iso.isValid) return iso.toUTC();
// 2. Apache/Nginx
const apacheMatch = s.match(
/\[(\d{2}\/\w{3}\/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4})\]/
);
if (apacheMatch) {
const dt = DateTime.fromFormat(
apacheMatch[1],
"dd/MMM/yyyy:HH:mm:ss ZZZ"
);
if (dt.isValid) return dt.toUTC();
}
// 3. Unix timestamp
if (/^\d+$/.test(s)) {
const len = s.length;
if (len === 10) return DateTime.fromSeconds(Number(s));
if (len === 13) return DateTime.fromMillis(Number(s));
}
throw new Error(`Formato no reconocido: ${raw}`);
}
Normalización
Siempre normaliza a un formato estándar después de parsear:
def normalizar_timestamp(dt: datetime) -> dict:
"""Normaliza datetime a formatos útiles"""
utc = dt.astimezone(timezone.utc)
return {
'iso': utc.isoformat(),
'unix_s': int(utc.timestamp()),
'unix_ms': int(utc.timestamp() * 1000),
'utc': utc
}
Mejores Prácticas
- Parsea a UTC primero - Evita problemas de zona horaria
- Valida el rango - Rechaza fechas implausibles
- Maneja años faltantes - Syslog no incluye año
- Usa bibliotecas probadas - No reinventes el wheel
- Registra errores de parsing - Para depuración
Resumen
Has aprendido a parsear timestamps de:
- Apache/Nginx (CLF)
- ISO 8601 / RFC 3339
- Syslog
- Unix timestamps
¡Usa nuestro Convertidor por Lotes para procesar múltiples timestamps!