Documentation

    Server Side

    ASP.NET Boilerplate uses Castle Windsor's logging facility. It can work with different logging libraries: Log4Net, NLog, Serilog, and more. Castle provides a common interface for all logger libraries. This way, you're independent from a specific logging library and can easily change it later if needed.

    Log4Net is one of the most popular logging libraries for .NET. The ASP.NET Boilerplate templates come with Log4Net properly configured and ready to use. There is just a single-line of code for the dependency to log4net (as seen in the configuration section), so you can easily change it to your favourite library.

    Getting The Logger

    No matter which logging library you choose, the code to write logs is the same (thanks to Castle's common ILogger interface).

    First, we need to get a Logger object to write logs. Since ASP.NET Boilerplate strongly uses dependency injection, we can easily inject a Logger object using the property injection (or constructor injection) pattern. Here's a sample class that writes a log line:

    using Castle.Core.Logging; //1: Import Logging namespace
    
    public class TaskAppService : ITaskAppService
    {    
        //2: Getting a logger using property injection
        public ILogger Logger { get; set; }
    
        public TaskAppService()
        {
            //3: Do not write logs if no Logger supplied.
            Logger = NullLogger.Instance;
        }
    
        public void CreateTask(CreateTaskInput input)
        {
            //4: Write logs
            Logger.Info("Creating a new task with description: " + input.Description);
    
            //TODO: save task to database...
        }
    }
    

    First, we imported the namespace of Castle's ILogger interface.

    Secondly, we defined a public ILogger object named Logger. This is the object we will write logs with. The dependency injection system will set (inject) this property after creating the TaskAppService object. This is known as the property injection pattern.

    Thirdly, we set Logger to NullLogger.Instance. The system will work fine without this line, but it is best practice to use the property injection pattern. If no one sets the Logger, it will be null and we will get an "object reference..." exception when we want to use it. This guarantees that it's not null. So if no one sets the Logger, it will be NullLogger. This is known as the null object pattern. NullLogger actually does nothing. It does not write any logs. This way, our class can work with and without an actual logger.

    Finally, we're writing a log text with the info level. There are different levels (see the configuration section).

    If we call the CreateTask method and check the log file, we see a log line like the one shown below:

    INFO  2014-07-13 13:40:23,360 [8    ] SimpleTaskSystem.Tasks.TaskAppService    - Creating a new task with description: Remember to drink milk before sleeping!
    

    Base Classes With Logger

    ASP.NET Boilerplate provides base classes for MVC controllers, Web API controllers, Application service classes and more. They declare a Logger property. This way, you can directly use this Logger to write logs, with no injection needed. Example:

    public class HomeController : SimpleTaskSystemControllerBase
    {
        public ActionResult Index()
        { 
            Logger.Debug("A sample log message...");
            return View();
        }
    }
    

    Note that SimpleTaskSystemControllerBase is our application specific base controller that inherits AbpController. This way, it can directly use the Logger. You can also write your own common base class for other classes. You will then not have to inject a logger each time.

    Configuration

    All the configuration is done for Log4Net when you create your application from the ASP.NET Boilerplate templates.

    The default configuration's log format is as shown below (for each line):

    • Log level: DEBUG, INFO, WARN, ERROR or FATAL.
    • Date and time: The time when the log line was written.
    • Thread number: The thread number that wrote the log line.
    • Logger name: This is generally the class name which writes the log line.
    • Log text: Actual log text that you write.

    It's defined in the log4net.config file of the application as shown below:

    <?xml version="1.0" encoding="utf-8" ?>
    <log4net>
      <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
        <file value="Logs/Logs.txt" />
        <appendToFile value="true" />
        <rollingStyle value="Size" />
        <maxSizeRollBackups value="10" />
        <maximumFileSize value="10000KB" />
        <staticLogFileName value="true" />
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
        </layout>
      </appender>
      <root>
        <appender-ref ref="RollingFileAppender" />
        <level value="DEBUG" />
      </root>
      <logger name="NHibernate">
        <level value="WARN" />
      </logger>
    </log4net>
    

    Log4Net is highly configurable and is a strong logging library. You can write logs in different formats and to different targets (text file, database...). You can set minimum log levels (as set for NHibernate in this configuration). You can write diffent loggers to different log files. It can automatically backup and create new log file when it reaches to a specific size (Rolling file adapter with 10000 KB per file in this configuration) and so on... Read it's own confuguration documentation for more info.

    Finally, in the Global.asax file, we declare that we use Log4Net with the log4net.config file:

    public class MvcApplication : AbpWebApplication
    {
        protected override void Application_Start(object sender, EventArgs e)
        {
            IocManager.Instance.IocContainer.AddFacility<LoggingFacility>(f => f.UseLog4Net().WithConfig("log4net.config"));
            base.Application_Start(sender, e);
        }
    }
    

    This is the only code line we directly depend on for log4net. Only the web project depends on log4net library's nuget package. You can also easily change to another library without changing your logging code.

    Abp.Castle.Log4Net Package

    ABP uses the Castle Logging Facility for logging and it does not directly depend on log4net, as declared above. There is, however, a problem with Castle's Log4Net integration... It does not support the latest log4net. We created a NuGet package, Abp.Castle.Log4Net, to solve this issue. After adding this package to our solution, all we have to do is to change the code in the application start method like this:

    public class MvcApplication : AbpWebApplication
    {
        protected override void Application_Start(object sender, EventArgs e)
        {
            IocManager.Instance.IocContainer.AddFacility<LoggingFacility>(f => f.UseAbpLog4Net().WithConfig("log4net.config"));
            base.Application_Start(sender, e);
        }
    }
    

    The only difference is that we used the "UseAbpLog4Net()" method (defined in Abp.Castle.Logging.Log4Net namespace) instead of "UseLog4Net()". When we use Abp.Castle.Log4Net package, you do not need to use the Castle.Windsor-log4net and Castle.Core-log4net packages.

    Client-Side

    ASP.NET Boilerplate defines a simple JavaScript logging API for the client side. It logs to the browser's console as default. Here's some JavaScript code to write logs:

    abp.log.warn('a sample log message...');
    

    For more information, see the logging API documentation.