C # Singleton Logging Class

I am trying to find the optimal registration strategy for the async-IO web server I'm working on. I thought the easiest way is to have one classmate who keeps Filestreams open to the corresponding log files, so I could just do something like:

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

Or something like that.

My class is as follows:

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

It’s all in my head, and I’m looking for suggestions on how to do it better, and also make sure that I am doing it right. Most importantly, I need it to be thread safe, which is clearly not in its current state. Not sure how to do this.

+6
c # thread-safety logging singleton
source share
7 answers

There is a TextWriter.Synchronized method that creates a thread-safe version of TextWriter. Try it.

+5
source share

This will be taken care of automatically if you use NLog - you define all your registrars in the .config file, and then access all of them through the static LogManager class, which is Singleton.

Here is an example that illustrates the thread-safe nature of NLog:

https://github.com/nlog/nlog/wiki/Tutorial#Adding_NLog_to_an_application

+8
source share

a) Do not include the "Log" in the names of the methods. Obviously the logs are logs ... Warning, .Error, etc. - The best method names, since they describe at what level the log entry.

b) Create a background thread that is written to the log.

c) Block entries from logging methods and specify a workflow.

d) Use (I don't know if I remember the names of the methods correctly)

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

to get the calling method.

Doing this will give you only one thread that accesses the file.

+4
source share

Perhaps you should try NLog or Log4net. Both of them are a wonderful magazine structure.

But if you want to write your own log component, Lock is a must when displaying log messages. It is well known that buffering log messages in memory and writing them to a file at a time.

+2
source share

Another structure that adds these issues to you is the Object Guy logging framework . He can, if necessary, record in the background. Several streams can be registered in one file. And several processes can be registered in one file.

+1
source share

I don’t think there is an easy way to lock if you want to write to the same file from multiple threads.

Thus, a simple solution is to add lock around any calls in StreamWriter . Alternatively, you can buffer the output in memory and only write it to a file once in a while, which still requires a lock, but the lock conflict will be much lower. However, if you go this length, you can go with the proper logging structure like log4net, which is thread safe .

0
source share

Or you can use the class using only general methods.

 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 

I found it more convenient to use this way than using singleton:

 Logger.log("Something to log") 

Greetings

0
source share

All Articles