2010-07-13 15 views
6

Sto cercando di capire la migliore strategia per l'accesso al server web async-IO su cui sto lavorando. Ho pensato che il modo più semplice era quello di avere una classe Singleton che mantiene filestreams aperto per i file di log appropriati in modo ho potuto solo fare qualcosa di simile:C# Singleton Logging Class

Util.Logger.GetInstance().LogAccess(str); 

O qualcosa del genere.

La mia classe si presenta così:

public sealed class Logger { 
    private static StreamWriter sw; 
    private static readonly Logger instance = new Logger(); 
    private Logger() { 
     sw = new StreamWriter(logfile); 
    } 
    public static Logger GetInstance() { 
     return instance; 
    } 
    public void LogAccess(string str) { 
     sw.WriteLine(str); 
    } 
} 

Questo è tutto solo nella mia testa davvero, e non vedo per suggerimenti su come farlo meglio e fare in modo che sto facendo in modo corretto anche. La cosa più importante è che ho bisogno che sia thread-safe, che ovviamente non è nel suo stato attuale. Non sono sicuro del modo migliore per farlo.

+0

Si sta utilizzando. NET 4, forse? Nuove librerie asincrone potrebbero aiutarti. (Coglierò anche l'occasione per sottolineare quanto sarebbe elegante in F # e mi congedo!) –

+1

Qual è il valore dell'uso di Singleton rispetto ai metodi statici? – kyoryu

+1

Mi piace il fatto che tu voglia provare tu stesso. La registrazione non è così difficile da creare, ma creare un buon modo per gestire il threading è una sfida. I framework suggeriti sono tutti a posto, ma crearli tu stesso ti darà una buona opportunità per conoscere e lavorare con thread-safety. Diventa davvero difficile se si desidera che più applicazioni (o in pool/server di applicazioni ASP.NET) scrivano sullo stesso file, perché in questo caso la sicurezza del thread non è sufficiente. – Gertjan

risposta

0

Non penso che ci sia un modo semplice per bloccare se si desidera scrivere sullo stesso file da più thread.

Quindi la soluzione semplice è aggiungere lock intorno a qualsiasi chiamata allo StreamWriter. In alternativa è possibile memorizzare in buffer l'output in memoria e scriverlo solo una volta ogni tanto, il che richiede comunque il blocco, ma la contesa del blocco sarebbe molto più bassa. Se si va a quella lunghezza, però, si potrebbe anche andare con un quadro di registrazione adeguato come log4net, which is thread-safe.

4

a) Non includere "Registro" nei nomi dei metodi. È ovvio che un logger registra. .Warning, .Error, ecc. Sono nomi di metodi migliori poiché descrivono il livello della voce di registro.

b) Creare un thread in background che scrive nel log.

c) Accedere alle voci dai metodi di registrazione e segnalare il thread di lavoro.

d) Utilizzo (non so se ricordo bene i nomi dei metodi)

var methodInfo = new StackFrame(1).GetMethod(); 
var classAndMethod = methodInfo.DeclaringType.Name + "." + methodInfo.Name; 

per ottenere il metodo chiamante.

In questo modo si otterrà solo un thread che accede al file.

+2

Non sono d'accordo con (a), perché 'Warning' e' Error' non sono verbi. I nomi dei metodi dovrebbero essere i verbi per convenzione. 'Avvisa? Sarebbe meglio, ma come dovremmo denominare metodi che registrano errori ed errori critici? 'LogWarning' e' LogError' sono molto più IMO, o preferisco usare un metodo generico chiamato 'Log' con un argomento' severity' che mostra il tipo. Mentre (b) potrebbe aumentare le prestazioni, la maggior parte dei framework di logging non accede in background. È difficile e normalmente molto più sicuro da eseguire in modo sincronizzato. – Steven

+0

C'è anche una regola che dice che il nome della classe non dovrebbe essere ripetuto nei nomi dei metodi. In questo caso si tratta di gusti, poiché è abbastanza ovvio che Error e LogError fanno la stessa cosa. Preferisco un metodo di errore invece di un metodo di registro con un parametro di gravità poiché è meno da digitare e leggere. Ma come ho detto: è tutto incentrato sul gusto. (b) Non vedo come scrivere in un thread separato sia complicato o pericoloso. È abbastanza semplice. Una discussione, una coda e una serratura, non serve più nulla – jgauffin

+0

Non ho detto che sarebbe stato difficile da implementare; il fatto è che la registrazione è spesso una parte importante di un processo aziendale e in tal caso non si desidera continuare l'elaborazione prima di sapere che il messaggio di registro è persistente. Ovviamente in altri scenari potrebbe essere utile mantenere una coda di messaggi di log. Dipende. Ma per questa ragione i framework di registrazione di solito li elaborano in modo sincrono. – Steven

2

Forse dovresti provare NLog o Log4net. Entrambi sono meravigliosi framework di log.

Ma se si desidera scrivere il proprio componente di registro, Blocco è un must quando si generano messaggi di registro. È normale che i messaggi del registro vengano memorizzati in memoria e vengano scritti su file una volta alla volta.

1

Un altro framework che risolve questi problemi è the Object Guy's logging framework. Può facoltativamente accedere in background.Più thread possono accedere allo stesso file. E più processi possono accedere allo stesso file.

0

Oppure si potrebbe usare una classe con metodi condivisi solo ..

Imports System.Threading 

Public Class Logger 
    Private Shared ReadOnly syncroot As New Object 

    Public Shared Sub log(ByVal vInt As Integer) 
     ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf logThread), CStr(vInt)) 
    End Sub 

    Public Shared Sub log(ByVal vStr As String) 
     ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf logThread), vStr) 
    End Sub 

    Private Shared Sub logThread(ByVal o As Object) 
     Dim str As String = CStr(o) 
     SyncLock syncroot 
      Using objWriter As New System.IO.StreamWriter(GetLogPath, True) 

       objWriter.WriteLine(str) 
       objWriter.Close() 

      End Using 
     End SyncLock 
    End Sub 

    Private Shared Function GetLogPath() As String 
     Return "logs.txt" 
    End Function 
End Class 

ho trovato più utilizzabile in questo modo di utilizzare un Singleton:

Logger.log("Something to log") 

Acclamazioni