Implémentation de classe de journalisation sécurisée des threads

Serait-ce la manière correcte d’implémenter une classe de journalisation relativement simple et sécurisée?

Je sais que je ne ferme jamais explicitement TextWriter , cela poserait-il un problème?

Lorsque j’ai initialement utilisé la méthode TextWriter.Synchronized , cela ne semblait pas fonctionner tant que je ne l’avais pas initialisé dans un constructeur statique et l’avais fait en lecture seule comme ceci:

 public static class Logger { static readonly TextWriter tw; static Logger() { tw = TextWriter.Synchronized(File.AppendText(SPath() + "\\Log.txt")); } public static ssortingng SPath() { return ConfigManager.GetAppSetting("logPath"); } public static void Write(ssortingng logMessage) { try { Log(logMessage, tw); } catch (IOException e) { tw.Close(); } } public static void Log(ssortingng logMessage, TextWriter w) { w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeSsortingng(), DateTime.Now.ToLongDateSsortingng()); w.WriteLine(" :"); w.WriteLine(" :{0}", logMessage); w.WriteLine("-------------------------------"); // Update the underlying file. w.Flush(); } } 

Je vais adopter une approche complètement différente des autres réponses et supposer que vous voulez réellement apprendre à écrire un meilleur code sensible aux threads, et ne cherchez pas de suggestions de notre part (même si vous finissez par utiliser un.)

Comme d’autres l’ont dit, vous créez un thread TextWriter sûr, TextWriter qui signifie que les appels à WriteLine sont sécurisés pour les threads, ce qui ne signifie pas qu’un grand nombre d’appels à WriteLine seront exécutés comme une opération atomique. Je veux dire par là que rien ne garantit que les quatre appels WriteLine vont se passer en séquence. Vous pouvez avoir un TextWriter thread-safe, mais vous n’avez pas une méthode Logger.Log thread-safe;) Pourquoi? Car à n’importe quel moment au cours de ces quatre appels, un autre thread peut décider d’appeler également Log . Cela signifie que vos appels WriteLine seront désynchronisés. La façon de résoudre ce problème est d’utiliser une instruction de lock comme suit:

 private static readonly object _syncObject = new object(); public static void Log(ssortingng logMessage, TextWriter w) { // only one thread can own this lock, so other threads // entering this method will wait here until lock is // available. lock(_syncObject) { w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeSsortingng(), DateTime.Now.ToLongDateSsortingng()); w.WriteLine(" :"); w.WriteLine(" :{0}", logMessage); w.WriteLine("-------------------------------"); // Update the underlying file. w.Flush(); } } 

Donc, maintenant vous avez un TextWriter ET un Logger thread-safe.

Avoir du sens?

Tout en appelant TextWriter.Synchronized protégera cette instance unique de TextWriter , il ne synchronisera pas vos écritures de sorte qu’un appel “Log” rest ensemble à l’intérieur du fichier.

Si vous appelez Write (ou Log à l’aide de l’instance TextWriter interne) à partir de plusieurs threads, les appels WriteLine individuels peuvent être entrelacés, rendant vos WriteLine inutilisables.

J’utiliserais personnellement une solution de journalisation tierce qui existe déjà pour cela. Si ce n’est pas une option, la synchronisation vous-même (même avec un simple verrou) sera probablement plus utile que d’utiliser le wrapper TextWriter.Synchronized du TextWriter.Synchronized .

Vous devriez regarder dans cette classe (partie de .NET 2.0), pas besoin de “créer” votre propre enregistreur. vous permet de vous connecter à un fichier texte, une vue d’événement, etc.

http://msdn.microsoft.com/en-us/library/system.diagnostics.tracesource.aspx

Votre méthode “Log” peut ressembler à ceci (en supposant qu’il existe une variable membre intermédiaire appelée “traceSource”):

  public void Log(TraceEventType eventType, ssortingng message) { this.traceSource.TraceEvent(eventType, 0, message); this.traceSource.Flush(); } 

Cette section contient une section de configuration qui nomme TraceSource et contient des parameters de configuration. On suppose que lorsque vous construisez un TraceSource dans votre enregistreur, vous l’instanciez avec l’une des sources de trace nommées dans la configuration.

         

En outre, ne rendez pas votre enregistreur statique. Au lieu de cela, utilisez Enterprise Library 5.0 Unity for Dependency Injection / IOC.

J’espère que cela t’aides!

Quelqu’un m’a signalé cet article en discutant de certains problèmes de journalisation aujourd’hui. Nous avons déjà de très bonnes réponses ici, mais j’ajoute ma réponse pour montrer une version plus simple de la classe Logger qui fait exactement la même chose, de manière complètement Threadsafe .
Une chose importante à noter ici est qu’aucun TextWriter.Synchronized n’est requirejs pour la sécurité des threads, car nous écrivons le fichier dans un lock approprié.

Note: Ceci a déjà été discuté dans la section commentaires de la réponse de x0n.

 public static class Logger { static readonly object _locker = new object(); public static void Log(ssortingng logMessage) { try { var logFilePath = Path.Combine(@"C:\YourLogDirectoryHere", "Log.txt"); //Use this for daily log files : "Log" + DateTime.Now.ToSsortingng("yyyy-MM-dd") + ".txt"; WriteToLog(logMessage, logFilePath); } catch (Exception e) { //log log-exception somewhere else if required! } } static void WriteToLog(ssortingng logMessage, ssortingng logFilePath) { lock (_locker) { File.AppendAllText(logFilePath, ssortingng.Format("Logged on: {1} at: {2}{0}Message: {3}{0}--------------------{0}", Environment.NewLine, DateTime.Now.ToLongDateSsortingng(), DateTime.Now.ToLongTimeSsortingng(), logMessage)); } } } 

Pour enregistrer quelque chose, appelez simplement comme

 Logger.Log("Some important event has occurred!"); 

Et il va faire une entrée de journal comme ça

Connecté le: 07 octobre 2015 à: 02:11:23
Message: Un événement important s’est produit!
——————–

Si vous recherchez une méthode simple d’instrumentation de votre code, cette fonctionnalité existe déjà dans .NET:

http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.aspx

De plus, des outils tiers vous apporteront des solutions robustes pour la journalisation. Par exemple, log4net , nLog et Enterprise Library .

Je recommande vraiment de ne pas réinventer la roue là-dessus 🙂