Come implementare un semplice logger in C #

Spesso vorrai registrare eventi o errori man mano che si verificano nella tua applicazione .Net. Per fare ciò, potresti sfruttare uno dei tanti framework di registrazione popolari disponibili, oppure puoi progettare e sviluppare il tuo framework di registrazione. In questo articolo vedremo come possiamo progettare e sviluppare il nostro framework di registrazione con facilità e seguire i passaggi per creare un semplice logger in C #.

Prima di tutto, sarà necessario comprendere gli obiettivi del registro, i vari punti in cui i dati potrebbero essere registrati. Supponiamo di registrare i dati su file flat, un database e il registro eventi. La seguente enumerazione definisce le destinazioni di log che utilizzeremmo in questo semplice framework.

public enum LogTarget

    {

        File, Database, EventLog

    }

Classi logger C #

Il passaggio successivo consiste nel progettare e implementare le classi. Useremo tre classi distinte, vale a dire, FileLoggere DBLogger, EventLoggerper registrare i dati in un file, un database e il registro eventi rispettivamente. Tutte queste classi dovrebbero ereditare la classe base astratta denominata LogBase. Ecco come sono organizzate queste classi.

    public abstract class LogBase

    {

        public abstract void Log(string message);

    }

    public class FileLogger : LogBase

     {

        public string filePath = @”D:\Log.txt”;

        public override void Log(string message)

        {

            using (StreamWriter streamWriter = new StreamWriter(filePath))

            {

                streamWriter.WriteLine(message);

                streamWriter.Close();

            }           

        }

    }

public class DBLogger : LogBase

    {

        string connectionString = string.Empty;

        public override void Log(string message)

        {

            //Code to log data to the database

        }

    }

    public class EventLogger: LogBase

    {

        public override void Log(string message)

        {

            EventLog eventLog = new EventLog(“”);

            eventLog.Source;

            eventLog.WriteEntry(message);

        }

    }                                

Ho lasciato la DBLoggerlezione incompleta. Lascerò a te il compito di inserire il codice appropriato per registrare i tuoi messaggi nel database.

Come si può vedere, tutte e tre le classi - FileLogger, EventLoggere DBLogger- estendere la classe base astratta LogBase. La classe base astratta LogBasedichiara il metodo astratto chiamato Log(). Il Log() metodo accetta una stringa come parametro; questa stringa è ciò che verrà registrato in un file o in un database o nel registro eventi. 

La classe C # LogHelper

Ora creiamo una classe helper che può essere utilizzata per invocare il rispettivo logger in base al parametro passato. Questa classe helper verrà utilizzata per semplificare le chiamate al Log()metodo in ciascuna delle classi logger. Il frammento di codice seguente illustra questa classe di supporto.

public static class LogHelper

    {

        private static LogBase logger = null;

        public static void Log(LogTarget target, string message)

        {

            switch(target)

            {

                case LogTarget.File:

                    logger = new FileLogger();

                    logger.Log(message);

                    break;

                case LogTarget.Database:

                    logger = new DBLogger();

                    logger.Log(message);

                    break;

                case LogTarget.EventLog:

                    logger = new EventLogger();

                    logger.Log(message);

                    break;

                default:

                    return;

            }

        }

    }

Il Log() metodo della LogHelperclasse accetta una stringa e un'istanza LogTargetdell'enumerazione come parametri. Quindi utilizza un switch: casecostrutto per determinare la destinazione in cui verrà registrato il messaggio di testo.

Sincronizzazione delle chiamate al metodo C # Log

Oops! Ci siamo dimenticati di sincronizzare le chiamate ai rispettivi Log()metodi. Per fare ciò, dobbiamo usare la parola chiave lock nel Log()metodo di ciascuna delle classi logger e incorporare il codice appropriato per sincronizzare quei  Log()metodi. Fare riferimento alla LogBaseclasse fornita di seguito. Abbiamo incorporato un membro protetto che verrà utilizzato per applicare il blocco nel Log()metodo di ciascuna delle classi derivate. Ecco le versioni modificate di queste classi.

public abstract class LogBase

    {

        protected readonly object lockObj = new object();

        public abstract void Log(string message);

    }

    public class FileLogger : LogBase

    {

        public string filePath = @”D:\Log.txt”;

        public override void Log(string message)

        {

            lock (lockObj)

            {

                using (StreamWriter streamWriter = new StreamWriter(filePath))

                {

                    streamWriter.WriteLine(message);

                    streamWriter.Close();

                }

            }

        }

    }

    public class EventLogger : LogBase

    {

        public override void Log(string message)

        {

            lock (lockObj)

            {

                EventLog m_EventLog = new EventLog(“”);

                m_EventLog.Source;

                m_EventLog.WriteEntry(message);

            }

        }

    }

    public class DBLogger : LogBase

    {

        string connectionString = string.Empty;

        public override void Log(string message)

        {

            lock (lockObj)

            {

                //Code to log data to the database

            }

        }

    }

È ora possibile chiamare il Log()metodo della LogHelperclasse e passare la destinazione del registro e il messaggio di testo da registrare come parametri.

class Program

    {

        static void Main(string[] args)

        {

            LogHelper.Log(LogTarget.File, “Hello”);

        }

    }

Se è necessario registrare il messaggio di testo in una destinazione di registro diversa, passare semplicemente la destinazione di registro appropriata come parametro al Log()metodo della LogHelperclasse.

Esistono molti modi per migliorare questo framework di registrazione. È possibile implementare l'asincronia e una coda in modo che quando arrivano un gran numero di messaggi, il logger possa elaborare questi messaggi in modo asincrono senza dover bloccare il thread corrente. Potresti anche voler implementare i livelli di criticità dei messaggi, come messaggi informativi, messaggi di avviso, messaggi di errore e così via.