yeasir007

Tuesday, October 23, 2018

How to implement log manager for C# WPF application

Why Logger Needed: 


 

Indexing log data is one of the finest ways of observing the deployed application. It will assist the developer to figure out the potential area when the problem will arise. According to the Twelve-Factor-App Should be treated as an event stream. There are several prevalent logging frameworks for the .NetFramework to assist the developer which also provides configuration options that can be modified in any environment, from development to production without any hassle.

Logging Frameworks:

In this post, I'll implement Log4Net in WPF application.

Steps to follow:

  • è Create your application

·         Go to NuGet package manager

·         Select Manage NuGet Packages for Solution

·         Select log4net by Apache Software

  1. è Add a config file for your application and renamed as you wish.(Like ApplicationPackages.config)

 

Add package id, version, and targetFramework under <packages> a tag like a bellow.


<?xml version="1.0" encoding="utf-8" ?>
<packages>
     <package id="log4net" version="2.0.10" targetFramework="net472" />  
</packages>


Now implement your log file handler like where your log will be saved or the size of the log and other pieces of stuff. For more details check this link


using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using System;

namespace MyGitHubProject.LogManagers
{
   public class LogHandler
   {
    private static bool isSetupLogHandler;

    public LogHandler()
    {
        isSetupLogHandler = false;
    }
    ~LogHandler()
    {

    }

    public static void Configure()
    {
        if (isSetupLogHandler)
            return;
        isSetupLogHandler = true;

        Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();

        PatternLayout patternLayout = new PatternLayout();
        patternLayout.ConversionPattern = "%date [%thread] %-5level %logger - %message%newline";
        patternLayout.ActivateOptions();

        RollingFileAppender roller = new RollingFileAppender();
        roller.AppendToFile = true;
        roller.File = Environment.ExpandEnvironmentVariables(@"%AppData%\MyGitHubProject\UseRegistryInWPF\UseRegistryInWPFLog.txt");
        roller.Layout = patternLayout;
        roller.MaxSizeRollBackups = 20;
        roller.MaximumFileSize = "20MB";
        roller.RollingStyle = RollingFileAppender.RollingMode.Size;
        roller.StaticLogFileName = true;
        roller.ActivateOptions();
        hierarchy.Root.AddAppender(roller);

        MemoryAppender memory = new MemoryAppender();
        memory.ActivateOptions();
        hierarchy.Root.AddAppender(memory);

        hierarchy.Root.Level = Level.Info;
        hierarchy.Configured = true;
    }
  }
 }

è

      Now initialize your Log manger in App.xml.cs class and create your customized method for the record the log     files.


    private static readonly ILog Log = LogManager.GetLogger(typeof(App));

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        try
        {
            ConfigureLoggerManager();

            //Checking commandline argument in WPF application
            string commandLineArg = e.Args.Length == 1 ? e.Args[0].ToString() : "";
        }
        catch (Exception ex)
        {
            App.Log.Info( Enum.GetName( typeof( LogLevel ), LogLevel.FATAL ), ex );
            Shutdown();
        }
    }


    private void ConfigureLoggerManager()
    {
        LogHandler.Configure(); //Configure log4net 
        LOG("****************** Start My Application Logging  **********************");

        AppDomain.CurrentDomain.UnhandledException +=
        (sender, args) =>
        {
            LOG(LogLevel.FATAL, $"Exception from all threads in the AppDomain : {args.ExceptionObject}");
        };

        Dispatcher.UnhandledException +=
        (sender, args) =>
        {
            LOG(LogLevel.FATAL, $"Exception from a single specific UI dispatcher thread : {args.Exception}");
        };

        Application.Current.DispatcherUnhandledException +=
        (sender, args) =>
        {
            LOG(LogLevel.FATAL, $"Exception from the main UI dispatcher thread in WPF application : {args.Exception}");
        };

        TaskScheduler.UnobservedTaskException +=
        (sender, args) =>
        {
            LOG(LogLevel.FATAL, $"Exception from within each AppDomain that uses a task scheduler for asynchronous operations. : {args.Exception}");
        };
    }

    /// <summary>
    /// Record app maintaing log
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="lineNumber"></param>
    /// <param name="caller"></param>
    public static void LOG(string msg, [CallerLineNumber] int lineNumber = 0, [CallerMemberName] string caller = null)
    {
        Log.Info($"{caller} {lineNumber} : {msg}");
    }

    /// <summary>
    /// Record app maintaing log
    /// </summary>
    /// <param name="logLevel"></param>
    /// <param name="msg"></param>
    /// <param name="lineNumber"></param>
    /// <param name="caller"></param>
    public static void LOG(LogLevel logLevel, string msg, [CallerLineNumber] int lineNumber = 0, [CallerMemberName] string caller = null)
    {
        string message = String.Empty;

        switch (logLevel)
        {
            case LogLevel.ERROR:
                message = "### ERROR ###";
                break;
            case LogLevel.DEBUG:
                message = "### DEBUG ###";
                break;
            case LogLevel.FATAL:
                message = "### FATAL ###";
                break;
            case LogLevel.INFO:
                message = "### INFO ###";
                break;
            case LogLevel.TRACE:
                message = "### TRACE ###";
                break;
            case LogLevel.WARN:
                message = "### WARN ###";
                break;
            default:
               evel == LogLevel.DEBUG)
        {
            Console.WriteLine(message);
        }                

        Log.Info(message);
    }

    /// <summary>
    /// Override OnExit to dispose other contoller classes if needed
    /// </summary>
    protected override void OnExit(ExitEventArgs e)
    {
        LOG(LogLevel.TRACE, "App exit has been called.");
        base.OnExit(e);
    }

        N.B: For any help please comments below. 

        Happy coding  :)



No comments:

Post a Comment

Thanks for your comments