Inloggen in ASP.NET-toepassingen (deel 1...waarschijnlijk) (Nederlands (Dutch))

Inloggen in ASP.NET-toepassingen (deel 1...waarschijnlijk)

Comments

NOTE: Apart from English (and even then it's questionable, I'm Scottish). These are machine translated in languages I don't read. If they're terrible please contact me.
You can see how this translation was done in this article.

Sunday, 27 October 2024

//

11 minute read

Inleiding

Loggen is natuurlijk een cruciaal onderdeel van toepassingen, maar ik zie het vaak verkeerd begrepen / misbruikt in ASP.NET toepassingen. Dit is deel post en deel manifest over hoe effectief in te loggen in ASP.NET toepassingen.

Dit is niet een volledige gids voor het loggen; er is LOTS van degenen die er zijn; het is meer over het kiezen van een effectieve logstrategie voor uw ASP.NET-toepassingen.

In de belangrijkste logging moet nuttig zijn; of het nu is loggen tijdens het ontwikkelen of inloggen in de productie moet nuttig zijn voor u / uw team / uw gebruikers.

Het probleem

Te vaak wordt loggen gezien als het 'alleen doen als er uitzonderingen zijn' ding. Ik denk dat dit verkeerd begrijpt wat houtkap zou moeten zijn.

LOGGEN IS NIET ALLEEN VOOR UITZONDERINGEN

In het algemeen moet u in staat zijn om een belangrijk deel van uw toepassing lokaal; in deze context log.LogInformation is je vriend.

De oplossing

Loggen Succes

Gedurende de 30 jaar heb ik code geschreven Ik heb een paar voorbeelden gezien van goede houtkap en WAY meer voorbeelden van slechte houtkap.

Beginselen van goede houtkap:

  1. Logging in Development moet voldoende informatie geven over hoe uw applicatie draait om te begrijpen wat er gebeurt wanneer.
  2. Loggen in Productie moet u een super snel en eenvoudig mechanisme om te begrijpen hoe uw toepassing mislukt.
  3. Veel te veel inloggen in de productie is een negatief; het kan uw toepassing vertragen en het moeilijker maken om de belangrijke dingen te vinden.

Vergeet niet; loggen sleept altijd je applicatieprestaties naar beneden; je moet inloggen wat je nodig hebt om een probleem te diagnosticeren, maar niet meer in productie / waar prestaties cruciaal zijn (bijv. geen prestatietest uitvoeren bij het gebruik van volledige Debuglogging).

Soorten loggen in ASP.NET

Serilog vs Microsoft.Extensions.logging

In ASP.NET heb je al een ingebouwd logsysteem; Microsoft.Extensions.Logging. Dit is een goed logsysteem, maar niet zo flexibel als Serilog. Serilog is een flexibeler logsysteem waarmee u kunt loggen naar meerdere spoelbakken (outputs) en uw logs kunt verrijken met aanvullende informatie.

BootStrap logging

Dit is de logging die gebeurt wanneer uw applicatie start. Het is het eerste wat er gebeurt, en het is het eerste wat je moet zien als je je aanvraag uitvoert. In ASP.NET vooral wanneer je configuratie gebruikt is het belangrijk dat je begrijpt wat er gebeurt als je applicatie start. Het is een super gemeenschappelijke bron van problemen in ASP.NET toepassingen.

Bijvoorbeeld in Serilog kun je dit doen:

Log.Logger = new LoggerConfiguration()
             .WriteTo.Console()
             .WriteTo.File("logs/boot-*.txt", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7)
             .CreateBootstrapLogger();

OPMERKING: Dit is beperkt omdat je geen toegang hebt tot de configuratie op dit punt, dus bijvoorbeeld om AppInsights te gebruiken heb je waarschijnlijk een #if RELEASE blok om de juiste sleutel in te stellen.

Dit geeft u gegevens over eventuele opstartproblemen in uw toepassing; het schrijft zowel naar console als naar een bestand. Het is ook belangrijk om ervoor te zorgen dat u niet alle logbestanden opslaat; u kunt hier zien dat we slechts 7 dagen aan logs besparen.

U wilt ook uw opstartmethode inpakken (in deze app gebruik ik de nieuwe Program.cs methode) in een poging/vangst en log eventuele uitzonderingen die zich daar voordoen.

try
 {
        ..all your startup code
 }
catch (Exception ex)
{
    if(args.Contains("migrate"))
    {
        Log.Information("Migration complete");
        return;
    }
    Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
    Log.CloseAndFlush();
}

Het Log.CloseAndFlush() is belangrijk omdat het ervoor zorgt dat alle logs naar de schijf worden geschreven (uw app crasht dus anders zal het stoppen voordat het dit doet).

Hier detecteer ik ook of de app draait in een migratiemodus en als dat zo is log ik dat en sluit ik af.

Log.Fatal is het meest ernstige logniveau; het wordt gebruikt wanneer uw toepassing op het punt staat te crashen. Niet alle uitzonderingen zijn dodelijk - u zou moeten gebruiken Log.Error voor degenen (tenzij zij de APP bedoelen (niet het verzoek) kan niet verder gaan dan dat punt).

Logniveaus

In ASP.NET (en.NET Meer in het algemeen) heb je een aantal log niveaus:

  1. Log.Fatal - Dit is het zwaarste logniveau; het wordt gebruikt wanneer uw toepassing op het punt staat te crashen.
  2. Log.Error - Dit wordt gebruikt wanneer er een uitzondering is die betekent dat de APP (niet het verzoek) niet verder kan gaan dan dat punt.
  3. Log.Warning - Dit wordt gebruikt als er iets gebeurt dat geen fout is maar iets waar je je bewust van moet zijn (bijvoorbeeld een gedegradeerde service / iets niet helemaal goed Maar geene dwaling.
  4. Log.Information - Dit wordt gebruikt voor algemene informatie over wat er gebeurt in je applicatie.
  5. Log.Debug - Dit wordt gebruikt voor informatie die alleen nuttig is wanneer u uw applicatie debuggen (het is ALLES in ontwikkeling, maar moet worden uitgeschakeld in de productie).

Voor de productie zou ik over het algemeen de logging instellen op Log.Fatal, Log.Error en Log.Warning Alleen.

Runtime loggen

In tegenstelling tot het opstarten logging dit is de logging die gebeurt wanneer uw toepassing wordt uitgevoerd. Dit is de logging die je vertelt wat er op elk moment in je toepassing gebeurt.

Bijvoorbeeld om deze in Serilog te gebruiken zou je dit doen:

  "Serilog": {
    "Enrich": ["FromLogContext", "WithThreadId", "WithThreadName", "WithProcessId", "WithProcessName", "FromLogContext"],
    "MinimumLevel": "Warning",
    "WriteTo": [
        {
          "Name": "Seq",
          "Args":
          {
            "serverUrl": "http://seq:5341",
            "apiKey": ""
          }
        },
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/applog-.txt",
          "rollingInterval": "Day"
        }
      }

    ],
    "Properties": {
      "ApplicationName": "mostlylucid"
    }
  },

Verrijkt

Zoals je zult zien ben ik een grote fan van Serilog; het is een geweldige houtkap bibliotheek die zeer flexibel is. Een van de dingen die ik graag over het is de mogelijkheid om uw logs te verrijken met aanvullende informatie. Dit kan zeer nuttig zijn bij het diagnosticeren van problemen in uw toepassing. In het bovenstaande voorbeeld zie je dat ik mijn logs verrijkt met de thread-id, thread-naam, proces-id en proces-naam. Dit kan zeer nuttig zijn bij het diagnosticeren van problemen in uw toepassing.

Ik heb ook de logging ingesteld om naar meerdere'sinks' (outputs) te gaan; in dit geval stuur ik het naar de console, naar een bestand en naar Seq (een logging service).

Het hebben van meerdere gootstenen is handig in het geval een faalt, in dit geval mijn voorkeur logging service is Seq, dus ik stuur het er eerst naar toe. Als dat niet lukt, stuur ik het naar de console en naar een bestand.

Ik heb ook de ApplicationName eigenschap in de logs ingesteld; dit kan handig zijn als je meerdere toepassingen hebt die inloggen op dezelfde service (die voor gedistribueerde toepassingen je vaak zult; samen met een correlatie ID om de logs aan elkaar te koppelen voor een enkele aanvraag).

Bijvoorbeeld als je een JS front end en een.NET backend hebt, kun je de correlatie ID aan de voorkant instellen en doorgeven aan de backend. Dit stelt u in staat om alle logs te zien voor een enkele aanvraag op één plaats. OF als u HttpClient in uw backend gebruikt, kunt u het correlatie-ID in de headers doorgeven aan de andere service.

Er is veel aandacht voor hoe je dit hier kunt doen: https://josef.codes/append-correlation-id-to-all-log-entries-in-asp-net-core/ maar ik zal het in een toekomstige post behandelen.

Gestructureerd loggen

Gestructureerde logging is een manier van loggen die het makkelijker maakt om uw logs te zoeken en te filteren. In Serilog kunt u dit doen door gebruik te maken van de Log.Information("This is a log message with {Property1} and {Property2}", property1, property2); syntaxis. Dit maakt het makkelijker om te zoeken naar logs met een bepaalde eigenschap.

Contextueel loggen

Met behulp van Serilog kunt u ook gebruiken LogContext.PushProperty om eigenschappen toe te voegen aan uw logs die alleen relevant zijn voor een bepaalde scope. Dit kan zeer nuttig zijn bij het diagnosticeren van problemen in uw toepassing.

Serilog instellen

Serilog is super flexibel in die zin dat het u toelaat om het te configureren in code en door middel van config. Bijvoorbeeld om de configuratie hierboven te gebruiken zou je dit doen:

builder.Host.UseSerilog((context, services, configuration) =>
{
    configuration
        .MinimumLevel.Warning()
        .Enrich.FromLogContext()
        .Enrich.WithThreadId()
        .Enrich.WithThreadName()
        .Enrich.WithProcessId()
        .Enrich.WithProcessName()
        .WriteTo.Seq("http://seq:5341", apiKey: "")
        .WriteTo.Console()
        .WriteTo.File("logs/applog-.txt", rollingInterval: RollingInterval.Day)
        .Enrich.WithProperty("ApplicationName", "mostlylucid");
});

Dit is hetzelfde als de configuratie hierboven, maar in code. Dit is handig als je je inlogcode wilt instellen; het is echt aan jou hoe je het doet.

Uitzonderingfilters

In ASP.NET kunt u Exception Filters gebruiken om uitzonderingen te vangen en ze te loggen. Dit is een geweldige manier om ervoor te zorgen dat u logt alle uitzonderingen in uw toepassing. Hoe dan ook het is niet een vervanging voor methode niveau loggen; je moet nog steeds loggen op het niveau van de methode, zodat je kunt zien wat er gebeurt in uw toepassing in detail; de Exception filter gewoon laat zien wat er gebeurt zodra de hele aanvraag stack is ontwond en kan vaak erg verwarrend zijn om uit te werken wat er gebeurd is.

Dit veranderde in ASP.NET Core 8 en er is een TON die je kunt gebruiken met deze nieuwe functies.

Bug opnieuw dezelfde principes van toepassing zijn; je moet loggen op het niveau van de methode, zodat u kunt zien wat er gebeurt in uw toepassing in detail; de Exception filters / status handlers gewoon laten zien wat er gebeurt zodra de hele aanvraag stack is ongedaan gemaakt en kan vaak erg verwarrend zijn om uit te werken wat er is gebeurd.

Haal niet alles uit Prod.

Loggen moet geschikt zijn voor het milieu; in Development log je alles in zodat je kunt zien wat er gebeurt op elk punt in je toepassing, maar in Test heb je minder loggen nodig (misschien log Informatie hier) en in Productie heb je nog minder (Waarschuwing en boven).

Het is verleidelijk om alles in productie te nemen, maar het is een slecht idee. Je moet alles inloggen wat je nodig hebt om een probleem te diagnosticeren, maar niet meer. In cloud providers kunt u gemakkelijk worden opgeladen voor de hoeveelheid gegevens die u naar de logservice stuurt, zodat u voorzichtig moet zijn met wat u logt en hoe lang u deze logs bewaart voor (Application Insights slaat logs voor 90 dagen standaard; dit is vaak te lang en zal u kosten voor zolang die loggegevens worden opgeslagen).

Voor een zeer 'actieve' app heb je gewoon geen lange termijn logging van die gegevens nodig; je hebt een goed idee van wat er gebeurt in de app van de laatste dagen van logs.

Aanmelden aanvragen

Eenmaal veel voorkomend probleem zie ik in de productie is loggen mislukte verzoeken; terwijl deze interessant kunnen zijn (niemand wil een 404 / 401) kunnen deze een enorme hoeveelheid gegevens en kan zeer duur zijn om op te slaan. Je moet alleen dingen inloggen. U bent van plan om te repareren, voor een 404 kan het zijn dat dit belangrijk is omdat het een verbroken link in uw applicatie kan aangeven; voor een 401 kan het zijn dat dit belangrijk is omdat het een gebroken authenticatiesysteem kan aangeven.

Hoe dan ook, zoals ik hierboven al zei, deze worden beter behandeld in de code waarin ze werkelijk voorkomen (in het geval van 401); het kan zijn dat deze ook als een Warning of Error in de code die de 401 genereert.

Voor het instellen van Request Logging in Serilog kunt u dit doen:

app.UseSerilogRequestLogging();

Dit zal alle verzoeken inloggen op uw applicatie; het is een geweldige manier om te zien wat er gebeurt in uw toepassing op een hoog niveau; maar opnieuw moet je voorzichtig zijn met wat je logt en hoe lang je deze logs te behouden voor.

Voor Application Insights kunt u nog steeds wilt loggen met behulp van Informatie-niveau als het geeft u de handige User Journey-functie; Dit is een geweldige manier om te zien hoe gebruikers zijn met behulp van uw toepassing en kan zeer nuttig zijn bij het diagnosticeren van problemen; maar nogmaals deze snel rack-up kosten dus je moet voorzichtig zijn met wat je logt en hoe lang u deze logs te behouden voor.

Conclusie

Dus dat is het, een snelle doorloop van hoe in te loggen in ASP.NET toepassingen. Veel van het is een reactie op overijverige, nutteloze logs zie ik in veel productie-toepassingen. In ontwikkeling die je wilt zien hoe de app draait; in productie die je wilt zien hoe de app mislukt. Loggen is te vaak een nutteloos, duur onderdeel van de ontwikkeling van toepassingen. Zoals met alles in software ontwikkeling logging moet worden gericht op de GEBRUIKER; of zijn u / andere ontwikkelaars tijdens het werken aan de app in uw IDE / lokaal of het sorteren van problemen in de productie snel en efficiënt.

logo

©2024 Scott Galloway