diff --git a/Logger/LokiLogger.py b/Logger/LokiLogger.py index 1f76848..de4ce96 100644 --- a/Logger/LokiLogger.py +++ b/Logger/LokiLogger.py @@ -36,7 +36,7 @@ class LokiLogger: :param default_labels: etiquetas estáticas comunes (ej: {"env": "dev"}) :param timeout: timeout en segundos para la petición HTTP :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.timeout = timeout @@ -47,9 +47,9 @@ class LokiLogger: raise ValueError(f"min_level debe estar en {self.ALLOWED_LEVELS}") 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["service"] = self.service_name + self.default_labels["service_name"] = self.service_name self._level_order = { "TRACE": 0, @@ -75,9 +75,9 @@ class LokiLogger: level: str, message: str, labels: Optional[Dict[str, str]] = None, - metadata: Optional[Dict[str, Any]] = None, + metadata: Optional[Dict[str, Any]] = None, # mantenemos metadata por compatibilidad ) -> 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() if level == "WARNING": level = "WARN" @@ -88,22 +88,23 @@ class LokiLogger: if not self._should_log(level): return - # Combinar etiquetas - final_labels = dict(self.default_labels) + # 🔸 Construimos labels: base + detected_level + custom + 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: final_labels.update(labels) - payload_metadata = { - "service": self.service_name, - "level": level, - } - if metadata: - payload_metadata.update(metadata) - + # 🧾 El log line solo lleva timestamp y message log_line = json.dumps({ "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "message": message, - **payload_metadata, }) body = { @@ -138,15 +139,10 @@ class LokiLogger: self.log("ERROR", message, labels, metadata) def exception(self, exc: Exception, labels=None, metadata=None): - """ - Registra una excepción con traceback incluido. - Uso típico dentro de un bloque try/except. - """ + """Registra una excepción con traceback incluido.""" tb = traceback.format_exc() message = str(exc) - metadata = metadata or {} - metadata["traceback"] = tb - self.log("ERROR", message, labels=labels, metadata=metadata) + self.log("ERROR", f"{message}\n{tb}", labels=labels) def fatal(self, message, labels=None, metadata=None): self.log("FATAL", message, labels, metadata) @@ -157,17 +153,9 @@ class LokiLogger: def unknown(self, message, labels=None, metadata=None): self.log("UNKNOWN", message, labels, metadata) - # 🧩 Nuevo decorador + # 🧩 Decorador para capturar excepciones def catch_exceptions(self, reraise: bool = False): - """ - 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(): - ... - """ + """Decorador que captura excepciones y las loguea.""" def decorator(func: Callable): @wraps(func) def wrapper(*args, **kwargs): @@ -176,8 +164,7 @@ class LokiLogger: except Exception as e: tb = traceback.format_exc() self.error( - f"Exception en función '{func.__name__}': {e}", - metadata={"traceback": tb}, + f"Exception en función '{func.__name__}': {e}\n{tb}" ) if reraise: raise