Best practice per la registrazione e la traccia in .NET


53

Ho letto molto su traccia e registrazione, cercando di trovare qualche regola d'oro per le migliori pratiche in materia, ma non ce ne sono. La gente dice che i bravi programmatori producono una buona traccia, ma la mettono così e deve provenire dall'esperienza.

Ho anche letto domande simili qui e attraverso Internet e non sono proprio la stessa cosa che sto chiedendo o non hanno una risposta soddisfacente, forse perché le domande mancano di qualche dettaglio.

Quindi, la gente dice che la traccia dovrebbe replicare l'esperienza di debug dell'applicazione nei casi in cui non è possibile collegare un debugger. Dovrebbe fornire un contesto sufficiente in modo da poter vedere quale percorso viene preso in ciascun punto di controllo nell'applicazione.

Andando più in profondità, puoi persino distinguere tra traccia e registrazione degli eventi, in quanto "la registrazione degli eventi è diversa dalla traccia in quanto cattura gli stati principali piuttosto che un flusso dettagliato di controllo".

Ora, dì che voglio fare la mia traccia e registrazione usando solo le classi .NET standard, quelle nello System.Diagnosticsspazio dei nomi. Ho pensato che la classe TraceSource fosse migliore per il lavoro rispetto alla classe Trace statica, perché voglio differenziare i livelli di traccia e usando la classe TraceSource posso passare un parametro che informa il tipo di evento, mentre usando la classe Trace devo usare Trace.WriteLineIfe quindi verifica cose come SourceSwitch.TraceInformatione SourceSwitch.TraceErrorse non ha nemmeno proprietà come TraceVerboseo TraceStart.

Con tutto ciò in mente, considereresti una buona pratica fare come segue:

  • Traccia un evento "Start" quando inizia un metodo, che dovrebbe rappresentare una singola operazione logica o una pipeline, insieme a una rappresentazione in stringa dei valori dei parametri passati al metodo.
  • Traccia un evento "Informazioni" quando si inserisce un elemento nel database.
  • Traccia un evento "Informazioni" quando segui un percorso o un altro in un'istruzione if / else importante.
  • Traccia un "Critico" o "Errore" in un blocco catch a seconda che si tratti di un errore recuperabile.
  • Traccia un evento "Stop" al termine dell'esecuzione del metodo.

Inoltre, chiarire quando è meglio rintracciare i tipi di eventi dettagliati e di avviso. Se hai esempi di codice con una buona traccia / registrazione e sei disposto a condividere, sarebbe eccellente.

Nota: ho trovato alcune buone informazioni qui, ma ancora non quello che sto cercando: http://msdn.microsoft.com/en-us/magazine/ff714589.aspx


forse è anche utile il modo preferito di logging in net net deployed to azure su stackoverflow.
k3b,

qualche applicazione di esempio del codice sorgente completo che utilizza buoni schemi per la registrazione?
Kiquenet,

Onestamente ... Se avessi lavorato con .NET probabilmente avrei semplicemente installato qualcosa come New Relic e l'avrei definito fatto. (Forse non è una buona opzione al momento della pubblicazione)
svidgen

Risposte:


17

L'importanza dei tipi di traccia non deve essere scelta a causa di dove si trova la traccia nel codice, ma perché il messaggio tracciato è più o meno importante. Esempio:

Traccia un evento "Start" quando inizia un metodo, che dovrebbe rappresentare una singola operazione logica o una pipeline, insieme a una rappresentazione in stringa dei valori dei parametri passati al metodo.

Utilizzare il tipo di avvio quando si avvia un'operazione logica. Ciò non significa che la traccia iniziale deve essere all'inizio di un metodo, né significa che un metodo deve avere una traccia iniziale.

Detto questo, nella maggior parte dei casi, un'operazione logica inizierà effettivamente all'inizio del metodo. Altrimenti, dovresti chiederti se il codice è stato refactored correttamente.

Anche i parametri di tracciamento possono essere una cattiva idea . Devi pensare a cosa rintracciare, caso per caso. Ad esempio, è davvero male tracciare i parametri di un metodo void Authenticate(string userName, string plainPassword).

Traccia un evento "Informazioni" quando si inserisce un elemento nel database.

Dipende. Alcuni elementi devono essere tracciati, ma non tutti gli articoli.

  • Ad esempio, immagina di inserire effettivamente un elemento del registro nel tuo database. Tracceresti i registri? E poi registra le tracce? E quindi tracciare la registrazione della traccia?
  • Un altro esempio: stai inserendo dati sensibili. Ciò richiede il controllo. Poiché hai verificato l'inserimento, perché tracciarlo?

Traccia un evento "Informazioni" quando segui un percorso o un altro in un'istruzione if / else importante.

Di nuovo, dipende.

Traccia un "Critico" o "Errore" in un blocco di cattura a seconda del tempo, si tratta di un errore recuperabile.

L'azione intrapresa dopo un errore non recuperabile può essere più che traccia. Ad esempio sul lato server, si desidera archiviare l'eccezione nel database per ulteriori analisi. Inoltre, alcune eccezioni sono meno importanti di altre e non richiedono traccia.

Traccia un evento "Stop" al termine dell'esecuzione del metodo.

Vedi il primo punto.

chiarire quando è meglio rintracciare i tipi di eventi verbose e di avviso.

verbose:

Il verbose viene utilizzato per tracciare ciò che è necessario tracciare quando qualcosa va davvero storto. Ciò significa che nella maggior parte dei casi disabiliterai la traccia dei messaggi dettagliati, ma a volte devi eseguire il debug di alcune parti del codice per capire perché qualcosa non funziona in un caso limite.

Di solito hai molti messaggi dettagliati che ti fanno capire davvero bene il flusso dell'applicazione. Significa anche che quei messaggi devono essere disabilitati il ​​più delle volte perché:

  • altrimenti, il registro crescerà molto velocemente,
  • non ti servono per la maggior parte del tempo,
  • possono contenere dati sensibili sul flusso dell'applicazione.

Pensa al prolisso come uno strumento che devi usare quando non hai accesso al debugger.

Avvertimento:

La traccia del tipo di avviso viene utilizzata quando accade qualcosa di sbagliato e importante, ma non è troppo cruciale per essere trattata come un errore. Ad esempio, RAM insufficiente può emettere un avviso, ma non vi è motivo di tracciare un errore, poiché l'applicazione può continuare, anche se sarà più lenta del solito.

Esempi:

  • Esempio 1: l'applicazione non è riuscita ad aprire il file che l'utente ha richiesto di aprire. Il file esiste e non è in uso, le autorizzazioni sono impostate correttamente, ma qualcosa blocca l'apertura di un file. In questo caso, si traccerà un errore , poiché l'applicazione non è in grado di gestire questo caso e continua a funzionare come previsto dall'utente (ovvero leggere effettivamente il file).

  • Esempio 2: dopo l'ispezione dell'errore nel primo esempio, si scopre che l'errore è causato dal fatto che il percorso del file è più lungo di 259 caratteri. Quindi refactoring il codice per catturare PathTooLongException. Quando, la volta successiva, l'utente tenta di aprire lo stesso file, la nuova versione dell'applicazione mostra un messaggio che spiega che il file è troppo lungo e deve essere spostato in un'altra cartella per accorciare il percorso completo al fine di aprire questo file in questa applicazione. Traccia anche un messaggio .

  • Esempio 3: l'applicazione ha impiegato venti secondi per aprire e analizzare un piccolo file mentre la maggior parte dei file impiegava da dieci a cento millisecondi per aprirsi e analizzarsi. Tieni traccia di un avviso con informazioni pertinenti: il tipo di disco in cui si trova effettivamente il file, il file system, la dimensione del file, il tempo esatto trascorso, il tempo in cui il computer era acceso, ecc. Quando l'utente si lamenta che ci vogliono venti secondi per aprire il file, prendi la traccia per trovare cosa succede. Ad esempio, potresti trovare che il caricamento dei file da una condivisione di rete richiede così tanto tempo quando il computer è appena stato avviato. Spieghi all'utente che il ritardo è dovuto alla rete e non è correlato alla tua applicazione.

  • Esempio 4: il file aperto viene visualizzato in modo errato. Si attiva la traccia dettagliata in cui si vede effettivamente come i dati vengono caricati dal file e quindi analizzati, passo dopo passo.


Un modello che usiamo dove lavoro è la registrazione di "KnownErrors" come avvertimenti e "UnknownErrors" come errori. Potrebbe non essere appropriato a seconda della tua infrastruttura e di come gestisce gli avvisi, ma funziona bene per noi.
Andrew dice di reintegrare Monica

5
 > say I want to do my tracing and logging using only the standard .NET classes

System.Diagnostics è fantastico perché è possibile configurare la destinazione delle informazioni di traccia (file, registro eventi, database, ....)

Sfortunatamente, se si desidera utilizzare, System.Diagnosticsè necessario sapere in anticipo ( in fase di progettazione ) quali flussi di tracce dovrebbero essere possibili da seguire. (Nell'articolo di esempio si tratta di Trasferimento, Riprendi, Sospendi, ...). Questi possono essere configurati su Disabilitato, Debuglevel o Errorlevel.

Preferisco avere un sistema di registrazione in cui posso decidere in fase di esecuzione su classlevel / namespacelevel , quanto dettagliato dovrebbe essere la registrazione. Ad esempio, tutto il debug e sopra da MyNamespace.Business.*ma non MyNamespace.Business.Calculations.

Se si utilizza log4net (o Common.logging) ogni classe ottiene il proprio logger in modo da poter decidere facilmente quali classi vengono registrate a quale livello.

Poiché le operazioni del database sono in una classe separata, non è più necessaria una regola distinta

Trace an "Information" event when inserting an item into the database.

Preferisco invece avere queste linee guida:

  • Tracelevel dovrebbe mostrare il flusso di lavoro di base
  • Il debuglevel dovrebbe mostrare dati dettagliati ed elaborazione all'interno del flusso di lavoro, comprese le decisioni nel flusso di programma con motivazioni (Creazione di un nuovo elemento perché l'elemento non esisteva nel DB)
  • Infolevel per l'avvio / arresto dei servizi e una voce per ogni flusso di lavoro / azione della GUI avviata

Capisco, queste sono buone informazioni, grazie! Tuttavia, come faccio nella mia domanda originale, chiarirebbe per favore gli usi dei tipi di evento verboso e di avvertimento? Inoltre, chiedo ad altre persone di contribuire con il loro punto di vista, perché questo argomento merita un'esplorazione più profonda di quella che ho visto su Internet.
Levidad,

4

Puoi provare il framework Story , ha un approccio unico alla registrazione in quanto "ti fa" scrivere tutti i log (e aggiungere altre informazioni rilevanti) nel contesto, quindi quando devi leggerlo in seguito ottieni tutto ciò di cui hai bisogno.

Aggiungerà automaticamente i concetti "inizio" e "arresto" come l'inizio e la fine di una storia.

E con un sistema basato su regole puoi controllare cosa fare di ogni storia (contesto) in base alle informazioni che ha, ad esempio stampare tutte le storie che hanno un errore o provengono dall'utente "admin".

Ulteriori informazioni su questo post del blog



1
risposta aggiornata con ulteriori informazioni
Amit Apple
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.