NLog为每个线程单独的内存记录器
本文关键字:内存 记录器 单独 线程 NLog | 更新日期: 2023-09-27 18:03:14
我使用的是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。这并不一定像每个线程都有单独的日志文件那样干净,但总比什么都没有好。查看文档。好运。