Wiring and injected NLog into a .Net Core console application

匿名 (未验证) 提交于 2019-12-03 08:36:05

问题:

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 aspnet 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> 

回答1:

Complete minimalistic example of NLog usage in a .NET Core 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> 


回答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.AddSingleton(new LoggerFactory()                 .AddNLog()                 .ConfigureNLog("nlog.config")                 );          services.AddLogging();          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; } } 


回答3:

My solution is to use an adapter pattern that uses Console.Writeline, until a more sane version of NLog becomes available.

using System; public static class Log {     public static void Write(string message)     {         Console.WriteLine($"{DateTime.Now}: {message}");     } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!