2017-06-13 71 views
0

我有一個已經使用NLog的項目。應用程序創建一個給定類的實例,將一個ILogger實例傳遞給它,然後在實例中調用一個「execute」方法 - 系統是多線程的,並且可以同時運行多達200個這樣的實例,日誌文件可以變得大而難以閱讀。NLog爲類的每個實例創建新的日誌文件

我們有一個要求,建立每一個類的實例一個新的日誌文件,並將其與該實例的輸出存儲(他們每個人都有一個唯一的標識符)

我的問題是:是否有可能有NLOG爲每個類的實例創建一個新文件?我知道你可以爲不同的類使用不同的日誌文件,我想要的是每個類的每個實例都有一個不同的日誌文件。

我看了網上,但無法找到關於此的很多信息,我不想通過創建我自己的日誌記錄類,如果它已經照顧在NLog重新發明輪子。

下面是我懷孕了證明重新配置現有的記錄儀時,會發生什麼控制檯應用程序 - 它本質上改變了記錄

class Program 
{ 
    static void Main(string[] args) 
    { 
     BackgroundWorker bw1 = new BackgroundWorker(); 
     bw1.DoWork += Bw1_DoWork; 
     bw1.RunWorkerAsync(); 

     BackgroundWorker bw2 = new BackgroundWorker(); 
     bw2.DoWork += Bw2_DoWork; 
     bw2.RunWorkerAsync(); 

     Console.ReadLine(); 
    } 

    private static void Bw1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     workLoad one = new workLoad("One"); 
     one.execute(); 
    } 

    private static void Bw2_DoWork(object sender, DoWorkEventArgs e) 
    { 
     workLoad one = new workLoad("Two"); 
     one.execute(); 
    } 

} 

public class workLoad 
{ 
    private ILogger _logger { get; set; } 
    private string _number { get; set; } 
    public workLoad(string number) 
    { 
     _logger = LogManager.GetCurrentClassLogger(); 
     _number = number; 

     var target = (FileTarget) LogManager.Configuration.FindTargetByName("DebugFile"); 
     target.FileName = $"c:\\temp\\File{number}.txt"; 
     LogManager.ReconfigExistingLoggers(); 
    } 

    public void execute() 
    { 
     for (int i = 0; i < 1000; i++) 
     { 
      _logger.Info(_number + " LOOPING" + i);   
     } 

    } 
} 

這將導致所有輸出將一個文件的所有實例(二.txt)日誌文件的示例如下。

2017年6月13日17:00:42.4156 TestNlog.workLoad兩個LOOPING0 2017年6月13日17:00:42.4156 TestNlog.workLoad一個LOOPING0 2017年6月13日17:00:42.4806 TestNlog。 WorkLoad One LOOPING1 2017-06-13 17:00:42.4746 TestNlog.workLoad兩個LOOPING1 2017-06-13 17:00:42.4806 TestNlog.workLoad一個LOOPING2 2017-06-13 17:00:00 42.4806 TestNlog.workLoad二LOOPING2 2017-06-13 17:00:42.4946 TestNlog.workLoad One LOOPING3 2017-06-13 17:00:42.4946 TestNlog.workLoad兩個LOOPING3 2017-06-13 17:00:42.4946 TestNlog.workLoad一個LOOPING4 2017-06-13 17:00:42.4946測試Nlog.workLoad 2 LOOPING4 2017-06-13 17:00:42.5132 TestNlog.workLoad One LOOPING5 2017-06-13 17:00:42.5132 TestNlog.workLoad Two LOOPING5 2017-06-13 17:00:00 42.5132 TestNlog。 WorkLoad One LOOPING6 2017-06-13 17:00:42.5257 TestNlog.workLoad兩個LOOPING6 2017-06-13 17:00:42.5257 TestNlog.workLoad一個LOOPING7 2017-06-13 17:00:00 42.5257 TestNlog.workLoad Two LOOPING7 2017-06-13 17:00:42.5407 TestNlog.workLoad兩個LOOPING8 2017-06-13 17:00:42.5407 TestNlog.workLoad一個LOOPING8 2017-06-13 17:00:42.5407 TestNlog.workLoad兩個LOOPING9 2017-06-13 17:00:42.5407 TestNlog.workLoad One LOOPING9 2017-06-13 17:00:42.5577 TestNlog.workLoad Two LOOPING10 2017年6月13日17:00:42.5577 TestNlog.workLoad一個LOOPING10

理想的ID來尋找一切從例如一個進入one.txt,同時一切從例如,兩個是在two.txt(你可以看到有200多個運行像這可能是一個問題!)

回答

0

也許你可以使類的構造函數初始化一個新的日誌

+0

試過了,我可能會錯過一些東西,但我不能看到一種方法來做到這一點。 – 5NRF

0

嘗試ReconfigExistingLoggers,可能是你最好的選擇。

<targets> 
    <target xsi:type="File" 
     name="Foo" 
     fileName="${basedir}/logs/logfile.txt" 
     keepFileOpen="false" 
     encoding="iso-8859-2" /> 
</targets> 

然後

var target = (FileTarget)LogManager.Configuration.FindTargetByName("Foo"); 
target.FileName = $"{change_my_location}/class_instance.txt"; 
LogManager.ReconfigExistingLoggers(); 

從這個答案在這裏: Update NLog target filename at runtime

+0

不工作,使用那個不起作用的目標來更改所有ILogger實例的日誌文件。 生病編輯現在的問題,我嘲笑你的建議,以表明我的意思是什麼樣的代碼。 – 5NRF

+0

多少個實例可以並行運行? 200?爲什麼不是數據庫目標?你可以做'SELECT * FROM logs WHERE instance ='blah'' – Kyle

+0

可以達到250--實際上它一次將達到25個左右。 針對數據庫是一個好主意,我沒有想到這一點 - 我認爲這是最後的手段 - 我真的想讓它與文件一起工作,儘管如此,過程的輸出和日誌都可以存儲一起......它也是用戶習慣的。好想法 - 但它最初的「可能」堆:) – 5NRF

2

也許嘗試在文件名中使用${logger}(這不會NLOG存檔邏輯阱工作):

<targets> 
    <target xsi:type="File" name="DebugFile" 
     fileName="${basedir}\logs\${logger:shortName=true}.txt" /> 
</targets> 

然後文件名將與記錄器名稱匹配。當創建記錄,然後,而不是這樣做:

_logger = LogManager.GetCurrentClassLogger(); 

然後像這樣做:你創建一個這樣的記錄儀

_logger = LogManager.GetCurrentClassLogger(typeof(workLoad).ToString() + "." + number); 

替代(沒有測試它是否工作):

private static object _lock = new object(); 

public static NLog.Logger PrepareLogger(string number) 
{ 
     lock (_lock) 
     { 
      var fileTarget = LogManager.Configuration.FindTargetByName(number); 
      if (fileTarget == null) 
      { 
       var fileTarget = new FileTarget(number); 
       fileTarget.FileName = $"c:\\temp\\File{number}.txt"; 

       var template = LogManager.Configuration.FindTargetByName("DebugFile"); 
       if (template != null) 
       { 
         fileTarget.Layout = template.Layout; 
       } 
       LogManager.Configuration.AddTarget(fileTarget); 
       var rule = new LoggingRule(number, LogLevel.Debug, fileTarget) { Final = true }; 
       LogManager.Configuration.LoggingRules.Add(rule); 
       LogManager.ReconfigExistingLoggers(); 
      } 
     } 
    return LogManager.GetLogger(number); 
} 
0

您可以在運行時創建自己的目標或向佈局添加參數並將其傳遞。

創建自定義日誌文件

/// <summary> 
    /// Creates the custom log file. 
    /// Logging of Info and Warning Message Only. 
    /// </summary> 
    /// <param name="TargetName">Name of the target.</param> 
    /// <param name="TargetFileName">Name of the target file.</param> 
    /// <param name="LoggerName">Name of the logger.</param> 
    public void CreateCustomLogFile(String TargetName, String TargetFileName, String LoggerName = "*") 
    { 
     try 
     { 
      var NLogTarget = LogManager.Configuration.FindTargetByName(TargetName); 

      if (NLogTarget == null) //Don't Re Add the Target 
      { 
       NLogTarget = new FileTarget() 
       { 
        Name = TargetName, 
        FileName = TargetFileName, 
        Layout = @"[${date:format=yyyy-MM-dd HH\:mm\:ss}] ${message}" 
       }; 

       LogManager.Configuration.AddTarget(TargetName, NLogTarget); 
      } 

      var NLogRule = new LoggingRule(LoggerName, NLogTarget); 
      NLogRule.EnableLoggingForLevel(LogLevel.Info); 
      NLogRule.EnableLoggingForLevel(LogLevel.Warn); 
      LogManager.Configuration.LoggingRules.Add(NLogRule); 

      LogManager.ReconfigExistingLoggers(); 
     } 
     catch { } 
    } 

    /// <summary> 
    /// Removes the custom log file. 
    /// </summary> 
    /// <param name="TargetName">Name of the target.</param> 
    public void RemoveCustomLogFile(String TargetName) 
    { 
     try 
     { 
      if (LogManager.Configuration.FindTargetByName(TargetName) != null) 
      { 
       var Target = LogManager.Configuration.FindTargetByName(TargetName); 

       foreach (var rule in LogManager.Configuration.LoggingRules) 
       { 
        rule.Targets.Remove(Target); 
       } 
       LogManager.Configuration.RemoveTarget(TargetName); 
       Target.Dispose(); 
       LogManager.ReconfigExistingLoggers(); 
      } 
     } 
     catch { } 
    } 

或參數添加到NLOG佈局

<target name="CTSCoreByPortNumber" xsi:type="File" 
    fileName="${logDirectory}/CTS${event-context:item=PortNumber}.log" 
    layout="${fulllayout}" /> 

實例函數寫入到正確的日誌。

/// <summary> 
    /// WriteLog - Overloaded Method to write a Message. 
    /// </summary> 
    /// <param name="LogType">LogLevel.Trace 
    /// LogLevel.Debug, 
    /// LogLevel.Info, 
    /// LogLevel.Warn, 
    /// LogLevel.Error, 
    /// LogLevel.Fatal,</param> 
    /// <param name="Msg">Message to write</param> 
    /// <param name="args">Arguments</param> 
    public void WriteLog(LogLevel LogType, String Msg, object[] args) 
    { 
     try 
     { 
      if (args == null) 
       args = new object[0]; 

      LogEventInfo logEvent = new LogEventInfo(LogType, GetCallingMethodName(), null, String.Format(Msg, args), null); 

      if (PortNumber != 0) 
       logEvent.Properties["PortNumber"] = ".Line_" + PortNumber; 

      Instance.Log(typeof(Logging), logEvent); 

      //Instance.Log((LogLevel)LogType, Msg, args); 
     } 
     catch (Exception) { throw; } 
    } 

在記錄之前,目標中的PortNumber由屬性代碼設置。

相關問題