NLog为每个线程单独的内存记录器



我使用的是NLog和Common Logging请找到我完整的代码片段

我也提到了当前输出和预期输出我想要每个线程单独的内存记录器,它们不应该相互交互。

设置
<targets>
    <target name="LogFile"
            xsi:type="File"
            fileName="${mdc:item=LogsDirectory}logfile.txt"
            layout="${message}"
            maxArchiveFiles="10"
            archiveAboveSize="20000000"
            archiveNumbering="Sequence"
            archiveFileName="${mdc:item=LogsDirectory}logfile.{#}.txt"/>
    <target name="Memory" xsi:type="Memory" layout="${message}"/>
</targets>`
<rules>
    <!-- add your logging rules here -->
    <logger name="LogFile" minlevel="Debug" writeTo="LogFile" />
    <logger name="LogFile" minlevel="Info" writeTo="Memory" />
</rules>
使用config: 的代码片段
static void Main(string[] args)
{
    List<Task> tasks = new List<Task>();
    for (int ctr = 1; ctr <= 3; ctr++)
    {
       tasks.Add(Task.Factory.StartNew(FirstWorldTask));
    }
    Task.WaitAll(tasks.ToArray());
}
private static void FirstWorldTask()
{
    var folderName = rnd.Next();
    var scenarioId = rnd.Next().ToString();
    Console.WriteLine(scenarioId);
    NLog.MappedDiagnosticsContext.Set("LogsDirectory", folderName);
    ILog logger = LogManager.GetLogger("LogFile");
    var memoryTarget = (MemoryTarget)NLog.LogManager.Configuration.FindTargetByName("Memory");
    memoryTarget.Logs.Clear();
    for (int i = 0; i < 5; i++)
    {
        logger.Info(i + " " + scenarioId);
        Thread.Sleep(10);
    }
    for (int i = 0; i < memoryTarget.Logs.Count; i++)
    {
        Console.WriteLine(memoryTarget.Logs[i] + " " + scenarioId);
    }
    memoryTarget.Logs.Clear();
}
随机数字

  • 960258078
  • 879841817
  • 1123570211

电流输出

  • 1 960258078 960258078
  • 0 1123570211 960258078
  • 1 879841817 960258078
  • 2 960258078 960258078
  • 1 1123570211 960258078
  • 2 879841817 960258078
  • 3 960258078 960258078
  • 2 1123570211 960258078
  • 3 879841817 960258078
  • 4 960258078 960258078
  • 3 1123570211 960258078
  • 4 879841817 960258078
  • 4 1123570211
预期输出

  • 0 960258078
  • 1 960258078 960258078
  • 2 960258078 960258078
  • 3 960258078 960258078
  • 4 960258078 960258078
  • 0 879841817
  • 1 879841817
  • 2 879841817
  • 3 879841817
  • 4 879841817
  • 0 1123570211
  • 1 1123570211
  • 2 1123570211
  • 3 1123570211
  • 4 1123570211
以编程方式使用 的代码片段
private static void FirstWorldTask()
{
    var folderName = rnd.Next();
    var scenarioId = rnd.Next().ToString();
    Console.WriteLine(scenarioId);
    NLog.MappedDiagnosticsContext.Set("LogsDirectory", folderName);
    ILog logger = LogManager.GetLogger("LogFile");
    var memoryTarget = new MemoryTarget();
    memoryTarget.Name = "Memory_" + scenarioId;
    memoryTarget.Layout = "${message}";
    var config = NLog.LogManager.Configuration;
    config.AddTarget(memoryTarget.Name, memoryTarget);
    var rule = new LoggingRule("LogFile", LogLevel.Info, memoryTarget);
    config.LoggingRules.Add(rule);
    NLog.LogManager.Configuration = config;
    for (int i = 0; i < 5; i++)
    {
        logger.Info(i + " " + scenarioId);
        Thread.Sleep(10);
    }
    while (memoryTarget.Logs.Count > 0)
    {
        int i = 0;
        while (memoryTarget.Logs.Count > 0 && i < 5)
        {
            Console.WriteLine(memoryTarget.Logs.First() + " " + scenarioId);
            memoryTarget.Logs.RemoveAt(0);
            i++;
        }
    }
}
随机数字

  • 903471573
  • 560466050
  • 898036495

程序输出

  • 560466050 560466050
  • 1 560466050 560466050
  • 0 898036495 560466050
  • 0 903471573 560466050
  • 1 898036495 560466050
  • 1 903471573 560466050
  • 2 560466050 560466050
  • 2 903471573 560466050
  • 3 560466050 560466050
  • 2 898036495 560466050
  • 3 903471573 560466050
  • 3 898036495 560466050
  • 4 560466050 560466050
  • 4 903471573 560466050
  • 0 560466050 903471573
  • 1 560466050 903471573
  • 0 898036495 903471573
  • 0 903471573
  • 1 898036495 903471573
  • 1 903471573
  • 2 560466050 903471573
  • 2 903471573
  • 3 560466050 903471573
  • 2 898036495 903471573
  • 3 903471573
  • 3 898036495 903471573
  • 4 560466050 903471573
  • 4 903471573
  • 0 560466050 898036495
  • 1 560466050 898036495
  • 0 898036495
  • 0 903471573 898036495
  • 1 898036495 898036495
  • 1 903471573 898036495
  • 2 560466050 898036495
  • 2 903471573 898036495
  • 3 560466050 898036495
  • 2 898036495
  • 3 903471573 898036495
  • 3 898036495
  • 4 560466050 898036495
  • 4 903471573 898036495
  • 4 898036495 898036495

日志被写入所有的memorytarget,而不是只有一个

这个问题在Github上讨论过。

目标应该有固定的名称(所以不是布局渲染器),所以目标和规则应该以编程方式创建。一个代码示例:

private static Random rnd = new Random();
private static object sync = new object();
static void Main(string[] args)
{
    List<Task> tasks = new List<Task>();
    // Execute the task 10 times.
    for (int ctr = 1; ctr <= 5; ctr++)
    {
        tasks.Add(Task.Factory.StartNew(FirstWorldTask));
        Thread.Sleep(10);
    }
    Task.WaitAll(tasks.ToArray());
}
private static void FirstWorldTask()
{
    string loggerName = "Logger";
    string randomName = rnd.Next().ToString(); //or GUID
    string targetFileName = "File";
    string targetMemoryName = "Memory";
    lock (sync)
    {
        //or using threadid here?
        loggerName += randomName;
        targetFileName += randomName;
        targetMemoryName += randomName;
        Console.WriteLine(loggerName);
    }
    var MB20 = 20 * 1024 * 1024;
    var fileTarget = new FileTarget(targetFileName)
    {
        ArchiveAboveSize = MB20,
        Layout = "${message}",  //probably you need more here
        FileName = "./" + randomName + "/logfile.txt",

    };
    LogManager.Configuration.AddTarget(fileTarget);
    LogManager.Configuration.AddRule(LogLevel.Info, LogLevel.Fatal, fileTarget, loggerName); //filter on loggerName;

    var memTarget = new MemoryTarget(targetMemoryName)
    {
        Layout = "${message}", //probably you need more here
    };
    LogManager.Configuration.AddTarget(memTarget);
    LogManager.Configuration.AddRule(LogLevel.Info, LogLevel.Fatal, memTarget, loggerName); //filter on loggerName;

    var m_log = LogManager.GetLogger(loggerName);

    for (int i = 0; i < 5; i++)
    {
        m_log.Info(i + " " + randomName);
        Thread.Sleep(10);
    }
    StringBuilder stringBuilder = new StringBuilder();
    foreach (var loggingEvent in memTarget.Logs)
    {
        stringBuilder.AppendLine(loggingEvent);
    }
    memTarget.Logs.Clear();
    Console.WriteLine(stringBuilder.ToString());
}

我不是很熟悉Nlog,但更熟悉Log4net。这些工具不是为特定于线程而设计的。如果您关心记录哪个线程正在做什么,可能有一个配置为您在日志的每行中包含线程ID。这并不一定像每个线程都有单独的日志文件那样干净,但总比什么都没有好。查看文档。好运。

最新更新