Recherche d'erreurs et journalisation
Introduction
Bonjour chers lecteurs !
Dans cet article, nous examinerons plusieurs façons de trouver des erreurs dans les Expert Advisors/Scripts/Indicators et les méthodes de connexion Je vais également vous proposer un petit programme pour afficher les fichiers journaux - LogMon.
La recherche d'erreurs fait partie intégrante de la programmation. Lorsque vous écrivez un nouveau bloc de code, il est nécessaire de vérifier s'il fonctionne correctement et ne comporte pas d'erreurs logiques. Vous pouvez trouver une erreur dans votre programme de trois manières différentes :
- Évaluation du résultat final
- Débogage pas à pas
-
Écriture des étapes logiques dans le fichier journal
Examinez chaque façon.
1. Évaluation du résultat finalAvec cette méthode, nous analysons le résultat du travail du programme ou une partie de son code. Par exemple, prenons un code simple, qui contient une erreur évidente faite uniquement par souci de clarté :
void OnStart() { //--- int intArray[10]; for(int i=0;i<9;i++) { intArray[i]=i; } Alert(intArray[9]); }
Compilez et exécutez, et l'écran affichera "0". En analysant les résultats, nous attendons le nombre "9", nous concluons donc que notre programme ne fonctionne pas comme il le devrait. Cette méthode de recherche d'erreurs est courante et ne permet pas de trouver l'emplacement de l'erreur. Examinons la deuxième façon de trouver des erreurs, nous utiliserons le débogage.
2. Débogage étape par étapeCette méthode vous permet de trouver exactement l'endroit où la logique du programme a été enfreinte. Dans MetaEditor, placez un point d'arrêt dans la boucle 'for', commencez le débogage et ajoutez veille pour la variable i :
Cliquez ensuite sur "Reprendre le débogage" tant que nous considérons l'ensemble du processus de travail du programme. Nous constatons que comme la variable "i" a la valeur "8", nous quittons la boucle, nous concluons donc que l'erreur est dans la ligne :
for(int i=0;i<9;i++)
Autrement dit, lorsque la valeur de i et le nombre 9 sont comparés. Fixez la ligne "i<9" " à "i<10" ou à "i<=9", vérifiez les résultats. Nous obtenons le numéro 9 - exactement ce à quoi nous nous attendions. En utilisant le débogage, nous avons appris comment le programme agit lors de son exécution et avons pu résoudre le problème. Les inconvénients de cette méthode :
- On ne sait pas où l'erreur s'est produite, par intuition.
- Vous devez ajouter des variables à la liste de surveillance et les afficher après chaque étape.
- Cette méthode ne peut pas détecter les erreurs lors de l'exécution du programme terminé, telles que le trading EA sur un compte réel ou démo.
Enfin, examinons la troisième façon de trouver des erreurs.
3. Écriture d'étapes logiques dans le journalEn utilisant cette méthode, nous enregistrons les étapes importantes de notre programme. Par exemple : initialisation, conclusion d’un deal, calcul d'indicateur, etc. Mettez à niveau notre script avec une ligne de code. Autrement dit , nous imprimerons la valeur de la variable i à chaque itération :
void OnStart() { //--- int intArray[10]; for(int i=0;i<9;i++) { intArray[i]=i; Alert(i); } Alert(intArray[9]); }
Exécutez et constatez la sortie du journal - nombres "0 1 2 3 4 5 6 7 8 0". Concluez pourquoi il peut en être ainsi et corrigez le script, comme la dernière fois.
Avantages et inconvénients de cette méthode de recherche d'erreurs :
- + Pas besoin d'exécuter le programme étape par étape, ce qui permet de gagner beaucoup de temps.
- + Souvent, il est évident, où se trouve l'erreur.
- + Vous pouvez continuer à vous connecter pendant l'exécution du programme.
- +Vous pouvez enregistrer le journal pour une analyse et une comparaison ultérieures (par exemple, lors de l'écriture dans un fichier. Voir ci-dessous.).
- -- Le code source augmente en taille en raison des opérateurs ajoutés, qui écrivent des données dans le journal.
-
-- Augmentation du temps d'exécution du programme (fondamentalement important pour l'optimisation).
Résumé:
La première façon de trouver des erreurs ne permet pas de localiser l'emplacement réel de l'erreur. Nous l'utilisons principalement pour sa rapidité. La deuxième façon - le débogage étape par étape vous permet de trouver l'emplacement exact de l'erreur, mais cela prend beaucoup de temps. Et si vous dépassez le bloc de code souhaité, vous devez tout recommencer.
Enfin, la troisième façon - l'enregistrement des étapes logiques dans le journal vous permet d'analyser rapidement le travail du programme et de sauvegarder le résultat. Lors de l'écriture des événements de vos Expert Advisors/Indicateurs/Scripts dans le journal, vous pouvez facilement trouver une erreur et vous ne devez pas à rechercher des conditions favorables dans lesquelles une erreur se produit, et vous n'avez pas à déboguer votre programme pendant des heures et des heures. Ensuite, nous examinerons les détails de méthodes de connexion et les comparerons. Je vous proposerai également le moyen le plus pratique et le plus rapide.
Quand devez-vous vous connecter ?
Voici quelques motifs de connexion :- Comportement erroné du programme.
- Durée d'exécution du programme trop longue (optimisation).
- Suivi de l'exécution (impression des notifications de positions d'ouverture/clôture, actions exécutées, etc.).
- Apprendre MQL5, par exemple - imprimer des tableaux.
- Vérification des Expert Advisors avant le championnat, etc.
Méthodes de journalisation
Il existe de nombreuses façons d'écrire des messages dans le journal, mais certaines sont utilisées partout, tandis que d'autres sont nécessaires dans des cas particuliers. Par exemple, l'envoi d’un journal par email ou via ICQ n'est pas toujours nécessaire.
Voici la liste des méthodes les plus couramment utilisées dans la programmation MQL5 :
- Utilisation de la fonction Commenter()
- Utilisation de la fonction Alerte()
- Utilisation de la fonction Imprimer()
- Écrire le journal dans le fichier à l'aide de la fonction FileWrite()
Ensuite, je donnerai des exemples de chaque méthode avec des codes sources et décrirai les caractéristiques de chaque méthode. Ces codes sources sont plutôt abstraits, nous n'irons donc pas loin de l'essence.
Utilisation de la fonction Commenter()
void OnStart() { //--- int intArray[10]; for(int i=0;i<10;i++) { intArray[i]=i; Comment("Variable i: ",i); Sleep(5000); } Alert(intArray[9]); }
Ainsi, dans le coin supérieur gauche, nous voyons la valeur actuelle de la variable "i":
Ainsi, nous pouvons surveiller l'état actuel du programme en cours d'exécution. Maintenant les avantages et les inconvénients :
- + Vous pouvez voir la valeur immédiatement.
- - Restriction de sortie.
- - Vous ne pouvez pas sélectionner un message en particulier.
- - Vous ne voyez pas son travail tout au long de l'exécution, seulement l'état actuel.
- - Méthode relativement lente.
- - Inadaptée à la surveillance continue du travail, car vous devez toujours surveiller la lecture.
La fonction Commenter() est utile pour afficher l'état actuel d'Expert Advisor. Par exemple, « Ouvrir 2 deal » ou « acheter un lot GBRUSD : 0.7".
Utilisation de la fonction Alerte()
Cette fonction affiche les messages dans une fenêtre séparée avec notification sonore. L'exemple de code :
void OnStart() { //--- Alert("Start script"); int intArray[10]; for(int i=0;i<10;i++) { intArray[i]=i; Alert("Variable i:", I); Sleep(1000); } Alert(intArray[9]); Alert("Stop script"); }Le résultat de l'exécution du code :
Et maintenant, nous sommes au septième ciel, tout est immédiatement évident même avec le son. Mais maintenant les avantages et inconvénients :
- + Tous les messages sont enregistrés de manière cohérente.
- +Notification sonore.
- +Tout est écrit dans le fichier "Terminal_dir\MQL5\Logs\data.txt".
- -Tous les messages de tous les scripts/conseillers experts/indicateurs sont écrits dans un seul journal.
- -Ne fonctionne pas dans le Testeur de Stratégie
- -- Lorsqu'il est appelé fréquemment, il peut geler le terminal pendant une longue période (par exemple, lors de l'appel à chaque tick ou lors de l'impression d'un tableau en boucle).
- -Impossible de grouper les messages.
- -Affichage peu pratique du fichier journal.
- -Impossible d'enregistrer les messages dans un dossier différent du dossier de données standard.
Le sixième point est capital dans le trading réel, notamment lors du scalpage ou de la modification d’Arrêt de Perte. Il y a pas mal d'inconvénients et vous pouvez en trouver d'autres, mais je pense que cela suffit.
Utilisation de la fonction Imprimer()
Cette fonction écrit les messages de journal dans une fenêtre spéciale appelée "Experts". Voici le code :
void OnStart() { //--- Print("Старт скрипта"); int intArray[10]; for(int i=0;i<10;i++) { intArray[i]=i; Print("Variable i: ",i); } Print(intArray[9]); Print("Stop script"); }
Comme vous pouvez le constater, cette fonction est appelée comme la fonction Alerte(), mais maintenant tous les messages sont écrits sans notifications dans l'onglet "Experts" et dans le fichier "Terminal_dir\MQL5\Logs\data.txt". Tenez compte des avantages et des inconvénients de cette méthode :
- +Tous les messages sont enregistrés de manière cohérente.
- +Tout est écrit dans le fichier "Terminal_dir\MQL5\Logs\data.txt".
- + Convient pour la journalisation continue du travail du programme.
- -Tous les messages de tous les scripts/conseillers experts/indicateurs sont écrits dans un seul journal.
- -Impossible de grouper les messages.
- -Affichage peu pratique du fichier journal.
- -Impossible d'enregistrer les messages dans un dossier différent du dossier de données standard.
Cette méthode est probablement utilisée par la plupart des programmeurs MQL5, elle est assez rapide et bien adaptée pour un grand nombre d'enregistrements de journaux.
Écriture du journal dans un fichier
Tenez compte de la dernière façon de se connecter - écrire des messages dans des fichiers. Cette méthode est beaucoup plus compliquée que toutes les précédentes, mais avec une bonne préparation assure une bonne vitesse d'écriture et une visualisation confortable du journal, ainsi que des notifications. Voici le code le plus simple pour écrire un journal dans un fichier :
void OnStart() { //--- Open log file int fileHandle=FileOpen("log.txt",FILE_WRITE|FILE_TXT|FILE_SHARE_READ|FILE_UNICODE); FileWrite(fileHandle,"Start script"); int intArray[10]; for(int i=0;i<10;i++) { intArray[i]=i; FileWrite(fileHandle,"Variable i: ",i); // Sleep(1000); } FileWrite(fileHandle,intArray[9]); FileWrite(FileHandle,"Stop script"); FileClose(fileHandle); // close log file }
Exécutez et parcourez jusqu’au dossier "Terminal_dir\MQL5\Files" et ouvrez le fichier "log.txt" dans l'éditeur de texte. Voici le sommaire :
Comme vous pouvez le constater r, la sortie est conséquente, pas de messages supplémentaires, juste ce que nous avons écrit dans le fichier. Tenez compte des avantages et les inconvénients :
- + Rapide.
- +N'écrit que ce que nous souhaitons.
- +Vous pouvez écrire des messages de différents programmes dans différents fichiers, de sorte que cela écarte l'intersection des journaux.
- - Aucune notification de nouveaux messages dans le journal.
- -Impossible de distinguer un message particulier ou une catégorie de message.
- - L'ouverture du journal prend beaucoup de temps, vous devez parcourir jusqu'au dossier et ouvrir le fichier.
Résumé:
Toutes les méthodes mentionnées ci-dessus ont leurs inconvénients, mais vous pouvez en modifier certaines. Les trois premières méthodes de journalisation ne sont pas flexibles, nous ne pouvons presque pas affecter leur comportement. Mais cette dernière méthode, Writing Log into File, est la plus flexible, nous pouvons décider comment et quand les messages sont enregistrés. Si vous souhaitez afficher un seul numéro, il est bien entendu plus simple d'utiliser les trois premières méthodes. Mais si vous avez un programme compliqué avec plusieurs codes, il sera difficile de l'utiliser sans vous connecter.
Nouvelle approche de journalisation
Maintenant, je vais vous dire et vous montrer comment vous pouvez améliorer la connexion à un fichier et vous donner l'outil pratique pour afficher les journaux. C'est l'application pour Windows, que j'ai écrite en C++ et que j'ai baptisée LogMon.
Commençons par écrire la classe, qui assurera toute la journalisation, notamment :
- Conservez l'emplacement du fichier dans lequel le journal et les autres paramètres du journal seront écrits.
- Créez des fichiers journaux en fonction du nom donné et de la date/heure.
- Convertissez les paramètres passés en ligne de log.
- Ajoutez du temps au message de journal.
- Ajouter la couleur du message.
- Ajouter une catégorie de message.
- Mettez les messages en cache et écrivez-les une fois toutes les n secondes ou tous les n messages.
Puisque MQL5 est un langage orienté-objet et ne diffère considérablement pas du C++ par sa vitesse, nous écrirons une classe spécifiquement pour MQL5. Commençons.
Implémentation de la classe d'écriture du journal dans le fichier
Nous mettrons notre classe dans un fichier d'inclusion séparé avec l'extension mqh. Voici la structure générale de la classe.
Maintenant le code source de la classe avec des commentaires détaillés :
//+------------------------------------------------------------------+ //| Clogger.mqh | //| ProF | //| http:// | //+------------------------------------------------------------------+ #property copyright "ProF" #property link "http://" // Max size of cache (quantity) #define MAX_CACHE_SIZE 10000 // Max file size in megabytes #define MAX_FILE_SIZEMB 10 //+------------------------------------------------------------------+ //| Logger | //+------------------------------------------------------------------+ class CLogger { private: string project,file; // Name of project and log file string logCache[MAX_CACHE_SIZE]; // Cache max size int sizeCache; // Cache counter int cacheTimeLimit; // Caching time datetime cacheTime; // Time of cache last flush into file int handleFile; // Handle of log file string defCategory; // Default category void writeLog(string log_msg); // Writing message into log or file, and flushing cache public: void CLogger(void){cacheTimeLimit=0; cacheTime=0; sizeCache=0;}; // Constructor void ~CLogger(void){}; // Destructor void SetSetting(string project,string file_name, string default_category="",int cache_time_limit=0); // Settings void init(); // Initialization, open file for writing void deinit(); // Deinitialization, closing file void write(string msg,string category=""); // Generating message void write(string msg,string category,color colorOfMsg,string file="",int line=0); // Generating message void write(string msg,string category,uchar red,uchar green,uchar blue, string file="",int line=0); // Generating message void flush(void); // Flushing cache into file }; //+------------------------------------------------------------------+ //| Settings | //+------------------------------------------------------------------+ void CLogger::SetSetting(string project_name,string file_name, string default_category="",int cache_time_limit=0) { project=project_name; // Project name file=file_name; // File name cacheTimeLimit=cache_time_limit; // Caching time if(default_category=="") // Setting default category { defCategory="Comment"; } else {defCategory = default_category;} } //+------------------------------------------------------------------+ //| Initialization | //+------------------------------------------------------------------+ void CLogger::init(void) { string path; MqlDateTime date; int i=0; TimeToStruct(TimeCurrent(),date); // Get current time StringConcatenate(path,"log\\log_",project,"\\log_",file,"_", date.year,date.mon,date.day); // Generate path and file name handleFile=FileOpen(path+".txt",FILE_WRITE|FILE_READ| FILE_UNICODE|FILE_TXT|FILE_SHARE_READ); // Open or create new file while(FileSize(handleFile)>(MAX_FILE_SIZEMB*1000000)) // Check file size { // Open or create new log file i++; FileClose(handleFile); handleFile=FileOpen(path+"_"+(string)i+".txt", FILE_WRITE|FILE_READ|FILE_UNICODE|FILE_TXT|FILE_SHARE_READ); } FileSeek(handleFile,0,SEEK_END); // Set pointer to the end of file } //+------------------------------------------------------------------+ //| Deinitialization | //+------------------------------------------------------------------+ void CLogger::deinit(void) { FileClose(handleFile); // Close file } //+------------------------------------------------------------------+ //| Write message into file or cache | //+------------------------------------------------------------------+ void CLogger::writeLog(string log_msg) { if(cacheTimeLimit!=0) // Check if cache is enabled { if((sizeCache<MAX_CACHE_SIZE-1 && TimeCurrent()-cacheTime<cacheTimeLimit) || sizeCache==0) // Check if cache time is out or if cache limit is reached { // Write message into cache logCache[sizeCache++]=log_msg; } else { // Write message into cache and flush cache into file logCache[sizeCache++]=log_msg; flush(); } } else { // Cache is disabled, immediately write into file FileWrite(handleFile,log_msg); } if(FileTell(handleFile)>(MAX_FILE_SIZEMB*1000000)) // Check current file size { // File size exceeds allowed limit, close current file and open new deinit(); init(); } } //+------------------------------------------------------------------+ //| Generate message and write into log | //+------------------------------------------------------------------+ void CLogger::write(string msg,string category="") { string msg_log; if(category=="") // Check if passed category exists { category=defCategory; } // Set default category // Generate line and call method of writing message StringConcatenate(msg_log,category,":|:",TimeToString(TimeCurrent(),TIME_SECONDS)," ",msg); writeLog(msg_log); } //+------------------------------------------------------------------+ //| Generate message and write into log | //+------------------------------------------------------------------+ void CLogger::write(string msg,string category,color colorOfMsg,string file="",int line=0) { string msg_log; int red,green,blue; red=(colorOfMsg &Red); // Select red color from constant green=(colorOfMsg &0x00FF00)>>8; // Select green color from constant blue=(colorOfMsg &Blue)>>16; // Select blue color from constant // Check if file or line are passed, generate line and call method of writing message if(file!="" && line!=0) { StringConcatenate(msg_log,category,":|:",red,",",green,",",blue, ":|:",TimeToString(TimeCurrent(),TIME_SECONDS)," ", "file: ",file," line: ",line," ",msg); } else { StringConcatenate(msg_log,category,":|:",red,",",green,",",blue, ":|:",TimeToString(TimeCurrent(),TIME_SECONDS)," ",msg); } writeLog(msg_log); } //+------------------------------------------------------------------+ //| Generate message and write into log | //+------------------------------------------------------------------+ void CLogger::write(string msg,string category,uchar red,uchar green,uchar blue,string file="",int line=0) { string msg_log; // Check if file or line are passed, generate line and call method of writing message if(file!="" && line!=0) { StringConcatenate(msg_log,category,":|:",red,",",green,",",blue, ":|:",TimeToString(TimeCurrent(),TIME_SECONDS)," ", "file: ",file," line: ",line," ",msg); } else { StringConcatenate(msg_log,category,":|:",red,",",green,",",blue, ":|:",TimeToString(TimeCurrent(),TIME_SECONDS)," ",msg); } writeLog(msg_log); } //+------------------------------------------------------------------+ //| Flush cache into file | //+------------------------------------------------------------------+ void CLogger::flush(void) { for(int i=0;i<sizeCache;i++) // In loop write all messages into file { FileWrite(handleFile,logCache[i]); } sizeCache=0; // Reset cache counter cacheTime=TimeCurrent(); // Set time of reseting cache } //+------------------------------------------------------------------+
Dans MetaEditor, créez le fichier d'inclusion (.mqh), copiez le code source de la classe et sauvegardez-le sous le nom "CLogger.mqh". Évoquons maintenant chaque méthode et de la façon d'appliquer la classe.
Utilisation de la classe CLogger
Pour commencer l’enregistrement des messages dans le journal à l'aide de cette classe, nous devons inclure le fichier de classe dans Expert Advisor/Indicator/Script :
#include <CLogger.mqh>
Ensuite, vous devez créer un objet de cette classe :
CLogger logger;
Nous mènerons toutes les actions avec l'objet "logger". Nous devons maintenant régler les paramètres en appelant la méthode "SetSetting()". Dans cette méthode, nous devons passer le nom du projet et le nom du fichier. Il existe également deux paramètres facultatifs : le nom de la catégorie par défaut et la durée de vie du cache (en secondes) pendant laquelle le cache est stocké avant d'être écrit dans le fichier. Si vous indiquez zéro, tous les messages seront écrits une fois.
SetSetting(string project, // Project name string file_name, // Log file name string default_category="", // Default category int cache_time_limit=0 // Cache lifetime in seconds );
Exemple d'appel :
logger.SetSetting("MyProject","myLog","Comment",60);
En conséquence, les messages seront écrits dans le fichier "Client_Terminal_dir\MQL5\Files\log\log_MyProject\log_myLog_date.txt", la catégorie par défaut est "Comment" et la durée de vie du cache est de 60 secondes. Ensuite, vous devez appeler la méthode init() pour ouvrir/créer un fichier journal. L'exemple d'appel est simple, car vous n'avez pas besoin de passer de paramètres :
logger.init();
Cette méthode génère le chemin et le nom du fichier journal, l'ouvre et vérifie s'il ne dépasse pas la taille maximale. Si la taille dépasse la valeur constante précédemment définie, un autre fichier est ouvert et 1 est enchaîné à son nom. Ensuite encore, la taille est vérifiée jusqu'à ce que le fichier avec la taille correcte soit ouvert.
Ensuite, le pointeur est déplacé pour se positionner à la fin du fichier. L'objet est maintenant prêt à écrire le journal. Nous avons remplacé la méthode d'écriture. Grâce à cela, nous pouvons définir différentes structures de messages, exemple d'appel de la méthode d'écriture et le résultat dans le fichier :
// Write message with default caegory logger.write("Test message"); // Write message with "Errors" category logger.write("Test message", "Errors"); // Write message with "Errors" category, that will be highlighted with red color in LogMon logger.write("Test message", "Errors",Red); // Write message with "Errors" category, that will be highlighted with red color in LogMon // Also message will contain current file name and current line logger.write("Test message", "Errors",Red,__FILE__,__LINE__); // Write message with "Errors" category, that will be highlighted with GreenYellow color in LogMon // But now we specify each color independently as: red, green, blue. 0-black, 255 - white logger.write("Test message", "Errors",173,255,47); // Write message with "Errors" category, that will be highlighted with GreenYellow color in LogMon // But now we specify each color independently as: red, green, blue. 0-black, 255 - white // Also message will contain current file name and current line logger.write("Test message", "Errors",173,255,47,__FILE__,__LINE__);
Le fichier journal contiendra les lignes suivantes :
Comment:|:23:13:12 Test message Errors:|:23:13:12 Test message Errors:|:255,0,0:|:23:13:12 Test message Errors:|:255,0,0:|:23:13:12 file: testLogger.mq5 line: 27 Test message Errors:|:173,255,47:|:23:13:12 Test message Errors:|:173,255,47:|:23:13:12 file: testLogger.mq5 line: 29 Test message
Comme vous pouvez le voir, tout est très simple. Appelez la méthode write() avec les paramètres requis n'importe où et le message sera écrit dans le fichier. A la fin de votre programme, vous devez insérer l'appel de deux méthodes - flush() et deinit().
logger.flush(); // Forcibly flush cache to hard disk logger.deinit(); // Close the log file
Voici un exemple simple de script qui écrit des nombres en boucle dans le journal :
//+------------------------------------------------------------------+ //| testLogger.mq5 | //| ProF | //| http:// | //+------------------------------------------------------------------+ #property copyright "ProF" #property link "http://" #property version "1.00" #include <Сlogger.mqh> CLogger logger; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- logger.SetSetting("proj","lfile"); // Settings logger.init(); // Initialization logger.write("Start script","system"); for(int i=0;i<100000;i++) // Write 100000 messages to the log { logger.write("log: "+(string)i,"Comment",100,222,100,__FILE__,__LINE__); } logger.write("Stop script","system"); logger.flush(); // Flush buffer logger.deinit(); // Deinitialization } //+------------------------------------------------------------------+
Script exécuté en trois secondes et créé 2 fichiers :
Contenu du fichier :
Et donc tous les 100000 messages. Comme vous pouvez le constater, tout fonctionne assez rapidement. Vous pouvez modifier cette classe, ajouter de nouvelles fonctionnalités ou l'optimiser.
Niveau de sortie des messages
Au fur et à mesure que vous écrivez un programme, vous devez afficher plusieurs types de messages :
- Erreurs critiques (le programme ne se comporte pas correctement)
- Notifications d'erreurs non critiques, d'opérations de trading, etc. (le programme connaît des erreurs temporaires ou le programme a effectué une action importante, dont l'utilisateur doit être informé)
- Informations de débogage (contenu des tableaux et des variables, et autres informations qui ne sont pas nécessaires dans le travail réel).
Il est également souhaitable de pouvoir ajuster les messages que vous souhaitez imprimer sans changer le code source. Nous implémenterons cet objectif en tant que fonction simple et n'utiliserons pas de classes et méthodes.
Déclarez le paramètre variable qui stockera le niveau de sortie des messages. Plus le nombre de variable est grand, plus de catégories de messages seront affichées. Si vous souhaitez désactiver complètement la sortie des messages, attribuez-lui la valeur "-1".
input int dLvl=2;
Ci-dessous se trouve le code source de la fonction, qui doit être déclaré après la création de l'objet de la classe CLogger.
void debug(string debugMsg, // Message text int lvl ) // Message level { if (lvl<=dLvl) // Compare message level with level of messages output { if (lvl==0) // If message is critical (level = 0) {logger.write(debugMsg,"",Red);} // mark it with red color else {logger.write(debugMsg);} // Else print it with default color } }
Maintenant un exemple : Indiquez le niveau "0" aux messages les plus importants, et n'importe quel nombre (par ordre croissant de zéro) aux plus inutiles :
debug("Error in Expert Advisor!",0); // Critical error debug("Stop-Loss execution",1); // Notification int i = 99; debug("Variable i:"+(string)i,2); // Debugging information, variable contents
Affichage facile des journaux à l'aide de LogMon
OK, maintenant nous avons des fichiers journaux contenant des milliers de lignes. Mais il est assez difficile d'y trouver des informations. Ils ne sont pas divisés en catégories et ne diffèrent pas les uns des autres. J'ai essayé de résoudre ce problème, autrement dit, j'ai écrit un programme pour afficher les journaux générés par la classe CLogger. Maintenant, je vais vous présenter brièvement le programme LogMon, qui est écrit en C++ à l'aide de WinAPI. Pour cette raison, il est rapide et de petite taille. Le programme est totalement gratuit.
Pour travailler avec le programme, vous devez :
- Copiez-le dans le dossier "Client_Terminal_dir\MQL5\Files\" et exécutez-le - en cas de mode normal.
- Copiez-le dans le dossier "Agents_dir\Agent\MQL5\Files\" et exécutez-le - en cas de test ou d'optimisation.
La fenêtre principale du programme ressemble à ceci :
La fenêtre principale contient la barre d'outils et la fenêtre avec vue arborescente. Pour étendre un élément, double-cliquez dessus avec le bouton gauche de la souris. Dossier dans la liste - sont les projets, situés dans le dossier "Client_Terminal_dir\MQL\Files\log\". Vous définissez le nom du projet dans la classe CLogger à l'aide de la méthode SetSetting(). Les fichiers dans la liste des dossiers - sont en fait les fichiers journaux. Les messages dans les fichiers journaux sont divisés en catégories que vous avez indiquées dans la méthode write(). Les nombres entre parenthèses - sont les nombres de messages dans cette catégorie.
Examinons ,à présent, les boutons de la barre d'outils de gauche à droite.
Bouton pour supprimer le projet ou le fichier journal, ainsi que pour réinitialiser la vue arborescente
Lorsque vous appuyez sur ce bouton, la fenêtre suivante apparaît :
Si vous appuyez sur le bouton "Supprimer et vider", tous les threads d'analyse des fichiers/dossiers seront interrompus, la vue arborescente sera réinitialisée et vous serez appelé à supprimer le fichier ou le projet sélectionné (cliquez simplement sur un élément pour le sélectionner - vous n’avez pas besoin de cocher la case !). Le bouton "Réinitialiser" arrêtera tous les threads d'analyse des fichiers/dossiers et effacera la vue arborescente.
Bouton pour afficher la boîte de dialogue "À propos"
Affiche de brèves informations sur le programme et son auteur.
Bouton pour afficher la fenêtre du programme toujours en haut
Place la fenêtre du programme au-dessus de toutes les autres fenêtres.
Bouton pour activer la surveillance des nouveaux messages dans les fichiers journaux
Ce bouton masque la fenêtre du programme dans la d'état système et active la surveillance des nouveaux messages dans les fichiers journaux. Pour sélectionner le projet/fichier/catégorie qui sera analysé, cochez les cases prés des éléments nécessaires.
Si vous cochez la case prés de la catégorie de messages, la notification se déclenchera sur un nouveau message dans ce projet/fichier/catégorie. Si vous cochez la case près du fichier, la notification se déclenchera sur un nouveau message dans ce fichier pour n'importe quelle catégorie. Enfin, si vous cochez la case prés du projet, la notification se déclenchera sur un nouveau fichier journal et les messages qu'il contient.
Surveillance
Si vous avez activé la surveillance et que la fenêtre du programme est réduite à la barre des tâches, lorsqu'un nouveau message apparaît dans les éléments sélectionnés, la fenêtre principale de l'application sera agrandie avec une notification sonore. Pour désactiver les notifications, cliquez n'importe où dans la liste avec le bouton gauche de la souris. Pour interrompre la surveillance, cliquez sur l'icône du programme dans la barre Pour modifier le son de la notification à la vôtre, placez le fichier .wav avec le nom "alert.wav" dans le même dossier que le fichier exécutable du programme.
Afficher la catégorie du journal
Pour afficher une catégorie spécifique, double-cliquez simplement dessus. Ensuite, vous verrez la boîte de message :
Dans cette fenêtre, vous pouvez rechercher des messages, épingler la fenêtre toujours en haut et basculer le défilement automatique. La couleur de chaque message est définie individuellement à l'aide de la méthode write() Clogger Class. L'arrière-plan du message sera mis en évidence avec la couleur sélectionnée.
Lorsque vous double-cliquez sur un message, il s'ouvre dans une fenêtre séparée. Ce sera pratique si le message est trop long et ne rentre pas dans la boîte de dialogue :
Vous disposez maintenant d'un outil pratique pour afficher et surveiller les fichiers journaux. Espérons que ce programme vous aidera à élaborer et à utiliser des programmes MQL5.
Conclusion
La collecte de données des événements dans votre programme est très utile, elle vous aide à identifier les erreurs cachées et à révéler les opportunités d'amélioration de votre programme. Dans cet article, j'ai décrit des méthodes et des programmes pour la connexion la plus simple au fichier, la surveillance et la visualisation des journaux.
Vos commentaires et suggestions seront appréciés!
Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/150
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation