web-dev-qa-db-fra.com

Comment écrire des journaux depuis Startup.cs

Afin de déboguer une application .net principale qui échoue au démarrage, j'aimerais écrire des journaux à partir du fichier startup.cs. J'ai une configuration de journalisation dans le fichier qui peut être utilisée dans le reste de l'application en dehors du fichier startup.cs, mais je ne sais pas comment écrire les journaux à partir du fichier startup.cs lui-même.

50
Mark Redman

Cela a considérablement changé avec la publication d'ASP.NET Core 2.0. Dans ASP.NET Core 2.x, la journalisation est créée dans le générateur Hôte. Cela signifie que la journalisation est disponible par défaut via DI et peut être injectée dans la classe Startup:

public class Startup
{
    private readonly ILogger<Startup> _logger;

    public IConfiguration Configuration { get; }

    public Startup(ILogger<Startup> logger, IConfiguration configuration)
    {
        _logger = logger;
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        _logger.LogInformation("ConfigureServices called");

        // …
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        _logger.LogInformation("Configure called");

        // …
    }
}

Malheureusement, pour ASP.NET Core 3.0, la situation est encore un peu différente. Les modèles par défaut utilisent le HostBuilder (au lieu du WebHostBuilder), qui configure un nouvel hôte générique pouvant héberger un certain nombre d'applications différentes, sans se limiter aux applications Web. Une partie de ce nouvel hôte consiste également à supprimer le deuxième conteneur d'injection de dépendance qui existait auparavant pour l'hôte Web. Cela signifie finalement que vous ne pourrez pas injecter de dépendances autres que le IConfiguration dans la classe Startup. Vous ne pourrez donc pas vous connecter avec la méthode ConfigureServices. Vous pouvez cependant injecter le logger dans la méthode Configure et vous y connecter:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILogger<Startup> logger)
{
    logger.LogInformation("Configure called");

    // …
}

Si vous avez absolument besoin de pour vous connecter dans ConfigureServices, vous pouvez continuer à utiliser le WebHostBuilder qui créera l'héritage. WebHost pouvant injecter le logger dans la classe Startup. Notez qu’il est probable que l’hôte Web sera supprimé à un moment donné. Donc, vous devriez essayer de trouver une solution qui fonctionne pour vous sans avoir à vous connecter dans ConfigureServices.

74
poke

Option 1: Utiliser directement le journal (par exemple, Serilog) lors du démarrage

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        Log.Logger = new LoggerConfiguration()
           .MinimumLevel.Debug()
           .WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "Serilog-{Date}.txt"))
           .CreateLogger();

        Log.Information("Inside Startup ctor");
        ....
    }

    public void ConfigureServices(IServiceCollection services)
    {
        Log.Information("ConfigureServices");
        ....
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        Log.Information("Configure");
        ....
    }

Sortie:

serilog

Pour installer Serilog dans l’application asp.net-core, consultez le package Serilog.AspNetCore sur GitHub .


Option2: Configurez la connexion à program.cs comme ceci-

var Host = new WebHostBuilder()
            .UseKestrel()
            .ConfigureServices(s => {
                s.AddSingleton<IFormatter, LowercaseFormatter>();
            })
            .ConfigureLogging(f => f.AddConsole(LogLevel.Debug))
            .UseStartup<Startup>()
            .Build();

Host.Run();

Utilisateur loggerFactory au démarrage comme ceci-

public class Startup
{
    ILogger _logger;
    IFormatter _formatter;
    public Startup(ILoggerFactory loggerFactory, IFormatter formatter)
    {
        _logger = loggerFactory.CreateLogger<Startup>();
        _formatter = formatter;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        _logger.LogDebug($"Total Services Initially: {services.Count}");

        // register services
        //services.AddSingleton<IFoo, Foo>();
    }

    public void Configure(IApplicationBuilder app, IFormatter formatter)
    {
        // note: can request IFormatter here as well as via constructor
        _logger.LogDebug("Configure() started...");
        app.Run(async (context) => await context.Response.WriteAsync(_formatter.Format("Hi!")));
        _logger.LogDebug("Configure() complete.");
    }
}

Détails complets disponibles sur ce lien

25
Sanket

Code principal:

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

CreateDefaultBuilder configure un consignateur de console par défaut.

... configure ILoggerFactory pour se connecter à la console et déboguer la sortie

Code de démarrage:

using Microsoft.Extensions.Logging;
...
public class Startup
{
    private readonly ILogger _logger;

    public Startup(IConfiguration configuration, ILoggerFactory logFactory)
    {
        _logger = logFactory.CreateLogger<Startup>();
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        _logger.LogInformation("hello stackoverflow");
    }

Je ne pouvais pas faire fonctionner l'injection d'un ILogger, mais c'est peut-être parce que ce n'est pas un contrôleur. Plus d'infos bienvenue!

Refs:

1
Tim Abell

J'ai réussi à le faire en créant de manière statique un enregistreur avec Nlog dans le fichier, puis en l'utilisant dans les méthodes de démarrage.

private readonly NLog.Logger _logger = new NLog.LogFactory().GetCurrentClassLogger();
0
Mark Redman