Sul logging in applicazioni ASP.NET (Parte 1...probabilmente) (Italiano (Italian))

Sul logging in applicazioni ASP.NET (Parte 1...probabilmente)

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

//

Less than a minute

Introduzione

La registrazione è di corso una parte critica delle applicazioni, tuttavia spesso lo vedo frainteso / abusato nelle applicazioni ASP.NET. Questo è parte post e parte manifesto su come effettuare il login in ASP.NET Applicazioni.

Questa non è una guida completa per la registrazione; c'è LOTS di quelli là fuori; è più sulla scelta di una strategia di registrazione efficace per le vostre applicazioni ASP.NET.

Nella registrazione principale dovrebbe essere utile; che si tratti di registrazione durante lo sviluppo o l'accesso alla produzione dovrebbe essere utile per voi / il vostro team / i vostri utenti.

Il problema

Troppo spesso la registrazione è vista come la cosa 'fallo solo quando ci sono eccezioni'. Penso che questo fraintenda quale registrazione dovrebbe essere.

L'accesso non è solo per le eccezioni

In generale, si dovrebbe essere in grado di eseguire una parte significativa della vostra applicazione a livello locale; in questo contesto log.LogInformation E' tuo amico.

La soluzione

Registrazione di successo

Nel corso dei 30 anni ho scritto codice Ho visto alcuni esempi di buona registrazione e WAY più esempi di scarsa registrazione.

Principi di buona registrazione:

  1. Accedi allo sviluppo dovrebbe fornire informazioni sufficienti su come la tua applicazione è in esecuzione per capire cosa sta accadendo quando.
  2. L'accesso alla produzione dovrebbe darvi un meccanismo super veloce e facile per capire come la vostra applicazione fallisce.
  3. Troppo la registrazione nella produzione è un negativo; può rallentare l'applicazione e rendere più difficile trovare la roba importante.

Ricorda; la registrazione SEMPRE trascina giù le prestazioni dell'applicazione; dovresti registrare quello che ti serve per diagnosticare un problema ma non più in produzione / dove le prestazioni sono critiche (ad esempio, non eseguire un test di performance quando si utilizza Debug Logging completo).

Tipi di registrazione in ASP.NET

Serilog vs Microsoft.Estensioni.Logging

In ASP.NET hai già una build in logging System; Microsoft.Extensions.Logging. Questo è un buon sistema di registrazione, ma non è flessibile come Serilog. Serilog è un sistema di registrazione più flessibile che consente di accedere a più lavandini (output) e arricchire i registri con ulteriori informazioni.

BootStrap Logging

Questa è la registrazione che accade quando l'applicazione si avvia. È la prima cosa che accade, ed è la prima cosa che si dovrebbe vedere quando si esegue la domanda. In ASP.NET soprattutto quando si utilizza la configurazione è fondamentale capire cosa sta accadendo quando l'applicazione si avvia. È una fonte super comune di problemi nelle applicazioni ASP.NET.

Per esempio in Serilog si può fare questo:

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

NOTA: Questo è limitato in quanto non hai accesso alla configurazione a questo punto, quindi per esempio per utilizzare AppInsights avresti probabilmente bisogno di un #if RELEASE block to set the appropriate key.

Ciò che questo fa è dare i dati su eventuali problemi di avvio nella vostra applicazione; scrive sia per console che per un file. E 'anche importante per assicurarsi di non salvare TUTTI i file di log; è possibile vedere qui stiamo salvando solo 7 giorni di log.

Avrete anche voglia di avvolgere il metodo di avvio (in questa applicazione uso il nuovo Program.cs metodo) in una prova/cattura e registro eventuali eccezioni che accadono lì.

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

Il Log.CloseAndFlush() è importante in quanto garantisce che tutti i log siano scritti su disco (la tua app è in crash così altrimenti uscirà prima di farlo).

Qui rilevo anche se l'app è in esecuzione in modalità migrazione e se è così, lo registro ed esco.

Log.Fatal è il livello di log più severo; viene utilizzato quando l'applicazione sta per bloccarsi. Non tutte le eccezioni sono letali - deve usare Log.Error per coloro che (a meno che non si riferiscano all'APP (non alla richiesta) non possono continuare oltre tale punto).

Livelli di registro

In ASP.NET (e.NET Più in generale) si dispone di una serie di livelli di log:

  1. Log.Fatal - Questo è il livello di log più severo; viene utilizzato quando l'applicazione sta per bloccarsi.
  2. Log.Error - Questo viene utilizzato quando accade un'eccezione che significa che l'APP (non la richiesta) non può continuare oltre quel punto.
  3. Log.Warning - Questo viene usato quando qualcosa accade che non è un errore, ma è qualcosa di cui si dovrebbe essere consapevoli (per esempio un servizio degradato / qualcosa Non del tutto giusto. ma non un errore).
  4. Log.Information - Questo è usato per informazioni generali su ciò che sta accadendo nella vostra applicazione.
  5. Log.Debug - Questo viene utilizzato per le informazioni che è utile solo quando si sta debug la tua applicazione (è OGNI DOVE in sviluppo, ma dovrebbe essere spento in produzione).

Per la produzione avevo generalmente impostato la registrazione per essere Log.Fatal, Log.Error e Log.Warning Solo.

Runtime Logging

Al contrario della registrazione di avvio questa è la registrazione che accade quando l'applicazione è in esecuzione. Questa è la registrazione che ti dice cosa sta succedendo nella tua applicazione in qualsiasi momento.

Per esempio per usare questi in Serilog faresti questo:

  "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"
    }
  },

EnrichesCity name (optional, probably does not need a translation)

Come vedrai sono un grande fan di Serilog; è una grande libreria di registrazione che è molto flessibile. Una delle cose che mi piace di esso è la capacità di arricchire i vostri registri con ulteriori informazioni. Questo può essere molto utile nella diagnosi dei problemi nella vostra applicazione. Nell'esempio di cui sopra potete vedere che sto arricchendo i miei log con il thread id, thread name, process id e process name. Questo può essere molto utile nella diagnosi dei problemi nella vostra applicazione.

Ho anche impostato la registrazione per andare a più'sink' (output); in questo caso la sto inviando alla console, a un file e a Seq (un servizio di registrazione).

Avere più lavelli è utile nel caso in cui uno fallisca, in questo caso il mio servizio di registrazione preferito è Seq, quindi lo mando lì prima. Se questo non funziona, lo mando alla console e a un file.

Ho anche impostato la proprietà ApplicationName nei registri; questo può essere utile se si dispone di più applicazioni di registrazione allo stesso servizio (che per le applicazioni distribuite spesso si; insieme con un ID di correlazione per collegare i registri insieme per una singola richiesta).

Ad esempio, se hai un front end JS e un backend.NET puoi impostare l'ID di correlazione nel front end e passarlo al backend. Questo permette di vedere tutti i log per una singola richiesta in un unico luogo. O se si utilizza HttpClient nel proprio backend è possibile passare l'ID di correlazione nelle intestazioni all'altro servizio.

C'è una grande copertura su come si potrebbe fare qui: https://josef.codes/append-correlation-id-to-all-log-entries-in-asp-net-core/ ma lo coprirò in un post futuro.

Logging strutturato

La registrazione strutturata è un modo di registrazione che rende più facile cercare e filtrare i registri. In Serilog si può fare questo utilizzando il Log.Information("This is a log message with {Property1} and {Property2}", property1, property2); sintassi. Questo rende più facile la ricerca di log con una particolare proprietà.

Registrazione contestuale

Utilizzando Serilog puoi anche usare LogContext.PushProperty per aggiungere proprietà ai tuoi log che sono rilevanti solo per un particolare scopo. Questo può essere molto utile nella diagnosi dei problemi nella vostra applicazione.

Impostazione Serilog

Serilog è super flessibile in quanto consente di configurarlo in codice così come attraverso la configurazione. Per esempio per usare la configurazione di cui sopra faresti questo:

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

Questo è lo stesso come la configurazione di cui sopra, ma in codice. Questo è utile se si desidera impostare il vostro login in codice; è davvero a voi come si fa.

Filtri di eccezione

In ASP.NET è possibile utilizzare Filtri di eccezione per catturare le eccezioni e registrarle. Questo è un ottimo modo per assicurarsi di registrare tutte le eccezioni nella vostra applicazione. Tuttavia non è un sostituto per la registrazione del livello di metodo; si dovrebbe ancora registrare al livello di metodo in modo da poter vedere cosa sta accadendo nella vostra applicazione in dettaglio; il filtro Eccezione mostra solo ciò che accade una volta che l'intero stack di richiesta è stato scartato e può spesso essere molto confuso per capire cosa è successo.

Questo è cambiato in ASP.NET Core 8 e c'è un TON che si può fare con questi nuove caratteristiche.

Inserisci ancora gli stessi principi si applicano; si dovrebbe log a livello di metodo in modo da poter vedere cosa sta accadendo nella tua applicazione in dettaglio; i filtri di eccezione / gestori di stato solo mostrare cosa succede una volta che l'intero stack di richiesta è stato scartato e può spesso essere molto confuso per capire cosa è successo.

NON PERDERE TUTTO IL PRODUTTORE

La registrazione dovrebbe essere adeguata all'ambiente; in Sviluppo si registra tutto in modo da poter vedere cosa sta accadendo in ogni punto della vostra applicazione, ma in Prova è necessario meno registrazione (forse registro informazioni qui) e in Produzione è necessario ancora meno (Attenzione e sopra).

E' una tentazione registrare tutto in produzione, ma e' una pessima idea. Si dovrebbe registrare tutto il necessario per diagnosticare un problema, ma non più. Nei provider di cloud si può facilmente ottenere addebitato per la quantità di dati che si invia al servizio di registrazione in modo da essere attenti a ciò che si effettua il log e per quanto tempo si conservano questi registri (Application Insights memorizza i registri per 90 giorni di default; questo è spesso troppo lungo e vi costerà fino a quando i dati di registro viene memorizzato).

Per un'app molto 'attiva' non avrai bisogno di una registrazione a lungo termine di quei dati; avrai una buona idea di cosa sta succedendo nell'app dagli ultimi giorni di log.

Richiesta registrazione

Una volta che il problema comune vedo nella produzione sta registrando le richieste fallite; mentre questi possono essere interessanti (nessuno vuole un 404 / 401) questi possono essere una quantità enorme di dati e possono essere molto costosi da memorizzare. Dovresti registrare solo le cose. hai intenzione di risolvere, per un 404 può essere che questo è importante in quanto può indicare un collegamento rotto nella vostra applicazione; per un 401 può essere che questo è importante in quanto può indicare un sistema di autenticazione rotto.

Tuttavia, come ho detto sopra, questi sono meglio gestiti nel codice che effettivamente avviene in (nel caso di 401); può darsi che essi dovrebbero anche essere registrati come un Warning oppure Error nel codice che genera effettivamente il 401.

Per impostare la richiesta di registrazione in Serilog puoi fare questo:

app.UseSerilogRequestLogging();

Questo registro tutte le richieste alla vostra applicazione; è un ottimo modo per vedere cosa sta accadendo nella vostra applicazione ad un alto livello; ma ancora una volta si dovrebbe fare attenzione a ciò che si effettua il log e per quanto tempo si conservano questi log.

Per gli Insight applicativi è comunque possibile effettuare il log utilizzando il livello di informazioni in quanto vi darà la caratteristica di viaggio utente nifty; questo è un ottimo modo per vedere come gli utenti stanno utilizzando la vostra applicazione e può essere molto utile per diagnosticare i problemi; tuttavia ancora una volta questi rapidamente accumulare i costi in modo da essere attenti a ciò che si effettua il log e per quanto tempo si conservano questi log per.

In conclusione

Quindi questo è tutto, una rapida analisi di come effettuare il login nelle applicazioni ASP.NET. Gran parte di esso è una reazione a tronchi troppo zelanti e inutili che vedo in molte applicazioni di produzione. In sviluppo si vuole vedere come funziona l'app; in produzione si vuole vedere come l'app fallisce. La registrazione è troppo spesso una parte inutile e costosa dello sviluppo delle applicazioni. Come con tutto lo sviluppo software di registrazione dovrebbe essere focalizzata sull'UTENTE; se il suo / altri sviluppatori mentre si lavora sull'applicazione nel vostro IDE / localmente o risolvere i problemi in produzione in modo rapido ed efficiente.

logo

©2024 Scott Galloway