solo campos necesarios
This commit is contained in:
+21
-34
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user