2017-06-21 25 views
5

Mam środowisko wielowątkowe, w którym aplikacja zaczyna się od WPF, która inicjuje 2 wątki pracujące w tle serwer gniazd internetowych i serwer Web API.Używanie Log4Net w środowisku wielowątkowym

Chcę zarejestrować wszystkie zdarzenia w jednym pliku dziennika. Używam log4Net (po raz pierwszy).

Tworzę 3 wystąpienia programu Logger i zakładam, że program dołączający plik zrozumie, że musi pisać tylko do jednego pliku.

Kod:

Logger Klasa:

public class Logger :ILogger 
{ 
    private static ILog log = null; 
    static Logger() 
    { 
     log = LogManager.GetLogger(typeof(Logger)); 
     GlobalContext.Properties["host"] = Environment.MachineName; 
    } 
    public Logger(Type logClass) 
    { 
     log = LogManager.GetLogger(logClass); 
    } 

    #region ILogger Members 
    public void LogException(Exception exception) 
    { 
     if (log.IsErrorEnabled) 
      log.Error(string.Format(CultureInfo.InvariantCulture, "{0}", exception.Message), exception); 
    } 
    public void LogError(string message) 
    { 
     if (log.IsErrorEnabled) 
      log.Error(string.Format(CultureInfo.InvariantCulture, "{0}", message)); 
    } 
    public void LogWarningMessage(string message) 
    { 
     if (log.IsWarnEnabled) 
      log.Warn(string.Format(CultureInfo.InvariantCulture, "{0}", message)); 
    } 
    public void LogInfoMessage(string message) 
    { 
     if (log.IsInfoEnabled) 
      log.Info(string.Format(CultureInfo.InvariantCulture, "{0}", message)); 
    } 
    #endregion 
} 

Log Config:

<log4net debug="true"> 
    <appender name="RollingLogFileAppender" 
       type="log4net.Appender.RollingFileAppender"> 
    <file value="/pathToLogFile" /> 
    <staticLogFileName value="false"/> 
    <appendToFile value="true" /> 
    <rollingStyle value="Date" /> 
    <datePattern value=" yyyy-MM-dd&quot;.txt&quot;"/> 
    <layout type="log4net.Layout.PatternLayout"> 
     <!--<param name="ConversionPattern" 
       value="%d [%t] %-5p %c %m%n" />--> 
     <conversionPattern 
     value="%date [%thread] %-5level %logger ==> %message%newline"/> 
    </layout> 
    </appender> 

    <root> 
    <level value="INFO" /> 
    <appender-ref ref="RollingLogFileAppender" /> 
    <appender-ref ref="AdoNetAppender" /> 
    </root> 
</log4net> 

tworzę 3 instancje Logger, w 3 różnych projektach jak:

static ILogger logger = new Logger(typeof(MainWindow)); 
static ILogger logger = new Logger(typeof(DefaultApiController)); 
static ILogger logger = new Logger(typeof(WebSocket)); 

Ale, Plik dziennika ma tylko dziennik WebSocket. Czy w moim rozumieniu istnieje luka? Gdzie się mylę?

Zasadniczo działają 3 wątki, więc zdecydowanie nie mogę przenieść tego samego obiektu Logger z jednego do drugiego.

+1

Dlaczego opakowanie? Wygląda na to, że po prostu powiela funkcjonalność (filtrowanie według poziomu logowania), która już istnieje w log4net - do tego celu używasz nawet konfiguracji log4net. – Adrian

Odpowiedz

7

Głównym problemem jest to, że używasz statycznego programu rejestrującego, ale próbujesz przypisać tę zmienną statyczną 3 razy w konstruktorze instancji, a ta ostatnia zawsze wygrywa. Liczba projektów nie ma znaczenia, jeśli wszystkie projekty są hostowane w tym samym uruchomionym pliku wykonywalnym, wystąpi tylko 1 instancja Logger::log (, zakładając, że nie tworzysz wielu domen aplikacji).

public class Logger :ILogger 
{ 
    private static ILog log = null; 
    static Logger() 
    { 
     log = LogManager.GetLogger(typeof(Logger)); 
     GlobalContext.Properties["host"] = Environment.MachineName; 
    } 
    public Logger(Type logClass) 
    { 
     log = LogManager.GetLogger(logClass); 
    } 

Powinny być

public class Logger :ILogger 
{ 
    private ILog log = null; 
    public Logger(Type logClass) 
    { 
     log = LogManager.GetLogger(logClass); 
    } 

Mimo to nie jestem pewien, dlaczego starasz się ustawić go w ten sposób. Znacznie łatwiej jest dostarczyć statyczny rejestrator w dowolnej klasie, która go potrzebuje. Przykład:

public class SomeInterestingType { 
    private static readonly ILog Logger = LogManager.GetLogger(typeof(SomeInterestingType)); 

    public void DoSomething() { 
    Logger.Info("Busy doing something"); 
    } 
} 

A następnie po prostu powtórz ten wzór.