|
|
""" |
|
|
Sistema de logging para o AgentPDF. |
|
|
|
|
|
Fornece logging estruturado e colorido para melhor debugging |
|
|
e monitoramento do sistema. |
|
|
""" |
|
|
|
|
|
import logging |
|
|
import sys |
|
|
from datetime import datetime |
|
|
from typing import Optional |
|
|
|
|
|
|
|
|
class ColoredFormatter(logging.Formatter): |
|
|
"""Formatter personalizado com cores para diferentes níveis de log.""" |
|
|
|
|
|
|
|
|
COLORS = { |
|
|
'DEBUG': '\033[36m', |
|
|
'INFO': '\033[32m', |
|
|
'WARNING': '\033[33m', |
|
|
'ERROR': '\033[31m', |
|
|
'CRITICAL': '\033[35m', |
|
|
'RESET': '\033[0m' |
|
|
} |
|
|
|
|
|
def format(self, record): |
|
|
|
|
|
color = self.COLORS.get(record.levelname, self.COLORS['RESET']) |
|
|
reset = self.COLORS['RESET'] |
|
|
|
|
|
|
|
|
record.levelname = f"{color}{record.levelname}{reset}" |
|
|
|
|
|
return super().format(record) |
|
|
|
|
|
|
|
|
def setup_logger(name: str = "AgentPDF", level: str = "INFO") -> logging.Logger: |
|
|
""" |
|
|
Configura e retorna um logger personalizado. |
|
|
|
|
|
Args: |
|
|
name: Nome do logger |
|
|
level: Nível de logging (DEBUG, INFO, WARNING, ERROR, CRITICAL) |
|
|
|
|
|
Returns: |
|
|
logging.Logger: Logger configurado |
|
|
""" |
|
|
logger = logging.getLogger(name) |
|
|
|
|
|
|
|
|
if logger.handlers: |
|
|
return logger |
|
|
|
|
|
|
|
|
numeric_level = getattr(logging, level.upper(), logging.INFO) |
|
|
logger.setLevel(numeric_level) |
|
|
|
|
|
|
|
|
console_handler = logging.StreamHandler(sys.stdout) |
|
|
console_handler.setLevel(numeric_level) |
|
|
|
|
|
|
|
|
formatter = ColoredFormatter( |
|
|
'%(asctime)s | %(levelname)s | %(name)s | %(message)s', |
|
|
datefmt='%H:%M:%S' |
|
|
) |
|
|
console_handler.setFormatter(formatter) |
|
|
|
|
|
logger.addHandler(console_handler) |
|
|
|
|
|
return logger |
|
|
|
|
|
|
|
|
def log_node_execution(node_name: str, status: str, details: Optional[str] = None): |
|
|
""" |
|
|
Log específico para execução de nós do LangGraph. |
|
|
|
|
|
Args: |
|
|
node_name: Nome do nó |
|
|
status: Status da execução (START, SUCCESS, ERROR) |
|
|
details: Detalhes adicionais |
|
|
""" |
|
|
logger = logging.getLogger("AgentPDF.Nodes") |
|
|
|
|
|
emoji_map = { |
|
|
"START": "🚀", |
|
|
"SUCCESS": "✅", |
|
|
"ERROR": "❌", |
|
|
"PROCESSING": "⚙️" |
|
|
} |
|
|
|
|
|
emoji = emoji_map.get(status, "📝") |
|
|
message = f"{emoji} {node_name} - {status}" |
|
|
|
|
|
if details: |
|
|
message += f" | {details}" |
|
|
|
|
|
if status == "ERROR": |
|
|
logger.error(message) |
|
|
elif status == "START" or status == "PROCESSING": |
|
|
logger.info(message) |
|
|
else: |
|
|
logger.info(message) |
|
|
|
|
|
|
|
|
def log_graph_execution(action: str, details: Optional[str] = None): |
|
|
""" |
|
|
Log específico para execução do grafo principal. |
|
|
|
|
|
Args: |
|
|
action: Ação sendo executada |
|
|
details: Detalhes adicionais |
|
|
""" |
|
|
logger = logging.getLogger("AgentPDF.Graph") |
|
|
|
|
|
message = f"🔄 {action}" |
|
|
if details: |
|
|
message += f" | {details}" |
|
|
|
|
|
logger.info(message) |
|
|
|
|
|
|
|
|
|
|
|
main_logger = setup_logger("AgentPDF", "INFO") |
|
|
|