top of page

NLog with ILogger in .Net 6.0 Web API

There are several .Net things that are essential, but, they keep flying under the radar. One of those things is logging.


A few years ago, I was working for a real estate company in UK, remotely from India, of course. We had issues with figuring out where int he 250 step process was a simple process crashing. I had to spend hours and hours debugging the thing. Then, I ended up building a simple logging library of my own. and, we started tracking the issues much faster.


The code is here.

CSharpForStudents/WebApiDotNet6/LoggingDotNet6 at main · Jay-study-nildana/CSharpForStudents

Why NLog?


My lifelong policy is do more with the absolute minimum. I chose NLog because the library has fantastic documentation. It took me only a few minutes to understand how to get the library working with .Net Web API. As a bonus, the documentation was updated to .Net 6.0.


Further, Remember Microsoft already has the excellent ILogger interface. The whole point of using a provider such as NLog, is so that, you can do extra things, like writing to files.


Microsoft does not provide any providers that write to file. However, they do have providers that write to Azure services.


In this demo, I am only looking at writing to a file. I am confident, NLog can be used to write to wherever you want — online service like Azure Application Insights or a local database like SQLite or an online Azure SQL Server. Really, the options are endless.


Setting It Up

You know, by far the most confusing thing about using NLog was the exact Nuget Package to use. It’s probalby just me. Then again, this is my medium publication where I write about feelings and thoughts and despair.


Eventually, I got the right package.

<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />

Logging happens at a higher level. I mean, you start logging even before your run your web api.


So, your Program.cs looks something like this.

using LoggingDotNet6.Helpers;
using NLog;
using NLog.Web;

var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings()
                                                .GetCurrentClassLogger();
logger.Debug("init main");

try
{
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    // your other stuff.
    
    // NLog: Setup NLog for Dependency injection
    builder.Logging.ClearProviders();
    builder.Logging.SetMinimumLevel
                    (Microsoft.Extensions.Logging.LogLevel.Trace);
    builder.Host.UseNLog();
    
    //other classes that need the logger 
    builder.Services.AddTransient<GenericHelper>();
        
        var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    // Other stuff
}
catch (Exception exception)
{
    // NLog: catch setup errors
    logger.Error(exception, "Stopped program because of exception");
    throw;
}
finally
{
    // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
    NLog.LogManager.Shutdown();
}

I want to point out this specific line.

builder.Services.AddTransient<GenericHelper>();

This helps me use the Logger outside the controller. For example, like this.

namespace LoggingDotNet6.Helpers
{
    //I wish to log in places outside the controller
    //for example here.
    public class GenericHelper    
    {
        private readonly ILogger<GenericHelper> _logger;
        public Generic Helper(ILogger<GenericHelper> logger)        
        {
            _logger=logger;
            _logger.LogInformation(1, "GenericHelper has been 
            constructed");        
        }
        publicvoidJustADumbFunctionCall()        
        {
            _logger.LogInformation("JustADumbFunctionCall has been 
            called");        
        }    
    }
}

Now, at this stage, you need to understand that we are banking on dependency injection to kick in. You will be doing this in the API Controller of course.


New to DI? Try one of my DI posts.

Simple Dependency Injection in .Net 6.0 Web API

In my example, I am logging directly from within the controller. I also end up logging outside the controller. This is useful because, ultimately, you want your controller to look sleek and simple. You want to put all your actual code outside the controller.

I mean, you are using Test Driven Development write?


Log Output and Files

In the current example, I am writing all the logs to a simple file. You see, NLog uses a configuration file. It dictates where the logs get written into.

<?xml version="1.0"encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    autoReload="true"
    internalLogLevel="Info"
    internalLogFile="c:\temp\internal-nlog-AspNetCore.txt">
    
        <!--enable asp.net core layout renderers-->
        <extensions>
            <addassembly="NLog.Web.AspNetCore"/>
        </extensions>
        
        <!--the targets to write to-->
        <targets>
            <!--File Target for all log messages with basic details-->
            <target xsi:type="File" name="allfile" fileName="c:\temp\nlog-
                AspNetCore-all-${shortdate}.log"layout="${longdate}|
                ${event-properties:item=EventId_Id:whenEmpty=0}|
                ${level:uppercase=true}|${logger}|${message} 
                ${exception:format=tostring}"/>
        </targets>
        
        <!--rules to map from logger name to target-->
        <rules>
        </rules>
</nlog>

In the above configuration, the log files will be located in ‘C:\temp’ folder.


If all goes well, you will see output which looks something like this.

2022-04-30 14:05:09.5755|1|INFO|LoggingDotNet6.Controllers.SherlockHolmesController|SherlockHolmesController has been constructed   

2022-04-30 14:05:09.5755|0|INFO|LoggingDotNet6.Helpers.GenericHelper|JustADumbFunctionCall has been called   

2022-04-30 14:05:10.6407|1|INFO|LoggingDotNet6.Helpers.GenericHelper|GenericHelper has been constructed   

2022-04-30 14:05:10.6407|1|INFO|LoggingDotNet6.Controllers.SherlockHolmesController|SherlockHolmesController has been constructed   

2022-04-30 14:05:10.6407|0|INFO|LoggingDotNet6.Helpers.GenericHelper|JustADumbFunctionCall has been called   

2022-04-30 14:07:02.1437|1|INFO|LoggingDotNet6.Helpers.GenericHelper|GenericHelper has been constructed   

2022-04-30 14:07:02.1449|1|INFO|LoggingDotNet6.Controllers.SherlockHolmesController|SherlockHolmesController has been constructed   

2022-04-30 14:07:02.1449|0|INFO|LoggingDotNet6.Helpers.GenericHelper|JustADumbFunctionCall has been called   

2022-04-30 14:07:03.0285|1|INFO|LoggingDotNet6.Helpers.GenericHelper|GenericHelper has been constructed   

2022-04-30 14:07:03.0285|1|INFO|LoggingDotNet6.Controllers.SherlockHolmesController|SherlockHolmesController has been constructed   

2022-04-30 14:07:03.0285|0|INFO|LoggingDotNet6.Helpers.GenericHelper|JustADumbFunctionCall has been called 

And, that’s all there is to it.





Source: Medium - Jay


The Tech Platform

www.thetechplatform.com

0 comments
bottom of page