📝 Guia de Logging¶
Este guia explica como configurar e utilizar o sistema de logging da biblioteca CreateAgentsAI, que agora segue Clean Architecture com interfaces de logging no domínio e implementações na infraestrutura.
🏗️ Arquitetura de Logging¶
LoggerInterface (Domínio)¶
A biblioteca define uma LoggerInterface abstrata no domínio (src/createagents/domain/interfaces/), permitindo que as camadas de domínio e aplicação usem logging sem depender de implementações concretas de infraestrutura.
from abc import ABC, abstractmethod
class LoggerInterface(ABC):
"""Interface abstrata para logging."""
@abstractmethod
def debug(self, message: str, *args, **kwargs) -> None:
pass
@abstractmethod
def info(self, message: str, *args, **kwargs) -> None:
pass
@abstractmethod
def warning(self, message: str, *args, **kwargs) -> None:
pass
@abstractmethod
def error(self, message: str, *args, **kwargs) -> None:
pass
@abstractmethod
def critical(self, message: str, *args, **kwargs) -> None:
pass
StandardLogger (Infraestrutura)¶
A implementação concreta está na camada de infraestrutura (src/createagents/infra/config/):
class StandardLogger(LoggerInterface):
"""Implementação padrão do LoggerInterface usando Python logging."""
def __init__(self, logger: logging.Logger):
self._logger = logger
def debug(self, message: str, *args, **kwargs) -> None:
self._logger.debug(message, *args, **kwargs)
# ...outros métodos
🔇 Comportamento Padrão¶
Ao importar e usar a biblioteca, nenhum log será exibido no console ou salvo em arquivo, a menos que você configure explicitamente o sistema de logging.
Isso é feito intencionalmente para evitar conflitos com a configuração de logging da aplicação que consome a biblioteca.
🛠️ Como Ativar Logs¶
Opção 1: Configuração Rápida (Desenvolvimento)¶
Para desenvolvimento, testes ou scripts simples, use o helper configure_for_development:
import logging
from createagents import LoggingConfig
# Ativa logs no nível INFO
LoggingConfig.configure_for_development(level=logging.INFO)
# Ou para ver tudo (DEBUG)
LoggingConfig.configure_for_development(level=logging.DEBUG)
Isso configurará logs coloridos no console e filtragem automática de dados sensíveis.
Opção 2: Configuração Padrão do Python¶
Se sua aplicação já configura o logging, a biblioteca respeitará essa configuração:
import logging
# Configuração da sua aplicação
logging.basicConfig(level=logging.INFO)
# Agora os logs da biblioteca aparecerão
from createagents import CreateAgent
Opção 3: Configuração Avançada¶
Para controlar apenas os logs da biblioteca:
import logging
# Configura apenas o logger 'createagents'
logger = logging.getLogger("createagents")
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler())
🎯 Uso em Componentes Customizados¶
Se você estiver estendendo a biblioteca (ex.: criando ferramentas customizadas ou handlers), pode usar a LoggerInterface:
Exemplo: Ferramenta Customizada com Logging¶
from createagents import BaseTool
from createagents.domain.interfaces import LoggerInterface
class MyCustomTool(BaseTool):
name = "my_tool"
description = "Minha ferramenta customizada"
parameters = {...}
def __init__(self, logger: LoggerInterface):
self._logger = logger
def execute(self, **kwargs) -> str:
self._logger.info("Executando MyCustomTool com: %s", kwargs)
try:
result = self._do_something(kwargs)
self._logger.debug("Resultado: %s", result)
return result
except Exception as e:
self._logger.error("Erro em MyCustomTool: %s", str(e))
raise
Injeção de Dependência¶
from createagents.infra.config import LoggingConfig, StandardLogger
# Criar logger
python_logger = LoggingConfig.get_logger(__name__)
logger_interface = StandardLogger(python_logger)
# Injetar na ferramenta
my_tool = MyCustomTool(logger=logger_interface)
🔒 Segurança e Privacidade¶
A biblioteca inclui recursos automáticos de segurança nos logs:
- Sanitização: Chaves de API, senhas e tokens são mascarados automaticamente (ex:
[API_KEY_REDACTED]). - Filtros: Em produção, você pode configurar para logar apenas erros.
⚙️ Variáveis de Ambiente¶
Você pode controlar o logging através de variáveis de ambiente:
| Variável | Descrição | Padrão |
|---|---|---|
LOG_LEVEL |
Nível de log (DEBUG, INFO, WARNING, ERROR) | INFO |
LOG_TO_FILE |
Salvar logs em arquivo (true/false) | false |
LOG_FILE_PATH |
Caminho do arquivo de log | logs/app.log |
LOG_JSON_FORMAT |
Usar formato JSON estruturado | false |
📊 Logs em JSON (Produção)¶
Para ambientes de produção com agregação de logs (Datadog, CloudWatch, ELK), ative o formato JSON:
LoggingConfig.configure(json_format=True)
Ou via ambiente:
export LOG_JSON_FORMAT=true
Isso gerará logs estruturados fáceis de indexar:
{
"timestamp": "2024-03-20 10:00:00,000",
"level": "INFO",
"logger": "createagents.service",
"message": "Agent initialized",
"module": "service",
"line": 42
}
🔍 Componentes que Usam Logging¶
AgentService¶
O AgentService usa LoggerInterface para logar operações de agente:
class AgentService:
def __init__(self, agent: Agent, logger: LoggerInterface):
self._agent = agent
self._logger = logger
self._logger.info(
"AgentService initialized - Name: %s, Provider: %s",
agent.name,
agent.provider
)
ToolExecutor¶
O ToolExecutor no domínio usa LoggerInterface para logar execuções de ferramentas:
class ToolExecutor:
def __init__(self, logger: LoggerInterface):
self._logger = logger
async def execute(self, tool: BaseTool, arguments: dict):
self._logger.info("Executing tool: %s", tool.name)
# ...
Handlers (OpenAI/Ollama)¶
Os handlers de streaming usam logging para métricas e debugging:
class OpenAIStreamHandler:
def __init__(self, ...):
self._logger = LoggingConfig.get_logger(__name__)
async def handle_streaming(self, ...):
self._logger.debug("Starting streaming response")
# ...
💡 Best Practices¶
- Use níveis apropriados:
DEBUG: Detalhes de execução, valores de variáveisINFO: Eventos normais (agent criado, ferramenta executada)WARNING: Situações incomuns mas recuperáveisERROR: Erros que impedem operaçãoCRITICAL: Falhas graves do sistema
- Nunca logue dados sensíveis:
- A biblioteca sanitiza automaticamente, mas evite logar explicitamente senhas, tokens, etc.
- Use formatação lazy:
# BOM - formatação lazy (não executa se log desabilitado)
logger.debug("Processing %s items", len(items))
# RUIM - formatação eager
logger.debug(f"Processing {len(items)} items")
- Contextualize com extra:
logger.info( "Tool executed successfully", extra={"tool_name": tool.name, "duration_ms": duration} )
Versão: 0.1.3 | Atualização: 01/12/2025