2017-06-13 162 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由属性代码设置。