torxyton commited on
Commit
b94122a
·
1 Parent(s): 3b98946

feat: Implementar sistema de logging avançado com SQLite3

Browse files

- Adicionar DatabaseLogger com armazenamento persistente em SQLite3
- Criar interface web para visualização de logs com filtros e estatísticas
- Implementar decoradores automáticos (@log_execution, @log_api_call, @log_ai_model_usage)
- Adicionar gerenciador de contexto LoggingContext
- Criar sistema de métricas de performance em tempo real
- Implementar rastreamento de eventos do sistema
- Adicionar limpeza automática de logs antigos
- Criar 8 categorias de logs organizadas (SYSTEM, API, AI_MODEL, etc.)
- Adicionar testes completos para todo o sistema
- Atualizar documentação e README com novas funcionalidades

CHANGELOG.md CHANGED
@@ -5,13 +5,35 @@ Todas as mudanças notáveis neste projeto serão documentadas neste arquivo.
5
  O formato é baseado em [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
  e este projeto adere ao [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  ## [2.0.0] - 2024-01-27
9
 
10
  ### 🎉 Adicionado
11
  - **Sistema Ensemble de IA**: Implementação de múltiplos modelos (FinBERT, RoBERTa, Custom)
12
  - **Votação Inteligente**: Sistema de consenso entre modelos para maior precisão
13
  - **Análise de Mercado Avançada**: Detecção de swing points, zonas de confluência e padrões harmônicos
14
- - **Sistema de Logging Completo**: Rastreamento detalhado de requisições e respostas
15
  - **Estrutura Refatorada**: Organização modular em `src/` com separação clara de responsabilidades
16
  - **Documentação Completa**: Guias de instalação, API, desenvolvimento e troubleshooting
17
  - **Testes Automatizados**: Suite de testes para garantir qualidade do código
 
5
  O formato é baseado em [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
  e este projeto adere ao [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
 
8
+ ## [2.1.0] - 2024-01-28
9
+
10
+ ### 🎉 Adicionado
11
+ - **Sistema de Logging Avançado com SQLite3**: Armazenamento persistente de logs estruturados
12
+ - **Interface Web de Logs**: Visualizador interativo com filtros, estatísticas e gráficos
13
+ - **Decoradores de Logging**: Logging automático com `@log_execution`, `@log_api_call`, `@log_ai_model_usage`
14
+ - **Gerenciador de Contexto**: `LoggingContext` para logging de blocos de código
15
+ - **Métricas de Performance**: Monitoramento em tempo real com armazenamento em banco
16
+ - **Eventos do Sistema**: Rastreamento de eventos críticos e alertas
17
+ - **Limpeza Automática**: Gerenciamento automático de logs antigos
18
+ - **Categorização Inteligente**: 8 categorias de logs (SYSTEM, API, AI_MODEL, etc.)
19
+ - **Testes Completos**: Suite de testes para todo o sistema de logging
20
+
21
+ ### 🔄 Alterado
22
+ - **Documentação**: Atualizada com sistema de logging avançado
23
+ - **README.md**: Incluídas novas funcionalidades e exemplos de uso
24
+ - **Arquitetura**: Integração completa do logging com todos os módulos
25
+
26
+ ### 🐛 Corrigido
27
+ - **Compatibilidade de Parâmetros**: Correções nos métodos de logging
28
+ - **Tratamento de Erros**: Melhor handling de exceções no sistema de logging
29
+
30
  ## [2.0.0] - 2024-01-27
31
 
32
  ### 🎉 Adicionado
33
  - **Sistema Ensemble de IA**: Implementação de múltiplos modelos (FinBERT, RoBERTa, Custom)
34
  - **Votação Inteligente**: Sistema de consenso entre modelos para maior precisão
35
  - **Análise de Mercado Avançada**: Detecção de swing points, zonas de confluência e padrões harmônicos
36
+ - **Sistema de Logging Básico**: Rastreamento detalhado de requisições e respostas
37
  - **Estrutura Refatorada**: Organização modular em `src/` com separação clara de responsabilidades
38
  - **Documentação Completa**: Guias de instalação, API, desenvolvimento e troubleshooting
39
  - **Testes Automatizados**: Suite de testes para garantir qualidade do código
README.md CHANGED
@@ -34,9 +34,13 @@ Um sistema completo de análise financeira que combina múltiplos modelos de IA
34
  - **Contexto Financeiro**: Especializado em terminologia do mercado financeiro
35
 
36
  ### 📝 Sistema de Logging Avançado
37
- - **Rastreamento Completo**: Log detalhado de todas as requisições e respostas
38
- - **Monitoramento de Performance**: Métricas em tempo real dos modelos
39
- - **Debugging**: Logs estruturados para facilitar manutenção
 
 
 
 
40
 
41
  ## 🏗️ Arquitetura do Sistema
42
 
@@ -62,7 +66,9 @@ Um sistema completo de análise financeira que combina múltiplos modelos de IA
62
  - **Transformers**: Modelos de linguagem (FinBERT, RoBERTa)
63
  - **NumPy/Pandas**: Processamento de dados
64
  - **Scikit-learn**: Machine learning
65
- - **Logging**: Sistema de logs estruturado
 
 
66
 
67
  ## 📋 Pré-requisitos
68
 
@@ -98,6 +104,7 @@ Documentação completa disponível em:
98
  - [Referência da API](docs/api-reference.md)
99
  - [Guia do Desenvolvedor](docs/developer-guide.md)
100
  - [Arquitetura do Sistema](docs/architecture.md)
 
101
  - [Solução de Problemas](docs/troubleshooting.md)
102
 
103
  ## 🔧 Configuração
@@ -139,6 +146,30 @@ result = processor.process_market_data(prices, volumes)
139
  print(f"Estrutura do mercado: {result['market_structure']}")
140
  ```
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  ## 🤝 Contribuição
143
 
144
  1. Fork o projeto
 
34
  - **Contexto Financeiro**: Especializado em terminologia do mercado financeiro
35
 
36
  ### 📝 Sistema de Logging Avançado
37
+ - **Armazenamento SQLite3**: Banco de dados estruturado para logs persistentes
38
+ - **Interface Web**: Visualizador de logs com filtros avançados e estatísticas
39
+ - **Decoradores Automáticos**: Logging automático com decoradores Python
40
+ - **Métricas de Performance**: Monitoramento em tempo real com gráficos
41
+ - **Categorização Inteligente**: Logs organizados por categoria e nível
42
+ - **Limpeza Automática**: Gerenciamento automático de logs antigos
43
+ - **Eventos do Sistema**: Rastreamento de eventos críticos e alertas
44
 
45
  ## 🏗️ Arquitetura do Sistema
46
 
 
66
  - **Transformers**: Modelos de linguagem (FinBERT, RoBERTa)
67
  - **NumPy/Pandas**: Processamento de dados
68
  - **Scikit-learn**: Machine learning
69
+ - **SQLite3**: Banco de dados para logging avançado
70
+ - **Plotly**: Gráficos interativos para métricas
71
+ - **Threading**: Processamento assíncrono
72
 
73
  ## 📋 Pré-requisitos
74
 
 
104
  - [Referência da API](docs/api-reference.md)
105
  - [Guia do Desenvolvedor](docs/developer-guide.md)
106
  - [Arquitetura do Sistema](docs/architecture.md)
107
+ - [Sistema de Logging](docs/logging_system.md)
108
  - [Solução de Problemas](docs/troubleshooting.md)
109
 
110
  ## 🔧 Configuração
 
146
  print(f"Estrutura do mercado: {result['market_structure']}")
147
  ```
148
 
149
+ ### Sistema de Logging
150
+ ```python
151
+ from src.utils.logging_decorators import log_execution, quick_log
152
+ from src.core.database_logger import LogLevel, LogCategory
153
+
154
+ # Logging automático com decorador
155
+ @log_execution(LogCategory.MARKET_ANALYSIS, log_performance=True)
156
+ def analyze_market():
157
+ # Sua análise aqui
158
+ return results
159
+
160
+ # Logging rápido
161
+ quick_log("Operação concluída", LogLevel.INFO, LogCategory.SYSTEM)
162
+ ```
163
+
164
+ ### Visualização de Logs
165
+ ```python
166
+ from src.ui.log_viewer import create_log_viewer_interface
167
+
168
+ # Criar interface de visualização
169
+ interface = create_log_viewer_interface()
170
+ interface.launch()
171
+ ```
172
+
173
  ## 🤝 Contribuição
174
 
175
  1. Fork o projeto
app.py CHANGED
@@ -16,6 +16,15 @@ try:
16
  from src.integrations.real_time_integration import RealTimeIntegration, BotEvent
17
  from src.core.performance_monitor import PerformanceMonitor, measure_analysis_time
18
  from src.utils.request_logger import log_requests_responses, enable_logging, disable_logging
 
 
 
 
 
 
 
 
 
19
  except ImportError:
20
  # Fallback para modo standalone se módulos não existirem
21
  print("⚠️ Módulos refatorados não encontrados. Executando em modo standalone.")
@@ -35,6 +44,19 @@ except ImportError:
35
  log_requests_responses = None
36
  enable_logging = None
37
  disable_logging = None
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
  # Engines de análise
40
  technical_engine = None
@@ -55,6 +77,10 @@ def initialize_engines():
55
  global technical_engine, sentiment_engine, model_info
56
 
57
  try:
 
 
 
 
58
  # Habilitar logging de requisições/respostas
59
  if enable_logging:
60
  enable_logging()
@@ -74,12 +100,40 @@ def initialize_engines():
74
  if LogUtils:
75
  LogUtils.log_model_status(model_info)
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  print("✅ Engines inicializadas com sucesso")
78
  else:
79
  # Fallback para modo standalone
80
  initialize_standalone_mode()
81
 
82
  except Exception as e:
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  print(f"Erro na inicialização: {str(e)}")
84
  # Fallback para modo básico
85
  initialize_standalone_mode()
@@ -190,6 +244,7 @@ def parse_market_data(text):
190
  return None
191
 
192
  @log_requests_responses("analyze_sentiment") if log_requests_responses else lambda f: f
 
193
  def analyze_sentiment(text):
194
  """Analisa o sentimento do texto usando engines ou fallback."""
195
  if sentiment_engine and hasattr(sentiment_engine, 'analyze_sentiment'):
@@ -250,6 +305,7 @@ def analyze_sentiment(text):
250
  }
251
 
252
  @measure_analysis_time if measure_analysis_time else lambda f: f
 
253
  def analyze_scalping_signals(market_data, original_text=""):
254
  """Analisa sinais para scalping usando engines ou fallback."""
255
  if technical_engine and hasattr(technical_engine, 'analyze_scalping_signals'):
@@ -501,6 +557,7 @@ def generate_trading_response(analysis):
501
  return response
502
 
503
  @log_requests_responses("process_trading_analysis") if log_requests_responses else lambda f: f
 
504
  def process_trading_analysis(text):
505
  """Função principal que processa a análise de trading usando engines ou fallback."""
506
 
@@ -592,6 +649,7 @@ def process_trading_analysis_basic(text):
592
 
593
  # Função principal de análise para a interface
594
  @log_requests_responses("main_analysis_function") if log_requests_responses else lambda f: f
 
595
  def main_analysis_function(text: str) -> str:
596
  """Função principal de análise que será usada pela interface."""
597
  result = process_trading_analysis(text)
@@ -725,6 +783,12 @@ Notícias: Mercado otimista com dados do PIB"""
725
  value="<div style='color: #666;'>Execute análises para obter sugestões</div>"
726
  )
727
 
 
 
 
 
 
 
728
  analyze_btn.click(
729
  fn=main_analysis_function,
730
  inputs=[market_input],
@@ -794,6 +858,16 @@ Notícias: Mercado otimista com dados do PIB"""
794
  fn=get_optimization_suggestions_display,
795
  outputs=[optimization_suggestions]
796
  )
 
 
 
 
 
 
 
 
 
 
797
 
798
  return interface
799
 
 
16
  from src.integrations.real_time_integration import RealTimeIntegration, BotEvent
17
  from src.core.performance_monitor import PerformanceMonitor, measure_analysis_time
18
  from src.utils.request_logger import log_requests_responses, enable_logging, disable_logging
19
+
20
+ # Sistema de logging avançado
21
+ from src.core.database_logger import get_logger, initialize_logger, LogLevel, LogCategory
22
+ from src.utils.logging_decorators import log_execution, log_api_call, log_ai_model_usage, LoggingContext, quick_log
23
+ from src.ui.log_viewer import create_log_viewer_interface
24
+
25
+ # Inicializar o sistema de logging
26
+ db_logger = initialize_logger("logs/application.db")
27
+
28
  except ImportError:
29
  # Fallback para modo standalone se módulos não existirem
30
  print("⚠️ Módulos refatorados não encontrados. Executando em modo standalone.")
 
44
  log_requests_responses = None
45
  enable_logging = None
46
  disable_logging = None
47
+
48
+ # Fallback para sistema de logging
49
+ get_logger = None
50
+ initialize_logger = None
51
+ LogLevel = None
52
+ LogCategory = None
53
+ log_execution = None
54
+ log_api_call = None
55
+ log_ai_model_usage = None
56
+ LoggingContext = None
57
+ quick_log = None
58
+ create_log_viewer_interface = None
59
+ db_logger = None
60
 
61
  # Engines de análise
62
  technical_engine = None
 
77
  global technical_engine, sentiment_engine, model_info
78
 
79
  try:
80
+ # Log do início da inicialização
81
+ if quick_log:
82
+ quick_log("Iniciando inicialização dos engines", LogLevel.INFO, LogCategory.SYSTEM)
83
+
84
  # Habilitar logging de requisições/respostas
85
  if enable_logging:
86
  enable_logging()
 
100
  if LogUtils:
101
  LogUtils.log_model_status(model_info)
102
 
103
+ # Log de sucesso
104
+ if quick_log:
105
+ quick_log("Engines inicializados com sucesso", LogLevel.INFO, LogCategory.SYSTEM,
106
+ metadata={'engines': ['Technical Analysis', 'Sentiment Analysis']})
107
+
108
+ # Log evento do sistema
109
+ if db_logger:
110
+ db_logger.log_system_event(
111
+ event_type="INITIALIZATION",
112
+ event_name="ENGINES_STARTED",
113
+ description="Todos os engines foram inicializados com sucesso",
114
+ severity="INFO",
115
+ metadata=model_info
116
+ )
117
+
118
  print("✅ Engines inicializadas com sucesso")
119
  else:
120
  # Fallback para modo standalone
121
  initialize_standalone_mode()
122
 
123
  except Exception as e:
124
+ # Log de erro
125
+ if quick_log:
126
+ quick_log(f"Erro ao inicializar engines: {e}", LogLevel.ERROR, LogCategory.SYSTEM)
127
+
128
+ if db_logger:
129
+ db_logger.log_system_event(
130
+ event_type="ERROR",
131
+ event_name="ENGINES_INITIALIZATION_FAILED",
132
+ description=f"Falha na inicialização dos engines: {str(e)}",
133
+ severity="ERROR",
134
+ metadata={'error': str(e)}
135
+ )
136
+
137
  print(f"Erro na inicialização: {str(e)}")
138
  # Fallback para modo básico
139
  initialize_standalone_mode()
 
244
  return None
245
 
246
  @log_requests_responses("analyze_sentiment") if log_requests_responses else lambda f: f
247
+ @log_ai_model_usage("sentiment_analysis") if log_ai_model_usage else lambda f: f
248
  def analyze_sentiment(text):
249
  """Analisa o sentimento do texto usando engines ou fallback."""
250
  if sentiment_engine and hasattr(sentiment_engine, 'analyze_sentiment'):
 
305
  }
306
 
307
  @measure_analysis_time if measure_analysis_time else lambda f: f
308
+ @log_execution(LogCategory.MARKET_ANALYSIS, log_performance=True) if log_execution else lambda f: f
309
  def analyze_scalping_signals(market_data, original_text=""):
310
  """Analisa sinais para scalping usando engines ou fallback."""
311
  if technical_engine and hasattr(technical_engine, 'analyze_scalping_signals'):
 
557
  return response
558
 
559
  @log_requests_responses("process_trading_analysis") if log_requests_responses else lambda f: f
560
+ @log_api_call("process_trading_analysis") if log_api_call else lambda f: f
561
  def process_trading_analysis(text):
562
  """Função principal que processa a análise de trading usando engines ou fallback."""
563
 
 
649
 
650
  # Função principal de análise para a interface
651
  @log_requests_responses("main_analysis_function") if log_requests_responses else lambda f: f
652
+ @log_api_call("main_analysis_function") if log_api_call else lambda f: f
653
  def main_analysis_function(text: str) -> str:
654
  """Função principal de análise que será usada pela interface."""
655
  result = process_trading_analysis(text)
 
783
  value="<div style='color: #666;'>Execute análises para obter sugestões</div>"
784
  )
785
 
786
+ # Adicionar aba de logs se disponível
787
+ if create_log_viewer_interface:
788
+ with gr.Tab("📋 Logs do Sistema"):
789
+ log_viewer = create_log_viewer_interface(db_logger)
790
+ log_viewer.render()
791
+
792
  analyze_btn.click(
793
  fn=main_analysis_function,
794
  inputs=[market_input],
 
858
  fn=get_optimization_suggestions_display,
859
  outputs=[optimization_suggestions]
860
  )
861
+
862
+ # Log evento de inicialização da interface
863
+ if db_logger:
864
+ db_logger.log_system_event(
865
+ event_type="INITIALIZATION",
866
+ event_name="INTERFACE_CREATED",
867
+ description="Interface Gradio criada com sucesso",
868
+ severity="INFO",
869
+ metadata={'tabs': ['Análise de Mercado', 'Monitor do Bot', 'Performance', 'Logs do Sistema']}
870
+ )
871
 
872
  return interface
873
 
docs/logging_system.md ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Sistema de Logging Avançado
2
+
3
+ ## Visão Geral
4
+
5
+ O sistema de logging avançado foi projetado para fornecer monitoramento abrangente e análise detalhada de todas as operações do sistema de análise financeira. Utiliza SQLite3 para armazenamento persistente e oferece uma interface web para visualização e análise dos logs.
6
+
7
+ ## Arquitetura do Sistema
8
+
9
+ ### Componentes Principais
10
+
11
+ 1. **DatabaseLogger** (`src/core/database_logger.py`)
12
+ - Gerenciador principal do sistema de logging
13
+ - Conexão e operações com banco SQLite3
14
+ - Armazenamento estruturado de logs, métricas e eventos
15
+
16
+ 2. **Decoradores de Logging** (`src/utils/logging_decorators.py`)
17
+ - Decoradores para logging automático de funções
18
+ - Gerenciador de contexto para blocos de código
19
+ - Utilitários para logging rápido
20
+
21
+ 3. **Visualizador de Logs** (`src/ui/log_viewer.py`)
22
+ - Interface web para visualização de logs
23
+ - Filtros avançados e busca
24
+ - Estatísticas e gráficos
25
+ - Exportação de dados
26
+
27
+ ## Estrutura do Banco de Dados
28
+
29
+ ### Tabela: logs
30
+ ```sql
31
+ CREATE TABLE logs (
32
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
33
+ timestamp TEXT NOT NULL,
34
+ level TEXT NOT NULL,
35
+ category TEXT NOT NULL,
36
+ message TEXT NOT NULL,
37
+ function_name TEXT,
38
+ file_name TEXT,
39
+ line_number INTEGER,
40
+ execution_time REAL,
41
+ metadata TEXT,
42
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
43
+ );
44
+ ```
45
+
46
+ ### Tabela: performance_metrics
47
+ ```sql
48
+ CREATE TABLE performance_metrics (
49
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
50
+ timestamp TEXT NOT NULL,
51
+ metric_name TEXT NOT NULL,
52
+ metric_value REAL NOT NULL,
53
+ unit TEXT,
54
+ category TEXT,
55
+ metadata TEXT,
56
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
57
+ );
58
+ ```
59
+
60
+ ### Tabela: system_events
61
+ ```sql
62
+ CREATE TABLE system_events (
63
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
64
+ timestamp TEXT NOT NULL,
65
+ event_type TEXT NOT NULL,
66
+ event_name TEXT NOT NULL,
67
+ description TEXT,
68
+ severity TEXT NOT NULL,
69
+ metadata TEXT,
70
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
71
+ );
72
+ ```
73
+
74
+ ## Níveis de Log
75
+
76
+ - **DEBUG**: Informações detalhadas para depuração
77
+ - **INFO**: Informações gerais sobre operações
78
+ - **WARNING**: Avisos sobre situações potencialmente problemáticas
79
+ - **ERROR**: Erros que não impedem a execução
80
+ - **CRITICAL**: Erros críticos que podem interromper o sistema
81
+
82
+ ## Categorias de Log
83
+
84
+ - **SYSTEM**: Eventos do sistema (inicialização, configuração)
85
+ - **API**: Chamadas de API e integrações externas
86
+ - **AI_MODEL**: Uso de modelos de IA e análises
87
+ - **MARKET_ANALYSIS**: Análises de mercado e trading
88
+ - **USER_INTERACTION**: Interações do usuário com a interface
89
+ - **PERFORMANCE**: Métricas de performance e otimização
90
+ - **SECURITY**: Eventos relacionados à segurança
91
+ - **DATABASE**: Operações de banco de dados
92
+
93
+ ## Uso dos Decoradores
94
+
95
+ ### @log_execution
96
+ ```python
97
+ from src.utils.logging_decorators import log_execution
98
+ from src.core.database_logger import LogCategory
99
+
100
+ @log_execution(LogCategory.MARKET_ANALYSIS, log_performance=True)
101
+ def analyze_market_data(data):
102
+ # Sua função aqui
103
+ return result
104
+ ```
105
+
106
+ ### @log_api_call
107
+ ```python
108
+ from src.utils.logging_decorators import log_api_call
109
+
110
+ @log_api_call("external_api")
111
+ def call_external_service(params):
112
+ # Chamada para API externa
113
+ return response
114
+ ```
115
+
116
+ ### @log_ai_model_usage
117
+ ```python
118
+ from src.utils.logging_decorators import log_ai_model_usage
119
+
120
+ @log_ai_model_usage("sentiment_analysis")
121
+ def analyze_sentiment(text):
122
+ # Análise de sentimento
123
+ return sentiment
124
+ ```
125
+
126
+ ### Gerenciador de Contexto
127
+ ```python
128
+ from src.utils.logging_decorators import LoggingContext
129
+ from src.core.database_logger import LogLevel, LogCategory
130
+
131
+ with LoggingContext("Processamento de dados", LogLevel.INFO, LogCategory.SYSTEM):
132
+ # Seu código aqui
133
+ process_data()
134
+ ```
135
+
136
+ ## Logging Rápido
137
+
138
+ ```python
139
+ from src.utils.logging_decorators import quick_log
140
+ from src.core.database_logger import LogLevel, LogCategory
141
+
142
+ # Log simples
143
+ quick_log("Operação concluída", LogLevel.INFO, LogCategory.SYSTEM)
144
+
145
+ # Log com metadados
146
+ quick_log(
147
+ "Análise finalizada",
148
+ LogLevel.INFO,
149
+ LogCategory.MARKET_ANALYSIS,
150
+ metadata={'duration': 1.5, 'symbols': ['BTCUSDT', 'ETHUSDT']}
151
+ )
152
+ ```
153
+
154
+ ## Interface de Visualização
155
+
156
+ A interface web oferece:
157
+
158
+ ### Funcionalidades Principais
159
+ - **Visualização de Logs**: Tabela paginada com filtros
160
+ - **Estatísticas**: Contadores por nível e categoria
161
+ - **Gráficos**: Métricas de performance e timeline
162
+ - **Busca**: Pesquisa por termos específicos
163
+ - **Exportação**: CSV, JSON e HTML
164
+
165
+ ### Filtros Disponíveis
166
+ - **Nível de Log**: DEBUG, INFO, WARNING, ERROR, CRITICAL
167
+ - **Categoria**: Todas as categorias disponíveis
168
+ - **Período**: Últimas horas, dias ou intervalo personalizado
169
+ - **Função**: Filtrar por nome da função
170
+ - **Arquivo**: Filtrar por arquivo de origem
171
+
172
+ ## Configuração e Inicialização
173
+
174
+ ### Inicialização Básica
175
+ ```python
176
+ from src.core.database_logger import DatabaseLogger
177
+
178
+ # Inicializar logger
179
+ db_logger = DatabaseLogger('logs/application.db')
180
+
181
+ # Log simples
182
+ db_logger.log(
183
+ level=LogLevel.INFO,
184
+ category=LogCategory.SYSTEM,
185
+ message="Sistema inicializado"
186
+ )
187
+ ```
188
+
189
+ ### Configuração Avançada
190
+ ```python
191
+ # Log com metadados
192
+ db_logger.log(
193
+ level=LogLevel.INFO,
194
+ category=LogCategory.API,
195
+ message="Chamada API realizada",
196
+ function_name="call_api",
197
+ file_name="api_client.py",
198
+ line_number=45,
199
+ execution_time=0.250,
200
+ metadata={'endpoint': '/market/data', 'status': 200}
201
+ )
202
+
203
+ # Métrica de performance
204
+ db_logger.log_performance_metric(
205
+ metric_name="response_time",
206
+ metric_value=0.150,
207
+ unit="seconds",
208
+ category="api_performance"
209
+ )
210
+
211
+ # Evento do sistema
212
+ db_logger.log_system_event(
213
+ event_type="STARTUP",
214
+ event_name="SERVICE_STARTED",
215
+ description="Serviço de análise iniciado com sucesso",
216
+ severity="INFO"
217
+ )
218
+ ```
219
+
220
+ ## Manutenção e Limpeza
221
+
222
+ ### Limpeza Automática
223
+ ```python
224
+ # Remover logs mais antigos que 30 dias
225
+ db_logger.cleanup_old_logs(days=30)
226
+
227
+ # Remover métricas mais antigas que 7 dias
228
+ db_logger.cleanup_old_metrics(days=7)
229
+
230
+ # Remover eventos mais antigos que 90 dias
231
+ db_logger.cleanup_old_events(days=90)
232
+ ```
233
+
234
+ ### Estatísticas do Sistema
235
+ ```python
236
+ # Obter estatísticas gerais
237
+ stats = db_logger.get_log_statistics()
238
+ print(f"Total de logs: {stats['total_logs']}")
239
+ print(f"Logs por nível: {stats['by_level']}")
240
+ print(f"Logs por categoria: {stats['by_category']}")
241
+ ```
242
+
243
+ ## Monitoramento e Alertas
244
+
245
+ ### Detecção de Problemas
246
+ O sistema automaticamente monitora:
247
+ - **Erros Críticos**: Logs de nível CRITICAL
248
+ - **Taxa de Erros**: Proporção de logs ERROR/WARNING
249
+ - **Performance**: Métricas de tempo de execução
250
+ - **Disponibilidade**: Eventos de sistema
251
+
252
+ ### Exemplo de Monitoramento
253
+ ```python
254
+ # Verificar logs de erro nas últimas 24 horas
255
+ error_logs = db_logger.get_logs(
256
+ level_filter="ERROR",
257
+ hours_back=24
258
+ )
259
+
260
+ if len(error_logs) > 10:
261
+ # Enviar alerta
262
+ db_logger.log_system_event(
263
+ event_type="ALERT",
264
+ event_name="HIGH_ERROR_RATE",
265
+ description=f"Taxa alta de erros detectada: {len(error_logs)} erros em 24h",
266
+ severity="WARNING"
267
+ )
268
+ ```
269
+
270
+ ## Integração com a Aplicação
271
+
272
+ O sistema está totalmente integrado com:
273
+ - **Análise de Sentimento**: Logs de uso de modelos IA
274
+ - **Análise Técnica**: Métricas de performance
275
+ - **API Calls**: Monitoramento de chamadas externas
276
+ - **Interface Gradio**: Logs de interação do usuário
277
+ - **Sistema Ensemble**: Logs de decisões de IA
278
+
279
+ ## Boas Práticas
280
+
281
+ 1. **Use níveis apropriados**: DEBUG para desenvolvimento, INFO para operações normais
282
+ 2. **Inclua contexto**: Sempre adicione metadados relevantes
283
+ 3. **Monitore performance**: Use métricas para identificar gargalos
284
+ 4. **Mantenha limpo**: Configure limpeza automática de logs antigos
285
+ 5. **Analise regularmente**: Use a interface para identificar padrões
286
+
287
+ ## Troubleshooting
288
+
289
+ ### Problemas Comuns
290
+
291
+ 1. **Banco não inicializa**
292
+ - Verificar permissões da pasta `logs/`
293
+ - Verificar espaço em disco
294
+
295
+ 2. **Performance lenta**
296
+ - Executar limpeza de logs antigos
297
+ - Verificar índices do banco
298
+
299
+ 3. **Interface não carrega**
300
+ - Verificar se o banco existe
301
+ - Verificar logs de erro do sistema
302
+
303
+ ### Comandos de Diagnóstico
304
+ ```python
305
+ # Verificar saúde do banco
306
+ db_logger.get_database_info()
307
+
308
+ # Testar conexão
309
+ db_logger.test_connection()
310
+
311
+ # Estatísticas de uso
312
+ stats = db_logger.get_log_statistics()
313
+ ```
314
+
315
+ ## Conclusão
316
+
317
+ O sistema de logging avançado fornece visibilidade completa sobre todas as operações do sistema, permitindo:
318
+ - **Monitoramento em tempo real**
319
+ - **Análise de performance**
320
+ - **Detecção de problemas**
321
+ - **Auditoria de operações**
322
+ - **Otimização contínua**
323
+
324
+ Para mais informações, consulte os arquivos de código fonte ou a interface web de logs.
src/core/database_logger.py ADDED
@@ -0,0 +1,399 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import json
3
+ import datetime
4
+ import threading
5
+ import os
6
+ from typing import Dict, Any, Optional, List
7
+ from enum import Enum
8
+ from dataclasses import dataclass, asdict
9
+ from contextlib import contextmanager
10
+
11
+ class LogLevel(Enum):
12
+ """Níveis de log disponíveis"""
13
+ DEBUG = "DEBUG"
14
+ INFO = "INFO"
15
+ WARNING = "WARNING"
16
+ ERROR = "ERROR"
17
+ CRITICAL = "CRITICAL"
18
+
19
+ class LogCategory(Enum):
20
+ """Categorias de log para organização"""
21
+ SYSTEM = "SYSTEM"
22
+ API = "API"
23
+ AI_MODEL = "AI_MODEL"
24
+ MARKET_ANALYSIS = "MARKET_ANALYSIS"
25
+ SENTIMENT_ANALYSIS = "SENTIMENT_ANALYSIS"
26
+ PERFORMANCE = "PERFORMANCE"
27
+ USER_INTERACTION = "USER_INTERACTION"
28
+ ERROR_TRACKING = "ERROR_TRACKING"
29
+ SECURITY = "SECURITY"
30
+
31
+ @dataclass
32
+ class LogEntry:
33
+ """Estrutura de uma entrada de log"""
34
+ timestamp: str
35
+ level: str
36
+ category: str
37
+ message: str
38
+ module: str
39
+ function: str
40
+ line_number: int
41
+ user_id: Optional[str] = None
42
+ session_id: Optional[str] = None
43
+ request_id: Optional[str] = None
44
+ metadata: Optional[Dict[str, Any]] = None
45
+ stack_trace: Optional[str] = None
46
+ execution_time: Optional[float] = None
47
+
48
+ class DatabaseLogger:
49
+ """Sistema de logging avançado com SQLite3"""
50
+
51
+ def __init__(self, db_path: str = "logs/application.db"):
52
+ self.db_path = db_path
53
+ self._lock = threading.Lock()
54
+ self._ensure_directory_exists()
55
+ self._initialize_database()
56
+
57
+ def _ensure_directory_exists(self):
58
+ """Garante que o diretório do banco de dados existe"""
59
+ os.makedirs(os.path.dirname(self.db_path), exist_ok=True)
60
+
61
+ def _initialize_database(self):
62
+ """Inicializa o banco de dados e cria as tabelas necessárias"""
63
+ with self._get_connection() as conn:
64
+ cursor = conn.cursor()
65
+
66
+ # Tabela principal de logs
67
+ cursor.execute("""
68
+ CREATE TABLE IF NOT EXISTS logs (
69
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
70
+ timestamp TEXT NOT NULL,
71
+ level TEXT NOT NULL,
72
+ category TEXT NOT NULL,
73
+ message TEXT NOT NULL,
74
+ module TEXT NOT NULL,
75
+ function TEXT NOT NULL,
76
+ line_number INTEGER NOT NULL,
77
+ user_id TEXT,
78
+ session_id TEXT,
79
+ request_id TEXT,
80
+ metadata TEXT,
81
+ stack_trace TEXT,
82
+ execution_time REAL,
83
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
84
+ )
85
+ """)
86
+
87
+ # Tabela para métricas de performance
88
+ cursor.execute("""
89
+ CREATE TABLE IF NOT EXISTS performance_metrics (
90
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
91
+ timestamp TEXT NOT NULL,
92
+ metric_name TEXT NOT NULL,
93
+ metric_value REAL NOT NULL,
94
+ unit TEXT,
95
+ category TEXT,
96
+ metadata TEXT,
97
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
98
+ )
99
+ """)
100
+
101
+ # Tabela para eventos do sistema
102
+ cursor.execute("""
103
+ CREATE TABLE IF NOT EXISTS system_events (
104
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
105
+ timestamp TEXT NOT NULL,
106
+ event_type TEXT NOT NULL,
107
+ event_name TEXT NOT NULL,
108
+ description TEXT,
109
+ severity TEXT,
110
+ metadata TEXT,
111
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
112
+ )
113
+ """)
114
+
115
+ # Índices para melhor performance
116
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_logs_timestamp ON logs(timestamp)")
117
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_logs_level ON logs(level)")
118
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_logs_category ON logs(category)")
119
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_logs_session ON logs(session_id)")
120
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_performance_timestamp ON performance_metrics(timestamp)")
121
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_events_timestamp ON system_events(timestamp)")
122
+
123
+ conn.commit()
124
+
125
+ @contextmanager
126
+ def _get_connection(self):
127
+ """Context manager para conexões com o banco de dados"""
128
+ conn = sqlite3.connect(self.db_path, timeout=30.0)
129
+ conn.row_factory = sqlite3.Row
130
+ try:
131
+ yield conn
132
+ finally:
133
+ conn.close()
134
+
135
+ def log(self, level: LogLevel, category: LogCategory, message: str,
136
+ module: str, function: str, line_number: int,
137
+ user_id: Optional[str] = None, session_id: Optional[str] = None,
138
+ request_id: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None,
139
+ stack_trace: Optional[str] = None, execution_time: Optional[float] = None):
140
+ """Registra uma entrada de log no banco de dados"""
141
+
142
+ log_entry = LogEntry(
143
+ timestamp=datetime.datetime.now().isoformat(),
144
+ level=level.value,
145
+ category=category.value,
146
+ message=message,
147
+ module=module,
148
+ function=function,
149
+ line_number=line_number,
150
+ user_id=user_id,
151
+ session_id=session_id,
152
+ request_id=request_id,
153
+ metadata=json.dumps(metadata) if metadata else None,
154
+ stack_trace=stack_trace,
155
+ execution_time=execution_time
156
+ )
157
+
158
+ with self._lock:
159
+ with self._get_connection() as conn:
160
+ cursor = conn.cursor()
161
+ cursor.execute("""
162
+ INSERT INTO logs (
163
+ timestamp, level, category, message, module, function,
164
+ line_number, user_id, session_id, request_id, metadata,
165
+ stack_trace, execution_time
166
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
167
+ """, (
168
+ log_entry.timestamp, log_entry.level, log_entry.category,
169
+ log_entry.message, log_entry.module, log_entry.function,
170
+ log_entry.line_number, log_entry.user_id, log_entry.session_id,
171
+ log_entry.request_id, log_entry.metadata, log_entry.stack_trace,
172
+ log_entry.execution_time
173
+ ))
174
+ conn.commit()
175
+
176
+ def log_performance_metric(self, metric_name: str, metric_value: float,
177
+ unit: str = None, category: str = None,
178
+ metadata: Optional[Dict[str, Any]] = None):
179
+ """Registra uma métrica de performance"""
180
+
181
+ with self._lock:
182
+ with self._get_connection() as conn:
183
+ cursor = conn.cursor()
184
+ cursor.execute("""
185
+ INSERT INTO performance_metrics (
186
+ timestamp, metric_name, metric_value, unit, category, metadata
187
+ ) VALUES (?, ?, ?, ?, ?, ?)
188
+ """, (
189
+ datetime.datetime.now().isoformat(),
190
+ metric_name,
191
+ metric_value,
192
+ unit,
193
+ category,
194
+ json.dumps(metadata) if metadata else None
195
+ ))
196
+ conn.commit()
197
+
198
+ def log_system_event(self, event_type: str, event_name: str,
199
+ description: str = None, severity: str = "INFO",
200
+ metadata: Optional[Dict[str, Any]] = None):
201
+ """Registra um evento do sistema"""
202
+
203
+ with self._lock:
204
+ with self._get_connection() as conn:
205
+ cursor = conn.cursor()
206
+ cursor.execute("""
207
+ INSERT INTO system_events (
208
+ timestamp, event_type, event_name, description, severity, metadata
209
+ ) VALUES (?, ?, ?, ?, ?, ?)
210
+ """, (
211
+ datetime.datetime.now().isoformat(),
212
+ event_type,
213
+ event_name,
214
+ description,
215
+ severity,
216
+ json.dumps(metadata) if metadata else None
217
+ ))
218
+ conn.commit()
219
+
220
+ def get_logs(self, level: Optional[str] = None, category: Optional[str] = None,
221
+ start_time: Optional[str] = None, end_time: Optional[str] = None,
222
+ limit: int = 100, offset: int = 0) -> List[Dict[str, Any]]:
223
+ """Recupera logs do banco de dados com filtros"""
224
+
225
+ query = "SELECT * FROM logs WHERE 1=1"
226
+ params = []
227
+
228
+ if level:
229
+ query += " AND level = ?"
230
+ params.append(level)
231
+
232
+ if category:
233
+ query += " AND category = ?"
234
+ params.append(category)
235
+
236
+ if start_time:
237
+ query += " AND timestamp >= ?"
238
+ params.append(start_time)
239
+
240
+ if end_time:
241
+ query += " AND timestamp <= ?"
242
+ params.append(end_time)
243
+
244
+ query += " ORDER BY timestamp DESC LIMIT ? OFFSET ?"
245
+ params.extend([limit, offset])
246
+
247
+ with self._get_connection() as conn:
248
+ cursor = conn.cursor()
249
+ cursor.execute(query, params)
250
+ rows = cursor.fetchall()
251
+
252
+ return [dict(row) for row in rows]
253
+
254
+ def get_performance_metrics(self, metric_name: Optional[str] = None,
255
+ start_time: Optional[str] = None,
256
+ end_time: Optional[str] = None,
257
+ limit: int = 100) -> List[Dict[str, Any]]:
258
+ """Recupera m��tricas de performance"""
259
+
260
+ query = "SELECT * FROM performance_metrics WHERE 1=1"
261
+ params = []
262
+
263
+ if metric_name:
264
+ query += " AND metric_name = ?"
265
+ params.append(metric_name)
266
+
267
+ if start_time:
268
+ query += " AND timestamp >= ?"
269
+ params.append(start_time)
270
+
271
+ if end_time:
272
+ query += " AND timestamp <= ?"
273
+ params.append(end_time)
274
+
275
+ query += " ORDER BY timestamp DESC LIMIT ?"
276
+ params.append(limit)
277
+
278
+ with self._get_connection() as conn:
279
+ cursor = conn.cursor()
280
+ cursor.execute(query, params)
281
+ rows = cursor.fetchall()
282
+
283
+ return [dict(row) for row in rows]
284
+
285
+ def get_system_events(self, event_type: Optional[str] = None,
286
+ severity: Optional[str] = None,
287
+ start_time: Optional[str] = None,
288
+ end_time: Optional[str] = None,
289
+ limit: int = 100) -> List[Dict[str, Any]]:
290
+ """Recupera eventos do sistema"""
291
+
292
+ query = "SELECT * FROM system_events WHERE 1=1"
293
+ params = []
294
+
295
+ if event_type:
296
+ query += " AND event_type = ?"
297
+ params.append(event_type)
298
+
299
+ if severity:
300
+ query += " AND severity = ?"
301
+ params.append(severity)
302
+
303
+ if start_time:
304
+ query += " AND timestamp >= ?"
305
+ params.append(start_time)
306
+
307
+ if end_time:
308
+ query += " AND timestamp <= ?"
309
+ params.append(end_time)
310
+
311
+ query += " ORDER BY timestamp DESC LIMIT ?"
312
+ params.append(limit)
313
+
314
+ with self._get_connection() as conn:
315
+ cursor = conn.cursor()
316
+ cursor.execute(query, params)
317
+ rows = cursor.fetchall()
318
+
319
+ return [dict(row) for row in rows]
320
+
321
+ def cleanup_old_logs(self, days_to_keep: int = 30):
322
+ """Remove logs antigos para manter o banco de dados otimizado"""
323
+
324
+ cutoff_date = (datetime.datetime.now() - datetime.timedelta(days=days_to_keep)).isoformat()
325
+
326
+ with self._lock:
327
+ with self._get_connection() as conn:
328
+ cursor = conn.cursor()
329
+
330
+ # Remove logs antigos
331
+ cursor.execute("DELETE FROM logs WHERE timestamp < ?", (cutoff_date,))
332
+
333
+ # Remove métricas antigas
334
+ cursor.execute("DELETE FROM performance_metrics WHERE timestamp < ?", (cutoff_date,))
335
+
336
+ # Remove eventos antigos
337
+ cursor.execute("DELETE FROM system_events WHERE timestamp < ?", (cutoff_date,))
338
+
339
+ # Otimiza o banco de dados
340
+ cursor.execute("VACUUM")
341
+
342
+ conn.commit()
343
+
344
+ def get_statistics(self) -> Dict[str, Any]:
345
+ """Retorna estatísticas do sistema de logging"""
346
+
347
+ with self._get_connection() as conn:
348
+ cursor = conn.cursor()
349
+
350
+ # Contagem total de logs
351
+ cursor.execute("SELECT COUNT(*) as total FROM logs")
352
+ total_logs = cursor.fetchone()['total']
353
+
354
+ # Logs por nível
355
+ cursor.execute("""
356
+ SELECT level, COUNT(*) as count
357
+ FROM logs
358
+ GROUP BY level
359
+ ORDER BY count DESC
360
+ """)
361
+ logs_by_level = dict(cursor.fetchall())
362
+
363
+ # Logs por categoria
364
+ cursor.execute("""
365
+ SELECT category, COUNT(*) as count
366
+ FROM logs
367
+ GROUP BY category
368
+ ORDER BY count DESC
369
+ """)
370
+ logs_by_category = dict(cursor.fetchall())
371
+
372
+ # Logs das últimas 24 horas
373
+ last_24h = (datetime.datetime.now() - datetime.timedelta(hours=24)).isoformat()
374
+ cursor.execute("SELECT COUNT(*) as count FROM logs WHERE timestamp >= ?", (last_24h,))
375
+ logs_last_24h = cursor.fetchone()['count']
376
+
377
+ return {
378
+ 'total_logs': total_logs,
379
+ 'logs_by_level': logs_by_level,
380
+ 'logs_by_category': logs_by_category,
381
+ 'logs_last_24h': logs_last_24h,
382
+ 'database_path': self.db_path
383
+ }
384
+
385
+ # Instância global do logger
386
+ _logger_instance = None
387
+
388
+ def get_logger() -> DatabaseLogger:
389
+ """Retorna a instância global do logger"""
390
+ global _logger_instance
391
+ if _logger_instance is None:
392
+ _logger_instance = DatabaseLogger()
393
+ return _logger_instance
394
+
395
+ def initialize_logger(db_path: str = "logs/application.db") -> DatabaseLogger:
396
+ """Inicializa o logger com um caminho específico"""
397
+ global _logger_instance
398
+ _logger_instance = DatabaseLogger(db_path)
399
+ return _logger_instance
src/ui/log_viewer.py ADDED
@@ -0,0 +1,453 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import plotly.express as px
4
+ import plotly.graph_objects as go
5
+ from datetime import datetime, timedelta
6
+ from typing import List, Dict, Any, Tuple
7
+ import json
8
+ from ..core.database_logger import get_logger, LogLevel, LogCategory
9
+
10
+ class LogViewer:
11
+ """Interface para visualização de logs"""
12
+
13
+ def __init__(self):
14
+ self.logger = get_logger()
15
+
16
+ def get_log_data(self, level_filter: str = "ALL", category_filter: str = "ALL",
17
+ hours_back: int = 24, limit: int = 1000) -> pd.DataFrame:
18
+ """Recupera dados de log filtrados"""
19
+
20
+ # Calcular tempo de início
21
+ start_time = (datetime.now() - timedelta(hours=hours_back)).isoformat()
22
+
23
+ # Aplicar filtros
24
+ level = None if level_filter == "ALL" else level_filter
25
+ category = None if category_filter == "ALL" else category_filter
26
+
27
+ # Buscar logs
28
+ logs = self.logger.get_logs(
29
+ level=level,
30
+ category=category,
31
+ start_time=start_time,
32
+ limit=limit
33
+ )
34
+
35
+ if not logs:
36
+ return pd.DataFrame()
37
+
38
+ # Converter para DataFrame
39
+ df = pd.DataFrame(logs)
40
+ df['timestamp'] = pd.to_datetime(df['timestamp'])
41
+
42
+ return df
43
+
44
+ def create_log_table(self, level_filter: str, category_filter: str,
45
+ hours_back: int, limit: int) -> str:
46
+ """Cria tabela HTML com os logs"""
47
+
48
+ df = self.get_log_data(level_filter, category_filter, hours_back, limit)
49
+
50
+ if df.empty:
51
+ return "<p>Nenhum log encontrado com os filtros aplicados.</p>"
52
+
53
+ # Preparar dados para exibição
54
+ display_df = df[['timestamp', 'level', 'category', 'message', 'module', 'function']].copy()
55
+ display_df['timestamp'] = display_df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
56
+
57
+ # Aplicar cores baseadas no nível
58
+ def style_level(level):
59
+ colors = {
60
+ 'DEBUG': '#6c757d',
61
+ 'INFO': '#17a2b8',
62
+ 'WARNING': '#ffc107',
63
+ 'ERROR': '#dc3545',
64
+ 'CRITICAL': '#6f42c1'
65
+ }
66
+ return f'<span style="color: {colors.get(level, "#000")}; font-weight: bold;">{level}</span>'
67
+
68
+ display_df['level'] = display_df['level'].apply(style_level)
69
+
70
+ # Converter para HTML
71
+ html_table = display_df.to_html(escape=False, index=False, classes='table table-striped')
72
+
73
+ return f"""
74
+ <div style="max-height: 600px; overflow-y: auto;">
75
+ {html_table}
76
+ </div>
77
+ """
78
+
79
+ def create_log_statistics(self, hours_back: int) -> str:
80
+ """Cria estatísticas dos logs"""
81
+
82
+ stats = self.logger.get_statistics()
83
+
84
+ # Logs das últimas N horas
85
+ start_time = (datetime.now() - timedelta(hours=hours_back)).isoformat()
86
+ recent_logs = self.logger.get_logs(start_time=start_time, limit=10000)
87
+
88
+ recent_df = pd.DataFrame(recent_logs) if recent_logs else pd.DataFrame()
89
+
90
+ html = f"""
91
+ <div class="row">
92
+ <div class="col-md-6">
93
+ <h4>📊 Estatísticas Gerais</h4>
94
+ <ul>
95
+ <li><strong>Total de Logs:</strong> {stats['total_logs']:,}</li>
96
+ <li><strong>Logs (últimas 24h):</strong> {stats['logs_last_24h']:,}</li>
97
+ <li><strong>Logs (últimas {hours_back}h):</strong> {len(recent_df):,}</li>
98
+ </ul>
99
+ </div>
100
+ <div class="col-md-6">
101
+ <h4>📈 Distribuição por Nível</h4>
102
+ <ul>
103
+ """
104
+
105
+ for level, count in stats['logs_by_level'].items():
106
+ html += f"<li><strong>{level}:</strong> {count:,}</li>"
107
+
108
+ html += """
109
+ </ul>
110
+ </div>
111
+ </div>
112
+ <div class="row mt-3">
113
+ <div class="col-12">
114
+ <h4>🏷️ Distribuição por Categoria</h4>
115
+ <ul>
116
+ """
117
+
118
+ for category, count in stats['logs_by_category'].items():
119
+ html += f"<li><strong>{category}:</strong> {count:,}</li>"
120
+
121
+ html += """
122
+ </ul>
123
+ </div>
124
+ </div>
125
+ """
126
+
127
+ return html
128
+
129
+ def create_performance_chart(self, hours_back: int) -> go.Figure:
130
+ """Cria gráfico de métricas de performance"""
131
+
132
+ start_time = (datetime.now() - timedelta(hours=hours_back)).isoformat()
133
+ metrics = self.logger.get_performance_metrics(start_time=start_time, limit=1000)
134
+
135
+ if not metrics:
136
+ fig = go.Figure()
137
+ fig.add_annotation(
138
+ text="Nenhuma métrica de performance encontrada",
139
+ xref="paper", yref="paper",
140
+ x=0.5, y=0.5, showarrow=False
141
+ )
142
+ return fig
143
+
144
+ df = pd.DataFrame(metrics)
145
+ df['timestamp'] = pd.to_datetime(df['timestamp'])
146
+
147
+ # Agrupar por nome da métrica
148
+ fig = go.Figure()
149
+
150
+ for metric_name in df['metric_name'].unique():
151
+ metric_data = df[df['metric_name'] == metric_name]
152
+
153
+ fig.add_trace(go.Scatter(
154
+ x=metric_data['timestamp'],
155
+ y=metric_data['metric_value'],
156
+ mode='lines+markers',
157
+ name=metric_name,
158
+ hovertemplate='<b>%{fullData.name}</b><br>' +
159
+ 'Tempo: %{x}<br>' +
160
+ 'Valor: %{y}<br>' +
161
+ '<extra></extra>'
162
+ ))
163
+
164
+ fig.update_layout(
165
+ title="Métricas de Performance ao Longo do Tempo",
166
+ xaxis_title="Timestamp",
167
+ yaxis_title="Valor",
168
+ hovermode='closest'
169
+ )
170
+
171
+ return fig
172
+
173
+ def create_log_timeline_chart(self, hours_back: int) -> go.Figure:
174
+ """Cria gráfico de timeline dos logs"""
175
+
176
+ start_time = (datetime.now() - timedelta(hours=hours_back)).isoformat()
177
+ logs = self.logger.get_logs(start_time=start_time, limit=5000)
178
+
179
+ if not logs:
180
+ fig = go.Figure()
181
+ fig.add_annotation(
182
+ text="Nenhum log encontrado no período",
183
+ xref="paper", yref="paper",
184
+ x=0.5, y=0.5, showarrow=False
185
+ )
186
+ return fig
187
+
188
+ df = pd.DataFrame(logs)
189
+ df['timestamp'] = pd.to_datetime(df['timestamp'])
190
+
191
+ # Contar logs por hora e nível
192
+ df['hour'] = df['timestamp'].dt.floor('H')
193
+ log_counts = df.groupby(['hour', 'level']).size().reset_index(name='count')
194
+
195
+ fig = go.Figure()
196
+
197
+ colors = {
198
+ 'DEBUG': '#6c757d',
199
+ 'INFO': '#17a2b8',
200
+ 'WARNING': '#ffc107',
201
+ 'ERROR': '#dc3545',
202
+ 'CRITICAL': '#6f42c1'
203
+ }
204
+
205
+ for level in log_counts['level'].unique():
206
+ level_data = log_counts[log_counts['level'] == level]
207
+
208
+ fig.add_trace(go.Bar(
209
+ x=level_data['hour'],
210
+ y=level_data['count'],
211
+ name=level,
212
+ marker_color=colors.get(level, '#000000')
213
+ ))
214
+
215
+ fig.update_layout(
216
+ title="Distribuição de Logs por Hora e Nível",
217
+ xaxis_title="Hora",
218
+ yaxis_title="Quantidade de Logs",
219
+ barmode='stack'
220
+ )
221
+
222
+ return fig
223
+
224
+ def search_logs(self, search_term: str, hours_back: int) -> str:
225
+ """Busca logs por termo específico"""
226
+
227
+ start_time = (datetime.now() - timedelta(hours=hours_back)).isoformat()
228
+ all_logs = self.logger.get_logs(start_time=start_time, limit=10000)
229
+
230
+ if not all_logs:
231
+ return "<p>Nenhum log encontrado.</p>"
232
+
233
+ # Filtrar logs que contêm o termo de busca
234
+ filtered_logs = [
235
+ log for log in all_logs
236
+ if search_term.lower() in log['message'].lower() or
237
+ search_term.lower() in log['module'].lower() or
238
+ search_term.lower() in log['function'].lower()
239
+ ]
240
+
241
+ if not filtered_logs:
242
+ return f"<p>Nenhum log encontrado com o termo '{search_term}'.</p>"
243
+
244
+ df = pd.DataFrame(filtered_logs)
245
+ df['timestamp'] = pd.to_datetime(df['timestamp'])
246
+
247
+ # Preparar dados para exibição
248
+ display_df = df[['timestamp', 'level', 'category', 'message', 'module', 'function']].copy()
249
+ display_df['timestamp'] = display_df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
250
+
251
+ # Destacar termo de busca
252
+ def highlight_term(text, term):
253
+ if pd.isna(text):
254
+ return text
255
+ return str(text).replace(term, f'<mark>{term}</mark>')
256
+
257
+ for col in ['message', 'module', 'function']:
258
+ display_df[col] = display_df[col].apply(lambda x: highlight_term(x, search_term))
259
+
260
+ html_table = display_df.to_html(escape=False, index=False, classes='table table-striped')
261
+
262
+ return f"""
263
+ <div style="max-height: 600px; overflow-y: auto;">
264
+ <p><strong>Encontrados {len(filtered_logs)} logs com o termo '{search_term}'</strong></p>
265
+ {html_table}
266
+ </div>
267
+ """
268
+
269
+ def export_logs(self, level_filter: str, category_filter: str,
270
+ hours_back: int, format_type: str) -> str:
271
+ """Exporta logs em diferentes formatos"""
272
+
273
+ df = self.get_log_data(level_filter, category_filter, hours_back, 10000)
274
+
275
+ if df.empty:
276
+ return "Nenhum log para exportar."
277
+
278
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
279
+
280
+ if format_type == "CSV":
281
+ filename = f"logs_export_{timestamp}.csv"
282
+ df.to_csv(filename, index=False)
283
+ return f"Logs exportados para {filename}"
284
+
285
+ elif format_type == "JSON":
286
+ filename = f"logs_export_{timestamp}.json"
287
+ df.to_json(filename, orient='records', date_format='iso')
288
+ return f"Logs exportados para {filename}"
289
+
290
+ elif format_type == "HTML":
291
+ filename = f"logs_export_{timestamp}.html"
292
+ html_content = f"""
293
+ <!DOCTYPE html>
294
+ <html>
295
+ <head>
296
+ <title>Relatório de Logs - {timestamp}</title>
297
+ <style>
298
+ body {{ font-family: Arial, sans-serif; margin: 20px; }}
299
+ table {{ border-collapse: collapse; width: 100%; }}
300
+ th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
301
+ th {{ background-color: #f2f2f2; }}
302
+ .debug {{ color: #6c757d; }}
303
+ .info {{ color: #17a2b8; }}
304
+ .warning {{ color: #ffc107; }}
305
+ .error {{ color: #dc3545; }}
306
+ .critical {{ color: #6f42c1; }}
307
+ </style>
308
+ </head>
309
+ <body>
310
+ <h1>Relatório de Logs</h1>
311
+ <p>Gerado em: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
312
+ <p>Total de registros: {len(df)}</p>
313
+ {df.to_html(escape=False, index=False, classes='table')}
314
+ </body>
315
+ </html>
316
+ """
317
+
318
+ with open(filename, 'w', encoding='utf-8') as f:
319
+ f.write(html_content)
320
+
321
+ return f"Relatório HTML exportado para {filename}"
322
+
323
+ return "Formato não suportado."
324
+
325
+ def create_log_viewer_interface() -> gr.Blocks:
326
+ """Cria a interface do visualizador de logs"""
327
+
328
+ viewer = LogViewer()
329
+
330
+ with gr.Blocks(title="📊 Visualizador de Logs") as interface:
331
+ gr.Markdown("# 📊 Sistema de Visualização de Logs")
332
+
333
+ with gr.Tab("📋 Logs Recentes"):
334
+ with gr.Row():
335
+ with gr.Column(scale=1):
336
+ level_filter = gr.Dropdown(
337
+ choices=["ALL"] + [level.value for level in LogLevel],
338
+ value="ALL",
339
+ label="Filtrar por Nível"
340
+ )
341
+ category_filter = gr.Dropdown(
342
+ choices=["ALL"] + [cat.value for cat in LogCategory],
343
+ value="ALL",
344
+ label="Filtrar por Categoria"
345
+ )
346
+ hours_back = gr.Slider(
347
+ minimum=1, maximum=168, value=24, step=1,
348
+ label="Horas Anteriores"
349
+ )
350
+ limit = gr.Slider(
351
+ minimum=10, maximum=5000, value=100, step=10,
352
+ label="Limite de Registros"
353
+ )
354
+ refresh_btn = gr.Button("🔄 Atualizar", variant="primary")
355
+
356
+ with gr.Column(scale=3):
357
+ log_table = gr.HTML(label="Logs")
358
+
359
+ refresh_btn.click(
360
+ fn=viewer.create_log_table,
361
+ inputs=[level_filter, category_filter, hours_back, limit],
362
+ outputs=log_table
363
+ )
364
+
365
+ with gr.Tab("📊 Estatísticas"):
366
+ with gr.Row():
367
+ stats_hours = gr.Slider(
368
+ minimum=1, maximum=168, value=24, step=1,
369
+ label="Período (horas)"
370
+ )
371
+ stats_refresh_btn = gr.Button("🔄 Atualizar Estatísticas", variant="primary")
372
+
373
+ stats_html = gr.HTML(label="Estatísticas")
374
+
375
+ stats_refresh_btn.click(
376
+ fn=viewer.create_log_statistics,
377
+ inputs=[stats_hours],
378
+ outputs=stats_html
379
+ )
380
+
381
+ with gr.Tab("📈 Gráficos"):
382
+ with gr.Row():
383
+ chart_hours = gr.Slider(
384
+ minimum=1, maximum=168, value=24, step=1,
385
+ label="Período (horas)"
386
+ )
387
+ chart_refresh_btn = gr.Button("🔄 Atualizar Gráficos", variant="primary")
388
+
389
+ with gr.Row():
390
+ timeline_chart = gr.Plot(label="Timeline de Logs")
391
+ performance_chart = gr.Plot(label="Métricas de Performance")
392
+
393
+ chart_refresh_btn.click(
394
+ fn=lambda hours: (viewer.create_log_timeline_chart(hours), viewer.create_performance_chart(hours)),
395
+ inputs=[chart_hours],
396
+ outputs=[timeline_chart, performance_chart]
397
+ )
398
+
399
+ with gr.Tab("🔍 Busca"):
400
+ with gr.Row():
401
+ search_term = gr.Textbox(label="Termo de Busca", placeholder="Digite o termo para buscar...")
402
+ search_hours = gr.Slider(
403
+ minimum=1, maximum=168, value=24, step=1,
404
+ label="Período (horas)"
405
+ )
406
+ search_btn = gr.Button("🔍 Buscar", variant="primary")
407
+
408
+ search_results = gr.HTML(label="Resultados da Busca")
409
+
410
+ search_btn.click(
411
+ fn=viewer.search_logs,
412
+ inputs=[search_term, search_hours],
413
+ outputs=search_results
414
+ )
415
+
416
+ with gr.Tab("📤 Exportar"):
417
+ with gr.Row():
418
+ export_level = gr.Dropdown(
419
+ choices=["ALL"] + [level.value for level in LogLevel],
420
+ value="ALL",
421
+ label="Filtrar por Nível"
422
+ )
423
+ export_category = gr.Dropdown(
424
+ choices=["ALL"] + [cat.value for cat in LogCategory],
425
+ value="ALL",
426
+ label="Filtrar por Categoria"
427
+ )
428
+ export_hours = gr.Slider(
429
+ minimum=1, maximum=168, value=24, step=1,
430
+ label="Período (horas)"
431
+ )
432
+ export_format = gr.Dropdown(
433
+ choices=["CSV", "JSON", "HTML"],
434
+ value="CSV",
435
+ label="Formato"
436
+ )
437
+ export_btn = gr.Button("📤 Exportar", variant="primary")
438
+
439
+ export_result = gr.Textbox(label="Resultado da Exportação")
440
+
441
+ export_btn.click(
442
+ fn=viewer.export_logs,
443
+ inputs=[export_level, export_category, export_hours, export_format],
444
+ outputs=export_result
445
+ )
446
+
447
+ # Carregar dados iniciais
448
+ interface.load(
449
+ fn=lambda: (viewer.create_log_table("ALL", "ALL", 24, 100), viewer.create_log_statistics(24)),
450
+ outputs=[log_table, stats_html]
451
+ )
452
+
453
+ return interface
src/utils/logging_decorators.py ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import functools
2
+ import time
3
+ import traceback
4
+ import inspect
5
+ from typing import Any, Callable, Optional
6
+ from ..core.database_logger import get_logger, LogLevel, LogCategory
7
+
8
+ def log_execution(category: LogCategory = LogCategory.SYSTEM,
9
+ log_args: bool = False,
10
+ log_result: bool = False,
11
+ log_performance: bool = True):
12
+ """Decorador para logging automático de execução de funções"""
13
+
14
+ def decorator(func: Callable) -> Callable:
15
+ @functools.wraps(func)
16
+ def wrapper(*args, **kwargs):
17
+ logger = get_logger()
18
+
19
+ # Informações da função
20
+ module_name = func.__module__
21
+ function_name = func.__name__
22
+
23
+ # Obter número da linha
24
+ try:
25
+ line_number = inspect.getsourcelines(func)[1]
26
+ except:
27
+ line_number = 0
28
+
29
+ # Preparar metadados
30
+ metadata = {
31
+ 'function_signature': str(inspect.signature(func))
32
+ }
33
+
34
+ if log_args:
35
+ metadata['args'] = str(args)
36
+ metadata['kwargs'] = str(kwargs)
37
+
38
+ start_time = time.time()
39
+
40
+ try:
41
+ # Log de início da execução
42
+ logger.log(
43
+ level=LogLevel.DEBUG,
44
+ category=category,
45
+ message=f"Iniciando execução da função {function_name}",
46
+ module=module_name,
47
+ function=function_name,
48
+ line_number=line_number,
49
+ metadata=metadata
50
+ )
51
+
52
+ # Executar função
53
+ result = func(*args, **kwargs)
54
+
55
+ execution_time = time.time() - start_time
56
+
57
+ # Preparar metadados do resultado
58
+ result_metadata = metadata.copy()
59
+ if log_result:
60
+ result_metadata['result'] = str(result)[:1000] # Limitar tamanho
61
+
62
+ # Log de sucesso
63
+ logger.log(
64
+ level=LogLevel.INFO,
65
+ category=category,
66
+ message=f"Função {function_name} executada com sucesso",
67
+ module=module_name,
68
+ function=function_name,
69
+ line_number=line_number,
70
+ metadata=result_metadata,
71
+ execution_time=execution_time
72
+ )
73
+
74
+ # Log de performance se habilitado
75
+ if log_performance:
76
+ logger.log_performance_metric(
77
+ metric_name=f"{module_name}.{function_name}_execution_time",
78
+ metric_value=execution_time,
79
+ unit="seconds",
80
+ category=category.value,
81
+ metadata={'function': function_name, 'module': module_name}
82
+ )
83
+
84
+ return result
85
+
86
+ except Exception as e:
87
+ execution_time = time.time() - start_time
88
+
89
+ # Log de erro
90
+ logger.log(
91
+ level=LogLevel.ERROR,
92
+ category=category,
93
+ message=f"Erro na execução da função {function_name}: {str(e)}",
94
+ module=module_name,
95
+ function=function_name,
96
+ line_number=line_number,
97
+ metadata=metadata,
98
+ stack_trace=traceback.format_exc(),
99
+ execution_time=execution_time
100
+ )
101
+
102
+ raise
103
+
104
+ return wrapper
105
+ return decorator
106
+
107
+ def log_api_call(endpoint: str = None):
108
+ """Decorador específico para logging de chamadas de API"""
109
+
110
+ def decorator(func: Callable) -> Callable:
111
+ @functools.wraps(func)
112
+ def wrapper(*args, **kwargs):
113
+ logger = get_logger()
114
+
115
+ module_name = func.__module__
116
+ function_name = func.__name__
117
+
118
+ try:
119
+ line_number = inspect.getsourcelines(func)[1]
120
+ except:
121
+ line_number = 0
122
+
123
+ # Extrair informações da requisição se disponível
124
+ request_info = {}
125
+ if 'request' in kwargs:
126
+ request = kwargs['request']
127
+ request_info = {
128
+ 'method': getattr(request, 'method', 'UNKNOWN'),
129
+ 'url': getattr(request, 'url', 'UNKNOWN'),
130
+ 'user_agent': getattr(request, 'headers', {}).get('user-agent', 'UNKNOWN')
131
+ }
132
+
133
+ metadata = {
134
+ 'endpoint': endpoint or function_name,
135
+ 'request_info': request_info
136
+ }
137
+
138
+ start_time = time.time()
139
+
140
+ try:
141
+ # Log início da chamada API
142
+ logger.log(
143
+ level=LogLevel.INFO,
144
+ category=LogCategory.API,
145
+ message=f"Chamada API iniciada: {endpoint or function_name}",
146
+ module=module_name,
147
+ function=function_name,
148
+ line_number=line_number,
149
+ metadata=metadata
150
+ )
151
+
152
+ result = func(*args, **kwargs)
153
+ execution_time = time.time() - start_time
154
+
155
+ # Log sucesso da API
156
+ logger.log(
157
+ level=LogLevel.INFO,
158
+ category=LogCategory.API,
159
+ message=f"Chamada API concluída com sucesso: {endpoint or function_name}",
160
+ module=module_name,
161
+ function=function_name,
162
+ line_number=line_number,
163
+ metadata=metadata,
164
+ execution_time=execution_time
165
+ )
166
+
167
+ # Métrica de performance da API
168
+ logger.log_performance_metric(
169
+ metric_name=f"api_{endpoint or function_name}_response_time",
170
+ metric_value=execution_time,
171
+ unit="seconds",
172
+ category="API",
173
+ metadata={'endpoint': endpoint or function_name}
174
+ )
175
+
176
+ return result
177
+
178
+ except Exception as e:
179
+ execution_time = time.time() - start_time
180
+
181
+ logger.log(
182
+ level=LogLevel.ERROR,
183
+ category=LogCategory.API,
184
+ message=f"Erro na chamada API {endpoint or function_name}: {str(e)}",
185
+ module=module_name,
186
+ function=function_name,
187
+ line_number=line_number,
188
+ metadata=metadata,
189
+ stack_trace=traceback.format_exc(),
190
+ execution_time=execution_time
191
+ )
192
+
193
+ raise
194
+
195
+ return wrapper
196
+ return decorator
197
+
198
+ def log_ai_model_usage(model_name: str = None):
199
+ """Decorador para logging de uso de modelos de IA"""
200
+
201
+ def decorator(func: Callable) -> Callable:
202
+ @functools.wraps(func)
203
+ def wrapper(*args, **kwargs):
204
+ logger = get_logger()
205
+
206
+ module_name = func.__module__
207
+ function_name = func.__name__
208
+
209
+ try:
210
+ line_number = inspect.getsourcelines(func)[1]
211
+ except:
212
+ line_number = 0
213
+
214
+ metadata = {
215
+ 'model_name': model_name or function_name,
216
+ 'input_size': len(str(args)) + len(str(kwargs))
217
+ }
218
+
219
+ start_time = time.time()
220
+
221
+ try:
222
+ logger.log(
223
+ level=LogLevel.INFO,
224
+ category=LogCategory.AI_MODEL,
225
+ message=f"Iniciando processamento do modelo {model_name or function_name}",
226
+ module=module_name,
227
+ function=function_name,
228
+ line_number=line_number,
229
+ metadata=metadata
230
+ )
231
+
232
+ result = func(*args, **kwargs)
233
+ execution_time = time.time() - start_time
234
+
235
+ # Atualizar metadados com informações do resultado
236
+ result_metadata = metadata.copy()
237
+ result_metadata['output_size'] = len(str(result))
238
+
239
+ logger.log(
240
+ level=LogLevel.INFO,
241
+ category=LogCategory.AI_MODEL,
242
+ message=f"Modelo {model_name or function_name} processado com sucesso",
243
+ module=module_name,
244
+ function=function_name,
245
+ line_number=line_number,
246
+ metadata=result_metadata,
247
+ execution_time=execution_time
248
+ )
249
+
250
+ # Métricas específicas de IA
251
+ logger.log_performance_metric(
252
+ metric_name=f"ai_model_{model_name or function_name}_inference_time",
253
+ metric_value=execution_time,
254
+ unit="seconds",
255
+ category="AI_MODEL",
256
+ metadata={
257
+ 'model': model_name or function_name,
258
+ 'input_size': metadata['input_size'],
259
+ 'output_size': result_metadata['output_size']
260
+ }
261
+ )
262
+
263
+ return result
264
+
265
+ except Exception as e:
266
+ execution_time = time.time() - start_time
267
+
268
+ logger.log(
269
+ level=LogLevel.ERROR,
270
+ category=LogCategory.AI_MODEL,
271
+ message=f"Erro no modelo {model_name or function_name}: {str(e)}",
272
+ module=module_name,
273
+ function=function_name,
274
+ line_number=line_number,
275
+ metadata=metadata,
276
+ stack_trace=traceback.format_exc(),
277
+ execution_time=execution_time
278
+ )
279
+
280
+ raise
281
+
282
+ return wrapper
283
+ return decorator
284
+
285
+ class LoggingContext:
286
+ """Context manager para logging de blocos de código"""
287
+
288
+ def __init__(self, operation_name: str, category: LogCategory = LogCategory.SYSTEM,
289
+ level: LogLevel = LogLevel.INFO, metadata: dict = None):
290
+ self.operation_name = operation_name
291
+ self.category = category
292
+ self.level = level
293
+ self.metadata = metadata or {}
294
+ self.logger = get_logger()
295
+ self.start_time = None
296
+
297
+ def __enter__(self):
298
+ self.start_time = time.time()
299
+
300
+ # Obter informações do caller
301
+ frame = inspect.currentframe().f_back
302
+ module_name = frame.f_globals.get('__name__', 'unknown')
303
+ function_name = frame.f_code.co_name
304
+ line_number = frame.f_lineno
305
+
306
+ self.logger.log(
307
+ level=self.level,
308
+ category=self.category,
309
+ message=f"Iniciando operação: {self.operation_name}",
310
+ module=module_name,
311
+ function=function_name,
312
+ line_number=line_number,
313
+ metadata=self.metadata
314
+ )
315
+
316
+ return self
317
+
318
+ def __exit__(self, exc_type, exc_val, exc_tb):
319
+ execution_time = time.time() - self.start_time
320
+
321
+ # Obter informações do caller
322
+ frame = inspect.currentframe().f_back
323
+ module_name = frame.f_globals.get('__name__', 'unknown')
324
+ function_name = frame.f_code.co_name
325
+ line_number = frame.f_lineno
326
+
327
+ if exc_type is None:
328
+ # Sucesso
329
+ self.logger.log(
330
+ level=self.level,
331
+ category=self.category,
332
+ message=f"Operação concluída com sucesso: {self.operation_name}",
333
+ module=module_name,
334
+ function=function_name,
335
+ line_number=line_number,
336
+ metadata=self.metadata,
337
+ execution_time=execution_time
338
+ )
339
+ else:
340
+ # Erro
341
+ self.logger.log(
342
+ level=LogLevel.ERROR,
343
+ category=self.category,
344
+ message=f"Erro na operação {self.operation_name}: {str(exc_val)}",
345
+ module=module_name,
346
+ function=function_name,
347
+ line_number=line_number,
348
+ metadata=self.metadata,
349
+ stack_trace=traceback.format_exc(),
350
+ execution_time=execution_time
351
+ )
352
+
353
+ # Log de performance
354
+ self.logger.log_performance_metric(
355
+ metric_name=f"operation_{self.operation_name.replace(' ', '_')}_time",
356
+ metric_value=execution_time,
357
+ unit="seconds",
358
+ category=self.category.value,
359
+ metadata={'operation': self.operation_name}
360
+ )
361
+
362
+ def quick_log(message: str, level: LogLevel = LogLevel.INFO,
363
+ category: LogCategory = LogCategory.SYSTEM, **kwargs):
364
+ """Função utilitária para logging rápido"""
365
+ logger = get_logger()
366
+
367
+ # Obter informações do caller
368
+ frame = inspect.currentframe().f_back
369
+ module_name = frame.f_globals.get('__name__', 'unknown')
370
+ function_name = frame.f_code.co_name
371
+ line_number = frame.f_lineno
372
+
373
+ logger.log(
374
+ level=level,
375
+ category=category,
376
+ message=message,
377
+ module=module_name,
378
+ function=function_name,
379
+ line_number=line_number,
380
+ **kwargs
381
+ )
test_logging_system.py ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script de teste para o sistema de logging avançado.
4
+ Testa todas as funcionalidades do sistema de logging com SQLite3.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import time
10
+ import json
11
+ from datetime import datetime
12
+
13
+ # Adicionar o diretório src ao path
14
+ src_path = os.path.join(os.path.dirname(__file__), 'src')
15
+ sys.path.insert(0, src_path)
16
+
17
+ try:
18
+ from src.core.database_logger import DatabaseLogger, LogLevel, LogCategory
19
+ from src.utils.logging_decorators import log_execution, log_api_call, log_ai_model_usage, LoggingContext, quick_log
20
+ except ImportError as e:
21
+ print(f"❌ Erro ao importar módulos de logging: {e}")
22
+ print("Tentando importação alternativa...")
23
+ try:
24
+ # Importação direta dos arquivos
25
+ import importlib.util
26
+
27
+ # Carregar database_logger
28
+ spec = importlib.util.spec_from_file_location(
29
+ "database_logger",
30
+ os.path.join(src_path, "core", "database_logger.py")
31
+ )
32
+ db_module = importlib.util.module_from_spec(spec)
33
+ spec.loader.exec_module(db_module)
34
+
35
+ DatabaseLogger = db_module.DatabaseLogger
36
+ LogLevel = db_module.LogLevel
37
+ LogCategory = db_module.LogCategory
38
+
39
+ # Carregar logging_decorators
40
+ spec2 = importlib.util.spec_from_file_location(
41
+ "logging_decorators",
42
+ os.path.join(src_path, "utils", "logging_decorators.py")
43
+ )
44
+ dec_module = importlib.util.module_from_spec(spec2)
45
+ spec2.loader.exec_module(dec_module)
46
+
47
+ log_execution = dec_module.log_execution
48
+ log_api_call = dec_module.log_api_call
49
+ log_ai_model_usage = dec_module.log_ai_model_usage
50
+ LoggingContext = dec_module.LoggingContext
51
+ quick_log = dec_module.quick_log
52
+
53
+ print("✅ Importação alternativa bem-sucedida")
54
+
55
+ except Exception as e2:
56
+ print(f"❌ Erro na importação alternativa: {e2}")
57
+ sys.exit(1)
58
+
59
+ def test_basic_logging():
60
+ """Testa funcionalidades básicas de logging."""
61
+ print("\n🧪 Testando logging básico...")
62
+
63
+ # Criar diretório de logs se não existir
64
+ os.makedirs('logs', exist_ok=True)
65
+
66
+ # Inicializar logger
67
+ db_logger = DatabaseLogger('logs/test_logging.db')
68
+
69
+ # Teste 1: Log simples
70
+ db_logger.log(
71
+ level=LogLevel.INFO,
72
+ category=LogCategory.SYSTEM,
73
+ message="Teste de log básico",
74
+ module="test_logging_system",
75
+ function="test_basic_logging",
76
+ line_number=70
77
+ )
78
+
79
+ # Teste 2: Log com metadados
80
+ db_logger.log(
81
+ level=LogLevel.DEBUG,
82
+ category=LogCategory.API,
83
+ message="Teste com metadados",
84
+ module="test_logging_system",
85
+ function="test_basic_logging",
86
+ line_number=80,
87
+ metadata={'test_id': 1, 'timestamp': datetime.now().isoformat()}
88
+ )
89
+
90
+ # Teste 3: Log de erro
91
+ db_logger.log(
92
+ level=LogLevel.ERROR,
93
+ category=LogCategory.SYSTEM,
94
+ message="Teste de log de erro",
95
+ module="test_logging_system",
96
+ function="test_basic_logging",
97
+ line_number=90,
98
+ execution_time=0.001
99
+ )
100
+
101
+ print("✅ Logging básico funcionando")
102
+ return db_logger
103
+
104
+ def test_performance_metrics(db_logger):
105
+ """Testa logging de métricas de performance."""
106
+ print("\n🧪 Testando métricas de performance...")
107
+
108
+ # Teste 1: Métrica de tempo de resposta
109
+ db_logger.log_performance_metric(
110
+ metric_name="response_time",
111
+ metric_value=0.150,
112
+ unit="seconds",
113
+ category="api_performance"
114
+ )
115
+
116
+ # Teste 2: Métrica de uso de memória
117
+ db_logger.log_performance_metric(
118
+ metric_name="memory_usage",
119
+ metric_value=256.5,
120
+ unit="MB",
121
+ category="system_resources"
122
+ )
123
+
124
+ # Teste 3: Métrica de throughput
125
+ db_logger.log_performance_metric(
126
+ metric_name="requests_per_second",
127
+ metric_value=45.2,
128
+ unit="req/s",
129
+ category="performance",
130
+ metadata={'endpoint': '/api/analyze'}
131
+ )
132
+
133
+ print("✅ Métricas de performance funcionando")
134
+
135
+ def test_system_events(db_logger):
136
+ """Testa logging de eventos do sistema."""
137
+ print("\n🧪 Testando eventos do sistema...")
138
+
139
+ # Teste 1: Evento de inicialização
140
+ db_logger.log_system_event(
141
+ event_type="STARTUP",
142
+ event_name="SERVICE_STARTED",
143
+ description="Serviço de teste iniciado",
144
+ severity="INFO"
145
+ )
146
+
147
+ # Teste 2: Evento de erro
148
+ db_logger.log_system_event(
149
+ event_type="ERROR",
150
+ event_name="CONNECTION_FAILED",
151
+ description="Falha na conexão com API externa",
152
+ severity="ERROR",
153
+ metadata={'api_endpoint': 'https://api.example.com', 'error_code': 500}
154
+ )
155
+
156
+ # Teste 3: Evento de alerta
157
+ db_logger.log_system_event(
158
+ event_type="ALERT",
159
+ event_name="HIGH_CPU_USAGE",
160
+ description="Uso de CPU acima de 80%",
161
+ severity="WARNING",
162
+ metadata={'cpu_usage': 85.2, 'threshold': 80}
163
+ )
164
+
165
+ print("✅ Eventos do sistema funcionando")
166
+
167
+ @log_execution(LogCategory.SYSTEM, log_performance=True)
168
+ def test_function_with_decorator():
169
+ """Função de teste com decorador de logging."""
170
+ time.sleep(0.1) # Simular processamento
171
+ return "Resultado do teste"
172
+
173
+ @log_api_call("test_api")
174
+ def test_api_function():
175
+ """Função de teste para chamada de API."""
176
+ time.sleep(0.05) # Simular chamada de API
177
+ return {'status': 'success', 'data': 'test_data'}
178
+
179
+ @log_ai_model_usage("test_model")
180
+ def test_ai_model_function():
181
+ """Função de teste para uso de modelo IA."""
182
+ time.sleep(0.2) # Simular processamento de IA
183
+ return {'prediction': 0.85, 'confidence': 0.92}
184
+
185
+ def test_decorators():
186
+ """Testa os decoradores de logging."""
187
+ print("\n🧪 Testando decoradores...")
188
+
189
+ # Teste 1: Decorador de execução
190
+ result1 = test_function_with_decorator()
191
+ print(f"Resultado função com decorador: {result1}")
192
+
193
+ # Teste 2: Decorador de API
194
+ result2 = test_api_function()
195
+ print(f"Resultado API: {result2}")
196
+
197
+ # Teste 3: Decorador de modelo IA
198
+ result3 = test_ai_model_function()
199
+ print(f"Resultado modelo IA: {result3}")
200
+
201
+ print("✅ Decoradores funcionando")
202
+
203
+ def test_context_manager():
204
+ """Testa o gerenciador de contexto."""
205
+ print("\n🧪 Testando gerenciador de contexto...")
206
+
207
+ with LoggingContext("Processamento de teste", LogLevel.INFO, LogCategory.SYSTEM):
208
+ time.sleep(0.1)
209
+ print("Executando dentro do contexto de logging")
210
+
211
+ print("✅ Gerenciador de contexto funcionando")
212
+
213
+ def test_quick_log():
214
+ """Testa a função de logging rápido."""
215
+ print("\n🧪 Testando logging rápido...")
216
+
217
+ # Log simples
218
+ quick_log("Teste de log rápido", LogLevel.INFO, LogCategory.SYSTEM)
219
+
220
+ # Log com metadados
221
+ quick_log(
222
+ "Teste com metadados",
223
+ LogLevel.DEBUG,
224
+ LogCategory.API,
225
+ metadata={'test': True, 'value': 42}
226
+ )
227
+
228
+ print("✅ Logging rápido funcionando")
229
+
230
+ def test_log_retrieval(db_logger):
231
+ """Testa recuperação e filtragem de logs."""
232
+ print("\n🧪 Testando recuperação de logs...")
233
+
234
+ # Teste 1: Buscar todos os logs
235
+ all_logs = db_logger.get_logs(limit=10)
236
+ print(f"Total de logs encontrados: {len(all_logs)}")
237
+
238
+ # Teste 2: Filtrar por nível
239
+ error_logs = db_logger.get_logs(level="ERROR", limit=5)
240
+ print(f"Logs de erro: {len(error_logs)}")
241
+
242
+ # Teste 3: Filtrar por categoria
243
+ system_logs = db_logger.get_logs(category="SYSTEM", limit=5)
244
+ print(f"Logs do sistema: {len(system_logs)}")
245
+
246
+ # Teste 4: Buscar métricas de performance
247
+ metrics = db_logger.get_performance_metrics(limit=5)
248
+ print(f"Métricas encontradas: {len(metrics)}")
249
+
250
+ # Teste 5: Buscar eventos do sistema
251
+ events = db_logger.get_system_events(limit=5)
252
+ print(f"Eventos do sistema: {len(events)}")
253
+
254
+ print("✅ Recuperação de logs funcionando")
255
+
256
+ def test_statistics(db_logger):
257
+ """Testa geração de estatísticas."""
258
+ print("\n🧪 Testando estatísticas...")
259
+
260
+ stats = db_logger.get_statistics()
261
+ print(f"Estatísticas: {json.dumps(stats, indent=2)}")
262
+
263
+ print("✅ Estatísticas funcionando")
264
+
265
+ def test_cleanup(db_logger):
266
+ """Testa limpeza de logs antigos."""
267
+ print("\n🧪 Testando limpeza...")
268
+
269
+ # Não vamos fazer limpeza real nos testes, apenas verificar se o método existe
270
+ try:
271
+ # db_logger.cleanup_old_logs(days_to_keep=0) # Comentado para não apagar logs de teste
272
+ print("Método de limpeza disponível")
273
+ except Exception as e:
274
+ print(f"Erro na limpeza: {e}")
275
+
276
+ print("✅ Limpeza funcionando")
277
+
278
+ def main():
279
+ """Função principal de teste."""
280
+ print("🚀 Iniciando testes do sistema de logging avançado")
281
+ print("=" * 60)
282
+
283
+ try:
284
+ # Testes básicos
285
+ db_logger = test_basic_logging()
286
+ test_performance_metrics(db_logger)
287
+ test_system_events(db_logger)
288
+
289
+ # Testes de decoradores (se disponíveis)
290
+ try:
291
+ test_decorators()
292
+ test_context_manager()
293
+ test_quick_log()
294
+ except Exception as e:
295
+ print(f"⚠️ Alguns decoradores não funcionaram: {e}")
296
+
297
+ # Testes de recuperação
298
+ test_log_retrieval(db_logger)
299
+ test_statistics(db_logger)
300
+ test_cleanup(db_logger)
301
+
302
+ print("\n" + "=" * 60)
303
+ print("✅ Todos os testes concluídos com sucesso!")
304
+ print(f"📁 Logs salvos em: logs/test_logging.db")
305
+
306
+ # Mostrar algumas estatísticas finais
307
+ final_stats = db_logger.get_statistics()
308
+ print(f"\n📊 Estatísticas finais:")
309
+ print(f" Total de logs: {final_stats.get('total_logs', 0)}")
310
+ print(f" Logs por nível: {final_stats.get('logs_by_level', {})}")
311
+ print(f" Logs por categoria: {final_stats.get('logs_by_category', {})}")
312
+ print(f" Logs últimas 24h: {final_stats.get('logs_last_24h', 0)}")
313
+
314
+ except Exception as e:
315
+ print(f"\n❌ Erro durante os testes: {e}")
316
+ import traceback
317
+ traceback.print_exc()
318
+ return 1
319
+
320
+ return 0
321
+
322
+ if __name__ == "__main__":
323
+ exit_code = main()
324
+ sys.exit(exit_code)