Per aggiungere un log al nostro Software possiamo aiutarci col sistema operativo, ad esempio in UNIX e Linux abbiamo Syslog che è molto flessibile e ci semplifica la vita. Nel caso di non potere (o non volere) usare i mezzi forniti dal OS si può pensare di scriversi un proprio sistema di log, come vedremo nel seguito di questo post. Cercheremo di emulare, più o meno, sintassi e funzionamento di Syslog, cercando di realizzare un prodotto semplice ma di qualità, cioè un prodotto professionale, perché noi cerchiamo sempre di essere professionali, magari senza arrivare agli eccessi di professionalità di quello del titolo.
Mi chiamo Log, James Log |
Vediamo l'header file, mylog.h:
Semplice e auto-esplicativo, no? Il nostro prodotto è formato da tre funzioni canoniche (apri, usa, chiudi), e lavora a livelli di gravità (per il momento quattro). Quasi inutile spiegare che, settando un livello, nel logfile appariranno tutti i messaggi di uguale o maggiore gravità del livello selezionato. Il livello NOLOG, poi, è in pratica un flag di disabilitazione che ci permette di avviare l'applicazione senza logfile, per alleggerire l'esecuzione: è scontato che deve essere una disabilitazione vera, cioè la CPU e il sistema di I/O devono veramente lavorare meno senza log attivato.// livelli di mylog #define MYLOG_NOLOG -1 // nessun messaggio di log #define MYLOG_ERROR 0 // condizione di errore #define MYLOG_WARNING 1 // condizione di warning #define MYLOG_DEBUG 2 // messaggi di debug // prototipi globali void myOpenLog(const char *fname, int level); void myLog(int level, const char *format, ...); void myCloseLog();
Vediamo ora l'esempio d'uso, main.c:
Semplice, no? Eseguo un test argomenti con esempio di lancio (usage...), e poi apro, uso, chiudo, esco. Usando una linea di comando del tipo "mylog log.log 1" quale sarà il risultato? Verrà creato un file "log.log" che conterrà le seguenti due linee:#include <stdio.h> #include <stdlib.h> #include "mylog.h" int main(int argc, char* argv[]) { // test argomenti if (argc != 3) { printf("mylog: wrong arguments counts\n"); printf("usage: mylog logfile loglevel [e.g.: mylog log.txt 1]\n"); return EXIT_FAILURE; } // open log: set logfname e loglevel (0=error/1=warning/2=debug; -1=nolog) myOpenLog(argv[1], atoi(argv[2])); // test mylog() myLog(MYLOG_ERROR, "questo è un msg di tipo %d (il livello impostato è %d)", MYLOG_ERROR, atoi(argv[2])); myLog(MYLOG_WARNING, "questo è un msg di tipo %d (il livello impostato è %d)", MYLOG_WARNING, atoi(argv[2])); myLog(MYLOG_DEBUG, "questo è un msg di tipo %d (il livello impostato è %d)", MYLOG_DEBUG, atoi(argv[2])); // close log myCloseLog(); // exit return EXIT_SUCCESS; }
Aggiungiamo dettagli alla specifica: successivi lanci dell'applicazione devono appendere linee al logfile, perché una dote fondamentale di un log è mantenere informazioni dell'accaduto (e se ogni volta resettiamo il file le perdiamo). E se vogliamo ripartire da zero possiamo usare un altro filename oppure cancellare il vecchio logfile prima di eseguire. Un altro dettaglio che si nota è che ci servono, oltre alle nostre scritte di traccia, anche delle informazioni orarie, magari molto precise (nell'esempio ci sono i microsecondi: nella prossima puntata spiegherò il perché).2014-01-18 18:39:33.890271 - questo è un msg di tipo 0 (il livello impostato è 1) 2014-01-18 18:39:33.890407 - questo è un msg di tipo 1 (il livello impostato è 1)
Per oggi abbiamo finito. I più volenterosi potranno, nell'attesa della seconda parte, scrivere una propria implementazione, e poi confrontarla con la mia, ma la mia sarà sicuramente meglio... (si allontana sghignazzando).
Ciao e al prossimo post!
Nessun commento:
Posta un commento