C # Singleton Logging Class - PullRequest
       33

C # Singleton Logging Class

6 голосов
/ 13 июля 2010

Я пытаюсь определить лучшую стратегию входа на веб-сервер async-IO, над которым я работаю.Я подумал, что проще всего было бы создать одноэлементный класс, который бы поддерживал файловые потоки открытыми для соответствующих файлов журналов, чтобы я мог просто сделать что-то вроде:

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

или что-то в этом роде.

Мой классвыглядит так:

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

Это все просто в моей голове, и я ищу предложения о том, как сделать это лучше, а также убедиться, что я делаю это правильно.Самое главное, мне нужно, чтобы он был потокобезопасным, что, очевидно, не в его текущем состоянии.Не уверен, что это лучший способ сделать это.

Ответы [ 7 ]

8 голосов
/ 13 июля 2010

Это позаботится о вас автоматически, если вы используете NLog - вы определяете все свои регистраторы в файле .config и затем получаете доступ ко всем им через статический класс LogManager, который является Singleton .

Вот пример, который иллюстрирует потокобезопасную природу NLog:

http://nlog -project.org / вики / Tutorial # Adding_NLog_to_an_application

5 голосов
/ 13 июля 2010

Существует метод TextWriter.Synchronized , который создает потокобезопасную версию TextWriter. Попробуйте это.

4 голосов
/ 13 июля 2010

а) Не включайте «Журнал» в названиях методов.Очевидно, что логгер логи..Warning, .Error и т. Д. Являются более подходящими именами методов, поскольку они описывают, какой уровень имеет запись журнала.

b) Создайте фоновый поток, который записывает в журнал.

c) Поставьте записи изметоды ведения журнала и сигнализируют рабочий поток.

d) Используйте (я не знаю, правильно ли я помню имена методов)

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

, чтобы получить вызывающий метод.

Это даст вам только один поток, который обращается к файлу.

2 голосов
/ 13 июля 2010

Может быть, вам стоит попробовать NLog или Log4net.Они оба являются прекрасной структурой журнала.

Но если вы действительно хотите написать свой собственный компонент журнала, блокировка необходима при выводе сообщений журнала.Обычно буферизуют сообщения журнала в памяти и записывают их в файл один раз за раз.

1 голос
/ 13 июля 2010

Еще один фреймворк, который решает эти проблемы для вас, - это каркас логирования Object Guy . При желании он может войти в фоновом режиме. Несколько потоков могут войти в один файл. И несколько процессов могут войти в один файл.

0 голосов
/ 22 июля 2010

Или вы можете использовать класс только с общими методами.

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

Я нашел его более удобным для использования, чем синглтон:

Logger.log("Something to log")

Cheers

0 голосов
/ 13 июля 2010

Я не думаю, что есть какой-то простой способ обойти блокировку, если вы хотите записать в один и тот же файл из нескольких потоков.

Таким образом, простое решение - добавить lock вокруг любых вызовов StreamWriter.В качестве альтернативы вы можете буферизовать вывод в памяти и записывать его в файл только время от времени, что все еще требует блокировки, но конкуренция за блокировку будет намного ниже.Однако, если вы пойдете на такую ​​длину, вы можете использовать подходящую структуру ведения журнала, такую ​​как log4net, которая является поточно-ориентированной .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...