.Net Core 3.1
Niestety w przypadku ASP.NET Core 3.0 sytuacja jest nieco inna. Domyślne szablony używają HostBuilder
(zamiast WebHostBuilder
), które konfiguruje nowy ogólny host, który może obsługiwać kilka różnych aplikacji, nie ograniczając się do aplikacji internetowych. Częścią tego nowego hosta jest również usunięcie drugiego kontenera iniekcji zależności, który wcześniej istniał dla hosta internetowego. Ostatecznie oznacza to, że nie będziesz w stanie wstrzyknąć IConfiguration
do Startup
klasy żadnych zależności poza . Więc nie będziesz mógł zalogować się podczas ConfigureServices
metody. Możesz jednak wstrzyknąć rejestrator do Configure
metody i zalogować się tam:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILogger<Startup> logger)
{
logger.LogInformation("Configure called");
}
Jeśli absolutnie musisz się zalogować ConfigureServices
, możesz nadal używać programu, WebHostBuilder
który utworzy starszą wersję, WebHost
która może wstrzyknąć rejestrator do Startup
klasy. Pamiętaj, że jest prawdopodobne, że usługodawca hostingowy zostanie usunięty w pewnym momencie w przyszłości. Dlatego powinieneś spróbować znaleźć rozwiązanie, które będzie dla Ciebie odpowiednie, bez konieczności logowania się ConfigureServices
.
.NET Core 2.x
Zmieniło się to znacznie wraz z wydaniem ASP.NET Core 2,0. W ASP.NET Core 2.x rejestrowanie jest tworzone w konstruktorze hosta. Oznacza to, że rejestrowanie jest domyślnie dostępne przez DI i można je wstrzyknąć do Startup
klasy:
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");
}
}
ConfigureServices
uruchomienia rejestrator jeszcze nie istnieje. Więc nie będziesz mógł zalogować się w tym momencie tylko dlatego, że nie ma jeszcze rejestratora. Plusem jest to, że nadal daje to możliwość skonfigurowania rejestratora w ramach,ConfigureServices
ponieważ jest to ten sam kontener DI (co jest w rzeczywistości dobrą rzeczą). - Jeśli absolutnie potrzebujesz rejestrować dane, możesz na przykład zebrać informacje oddzielnie (np. W postaci listy), a następnie wylogować się, gdy tylko rejestrator będzie dostępny..NET 3.1
obecnie mogą logować się wConfigureServices
metodzie bez upadku na plecyWebHostBuilder
. Użyj odpowiedzi poniżej: stackoverflow.com/a/61488490/2877982Startup.cs
(więc otrzymuję błędy kompilatora, gdy zapominam o zależności), zamiast rejestrować tylko niestandardowe zależności. Dlatego muszę rozwiązać te rejestratory. Ale to może być trochę hakerskie, tak.Opcja 1: Bezpośrednio użyj dziennika (np. Serilog) podczas uruchamiania
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"); .... }
Wynik:
Aby skonfigurować Serilog w aplikacji asp.net-core, sprawdź pakiet Serilog.AspNetCore w serwisie GitHub .
Opcja 2: Skonfiguruj logowanie w program.cs w ten sposób-
var host = new WebHostBuilder() .UseKestrel() .ConfigureServices(s => { s.AddSingleton<IFormatter, LowercaseFormatter>(); }) .ConfigureLogging(f => f.AddConsole(LogLevel.Debug)) .UseStartup<Startup>() .Build(); host.Run();
Rejestrator użytkownika Fabryka w starcie w ten sposób-
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."); } }
Pełne informacje dostępne pod tym linkiem
źródło
Zgodnie z .net core 3.1 , możesz utworzyć rejestrator bezpośrednio przy użyciu LogFactory.
var loggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); ILogger logger = loggerFactory.CreateLogger<Startup>(); logger.LogInformation("Example log message");
źródło
ILogger logger = LoggerFactory.Create(builder => builder.AddLog4Net()).CreateLogger<Startup>();
. Jeśli jednak rejestrujesz tylko wyjątki, nie ujawni to nic więcej niż to, co już pojawia się w dzienniku zdarzeń systemu Windows (podczas korzystania z usług IIS).W przypadku .NET Core 3.0 oficjalna dokumentacja ma to do powiedzenia: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.0#create-logs-in-startup
Ale jak mówią w dokumentach, możesz skonfigurować usługę, która zależy od ILogger, więc jeśli napisałeś klasę StartupLogger:
public class StartupLogger { private readonly ILogger _logger; public StartupLogger(ILogger<StartupLogger> logger) { _logger = logger; } public void Log(string message) { _logger.LogInformation(message); } }
Następnie w Startup.ConfigureServices dodaj usługę, a następnie musisz zbudować dostawcę usług, aby uzyskać dostęp do kontenera DI:
public void ConfigureServices(IServiceCollection services) { services.AddSingleton(provider => { var service = provider.GetRequiredService<ILogger<StartupLogger>>(); return new StartupLogger(service); }); var logger = services.BuildServiceProvider().GetRequiredService<StartupLogger>(); logger.Log("Startup.ConfigureServices called"); }
Edycja: to generuje ostrzeżenie kompilatora, w celu debugowania klasy StartUp powinno to być OK, ale nie do produkcji:
źródło
Oficjalnym rozwiązaniem jest obecnie konfiguracja lokalnej LoggerFactory w następujący sposób:
using var loggerFactory = LoggerFactory.Create(builder => { builder.SetMinimumLevel(LogLevel.Information); builder.AddConsole(); builder.AddEventSourceLogger(); }); var logger = loggerFactory.CreateLogger("Startup"); logger.LogInformation("Hello World");
Zobacz też: https://github.com/dotnet/aspnetcore/issues/9337#issuecomment-539859667
źródło
Używam rozwiązania unikającego loggerów firm trzecich implementujących "bufor loggera" z interfejsem ILogger .
public class LoggerBuffered : ILogger { class Entry { public LogLevel _logLevel; public EventId _eventId; public string _message; } LogLevel _minLogLevel; List<Entry> _buffer; public LoggerBuffered(LogLevel minLogLevel) { _minLogLevel = minLogLevel; _buffer = new List<Entry>(); } public IDisposable BeginScope<TState>(TState state) { return null; } public bool IsEnabled(LogLevel logLevel) { return logLevel >= _minLogLevel; } public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) { if (IsEnabled(logLevel)) { var str = formatter(state, exception); _buffer.Add(new Entry { _logLevel = logLevel, _eventId = eventId, _message = str }); } } public void CopyToLogger (ILogger logger) { foreach (var entry in _buffer) { logger.Log(entry._logLevel, entry._eventId, entry._message); } _buffer.Clear(); } }
Użycie w startup.cs jest łatwe, oczywiście po wywołaniu Configure otrzymujesz dane wyjściowe dziennika. Ale lepsze niż nic. :
public class Startup { ILogger _logger; public Startup(IConfiguration configuration, IWebHostEnvironment env) { _logger = new LoggerBuffered(LogLevel.Debug); _logger.LogInformation($"Create Startup {env.ApplicationName} - {env.EnvironmentName}"); } public void ConfigureServices(IServiceCollection services) { _logger.LogInformation("ConfigureServices"); services.AddControllersWithViews(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger) { (_logger as LoggerBuffered).CopyToLogger(logger); _logger = logger; // Replace buffered by "real" logger _logger.LogInformation("Configure"); if (env.IsDevelopment())
źródło
Kod główny:
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 konfiguruje domyślny rejestrator konsoli.
Kod startowy:
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"); }
Nie mogłem uruchomić wtrysku ILoggera, ale może to dlatego, że nie jest to kontroler. Więcej informacji zapraszamy!
Odniesienia:
źródło
Żadna z powyższych odpowiedzi nie zadziałała dla mnie. Używam NLog, a nawet buduję nową usługę ServiceCollection, wywołuję .CreateBuilder () w dowolnej kolekcji usług, tworzę usługę rejestrowania ... nic z tego nie zapisuje w pliku dziennika podczas ConfigureServices.
Problem polega na tym, że rejestrowanie nie jest tak naprawdę rzeczą do czasu skompilowania ServiceCollection i nie jest budowane podczas ConfigureServices.
Zasadniczo chcę (muszę) rejestrować, co się dzieje podczas uruchamiania w metodzie rozszerzenia konfiguracji, ponieważ jedyną warstwą, z którą mam problem, jest PROD, gdzie nie mogę dołączyć debugera.
Rozwiązaniem, które zadziałało, było użycie starej metody .NET Framework NLog:
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
dodano to prawo do klasy metody rozszerzającej i mogłem zapisywać do dziennika („dziennika”) podczas ConfigureServices i później.Nie mam pojęcia, czy to jest dobry pomysł, aby faktycznie udostępnić kod produkcyjny (nie wiem, czy ILogger kontrolowany. na.
źródło
Udało mi się to zrobić, statycznie tworząc rejestrator z Nlog w pliku, a następnie wykorzystując to w ramach metod uruchamiania.
private readonly NLog.Logger _logger = new NLog.LogFactory().GetCurrentClassLogger();
źródło
System.IO.File.Write()
metody.Po prostu użyj poniższej linii, aby zalogować się do Startup.cs
Log.Information("App started.");
źródło