Pourquoi cette page
Les logs arrivent avec des formats mixtes, fuseaux horaires et précisions différentes. Un horodatage incorrect casse l'ordonnancement, les tableaux de bord et les chronologies d'incidents. Ce guide vous donne des vérifications rapides, des modèles regex et des extraits de code pour normaliser rapidement les temps des logs—et vous dirige vers des convertisseurs quand vous devez vérifier des cas limites.
Liste de vérification diagnostic rapide
- Identifier format : ISO 8601/RFC 3339, Apache/Nginx (
[dd/Mon/yyyy:HH:mm:ss Z]), syslog (MMM d HH:mm:ss), ou personnalisé. - Vérifier fuseau horaire : décalage explicite (
+0100,Z) vs. local implicite. Utiliser UTC par défaut si absent. - Vérifier précision : secondes vs. millisecondes vs. microsecondes ; assurer une longueur cohérente.
- Gérer bords DST : parser en UTC d'abord ; éviter le parsing local naïf.
- Appliquer gardes de plage : rejeter les années implausibles (ex.,
<2000ou>2100).
Formats de log courants (modèles)
- ISO 8601 / RFC 3339 :
2024-12-01T10:15:30Z,2024-12-01T18:15:30+01:00 - Apache/Nginx :
[01/Dec/2024:10:15:30 +0000] - Syslog :
Dec 1 10:15:30 hostname app[123]: message(sans année/décalage) - Numérique personnalisé :
1701425730(secondes),1701425730000(ms)
Étapes de normalisation
- Détecter format et fuseau horaire. Si absent, supposer UTC.
- Parser en datetime aware (UTC).
- Si epoch numérique : mettre à l'échelle par longueur (10s/13ms/16µs/19ns).
- Stocker dans une colonne canonique (ex., millis UTC) et optionnellement garder la chaîne brute.
- Valider la plage ; rejeter ou marquer les valeurs aberrantes avant l'indexation.
Extraits de code
JavaScript / Node.js
JAVASCRIPT1import { DateTime } from "luxon"; 2 3export function parseLogTime(raw) { 4 const trimmed = raw.trim(); 5 // ISO/RFC d'abord 6 const iso = DateTime.fromISO(trimmed, { setZone: true }); 7 if (iso.isValid) return iso.toUTC().toMillis(); 8 9 // Apache/Nginx: [01/Dec/2024:10:15:30 +0000] 10 const m = trimmed.match(/\[(\d{2}\/\w{3}\/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4})\]/); 11 if (m) { 12 const dt = DateTime.fromFormat(m[1], "dd/MMM/yyyy:HH:mm:ss ZZZZ", { zone: "utc" }); 13 if (dt.isValid) return dt.toMillis(); 14 } 15 16 // Epoch numérique (secondes/ms/us/ns) 17 if (/^\d+$/.test(trimmed)) { 18 const len = trimmed.length; 19 if (len === 10) return Number(trimmed) * 1000; 20 if (len === 13) return Number(trimmed); 21 if (len === 16) return Number(trimmed) / 1000; 22 if (len === 19) return Number(trimmed) / 1_000_000; 23 } 24 25 throw new Error("Horodatage de log non reconnu"); 26}
Python
PYTHON1from datetime import datetime, timezone, timedelta 2from dateutil import parser 3 4def parse_log_time(raw: str) -> int: 5 s = raw.strip() 6 # ISO/RFC 3339, syslog avec tz, etc. 7 try: 8 dt = parser.isoparse(s) 9 if dt.tzinfo is None: 10 dt = dt.replace(tzinfo=timezone.utc) 11 return int(dt.astimezone(timezone.utc).timestamp() * 1000) 12 except Exception: 13 pass 14 15 # Apache/Nginx: [01/Dec/2024:10:15:30 +0000] 16 if s.startswith("[") and s.endswith("]"): 17 inner = s[1:-1] 18 dt = datetime.strptime(inner, "%d/%b/%Y:%H:%M:%S %z") 19 return int(dt.astimezone(timezone.utc).timestamp() * 1000) 20 21 # Epoch numérique 22 if s.isdigit(): 23 n = len(s) 24 if n == 10: 25 return int(s) * 1000 26 if n == 13: 27 return int(s) 28 if n == 16: 29 return int(int(s) / 1000) 30 if n == 19: 31 return int(int(s) / 1_000_000) 32 raise ValueError("Horodatage de log non reconnu")
Modèles Regex
REGEX1# ISO 8601 / RFC 3339 avec décalage 2^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})$ 3 4# Apache/Nginx 5^\[\d{2}/[A-Za-z]{3}/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4}\]$ 6 7# Syslog (sans année/décalage, ajouter externellement) 8^[A-Za-z]{3}\s+\d{1,2}\s\d{2}:\d{2}:\d{2}\s.+$
FAQ
- Que faire si le fuseau horaire est absent ? Supposer UTC et documenter l'hypothèse.
- Comment gérer les logs de multiples sources ? Normaliser tout en UTC millis avant agrégation.
- Qu'en est-il des logs syslog sans année ? Utiliser l'année courante ou inférer du contexte du fichier.