Как записывать журналы из Startup.cs

Для отладки основного приложения .net, которое не работает при запуске, я хотел бы написать журналы из файла startup.cs. У меня есть настройка ведения журнала в файле, который можно использовать в остальной части приложения вне файла startup.cs, но не уверен, как записывать журналы из самого файла startup.cs.

Ответ 1

Это значительно изменилось с выпуском ASP.NET Core 2.0. В ASP.NET Core 2.x ведение журнала создается в компоновщике хоста. Это означает, что протоколирование доступно через DI по умолчанию и может быть внедрено в класс 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");

        // …
    }
}

К сожалению, для ASP.NET Core 3.0 ситуация снова несколько иная. В шаблонах по умолчанию используется HostBuilder (вместо WebHostBuilder), который устанавливает новый универсальный хост, который может размещать множество различных приложений, не ограничиваясь веб-приложениями. Частью этого нового хоста также является удаление второго контейнера внедрения зависимостей, который ранее существовал для веб-хоста. В конечном итоге это означает, что вы не сможете внедрить любые зависимости, кроме IConfiguration в класс Startup. Таким образом, вы не сможете войти во время метода ConfigureServices. Однако вы можете добавить регистратор в метод Configure и войти туда:

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

    // …
}

Если вам абсолютно необходимо войти в ConfigureServices, то вы можете продолжать использовать WebHostBuilder который создаст устаревший WebHost который может внедрить регистратор в класс Startup. Обратите внимание, что вполне вероятно, что веб-хостинг будет удален в будущем. Таким образом, вы должны попытаться найти решение, которое работает для вас без входа в ConfigureServices.

Ответ 2

Вариант 1: Непосредственно используйте журнал (например, Serilog) при запуске -

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

Вывод:

serilog

Чтобы настроить Serilog в приложении asp.net-core, проверьте пакет Serilog.AspNetCore на GitHub.


Вариант 2: Настроить ведение журнала в program.cs как это -

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

host.Run();

Пользователь loggerFactory при запуске, как это -

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

Подробная информация доступна на этой ссылке

Ответ 3

Мне удалось это сделать, статически создав в нем регистратор с Nlog, а затем используйте его в методах запуска.

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

Ответ 4

Основной код:

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 устанавливает консольный логгер по умолчанию.

... настраивает ILoggerFactory для входа в консоль и отладки вывода

Код запуска:

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

Я не мог заставить работать ILogger, но, возможно, потому, что это не контроллер. Больше информации добро пожаловать!

Refs: