
Dominando Registros de Log (Parte 1): Conceitos Fundamentais e Primeiros Passos em MQL5
Introdução
Bem-vindo ao início de mais uma jornada! Este artigo abre uma série especial onde criaremos, passo a passo, uma biblioteca para manipulação de logs, feita sob medida para quem desenvolve na linguagem MQL5. A ideia é simples, mas ambiciosa: oferecer uma ferramenta robusta, flexível e de alta qualidade, capaz de tornar o registro e a análise de logs em Expert Advisors (EAs) algo mais prático, eficiente e poderoso.
Hoje, temos os logs nativos do MetaTrader 5, que até cumprem seu papel de monitorar o básico: inicialização do terminal, conexões com servidores, detalhes do ambiente. Mas sejamos sinceros, esses logs não foram feitos para as particularidades do desenvolvimento de EAs. Quando queremos entender o comportamento específico de um EA em execução, surgem limitações. Falta precisão, controle e aquela personalização que faz toda a diferença.
É aí que entra a proposta desta série: ir além. Vamos construir do zero um sistema de logs sob medida, totalmente customizável. Imagine ter controle total sobre o que registrar: eventos críticos, rastreamento de erros, análise de performance ou até armazenar informações específicas para futuras investigações. Tudo isso, claro, de forma organizada e com a eficiência que o cenário exige.
Mas não se trata apenas de código. Esta série vai além do teclado. Vamos explorar os fundamentos do logging, entender o “porquê” antes do “como”, discutir as melhores práticas de design e, juntos, construir algo que não seja apenas funcional, mas também elegante e intuitivo. Afinal, criar software não é apenas resolver problemas, é também uma arte.
O que são Logs?
Funcionalmente, logs são registros cronológicos de eventos que sistemas e aplicações geram constantemente. Eles são como testemunhas oculares de cada requisição feita, cada erro lançado e cada decisão tomada pelo expert advisor. Se um desenvolvedor quiser rastrear por que um fluxo quebrou, os logs são seu ponto de partida. Sem eles, interpretar o que acontece seria equivalente a explorar um labirinto no escuro.
A verdade é que estamos cada vez mais cercados por um universo digital onde os sistemas não são apenas ferramentas, mas engrenagens essenciais em um mundo que respira código. Pense em comunicações instantâneas, transações financeiras em frações de segundo ou no controle automatizado de uma planta industrial. Confiabilidade aqui não é luxo, é pré-requisito. Mas… o que acontece quando algo dá errado? Onde começa a busca pelo que quebrou? Logs são a resposta. Eles são os olhos e ouvidos dentro da caixa-preta que chamamos de sistemas.
Imagine o seguinte: um expert advisor, em uma negociação automatizada, começa a falhar ao enviar requisições em massa ao servidor. De repente, surgem rejeições. Sem logs estruturados, você fica jogando hipóteses ao vento: o servidor está sobrecarregado? Talvez uma configuração do expert advisor esteja errada? Com logs bem projetados, você não apenas encontra o “palheiro”, mas localiza a agulha exata: um erro de autenticação, um timeout ou até mesmo um volume excessivo de requisições.
Mas nem tudo é perfeito nos logs. Usá-los sem critério pode acabar virando um tiro no pé: dados irrelevantes se acumulam, os custos de armazenamento explodem e, no pior cenário, informações sensíveis podem vazar. Além disso, não basta ter logs; é preciso saber configurá-los com clareza e interpretá-los com precisão. Do contrário, o que deveria ser um mapa vira ruído caótico, mais confusão do que solução.
Enxergar logs em profundidade é entender que eles não são apenas ferramentas. São parceiros silenciosos que revelam, no momento certo, o que os sistemas têm a dizer. E como em qualquer boa parceria, o valor está em saber ouvir.
De forma um pouco mais prática, logs consistem em linhas de texto que documentam eventos específicos dentro de um sistema. Eles podem conter informações como:
- Event date and time: to track when something happened.
- Event type: error, warning, information, debug, among others.
- Descriptive message: explanation of what happened.
- Additional context: technical details, such as variable values at the time, data about the chart, such as timeframe or symbol, or even some value of a parameter that was used.
Vantagens do Uso de Logs
A seguir, detalhamos algumas das principais vantagens que o uso de logs oferece, destacando como eles podem otimizar operações e garantir a eficiência dos expert advisors.
1.Debugging and Troubleshooting
Com logs bem estruturados, tudo muda. Eles fornecem não apenas uma visão do que deu errado, mas também do porquê e do como. Um erro, que antes parecia uma sombra passageira, torna-se algo que você pode rastrear, compreender e corrigir. É como ter uma lupa que amplia cada detalhe crítico do momento em que o problema ocorreu.
Imagine, por exemplo, que uma requisição falhe inesperadamente. Sem logs, o problema poderia ser atribuído ao acaso, e a solução ficaria no campo da adivinhação. Mas com logs claros, o cenário muda. A mensagem de erro surge como um farol, acompanhada de dados valiosos sobre a requisição em questão: parâmetros enviados, resposta do servidor ou até um timeout inesperado. Esse contexto não apenas revela a origem do erro, mas também ilumina o caminho para solucioná-lo.
Exemplo prático de um log de erro:
[2024-11-18 14:32:15] ERROR : Limit Buy Trade Request Failed - Invalid Price in Request [10015 | TRADE_RETCODE_INVALID_PRICE]
Este log revela exatamente qual foi o erro, a tentativa de envio de uma requisição ao servidor, mostrando que o código de erro foi 10015, que representa um erro de preço inválido na requisição, assim o desenvolvedor do expert advisor pode saber exatamente em qual ordem ocorreu o erro, neste exemplo, ao enviar uma ordem de compra limitada.
2.Auditing and Compliance
Os logs desempenham um papel essencial quando se trata de auditoria e compliance com padrões e políticas de segurança. Em setores que lidam com dados sensíveis, como o financeiro, a exigência por registros detalhados vai além da mera organização: trata-se de estar alinhado às leis e regulamentos que regem a operação.
Eles servem como um rastro confiável que documenta cada ação relevante: quem acessou a informação, em que horário e o que foi feito. Isso não apenas traz transparência ao ambiente, mas também se torna uma poderosa ferramenta na investigação de incidentes de segurança ou práticas questionáveis. Com logs bem estruturados, identificar atividades irregulares deixa de ser um desafio nebuloso e se torna um processo direto e eficiente, fortalecendo a confiança e a segurança no sistema.
3.Monitoramento de desempenho
O uso de logs também é crucial para o monitoramento de performance dos sistemas. Em ambientes de produção, onde tempo de resposta e eficiência são cruciais, os logs permitem acompanhar a saúde do seu expert advisor em tempo real. Logs de performance podem incluir informações sobre tempo de resposta de ordens, uso de recursos (como CPU, memória e disco) e taxas de erro. A partir daí, podem ser tomadas ações corretivas, como a otimização do código.
Exemplo de log de performance:
[2024-11-18 16:45:23] INFO - Server response received, EURUSD purchase executed successfully | Volume: 0.01 | Price: 1.01234 | Duration: 49 ms
4. Automação e Alertas
A automação se destaca como uma das grandes vantagens dos logs, especialmente quando integrada a ferramentas de monitoramento e análise. Com a configuração correta, os logs podem disparar alertas automáticos assim que eventos críticos forem detectados, garantindo que o desenvolvedor seja imediatamente informado sobre falhas, erros ou até grandes perdas geradas pelo Expert Advisor.
Esses alertas vão além de simples avisos: podem ser enviados por e-mail, SMS ou integrados a plataformas de gestão, permitindo uma reação rápida e precisa. Esse nível de automação não apenas protege o sistema contra problemas que podem escalar rapidamente, mas também dá ao desenvolvedor o poder de agir de forma proativa, minimizando impactos e garantindo a estabilidade do ambiente.
Exemplo de um log com alerta:
[2024-11-18 19:15:50] FATAL - CPU usage exceeded 90%, immediate attention required.
Em resumo, os benefícios do uso de logs vão muito além de simplesmente registrar informações sobre o que está acontecendo no seu Expert Advisor. Eles fornecem uma ferramenta poderosa para depuração, monitoramento de performance, auditoria de segurança e automação de alertas, tornando-se um componente indispensável na gestão eficiente da infraestrutura dos seus experts.
Definindo os Requisitos da Biblioteca
Antes de iniciar o desenvolvimento, é essencial estabelecer uma visão clara do que queremos alcançar. Dessa forma, evitamos retrabalho e garantimos que a biblioteca atenderá às reais necessidades de quem irá utilizá-la. Com isso em mente, listei os principais recursos que esta biblioteca de manipulação de logs deve oferecer:
-
Singleton
A biblioteca deve implementar o padrão de projeto Singleton para garantir que todas as instâncias acessem o mesmo objeto de log. Isso assegura consistência na gestão de logs em diferentes partes do código e evita duplicação desnecessária de recursos. No próximo artigo abordarei isso em mais detalhes.
-
Armazenamento em Banco de Dados
Quero que todos os logs sejam armazenados em um banco de dados, permitindo consultas sobre os dados. Esse é um recurso fundamental para analisar históricos, auditorias e até identificar padrões de comportamento.
-
Saídas Diferentes
A biblioteca deve oferecer flexibilidade para exibir logs de várias formas, como:
- Console
- Terminal
- Arquivo
- Banco de Dados
Essa diversidade permite que os logs sejam acessados no formato mais conveniente para cada situação.
-
Níveis de Log
Devemos suportar diferentes níveis de log para classificar mensagens de acordo com sua gravidade. Os níveis incluem:
- DEBUG : Mensagens detalhadas para depuração.
- INFO : Informações gerais sobre o funcionamento do sistema.
- ALERT : Alertas para situações que exigem atenção, mas não são críticas.
- ERROR : Erros que afetam partes do sistema, mas permitem continuidade.
- FATAL : Problemas graves que interrompem a execução do sistema.
-
Formato Personalizado de Log
É importante permitir que o formato das mensagens de log seja customizável. Um exemplo seria:
([{timestamp}] {level} : {origin} {message})
Isso fornece flexibilidade para adaptar a saída às necessidades específicas de cada projeto.
-
Rotação de Log
Para evitar o crescimento descontrolado de arquivos de log, a biblioteca deve implementar um sistema de rotação, salvando logs em arquivos diferentes a cada dia ou após atingirem determinado tamanho.
-
Colunas Dinâmicas de Dados
Um recurso essencial é a capacidade de armazenar metadados dinâmicos em formato JSON. Esses dados podem incluir informações específicas do Expert Advisor no momento em que a mensagem foi registrada, enriquecendo o contexto dos logs.
-
Notificações Automáticas
A biblioteca deve ser capaz de enviar notificações em níveis de gravidade específicos, como FATAL. Esses alertas podem ser enviados por:
- SMS
- Alertas no Terminal
Isso garante que os responsáveis sejam informados imediatamente sobre problemas críticos.
-
Medição de Comprimento de Código
Por fim, é essencial incluir um recurso para medir o comprimento de trechos de código. Isso permitirá identificar gargalos de performance e otimizar processos.
Esses requisitos serão a base para o desenvolvimento desta biblioteca. À medida que avançarmos na implementação, exploraremos como cada funcionalidade será construída e integrada ao todo. Essa abordagem estruturada não apenas ajuda a manter o foco, mas também garante que o produto final seja robusto, flexível e adaptável às necessidades de desenvolvedores de Expert Advisors no ambiente MQL5.
Estruturando a base do projeto
Agora que temos os requisitos bem definidos, o próximo passo é começar a estruturar a base do nosso projeto. A organização correta de arquivos e pastas é crucial para manter o código modular, fácil de entender e de manter. Com isso em mente, vamos começar criando a estrutura inicial de diretórios e arquivos para nossa biblioteca de logs.
O primeiro passo é criar uma nova pasta dentro da pasta Includes, que será responsável por armazenar todos os arquivos relacionados à biblioteca de logs. Para isso, basta clicar com o botão direito na pasta Includes na aba de navegação, como mostrado na imagem, e selecionar a opção “New folder”:
Uma janela aparecerá com as opções para o novo arquivo, selecione a opção “New class” e pressione “Next“, ao fazer isso você verá esta janela:
Preencha os parâmetros, o nome da classe será CLogify, depois alterei o nome do autor e o link, mas esses parâmetros não são relevantes para a classe. No final ficará assim:
//+------------------------------------------------------------------+ //| Logify.mqh | //| joaopedrodev | //| https://www.mql5.com/en/users/joaopedrodev | //+------------------------------------------------------------------+ #property copyright "joaopedrodev" #property link "https://www.mql5.com/en/users/joaopedrodev" #property version "1.00" class CLogify { private: public: CLogify(); ~CLogify(); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CLogify::CLogify() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CLogify::~CLogify() { } //+------------------------------------------------------------------+
Seguindo esse mesmo passo a passo, crie outros dois arquivos:
- LogifyLevel.mqh → Define um enum com os níveis de log que serão utilizados.
- LogifyModel.mqh → Estrutura de dados para armazenar informações detalhadas sobre cada log
No final, teremos esta estrutura de pastas e arquivos:
|--- Logify |--- Logify.mqh |--- LogifyLevel.mqh |--- LogifyModel.mqh
Com a estrutura básica e os arquivos iniciais criados, teremos um esqueleto funcional da biblioteca de logs.
Criando níveis de severidade
Aqui usaremos o arquivo LogifyLevel.mqh, este arquivo define os diferentes níveis de severidade que um log pode ter, encapsulado em uma enumeração. Este é o código do enum que será usado:
enum ENUM_LOG_LEVEL { LOG_LEVEL_DEBUG = 0, // Debug LOG_LEVEL_INFOR, // Infor LOG_LEVEL_ALERT, // Alert LOG_LEVEL_ERROR, // Error LOG_LEVEL_FATAL, // Fatal };
Explicação:
- Enumeração: Cada valor do enum representa um nível de severidade para os logs, variando de LOG_LEVEL_DEBUG (menos severo) até LOG_LEVEL_FATAL (mais severo).
- Usabilidade: Este enum será utilizado para categorizar os logs em diferentes níveis, facilitando o filtro ou ações específicas baseadas na gravidade.
Criando o Modelo de Dados
Agora, vamos criar uma estrutura de dados para armazenar as informações de log que serão manipuladas pela biblioteca. Essa estrutura será armazenada no arquivo LogifyModel.mqh e servirá como base para armazenar todos os logs capturados pelo sistema.
Abaixo está o código de definição da structure MqlLogifyModel, que será responsável por armazenar os dados essenciais de cada entrada de log, como o timestamp (data e hora do evento), a origem (de onde o log foi gerado), a mensagem do log e quaisquer metadados adicionais.
//+------------------------------------------------------------------+ //| LogifyModel.mqh | //| joaopedrodev | //| https://www.mql5.com/en/users/joaopedrodev | //+------------------------------------------------------------------+ #property copyright "joaopedrodev" #property link "https://www.mql5.com/en/users/joaopedrodev" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "LogifyLevel.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ struct MqlLogifyModel { ulong timestamp; // Date and time of the event ENUM_LOG_LEVEL level; // Severity level string origin; // Log source string message; // Log message string metadata; // Additional information in JSON or text MqlLogifyModel::MqlLogifyModel(void) { timestamp = 0; level = LOG_LEVEL_DEBUG; origin = ""; message = ""; metadata = ""; } MqlLogifyModel::MqlLogifyModel(ulong _timestamp,ENUM_LOG_LEVEL _level,string _origin,string _message,string _metadata) { timestamp = _timestamp; level = _level; origin = _origin; message = _message; metadata = _metadata; } }; //+------------------------------------------------------------------+
Explicação da Estrutura de Dados
- timestamp: Um valor ulong que armazena a data e a hora do evento. Esse campo será preenchido com o timestamp do log no momento em que a entrada foi criada.
- level: Nível de severidade da mensagem
- origin: Um campo string que identifica a origem do log. Isso pode ser útil para determinar qual parte do sistema gerou a mensagem de log (por exemplo, o nome do módulo ou função).
- message: A própria mensagem de log, também do tipo string, que descreve o evento ou ação que ocorreu no sistema.
- metadata: Um campo adicional que armazena informações extras sobre o log. Isso pode ser um objeto JSON ou uma simples string de texto que contenha dados adicionais relacionados ao evento. Isso é útil para armazenar informações contextuais, como parâmetros de execução ou dados específicos do sistema.
Construtores:
- O construtor padrão inicializa todos os campos com valores vazios ou zero.
- O construtor parametrizado permite criar uma instância de MqlLogifyModel preenchendo diretamente os campos com valores específicos, como timestamp, origem, mensagem e metadados.
Implementando a Classe Principal CLogify
Agora vamos implementar a classe principal da biblioteca de logs, CLogify, que servirá como núcleo para gerenciar e exibir logs. Essa classe inclui métodos para diferentes níveis de log e um método genérico chamado Append que é utilizado por todos os outros métodos.
A classe será definida no arquivo Logify.mqh e conterá os seguintes métodos:
//+------------------------------------------------------------------+ //| class : CLogify | //| | //| [PROPERTY] | //| Name : Logify | //| Heritage : No heritage | //| Description : Core class for log management. | //| | //+------------------------------------------------------------------+ class CLogify { private: public: CLogify(); ~CLogify(); //--- Generic method for adding logs bool Append(ulong timestamp, ENUM_LOG_LEVEL level, string message, string origin = "", string metadata = ""); //--- Specific methods for each log level bool Debug(string message, string origin = "", string metadata = ""); bool Infor(string message, string origin = "", string metadata = ""); bool Alert(string message, string origin = "", string metadata = ""); bool Error(string message, string origin = "", string metadata = ""); bool Fatal(string message, string origin = "", string metadata = ""); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CLogify::CLogify() { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CLogify::~CLogify() { } //+------------------------------------------------------------------+Os métodos da classe serão implementados para exibir logs no console, utilizando a função Print. Posteriormente, esses logs poderão ser direcionados para outras saídas, como arquivos, bancos de dados ou gráficos.
//+------------------------------------------------------------------+ //| Generic method for adding logs | //+------------------------------------------------------------------+ bool CLogify::Append(ulong timestamp,ENUM_LOG_LEVEL level,string message,string origin="",string metadata="") { MqlLogifyModel model(timestamp,level,origin,message,metadata); string levelStr = ""; switch(level) { case LOGIFY_DEBUG: levelStr = "DEBUG"; break; case LOGIFY_INFO: levelStr = "INFO"; break; case LOGIFY_ALERT: levelStr = "ALERT"; break; case LOGIFY_ERROR: levelStr = "ERROR"; break; case LOGIFY_FATAL: levelStr = "FATAL"; break; } Print("[" + TimeToString(timestamp) + "] [" + levelStr + "] [" + origin + "] - " + message + " " + metadata); return(true); } //+------------------------------------------------------------------+ //| Debug level message | //+------------------------------------------------------------------+ bool CLogify::Debug(string message,string origin="",string metadata="") { return(this.Append(TimeCurrent(),LOG_LEVEL_DEBUG,message,origin,metadata)); } //+------------------------------------------------------------------+ //| Infor level message | //+------------------------------------------------------------------+ bool CLogify::Infor(string message,string origin="",string metadata="") { return(this.Append(TimeCurrent(),LOG_LEVEL_INFOR,message,origin,metadata)); } //+------------------------------------------------------------------+ //| Alert level message | //+------------------------------------------------------------------+ bool CLogify::Alert(string message,string origin="",string metadata="") { return(this.Append(TimeCurrent(),LOG_LEVEL_ALERT,message,origin,metadata)); } //+------------------------------------------------------------------+ //| Error level message | //+------------------------------------------------------------------+ bool CLogify::Error(string message,string origin="",string metadata="") { return(this.Append(TimeCurrent(),LOG_LEVEL_ERROR,message,origin,metadata)); } //+------------------------------------------------------------------+ //| Fatal level message | //+------------------------------------------------------------------+ bool CLogify::Fatal(string message,string origin="",string metadata="") { return(this.Append(TimeCurrent(),LOG_LEVEL_FATAL,message,origin,metadata)); } //+------------------------------------------------------------------+
Agora que temos a estrutura principal e os métodos para exibir logs básicos, o próximo passo será criar testes para garantir que funcionem corretamente. Novamente, adicionaremos suporte para diferentes tipos de saída mais tarde, como arquivos, bancos de dados e gráficos.
Testes
Para realizar testes na biblioteca Logify, criaremos um Expert Advisor dedicado. Primeiro, crie uma nova pasta chamada Logify dentro do diretório experts, que conterá todos os arquivos de teste. Depois, crie o arquivo LogifyTest.mq5 com a estrutura inicial: //+------------------------------------------------------------------+ //| LogifyTest.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+
Inclua o arquivo principal da biblioteca e instancie a classe CLogify:
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include <Logify/Logify.mqh> CLogify logify;
Na função OnInit, adicione chamadas de log para testar todos os níveis disponíveis:
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- logify.Debug("RSI indicator value calculated: 72.56", "Indicators", "Period: 14"); logify.Infor("Buy order sent successfully", "Order Management", "Symbol: EURUSD, Volume: 0.1"); logify.Alert("Stop Loss adjusted to breakeven level", "Risk Management", "Order ID: 12345678"); logify.Error("Failed to send sell order", "Order Management", "Reason: Insufficient balance"); logify.Fatal("Failed to initialize EA: Invalid settings", "Initialization", "Missing or incorrect parameters"); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
Ao executar o código, as mensagens esperadas no terminal do MetaTrader 5 serão exibidas conforme abaixo:
Conclusão
O teste da biblioteca Logify foi realizado com sucesso, exibindo corretamente as mensagens de log para todos os níveis disponíveis. Essa estrutura básica permite um gerenciamento de logs organizado e extensível, fornecendo uma base sólida para melhorias futuras, como integração com bancos de dados, arquivos ou gráficos.
Com uma implementação modular e métodos fáceis de usar, a Logify oferece flexibilidade e clareza no gerenciamento de logs em aplicações MQL5. Os próximos passos podem incluir a criação de saídas alternativas e a adição de configurações dinâmicas para personalizar o comportamento da biblioteca. Até o próximo artigo!
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/16447
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso