1

我正在使用 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>

使用配置的代码片段:

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 1123570211

预期产出

  • 0 960258078 960258078
  • 1 960258078 960258078
  • 2 960258078 960258078
  • 3 960258078 960258078
  • 4 960258078 960258078
  • 0 879841817 879841817
  • 1 879841817 879841817
  • 2 879841817 879841817
  • 3 879841817 879841817
  • 4 879841817 879841817
  • 0 1123570211 1123570211
  • 1 1123570211 1123570211
  • 2 1123570211 1123570211
  • 3 1123570211 1123570211
  • 4 1123570211 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

程序输出

  • 0 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 903471573
  • 1 898036495 903471573
  • 1 903471573 903471573
  • 2 560466050 903471573
  • 2 903471573 903471573
  • 3 560466050 903471573
  • 2 898036495 903471573
  • 3 903471573 903471573
  • 3 898036495 903471573
  • 4 560466050 903471573
  • 4 903471573 903471573
  • 0 560466050 898036495
  • 1 560466050 898036495
  • 0 898036495 898036495
  • 0 903471573 898036495
  • 1 898036495 898036495
  • 1 903471573 898036495
  • 2 560466050 898036495
  • 2 903471573 898036495
  • 3 560466050 898036495
  • 2 898036495 898036495
  • 3 903471573 898036495
  • 3 898036495 898036495
  • 4 560466050 898036495
  • 4 903471573 898036495
  • 4 898036495 898036495

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

4

2 回答 2

1

这个问题在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());
}
于 2016-09-07T20:50:35.383 回答
0

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

于 2016-08-19T05:55:23.007 回答