Um eine .net-Kern-App zu debuggen, die beim Start fehlschlägt, möchte ich Protokolle aus der Datei startup.cs schreiben. Ich habe ein Protokollierungssetup in der Datei, das im Rest der App außerhalb der Datei startup.cs verwendet werden kann, bin mir jedoch nicht sicher, wie Protokolle aus der Datei startup.cs selbst geschrieben werden sollen.
Leider ist die Situation für ASP.NET Core 3.0 wieder etwas anders. Die Standardvorlagen verwenden den HostBuilder(anstelle des WebHostBuilder), der einen neuen generischen Host einrichtet, der mehrere verschiedene Anwendungen hosten kann, nicht nur Webanwendungen. Teil dieses neuen Hosts ist auch das Entfernen des zweiten Abhängigkeitsinjektionscontainers, der zuvor für den Webhost vorhanden war. Dies bedeutet letztendlich, dass Sie keine Abhängigkeiten außer der IConfigurationin die StartupKlasse einfügen können . Sie können sich also während der ConfigureServicesMethode nicht anmelden . Sie können den Logger jedoch in die ConfigureMethode einfügen und dort protokollieren:
Wenn Sie unbedingt brauchen innerhalb anmelden ConfigureServices, dann können Sie auch weiterhin die verwenden , WebHostBuilderdie das Vermächtnis wird erstellen , WebHostdie den Logger in die injizieren StartupKlasse. Beachten Sie, dass der Webhost wahrscheinlich zu einem späteren Zeitpunkt entfernt wird. Sie sollten also versuchen, eine Lösung zu finden, die für Sie funktioniert, ohne sich anmelden zu müssen ConfigureServices.
.NET Core 2.x.
Dies hat sich mit der Veröffentlichung von ASP.NET Core 2.0 erheblich geändert. In ASP.NET Core 2.x wird die Protokollierung beim Host Builder erstellt. Dies bedeutet, dass die Protokollierung standardmäßig über DI verfügbar ist und in die StartupKlasse eingefügt werden kann :
DANKE. Es ist erstaunlich, wie viel Zeit Sie verbrennen können, um Antworten auf einfache Fragen zu finden. @poke Vielen Dank (noch einmal), dass Sie mich über meine Optionen informiert haben. Woher haben Sie diese Informationen? Ich habe bestätigt, dass ich Dinge in Configure protokollieren kann, was einem Stich (Wortspiel beabsichtigt) mit einem scharfen Stock vorzuziehen ist, aber vielleicht nicht so großartig, wie es bei ConfigureServices möglich ist. In meinem Fall möchte ich protokollieren, ob ich env-Einstellungen habe oder nicht, vielleicht sogar im Protokoll veröffentlichen. Kein Würfel? Seufz ... nicht sicher, warum das so schwer sein sollte. Aber zumindest weiß ich dank dieses Beitrags, was ich kann und was nicht.
Wellspring
2
@Wellspring In 3.0 ist es „schwer“, da ConfigureServicesder Logger zum Zeitpunkt der Ausführung noch nicht vorhanden ist. Sie können sich zu diesem Zeitpunkt also nicht einfach anmelden, da noch kein Protokollierer vorhanden ist. Auf der positiven Seite gibt Ihnen dies immer noch die Möglichkeit, den Logger innerhalb des zu konfigurieren, ConfigureServicesda es sich um denselben DI-Container handelt (was eigentlich eine gute Sache ist). - Wenn Sie unbedingt Daten protokollieren müssen, können Sie die Informationen beispielsweise separat sammeln (z. B. in einer Liste) und diese dann abmelden, sobald der Protokollierer verfügbar ist.
Poke
Verstanden, @poke - aber wenn Sie versuchen, etwas zu debuggen, das beim Start passiert (z. B. Umgebungsvariablen, die auf mysteriöse Weise nicht richtig eingehen ConfiguringServices?), Wäre es sicher schön, protokollieren zu können, was los ist! Übrigens habe ich das im Wesentlichen getan - Dinge nachträglich im ConfigureCode protokolliert .
Wellspring
@ Wellspring Ja, ich verstehe den Anwendungsfall vollkommen. Ich habe mich auch für eine Möglichkeit ausgesprochen, Dinge während des Startvorgangs zu protokollieren, aber leider gibt es keine wirklich gute Möglichkeit, dies zu tun, wenn Sie den Logger über DI konfigurieren möchten, aber auch mehrere DI-Container vermeiden möchten.
stupsen
1
@Aage Dies hat jedoch mehrere Nachteile: Sie müssen Ihre vollständige Protokollierungskonfiguration wiederholen, die Protokollierungskonfiguration spiegelt auch nicht Ihre Anwendungskonfiguration wider (z. B. in Appsettings usw. konfigurierte Protokollebenen), und Sie richten im Allgemeinen eine zweite Protokollierungsinfrastruktur ein. Ich würde Ihnen dennoch empfehlen, nach einer Lösung zu suchen, wie Sie die Protokollierung während des DI-Setups insgesamt vermeiden können.
stecken
36
Option 1: Verwenden Sie das Protokoll (z. B. Serilog) direkt beim Start.
Das Schreiben von Protokollen vor Abschluss des DI-Container-Setups in der Startup.ConfigureServices-Methode wird nicht unterstützt:
Die Logger-Injection in den Startup-Konstruktor wird nicht unterstützt.
Die Logger-Injektion in die Signatur der Startup.ConfigureServices-Methode wird nicht unterstützt
Aber wie in den Dokumenten angegeben, können Sie einen Dienst konfigurieren, der von ILogger abhängt. Wenn Sie also eine Klasse StartupLogger geschrieben haben:
Fügen Sie dann in Startup.ConfigureServices den Dienst hinzu. Anschließend müssen Sie den Dienstanbieter erstellen, um Zugriff auf den DI-Container zu erhalten:
Bearbeiten: Dies erzeugt eine Compiler-Warnung. Zum Debuggen Ihrer StartUp-Klasse sollte dies in Ordnung sein, jedoch nicht für die Produktion:
Startup.cs(39,32):[ASP0000]Calling'BuildServiceProvider'from application code results in an additional copy of singleton services being created.Consider alternatives such as dependency injecting services as parameters to 'Configure'.
... konfiguriert die ILoggerFactory so, dass sie sich an der Konsole anmeldet und die Ausgabe debuggt
Startcode:
using Microsoft.Extensions.Logging;...publicclassStartup{privatereadonlyILogger _logger;publicStartup(IConfiguration configuration,ILoggerFactory logFactory){
_logger = logFactory.CreateLogger<Startup>();Configuration= configuration;}publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollection services){
_logger.LogInformation("hello stackoverflow");}
Ich konnte die Injektion eines ILoggers nicht zum Laufen bringen, aber vielleicht liegt das daran, dass es kein Controller ist. Weitere Infos willkommen!
Keine der oben genannten Antworten hat bei mir funktioniert. Ich verwende NLog und erstelle sogar eine neue ServiceCollection, rufe .CreateBuilder () für eine beliebige Service-Sammlung auf, erstelle einen Protokollierungsdienst ... nichts davon würde während ConfigureServices in eine Protokolldatei schreiben.
Das Problem ist, dass die Protokollierung erst nach dem Erstellen der SericeCollection erfolgt und erst während ConfigureServices erstellt wird.
Grundsätzlich möchte (muss) ich nur protokollieren, was während des Starts in einer Konfigurationserweiterungsmethode vor sich geht, da die einzige Ebene, auf der ich ein Problem habe, PROD ist, bei der ich keinen Debugger anhängen kann.
Die Lösung, die für mich funktioniert hat, war die Verwendung der alten .NET Framework NLog-Methode: Dieses
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
Recht wurde der Erweiterungsmethodenklasse hinzugefügt, und ich konnte während ConfigureServices und danach in ein Protokoll ("das" Protokoll) schreiben.
Ich habe keine Ahnung, ob dies eine gute Idee ist, um tatsächlich in Produktionscode zu veröffentlichen (ich weiß nicht, ob der .NET-gesteuerte ILogger und dieser NLog.ILogger zu irgendeinem Zeitpunkt Konflikte verursachen werden), aber ich brauchte ihn nur, um zu sehen, was los war auf.
Während dies funktioniert, würde ich empfehlen, die Standardschnittstellen, die mit ASP.NET Core und Dependency Injection (DI) geliefert werden - entweder integriert oder von Drittanbietern - für die Protokollierung zu verwenden. Durch die Verwendung von Schnittstellen können Sie a) die bereitgestellte Protokollierung bei Bedarf ersetzen und b) sie leichter verspotten, wenn Sie Klassen (z. B. Controller) testen, in die Sie ILogger <TController> als Dienst einfügen.
Manfred
Ich habe das gerade zum ersten Mal gesehen, nachdem ich meine eigene Antwort auf genau das Gleiche veröffentlicht hatte. @Manfred gibt es einfach keinen anderen Weg, der funktioniert. Ich denke anders als System.IO.File.Write()Methoden.
emery.noel
-2
Verwenden Sie einfach die folgende Zeile, um sich bei Startup.cs anzumelden
ConfigureServices
der Logger zum Zeitpunkt der Ausführung noch nicht vorhanden ist. Sie können sich zu diesem Zeitpunkt also nicht einfach anmelden, da noch kein Protokollierer vorhanden ist. Auf der positiven Seite gibt Ihnen dies immer noch die Möglichkeit, den Logger innerhalb des zu konfigurieren,ConfigureServices
da es sich um denselben DI-Container handelt (was eigentlich eine gute Sache ist). - Wenn Sie unbedingt Daten protokollieren müssen, können Sie die Informationen beispielsweise separat sammeln (z. B. in einer Liste) und diese dann abmelden, sobald der Protokollierer verfügbar ist.ConfiguringServices
?), Wäre es sicher schön, protokollieren zu können, was los ist! Übrigens habe ich das im Wesentlichen getan - Dinge nachträglich imConfigure
Code protokolliert .Option 1: Verwenden Sie das Protokoll (z. B. Serilog) direkt beim Start.
Ausgabe:
Informationen zum Einrichten von Serilog in der asp.net-core-Anwendung finden Sie im Serilog.AspNetCore-Paket auf GitHub .
Option 2: Konfigurieren Sie die Anmeldung in program.cs wie folgt:
Benutzer loggerFactory beim Start wie folgt:
Vollständige Details finden Sie unter diesem Link
quelle
Für .NET Core 3.0 haben die offiziellen Dokumente Folgendes zu sagen: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.0#create-logs-in-the- Startklasse
Aber wie in den Dokumenten angegeben, können Sie einen Dienst konfigurieren, der von ILogger abhängt. Wenn Sie also eine Klasse StartupLogger geschrieben haben:
Fügen Sie dann in Startup.ConfigureServices den Dienst hinzu. Anschließend müssen Sie den Dienstanbieter erstellen, um Zugriff auf den DI-Container zu erhalten:
Bearbeiten: Dies erzeugt eine Compiler-Warnung. Zum Debuggen Ihrer StartUp-Klasse sollte dies in Ordnung sein, jedoch nicht für die Produktion:
quelle
Ich verwende eine Lösung, die verhindert, dass Logger von Drittanbietern einen "Logger-Puffer" mit ILogger- Schnittstelle implementieren.
Die Verwendung in startup.cs ist einfach. Natürlich erhalten Sie nach dem Aufruf von Configure eine Protokollausgabe. Aber besser als nichts. ::
quelle
Gemäß .net Core 3.1 können Sie einen Logger direkt mit LogFactory erstellen.
quelle
Die offizielle Lösung besteht derzeit darin, eine lokale LoggerFactory wie folgt einzurichten:
Siehe auch: https://github.com/dotnet/aspnetcore/issues/9337#issuecomment-539859667
quelle
Haupt code:
CreateDefaultBuilder richtet einen Standard-Konsolenlogger ein.
Startcode:
Ich konnte die Injektion eines ILoggers nicht zum Laufen bringen, aber vielleicht liegt das daran, dass es kein Controller ist. Weitere Infos willkommen!
Refs:
quelle
Keine der oben genannten Antworten hat bei mir funktioniert. Ich verwende NLog und erstelle sogar eine neue ServiceCollection, rufe .CreateBuilder () für eine beliebige Service-Sammlung auf, erstelle einen Protokollierungsdienst ... nichts davon würde während ConfigureServices in eine Protokolldatei schreiben.
Das Problem ist, dass die Protokollierung erst nach dem Erstellen der SericeCollection erfolgt und erst während ConfigureServices erstellt wird.
Grundsätzlich möchte (muss) ich nur protokollieren, was während des Starts in einer Konfigurationserweiterungsmethode vor sich geht, da die einzige Ebene, auf der ich ein Problem habe, PROD ist, bei der ich keinen Debugger anhängen kann.
Die Lösung, die für mich funktioniert hat, war die Verwendung der alten .NET Framework NLog-Methode: Dieses
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
Recht wurde der Erweiterungsmethodenklasse hinzugefügt, und ich konnte während ConfigureServices und danach in ein Protokoll ("das" Protokoll) schreiben.Ich habe keine Ahnung, ob dies eine gute Idee ist, um tatsächlich in Produktionscode zu veröffentlichen (ich weiß nicht, ob der .NET-gesteuerte ILogger und dieser NLog.ILogger zu irgendeinem Zeitpunkt Konflikte verursachen werden), aber ich brauchte ihn nur, um zu sehen, was los war auf.
quelle
Ich habe es geschafft, indem ich statisch einen Logger mit Nlog in der Datei erstellt und diesen dann innerhalb der Startmethoden verwendet habe.
quelle
System.IO.File.Write()
Methoden.Verwenden Sie einfach die folgende Zeile, um sich bei Startup.cs anzumelden
quelle