web-dev-qa-db-fra.com

Câblage et injection de NLog dans une application console .Net Core

J'ai créé un consommateur/travail que j'aurai à exécuter en tant que processus sur Linux écrit en C #.

Le processus:

  1. Lire un message de RabbitMQ
  2. Apportez des modifications à la base de données
  3. Consigner toutes les erreurs

Toute la documentation sur nlog sur .net core est sur aspnet core. Lorsque j'essaie d'obtenir une implémentation ILogger, elle retourne null.

Voici une exception de câblage et d'utilisation:

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");

    [...]
}

Ne pas confondre avec la variable d'environnement ASPNETCORE_ENVIRONMENT; il sert uniquement à déterminer quels appsettings.json utiliser.

J'ai basé mon code sur cela rapport de problème .

Enfin, ce sont les packages que j'ai actuellement installés.

<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>
14
Matt R

Un exemple minimaliste complet de NLog dans une application console .NET Core 1 (basé sur le référentiel NLog.Extensions.Logging ):

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");

Références:

    <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>
19
Ilya Chumakov

Dans DotNet Core 2, vous pouvez utiliser la classe de démarrage maintenant et nettoyer un peu le code pour ressembler davantage à celui du Web.

Et en bonus, un moyen de démarrer votre application à l'intérieur du conteneur DI en utilisant 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; }
}
3
Piotr Kula