Wire and inject NLog into .NET Core console app

19,041

Solution 1

A complete minimalistic example of NLog in a .NET Core 1 console app (based on NLog.Extensions.Logging repository):

var services = new ServiceCollection();
services.AddLogging();
var provider = services.BuildServiceProvider();

var factory = provider.GetService<ILoggerFactory>();
factory.AddNLog();
factory.ConfigureNLog("nlog.config");

var logger = provider.GetService<ILogger<Program>>();
logger.LogCritical("hello nlog");

References:

    <ItemGroup>
        <PackageReference Include="NLog.Extensions.Logging" Version="1.0.0-rtm-beta5" />
        <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.2" />
        <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.1" />
        <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
    </ItemGroup>

nlog.config:

<?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"
      internalLogFile="internal-nlog.txt">

  <variable name="Layout"
            value="${longdate}|${level:uppercase=true}|${logger}|${message}"/>

  <!-- the targets to write to -->
  <targets>
    <!-- write logs to file -->
    <target xsi:type="File" 
            name="allfile" 
            fileName="nlog-all-${shortdate}.log"
            layout="${Layout}" />

    <!-- write to the void aka just remove -->
    <target xsi:type="Null" name="blackhole" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <!--All logs, including from Microsoft-->
    <logger name="*" minlevel="Trace" writeTo="allfile" />

    <!--Skip Microsoft logs and so log only own logs-->
    <logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" />
  </rules>
</nlog>

Solution 2

In DotNet Core 2 you can use the start up class now and clean up the code a bit to look more like the web one.

And as a bonus a way to start your app inside the DI container using ConsoleApp

Program.cs

static void Main(string[] args)
{
    IServiceCollection services = new ServiceCollection();

    Startup startup = new Startup();
    startup.ConfigureServices(services);

    IServiceProvider serviceProvider = services.BuildServiceProvider();

    // entry to run app
    serviceProvider.GetService<ConsoleApp>().Run();
}

Startup.cs

public class Startup
{
    IConfigurationRoot Configuration { get; }

    public Startup()
    {
        var builder = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

        Configuration = builder.Build();
    }


    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IConfigurationRoot>(Configuration);

        services.AddSingleton<IMyConfiguration, MyConfiguration>();

        services.AddLogging(loggingBuilder => {
           loggingBuilder.AddNLog("nlog.config");
        });

        services.AddTransient<ConsoleApp>();
    }
}

ConsoleApp.cs

public class ConsoleApp
{
    private readonly ILogger<ConsoleApp> _logger;
    private readonly IMyConfiguration _config;

    public ConsoleApp(IMyConfiguration configurationRoot, ILogger<ConsoleApp> logger)
    {
        _logger = logger;
        _config = configurationRoot;
    }


    public void Run()
    {
        var test = _config.YourItem;

        _logger.LogCritical(test);

        System.Console.ReadKey();
    }
}

Configuration.cs

public class MyConfiguration : IMyConfiguration
{

    IConfigurationRoot _configurationRoot;
    public MyConfiguration(IConfigurationRoot configurationRoot)
    {
        _configurationRoot = configurationRoot;
    }

    public string YourItem => _configurationRoot["YourItem"];
}


public interface IMyConfiguration
{
    string YourItem { get; }
}
Share:
19,041
Matt R
Author by

Matt R

Updated on June 15, 2022

Comments

  • Matt R
    Matt R almost 2 years

    I created a consumer/job that I will have running as a process on Linux written in C#.

    The process will:

    1. Read a message from RabbitMQ
    2. Make changes to the database
    3. Log any errors

    All the documentation on NLog about .NET Core are on ASP.NET Core. When I try to get an ILogger implementation, it returns null.

    Here is an except of wiring and usage:

    static void ConfigureServices()
    {
        string environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
    
        var builder = new ConfigurationBuilder()
             .SetBasePath(Path.Combine(AppContext.BaseDirectory))
             .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
             .AddJsonFile($"appsettings.{environment}.json", optional: true);
    
        var services = new ServiceCollection();
    
        Configuration = builder.Build();
    
        [...]
    
        services.AddLogging();
    
        ServiceProvider = services.BuildServiceProvider();
    
        var loggerFactory = ServiceProvider.GetService<ILoggerFactory>();
        loggerFactory.AddNLog();
    }
    
    static void Main(string[] args)
    {
        ConfigureServices();
        
        var logger = ServiceProvider.GetService<NLog.ILogger>();
    
        logger.Debug("Logging");
    
        [...]
    }
    

    Do not be confused with the environment variable ASPNETCORE_ENVIRONMENT; it is used solely to determine which appsettings.json to use.

    I've based my code on this issue report.

    Finally, these are the packages I currently have installed.

    <ItemGroup>
      <PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
      <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.2" />
      <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="1.1.2" />
      <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.2" />
      <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" />
      <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
      <PackageReference Include="NLog" Version="5.0.0-beta09" />
      <PackageReference Include="NLog.Extensions.Logging" Version="1.0.0-rtm-beta5" />
      <PackageReference Include="Npgsql" Version="3.2.4.1" />
      <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="1.1.0" />
    </ItemGroup>