Tags

, , ,

In my ASP.NET MVC app I tend to use ELMAH as my logging provider; yet, Quartz.NET comes out of the box with support for NLog, Log4Net, and System.Diagnostic.Trace. In order for Quartz.NET to use ELMAH to log, we must implement two very simple classes based on the Common.Logging documentation which I’ve taken the time to paste below:

if you want to plug in a new, yet unsupported logging library, you need to provide a logger factory adapter that implementes the Common.Logging.ILoggerFactoryAdapter interface. Loggers must implement the Common.Logging.ILog interface.

Important: Any implementation must provide a public constructor accepting a NameValueCollection parameter as shown in the example below:

public class MyLoggingFactoryAdapter :  ILoggerFactoryAdapter
{
  public MyLoggingFactoryAdapter(NameValueCollection properties)
  {
    // configure according to properties
  }

  public ILog GetLogger(Type type) { ... }

  public ILog GetLogger(string name) { ... }
}

For convenience, Common.Logging comes with an abstract base class Common.Logging.Factory.AbstractCachingLoggerFactoryAdapter for easier implemention of factory adapters andCommon.Logging.Factory.AbstractLogger for implementing loggers.

Implementing our integration module begins with the provisionning of a new class library.  I call mine WoroArch.Web.Logging simply because for my Desktop apps I simply wraps Log4Net inside an Adapter that implements our logging interface.  That being said, WoroArch.Web.Logging is a class library that uses NuGet to reference Common.Logging and ELMAH. 

image

Next, Create a class marked as Serializable that implements Common.Logging.Simple.AbstractSimpleLogger found in Common.Logging.dll.

 

using System;
using System.Text;
using Common.Logging;

namespace WoroArch.Web.Logging
{
    [Serializable]
    class ElmahLogger : Common.Logging.Simple.AbstractSimpleLogger
    {
        public ElmahLogger(string logName, LogLevel logLevel, bool showlevel, bool showDateTime, bool showLogName, string dateTimeFormat) 
            : base(logName, logLevel, showlevel, showDateTime, showLogName, dateTimeFormat)
        {
        }

        protected override void WriteInternal(LogLevel level, object message, Exception exception)
        {
            var stringBuilder = new StringBuilder();
            FormatOutput(stringBuilder, level, message, exception);
            Elmah.ErrorSignal.FromCurrentContext().Raise(new AggregateException(stringBuilder.ToString(), exception));
        }
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Afterward,  create a factory class that implements LoggerFactoryAdapter and provide your AbstractSimpleLogger instance as the concrete ILog.  Watch how this implementation is marked as being publicly accessible.  It must be so to be used within web.config.

 

using Common.Logging;
using Common.Logging.Configuration;
using Common.Logging.Simple;

namespace WoroArch.Web.Logging
{
    public class ElmahLoggerFactoryAdapter : AbstractSimpleLoggerFactoryAdapter
    {
        public ElmahLoggerFactoryAdapter(NameValueCollection properties) : base(properties)
        {
        }

        public ElmahLoggerFactoryAdapter(LogLevel level, bool showDateTime, bool showLogName, bool showLevel, string dateTimeFormat) : base(level, showDateTime, showLogName, showLevel, dateTimeFormat)
        {
        }

        protected override ILog CreateLogger(string name, LogLevel level, bool showLevel, bool showDateTime, bool showLogName,
            string dateTimeFormat)
        {
            return  new ElmahLogger(name,level,showLevel,showDateTime,showLogName,dateTimeFormat);
        }
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Compile your project to generate its dll and add a reference to it inside your ASP.NET project.

image

configure your web.config file to use your provider to get access to a concrete instance of ILog.

image

Quartz.NET should now log to Elmah

Advertisements