Ricerca di Errori e Registrazione
Introduzione
Ciao, cari lettori!
In questo articolo considereremo diversi modi per trovare errori in Expert Advisor / Script / Indicatori e metodi di logging. Inoltre ti offrirò un piccolo programma per visualizzare i log - LogMon.
Trovare errori è parte integrante della programmazione. Mentre scrivi un nuovo blocco di codice, è necessario verificare se funziona correttamente e non presenta errori logici. È possibile trovare un errore nel programma in tre modi diversi:
- Valutazione del risultato finale
- Debug passo dopo passo
-
Scrittura di passaggi logici nel log
Considera ogni modo.
1. Valutazione del Risultato FinaleCon questo metodo, analizziamo il risultato del lavoro del programma o parte del suo codice. Ad esempio, prendi un codice semplice, che contiene un errore evidente fatto solo per chiarezza:
void OnStart() { //--- int intArray[10]; for(int i=0;i<9;i++) { intArray[i]=i; } Alert(intArray[9]); }
Compila ed esegui e sullo schermo verrà visualizzato "0". Analizzando i risultati ci aspettiamo il numero "9", quindi concludiamo che il nostro programma non funziona come dovrebbe. Questo metodo di ricerca degli errori è comune e non riesce a trovare la posizione dell'errore. Considerando il secondo modo di trovare gli errori, useremo il debug.
2. Debug Passo per PassoQuesto metodo consente di trovare esattamente il luogo in cui la logica del programma è stata violata. In MetaEditor inserisci un punto di interruzione all'interno del ciclo 'for', inizia il debug e aggiungi watch per la variabile i:
Quindi fare clic su "Riprendi il debug" per tutto il tempo in cui consideriamo l'intero processo di lavoro del programma. Vediamo che poiché la variabile "i" ha il valore di "8", usciamo dal ciclo, quindi concludiamo che l'errore è nella riga:
for(int i=0;i<9;i++)
Vale a dire, quando vengono confrontati il valore di i e il numero 9. Correggi la riga "i<9" " a "i<10" o a "i< = 9", controlla i risultati. Otteniamo il numero 9 - esattamente quello che ci aspettavamo. Utilizzando il debug, abbiamo imparato come agisce il programma in fase di esecuzione e siamo stati in grado di risolvere il problema. I contro di questo metodo:
- Non è chiaro dove si sia verificato l'errore, per intuizione.
- È necessario aggiungere variabili all'elenco di controllo e visualizzarle dopo ogni passaggio.
- Questo metodo non è in grado di rilevare errori durante l'esecuzione del programma finito, come il trading EA su account reale o demo.
Infine, considera il terzo modo di trovare gli errori.
3. Scrittura di Passaggi Logici nel LogUtilizzando questo metodo, registriamo i passaggi significativi del nostro programma. Ad esempio: inizializzazione, calcolo dell'indicatore, ecc. Aggiorna il nostro script con una riga di codice. Vale a dire, stamperemo il valore della variabile i su ogni iterazione:
void OnStart() { //--- int intArray[10]; for(int i=0;i<9;i++) { intArray[i]=i; Alert(i); } Alert(intArray[9]); }
Esegui e vedi l'output del registro - numeri "0 1 2 3 4 5 6 7 8 0". Concludi perché può essere così e correggi lo script, proprio come l'ultima volta.
Pro e contro di questo metodo di ricerca degli errori:
- + Non è necessario eseguire il programma passo dopo passo, in modo da risparmiare molto tempo.
- + Spesso è evidente dove si trova l'errore.
- + Puoi continuare a registrare mentre il programma viene eseguito.
- + È possibile salvare il registro per un'analisi e un confronto successivi (ad esempio, quando si scrive in un file. Vedi sotto.).
- - Il codice sorgente cresce di dimensioni grazie all'aggiunta di operatori che scrivono i dati nel log.
-
- Aumento del runtime del programma (principalmente importante per l'ottimizzazione).
Sommario:
Il primo modo per trovare gli errori non può tenere traccia di dove si trova effettivamente l'errore. Lo usiamo principalmente per la sua velocità. Il secondo modo: il debug passo-passo consente di trovare la posizione esatta dell'errore, ma richiede molto tempo. E se scivolerai oltre il blocco di codice desiderato, devi ricominciare tutto da capo.
Infine, il terzo modo: la registrazione dei passaggi logici nel log consente di analizzare rapidamente il lavoro del programma e salvare il risultato. Durante la scrittura degli eventi dei tuoi Expert Advisor / Indicatori / Script nel log, puoi facilmente trovare un errore e non devi cercare le giuste condizioni in cui si verifica un errore e non devi eseguire il debug del tuo programma per ore e ore. Successivamente, considereremo i modi di accedere ai dettagli e confrontarli. Inoltre ti offrirò il modo più conveniente e veloce.
Quando è necessario effettuare il log?
Ecco alcuni motivi per il logging:- Comportamento errato del programma.
- Runtime del programma troppo lungo (ottimizzazione).
- Monitoraggio del runtime (notifiche di stampa delle posizioni di apertura/chiusura, azioni eseguite, ecc.).
- Apprendimento di MQL5, ad esempio - stampa di matrici.
- Controllare gli Expert Advisor prima del campionato, ecc.
Metodi di Logging
Esistono molti modi per scrivere messaggi nel log, ma alcuni sono utilizzati in tutto, mentre altri sono necessari in casi speciali. Ad esempio, l'invio del log via e-mail o tramite ICQ non è sempre necessario.
Ecco l'elenco dei metodi più comuni utilizzati nella programmazione MQL5:
- Utilizzo della funzione Comment()
- Utilizzo della funzione Alert()
- Utilizzo della funzione Print()
- Scrivere il log nel file utilizzando la funzione FileWrite()
Successivamente fornirò esempi di ciascun metodo con codici sorgente e descriverò le caratteristiche di ciascun metodo. Questi codici sorgente sono piuttosto astratti, quindi non andremo lontano dall'essenza.
Utilizzo della Funzione Comment()
void OnStart() { //--- int intArray[10]; for(int i=0;i<10;i++) { intArray[i]=i; Comment("Variable i: ",i); Sleep(5000); } Alert(intArray[9]); }
Quindi, nell'angolo in alto a sinistra vediamo il valore corrente della variabile "i":
In questo modo possiamo monitorare lo stato corrente del programma in esecuzione. Ora i pro ei contro:
- + Puoi vedere immediatamente il valore.
- - Limitazione dell'output.
- - Non è possibile selezionare alcun messaggio particolare.
- - Non vedi il suo lavoro in tutto il runtime, solo lo stato corrente.
- - Metodo relativamente lento.
- - Inadatto per il monitoraggio continuo del lavoro, in quanto è sempre necessario guardare la lettura.
La funzione Comment() è utile per visualizzare lo stato corrente di un Expert Advisor. Ad esempio, "Apri 2 deal" o "acquista lotto GBRUSD: 0,7".
Utilizzo della Funzione Alert()
Questa funzione visualizza i messaggi in una finestra separata con notifica sonora. L'esempio di codice:
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"); }Il risultato dell'esecuzione del codice:
E ora siamo al settimo cielo, tutto è immediatamente evidente anche con il suono. Ma ora i pro e i contro:
- + Tutti i messaggi vengono registrati in modo coerente.
- + Notifica sonora.
- + Tutto è scritto nel file "Terminal_dir\MQL5\Logs\data.txt".
- - Tutti i messaggi provenienti da tutti gli script / Expert Advisor / Indicatori sono scritti in un unico log.
- - Non funziona in Strategy Tester.
- - Quando viene chiamato frequentemente, può bloccare il terminale per un lungo periodo (ad esempio, quando si chiama ogni segno di spunta o quando si stampa l'array in loop).
- - Impossibile raggruppare i messaggi.
- - Visualizzazione scomoda del file di log.
- - Impossibile salvare i messaggi in una cartella diversa dalla cartella dati standard.
Il sesto punto è molto critico nel trading reale, specialmente quando si esegue lo scalping o si modifica lo Stop Loss. Ci sono tanti contro e puoi trovarne altri, ma penso che sia abbastanza.
Utilizzo della Funzione Print()
Questa funzione scrive i messaggi di log in una finestra speciale chiamata "Experts". Ecco il codice:
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"); }
Come puoi vedere, questa funzione è chiamata proprio come la funzione Alert(), ma ora tutti i messaggi vengono scritti senza notifiche nella scheda "Experts" e nel file "Terminal_dir\MQL5\Logs\data.txt". Considera i pro e i contro di questo metodo:
- + Tutti i messaggi vengono registrati in modo coerente.
- + Tutto è scritto nel file "Terminal_dir\MQL5\Logs\data.txt".
- + Adatto per la registrazione continua del lavoro del programma.
- - Tutti i messaggi provenienti da tutti gli script / Expert Advisor / Indicatori sono scritti in un unico log.
- - Impossibile raggruppare i messaggi.
- - Visualizzazione scomoda del file di log.
- - Impossibile salvare i messaggi in una cartella diversa dalla cartella dati standard.
Questo metodo è probabilmente utilizzato dalla maggior parte dei programmatori MQL5, è abbastanza veloce e adatto per un gran numero di record di log.
Scrittura del Log nel File
Considera l'ultimo modo di logging: scrivere messaggi nei file. Questo metodo è molto più complicato di tutti i precedenti, ma con una preparazione adeguata garantisce una buona velocità di scrittura e una comoda visualizzazione del log, nonché delle notifiche. Ecco il codice più semplice per scrivere il log in un file:
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 }
Eseguire e passare alla cartella "Terminal_dir\MQL5\Files" e aprire il file "log.txt" nell'editor di testo. Ecco i contenuti:
Come puoi vedere, l'output è conseguente, nessun messaggio extra, solo quello che abbiamo scritto sul file. Considera i pro e i contro:
- + Veloce.
- + Scrive solo quello che vogliamo.
- + È possibile scrivere messaggi da diversi programmi in file diversi, in modo che ciò escluda l'intersezione dei log.
- - Nessuna notifica di nuovi messaggi nel log.
- - Impossibile distinguere un particolare messaggio o categoria di messaggio.
- - Ci vuole molto tempo per aprire il log, è necessario passare alla cartella e aprire il file.
Sommario:
Tutti i metodi sopra menzionati hanno i loro svantaggi, ma è possibile modificarne alcuni. I primi tre metodi di logging non sono flessibili, quasi da non poter influenzare il loro comportamento. Ma quest'ultimo metodo, Writing Log into File è il più flessibile, possiamo decidere come e quando vengono registrati i messaggi. Se si desidera visualizzare un singolo numero, ovviamente è più facile utilizzare i primi tre metodi. Ma se hai un programma complicato con molti codici, sarà difficile usarlo senza fare il logging.
Nuovo Approccio al Logging
Ora ti dirò e ti mostrerò come puoi migliorare l'accesso a un file e darti il pratico strumento per visualizzare i log. Questa è l'applicazione per Windows, che ho scritto in C ++ e l'ho chiamata LogMon.
Iniziamo con la scrittura della classe, che farà tutta il logging, vale a dire:
- Mantenere la posizione del file, in cui verranno scritte le impostazioni del log e di altre impostazioni del log.
- Creare file di log in base al nome e alla data/ora.
- Convertire i parametri passati in una riga di log.
- Aggiungere tempo al messaggio di log.
- Aggiungi il colore del messaggio.
- Aggiungi categoria di messaggi.
- Memorizza i messaggi nella cache e scrivili una volta per n-secondi o ogni n-messaggi.
Poiché MQL5 è un linguaggio orientato agli oggetti e non differisce significativamente da C ++ nella sua velocità, scriveremo una classe specifica per MQL5. Cominciamo.
Implementazione della Classe di Scrittura del Log nel File
Metteremo la nostra classe in un file di include separato con l'estensione mqh. Ecco la struttura generale della classe.
Ora il codice sorgente della classe con commenti dettagliati:
//+------------------------------------------------------------------+ //| 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 } //+------------------------------------------------------------------+
In MetaEditor creare il file di include (.mqh) e copiare il codice sorgente della classe e salvare con il nome "CLogger.mqh". Ora parliamo di più su ciascun metodo e su come applicare la classe.
Utilizzo della classe CLogger
Per iniziare a registrare i messaggi nel log utilizzando questa classe, dobbiamo includere il file di classe negli Expert Advisor/ Indicatori/Script:
#include <CLogger.mqh>
Successivamente, è necessario creare un oggetto di questa classe:
CLogger logger;
Eseguiremo tutte le azioni con l'oggetto "logger". Ora dobbiamo regolare le impostazioni chiamando il metodo "SetSetting()". In questo metodo dobbiamo passare il nome del progetto e il nome del file. Ci sono anche due parametri facoltativi: il nome della categoria predefinita e la durata della cache (in secondi) durante la quale la cache viene memorizzata prima di essere scritta nel file. Se si specifica zero, tutti i messaggi verranno scritti una sola volta.
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 );
Esempio di chiamata:
logger.SetSetting("MyProject","myLog","Comment",60);
Di conseguenza, i messaggi verranno scritti nel file "Client_Terminal_dir\MQL5\Files\log\log_MyProject\log_myLog_date.txt", la categoria predefinita è "Commento" e la durata della cache è di 60 secondi. Quindi è necessario chiamare il metodo init() per aprire / creare il file di log. L'esempio di chiamata è semplice, in quanto non è necessario passare i parametri:
logger.init();
Questo metodo genera il percorso e il nome del file di log, lo apre e controlla se non supera la dimensione massima. Se la dimensione supera il valore costante impostato in precedenza, viene aperto un altro file e 1 viene concatenato al suo nome. Quindi di nuovo, la dimensione viene controllata fino a quando non viene aperto il file con la dimensione corretta.
Quindi il puntatore viene spostato in posizione alla fine del file. Ora l'oggetto è pronto per scrivere il log. Abbiamo sovrascritto il metodo di scrittura. Grazie a questo possiamo impostare diverse strutture di messaggi, esempio di chiamare il metodo di scrittura e il risultato nel file:
// 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__);
Il file di log conterrà le seguenti righe:
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
Come puoi vedere, tutto è molto semplice. Chiamare il metodo write() con i parametri richiesti ovunque e il messaggio verrà scritto nel file. Alla fine del programma è necessario inserire la chiamata di due metodi: flush() e deinit().
logger.flush(); // Forcibly flush cache to hard disk logger.deinit(); // Close the log file
Ecco un semplice esempio di script che scrive numeri in un ciclo nel log:
//+------------------------------------------------------------------+ //| 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 eseguito in tre secondi e creato 2 file:
Contenuto del file:
E così tutti i 100000 messaggi. Come puoi vedere, tutto funziona abbastanza rapidamente. È possibile modificare questa classe, aggiungere nuove funzionalità o ottimizzarla.
Livello di Output dei Messaggi
Mentre scrivi un programma, devi visualizzare diversi tipi di messaggi:
- Errori critici (il programma non si comporta correttamente)
- Notifiche di errori non critici, operazioni di trading, ecc. (il programma sta riscontrando errori temporanei, o il programma ha effettuato un'azione importante, di cui l'utente deve essere informato)
- Informazioni di debug (contenuto di matrici e variabili e altre informazioni che non sono necessarie nel lavoro reale).
Inoltre è consigliabile essere in grado di regolare quali messaggi si desidera stampare senza modificare il codice sorgente. Implementeremo questo obiettivo come una semplice funzione e non useremo classi e metodi.
Dichiarare il parametro variabile che memorizzerà il livello di output dei messaggi. Maggiore è il numero in variabile, più categorie di messaggi verranno visualizzate. Se si desidera disabilitare completamente l'output dei messaggi, assegnarlo con il valore "-1".
input int dLvl=2;
Di seguito è riportato il codice sorgente della funzione, che deve essere dichiarato dopo aver creato l'oggetto della 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 } }
Ora un esempio: specificare il livello "0" ai messaggi più importanti e qualsiasi numero (in ordine crescente da zero) a quelli più inutili:
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
Facile Visualizzazione dei Log con LogMon
OK, ora abbiamo file di log contenenti migliaia di righe. Ma è piuttosto difficile trovare informazioni in loro. Non sono divisi in categorie e non differiscono l'uno dall'altro. Ho cercato di risolvere questo problema, vale a dire, ho scritto un programma per visualizzare i log generati dalla classe CLogger. Ora ti presenterò brevemente il programma LogMon, che è scritto in C ++ usando WinAPI. A causa di ciò è veloce e di piccole dimensioni. Il programma è assolutamente gratuito.
Per lavorare con il programma è necessario:
- Copialo nella cartella "Client_Terminal_dir\MQL5\Files\" ed eseguilo - in caso di modalità normale.
- Copialo nella cartella "Agents_dir\Agent\MQL5\Files\" ed eseguilo - in caso di test o ottimizzazione.
La finestra principale del programma si presenta così:
La finestra principale contiene la barra degli strumenti e la finestra con la vista ad albero. Per espandere un elemento, fare doppio clic su di esso con il pulsante sinistro del mouse. Cartella nell'elenco - sono i progetti, che si trovano nella cartella "Client_Terminal_dir\MQL\Files\log\". È possibile impostare il nome del progetto nella classe CLogger utilizzando il metodo SetSetting(). I file nell'elenco delle cartelle - sono in realtà i file di log. I messaggi nei file di log sono suddivisi in categorie specificate nel metodo write(). Numeri tra parentesi - sono i numeri di messaggi in quella categoria.
Ora consideriamo i pulsanti sulla barra degli strumenti da sinistra a destra.
Pulsante per eliminare il progetto o il file di log, nonché per reimpostare la visualizzazione ad albero
Quando si preme questo pulsante, viene visualizzata la seguente finestra:
Se si preme il pulsante "Delete and Flush", tutti i thread di scansione di file/cartelle verranno interrotti, la visualizzazione ad albero verrà ripristinata e verrà richiesto di eliminare il file o il progetto selezionato (è sufficiente fare click su un elemento per selezionarlo - non è necessario selezionare la casella di controllo!). Il pulsante "Ripristina" interromperà tutti i thread di scansione di file / cartelle e cancellerà la vista ad albero.
Pulsante per visualizzare la finestra di dialogo "Informazioni"
Mostra brevi informazioni sul programma e sul suo autore.
Pulsante per visualizzare la finestra del programma sempre in alto
Posiziona la finestra del programma sopra tutte le altre finestre.
Pulsante per attivare il monitoraggio dei nuovi messaggi nei file di log
Questo pulsante nasconde la finestra del programma per vassoio e attiva il monitoraggio dei nuovi messaggi nei file di registro. Per selezionare il progetto/file/la categoria che verrà analizzato, selezionare le caselle di controllo accanto agli elementi necessari.
Se si seleziona la casella di controllo accanto alla categoria di messaggi, la notifica verrà attivata su un nuovo messaggio in questo progetto/file/categoria. Se si seleziona la casella di controllo accanto al file, la notifica verrà attivata su un nuovo messaggio in questo file per qualsiasi categoria. Infine, se si seleziona la casella di controllo accanto al progetto, la notifica verrà attivata su un nuovo file di log e sui messaggi in essi.
Monitoraggio
Se è stato attivato il monitoraggio e la finestra del programma è ridotta a icona a tray, quando viene visualizzato un nuovo messaggio negli elementi selezionati, la finestra principale dell'applicazione verrà ingrandita con una notifica sonora. Per disabilitare le notifiche, fare clic in un punto qualsiasi dell'elenco con il pulsante sinistro del mouse. Per interrompere il monitoraggio, fare click sull'icona del programma nella barra delle applicazioni . Per modificare il suono della notifica con il proprio, inserire .wav file con nome "alert.wav" nella stessa cartella con il file eseguibile del programma.
Visualizza Categoria Log
Per visualizzare una categoria specifica è sufficiente fare doppio clic su di essa. Quindi vedrai la finestra di messaggio:
In questa finestra puoi cercare i messaggi, appuntare la finestra sempre in alto e attivare lo scorrimento automatico. Il colore di ogni messaggio viene impostato singolarmente utilizzando il metodo write() della classe CLogger. Lo sfondo del messaggio verrà evidenziato con il colore selezionato.
Quando si fa doppio clic su un messaggio, questo si aprirà in una finestra separata. Sarà utile se il messaggio è troppo lungo e non si adatta alla finestra di dialogo:
Ora hai un pratico strumento per visualizzare e monitorare i file di log. Speriamo che questo programma ti aiuti, mentre sviluppi e usi i programmi MQL5.
Conclusione
La registrazione degli eventi nel tuo programma è molto utile, ti aiuta a identificare gli errori nascosti e rivelare le opportunità per migliorare il tuo programma. In questo articolo ho descritto metodi e programmi per l'accesso più semplice ai file, il monitoraggio e la visualizzazione dei log.
I vostri commenti e suggerimenti saranno apprezzati!
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/150
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso