solo campos necesarios

This commit is contained in:
2025-10-31 18:45:02 +01:00
parent 210d23f949
commit 9755fda5ea
+21 -34
View File
@@ -36,7 +36,7 @@ class LokiLogger:
:param default_labels: etiquetas estáticas comunes (ej: {"env": "dev"}) :param default_labels: etiquetas estáticas comunes (ej: {"env": "dev"})
:param timeout: timeout en segundos para la petición HTTP :param timeout: timeout en segundos para la petición HTTP
:param min_level: nivel mínimo para enviar logs :param min_level: nivel mínimo para enviar logs
:param service_name: nombre del servicio (se usará también como 'job') :param service_name: nombre del servicio (usado como 'service_name' label)
""" """
self.endpoint = endpoint self.endpoint = endpoint
self.timeout = timeout self.timeout = timeout
@@ -47,9 +47,9 @@ class LokiLogger:
raise ValueError(f"min_level debe estar en {self.ALLOWED_LEVELS}") raise ValueError(f"min_level debe estar en {self.ALLOWED_LEVELS}")
self.min_level = min_level self.min_level = min_level
# Base labels: incluye el job automáticamente # 🔹 Labels base (solo service_name + default_labels)
self.default_labels = dict(default_labels or {}) self.default_labels = dict(default_labels or {})
self.default_labels["service"] = self.service_name self.default_labels["service_name"] = self.service_name
self._level_order = { self._level_order = {
"TRACE": 0, "TRACE": 0,
@@ -75,9 +75,9 @@ class LokiLogger:
level: str, level: str,
message: str, message: str,
labels: Optional[Dict[str, str]] = None, labels: Optional[Dict[str, str]] = None,
metadata: Optional[Dict[str, Any]] = None, metadata: Optional[Dict[str, Any]] = None, # mantenemos metadata por compatibilidad
) -> None: ) -> None:
"""Envía un log a Loki con los campos mínimos + metadata opcional.""" """Envía un log a Loki con los campos mínimos (timestamp + message)."""
level = level.upper() level = level.upper()
if level == "WARNING": if level == "WARNING":
level = "WARN" level = "WARN"
@@ -88,22 +88,23 @@ class LokiLogger:
if not self._should_log(level): if not self._should_log(level):
return return
# Combinar etiquetas # 🔸 Construimos labels: base + detected_level + custom
final_labels = dict(self.default_labels) final_labels = {
"service_name": self.service_name,
"detected_level": level,
}
# Agrega default_labels (si existen)
final_labels.update(self.default_labels)
# Agrega labels personalizados
if labels: if labels:
final_labels.update(labels) final_labels.update(labels)
payload_metadata = { # 🧾 El log line solo lleva timestamp y message
"service": self.service_name,
"level": level,
}
if metadata:
payload_metadata.update(metadata)
log_line = json.dumps({ log_line = json.dumps({
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"message": message, "message": message,
**payload_metadata,
}) })
body = { body = {
@@ -138,15 +139,10 @@ class LokiLogger:
self.log("ERROR", message, labels, metadata) self.log("ERROR", message, labels, metadata)
def exception(self, exc: Exception, labels=None, metadata=None): def exception(self, exc: Exception, labels=None, metadata=None):
""" """Registra una excepción con traceback incluido."""
Registra una excepción con traceback incluido.
Uso típico dentro de un bloque try/except.
"""
tb = traceback.format_exc() tb = traceback.format_exc()
message = str(exc) message = str(exc)
metadata = metadata or {} self.log("ERROR", f"{message}\n{tb}", labels=labels)
metadata["traceback"] = tb
self.log("ERROR", message, labels=labels, metadata=metadata)
def fatal(self, message, labels=None, metadata=None): def fatal(self, message, labels=None, metadata=None):
self.log("FATAL", message, labels, metadata) self.log("FATAL", message, labels, metadata)
@@ -157,17 +153,9 @@ class LokiLogger:
def unknown(self, message, labels=None, metadata=None): def unknown(self, message, labels=None, metadata=None):
self.log("UNKNOWN", message, labels, metadata) self.log("UNKNOWN", message, labels, metadata)
# 🧩 Nuevo decorador # 🧩 Decorador para capturar excepciones
def catch_exceptions(self, reraise: bool = False): def catch_exceptions(self, reraise: bool = False):
""" """Decorador que captura excepciones y las loguea."""
Decorador que captura cualquier excepción dentro de la función,
la loguea con traceback, y opcionalmente la relanza.
Ejemplo:
@logger.catch_exceptions()
def run_job():
...
"""
def decorator(func: Callable): def decorator(func: Callable):
@wraps(func) @wraps(func)
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
@@ -176,8 +164,7 @@ class LokiLogger:
except Exception as e: except Exception as e:
tb = traceback.format_exc() tb = traceback.format_exc()
self.error( self.error(
f"Exception en función '{func.__name__}': {e}", f"Exception en función '{func.__name__}': {e}\n{tb}"
metadata={"traceback": tb},
) )
if reraise: if reraise:
raise raise