如何使用 nlog 为每个线程创建单独的日志文件
How to create separate log files per thread using nlog
我有一个简单的 ASP.NET 应用程序,我想为每个请求创建单独的日志文件。该应用程序创建了日志文件,但我从日志文件中的其他线程获得了信息。我创建了一个 nlog.config 文件,我希望所有线程都使用它 file.Here 是配置文件的内容
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets async="true">
<!-- write logs to file -->
<target
xsi:type="File"
name="allfile"
fileName="c:/temp/nlog-Navigator-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|TraceIdentifier: ${aspnet-TraceIdentifier}|SessionId: ${aspnet-sessionid}|${message} ${exception:format=tostring}" />
<target
xsi:type="Console"
name="detailConsole"
layout="${level:truncate=4:lowercase=true}: ${aspnet-sessionid} - ${logger}[0] ${newline} ${message}${exception:format=tostring}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="allfile" />
<logger name="*" minlevel="Trace" writeTo="detailConsole" />
</rules>
</nlog>
我使用邮递员向应用程序发送多个请求。请求正文如下所示
{
"fileName": "testfileName1.txt"
}
我目前正在发送 4 个请求,创建的日志文件名是基于请求中的文件名。所以这意味着创建了 4 个名为 testfileName1.txt, testfileName2.txt, testfileName4.txt, testfileName4.txt
的日志文件。
这是我的控制器:
[HttpPost]
public async Task<IActionResult> Index([FromBody] JsonElement requestElement)
{
try
{
var myJsonString = JObject.Parse(requestElement.GetRawText());
var fileName = myJsonString["fileName"].ToString();
using (this._logger.BeginScope(fileName))
{
for (int i = 0; i < 10; i++)
{
await this.StartJobLogger(fileName);
this._logger.LogInformation($"File: {fileName}");
await Task.Delay(1000);
}
return this.Ok("done");
}
}
catch (Exception e)
{
throw;
}
finally
{
}
}
#region Private Methods
private Task StartJobLogger( string fileName)
{
var target = new FileTarget();
target.Name = fileName;
target.FileName = $"c:\temp\{Path.GetFileNameWithoutExtension(fileName)}.log";
target.Layout = "${longdate} ${threadid} ${callsite} ${level} ${message}";
var config = LogManager.Configuration;
config.AddTarget("testName", target);
var rule = new LoggingRule("*", NLog.LogLevel.Info, target);
config.LoggingRules.Add(rule);
LogManager.Configuration = config;
LogManager.GetLogger(fileName);
return Task.CompletedTask;
}
但是,第一个日志文件中正在写入以下内容。
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.6422 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName2.txt
2022-01-03 10:34:21.6422 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName2.txt
2022-01-03 10:34:21.6422 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName2.txt
2022-01-03 10:34:21.6422 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName2.txt
我只想将与第一个请求相关的信息记录在第一个日志文件中,将与第二个请求相关的信息记录在第二个文件中,依此类推。但这目前会创建包含混合信息的文件。
尝试这样做(使用 BeginScope 将 ScopeFileName-属性 注入 NLog MDLC):
[HttpPost]
public async Task<IActionResult> Index([FromBody] JsonElement requestElement)
{
try
{
var myJsonString = JObject.Parse(requestElement.GetRawText());
var fileName = myJsonString["fileName"].ToString();
// Pushing input-filename as scope-property, accessible from MDLC
using (this._logger.BeginScope(new [] { new KeyValuePair<string, object>("ScopeFileName", fileName) }))
{
for (int i = 0; i < 10; i++)
{
// REMOVED AS BROKEN -> await this.StartJobLogger(fileName);
this._logger.LogInformation($"File: {fileName}");
await Task.Delay(1000);
}
return this.Ok("done");
}
}
catch (Exception e)
{
throw;
}
finally
{
}
}
但请注意,获取用户输入并用作文件名可以用作攻击向量。
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<variable name="ScopeFileName" value="${mdlc:ScopeFileName:whenEmpty=Navigator}" />
<!-- the targets to write to -->
<targets async="true">
<!-- write logs to file -->
<target
xsi:type="File"
name="allfile"
fileName="c:/temp/${ScopeFileName}-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|TraceIdentifier: ${aspnet-TraceIdentifier}|SessionId: ${aspnet-sessionid}|${message} ${exception:format=tostring}" />
<target
xsi:type="Console"
name="detailConsole"
layout="${level:truncate=4:lowercase=true}: ${aspnet-sessionid} - ${logger}[0] ${newline} ${message}${exception:format=tostring}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="allfile" />
<logger name="*" minlevel="Trace" writeTo="detailConsole" />
</rules>
</nlog>
我有一个简单的 ASP.NET 应用程序,我想为每个请求创建单独的日志文件。该应用程序创建了日志文件,但我从日志文件中的其他线程获得了信息。我创建了一个 nlog.config 文件,我希望所有线程都使用它 file.Here 是配置文件的内容
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets async="true">
<!-- write logs to file -->
<target
xsi:type="File"
name="allfile"
fileName="c:/temp/nlog-Navigator-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|TraceIdentifier: ${aspnet-TraceIdentifier}|SessionId: ${aspnet-sessionid}|${message} ${exception:format=tostring}" />
<target
xsi:type="Console"
name="detailConsole"
layout="${level:truncate=4:lowercase=true}: ${aspnet-sessionid} - ${logger}[0] ${newline} ${message}${exception:format=tostring}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="allfile" />
<logger name="*" minlevel="Trace" writeTo="detailConsole" />
</rules>
</nlog>
我使用邮递员向应用程序发送多个请求。请求正文如下所示
{
"fileName": "testfileName1.txt"
}
我目前正在发送 4 个请求,创建的日志文件名是基于请求中的文件名。所以这意味着创建了 4 个名为 testfileName1.txt, testfileName2.txt, testfileName4.txt, testfileName4.txt
的日志文件。
这是我的控制器:
[HttpPost]
public async Task<IActionResult> Index([FromBody] JsonElement requestElement)
{
try
{
var myJsonString = JObject.Parse(requestElement.GetRawText());
var fileName = myJsonString["fileName"].ToString();
using (this._logger.BeginScope(fileName))
{
for (int i = 0; i < 10; i++)
{
await this.StartJobLogger(fileName);
this._logger.LogInformation($"File: {fileName}");
await Task.Delay(1000);
}
return this.Ok("done");
}
}
catch (Exception e)
{
throw;
}
finally
{
}
}
#region Private Methods
private Task StartJobLogger( string fileName)
{
var target = new FileTarget();
target.Name = fileName;
target.FileName = $"c:\temp\{Path.GetFileNameWithoutExtension(fileName)}.log";
target.Layout = "${longdate} ${threadid} ${callsite} ${level} ${message}";
var config = LogManager.Configuration;
config.AddTarget("testName", target);
var rule = new LoggingRule("*", NLog.LogLevel.Info, target);
config.LoggingRules.Add(rule);
LogManager.Configuration = config;
LogManager.GetLogger(fileName);
return Task.CompletedTask;
}
但是,第一个日志文件中正在写入以下内容。
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:20.0592 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.0805 12 MultiThreadLogging.Controllers.HomeController+<Index>d__2.MoveNext Info File: testfileName1.txt
2022-01-03 10:34:21.6422 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName2.txt
2022-01-03 10:34:21.6422 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName2.txt
2022-01-03 10:34:21.6422 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName2.txt
2022-01-03 10:34:21.6422 12 MultiThreadLogging.Controllers.HomeController.Index Info File: testfileName2.txt
我只想将与第一个请求相关的信息记录在第一个日志文件中,将与第二个请求相关的信息记录在第二个文件中,依此类推。但这目前会创建包含混合信息的文件。
尝试这样做(使用 BeginScope 将 ScopeFileName-属性 注入 NLog MDLC):
[HttpPost]
public async Task<IActionResult> Index([FromBody] JsonElement requestElement)
{
try
{
var myJsonString = JObject.Parse(requestElement.GetRawText());
var fileName = myJsonString["fileName"].ToString();
// Pushing input-filename as scope-property, accessible from MDLC
using (this._logger.BeginScope(new [] { new KeyValuePair<string, object>("ScopeFileName", fileName) }))
{
for (int i = 0; i < 10; i++)
{
// REMOVED AS BROKEN -> await this.StartJobLogger(fileName);
this._logger.LogInformation($"File: {fileName}");
await Task.Delay(1000);
}
return this.Ok("done");
}
}
catch (Exception e)
{
throw;
}
finally
{
}
}
但请注意,获取用户输入并用作文件名可以用作攻击向量。
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<variable name="ScopeFileName" value="${mdlc:ScopeFileName:whenEmpty=Navigator}" />
<!-- the targets to write to -->
<targets async="true">
<!-- write logs to file -->
<target
xsi:type="File"
name="allfile"
fileName="c:/temp/${ScopeFileName}-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|TraceIdentifier: ${aspnet-TraceIdentifier}|SessionId: ${aspnet-sessionid}|${message} ${exception:format=tostring}" />
<target
xsi:type="Console"
name="detailConsole"
layout="${level:truncate=4:lowercase=true}: ${aspnet-sessionid} - ${logger}[0] ${newline} ${message}${exception:format=tostring}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="allfile" />
<logger name="*" minlevel="Trace" writeTo="detailConsole" />
</rules>
</nlog>