NLog 写入 .Net Core 3.1 中的多个日志
NLog write to multiple logs in .Net Core 3.1
我必须编写一个文件实用程序来读取导入文件和创建导出文件。我希望写入不同的 NLog 文件,具体取决于我是在处理导入文件还是创建导出文件。我今天一直在搜索和阅读不同的文章,但我要么没有搜索正确的东西,要么我只是不了解如何使用依赖注入写入不同的日志文件。
这是我正在尝试解决的基本概念。我 运行 一个控制台应用程序,它使用 JSON 文件读取文件设置列表。该文件 setting/config JSON 文件将有一个设置让我知道这是出站文件还是入站文件。因此,假设我正在使用的当前文件是一个出站文件,我会将它的日志记录写入我的 OutboundFiles.log 而不是我的 InboundFiles.log.
目前,我将以下内容与我创建的大多数 .Net Core 控制台应用程序一起使用,它将使用 _log(例如:_log.LogInformation)将其写入单个日志文件。我不明白的是我怎么能说出 _logOutbound.LogInformation 和 _logInbound.LogInformation 我会根据我正在使用的文件时间以及我将如何改变我的 NLog.config 文件用于不同的日志名称和目录。这是我当前用于写入单个文件的代码。
Program.cs
public class Program
{
static void Main(string[] args)
{
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("Initializing Program.Main");
var host = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Path.Combine(AppContext.BaseDirectory));
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
})
.ConfigureServices((context, services) =>
{
services.AddTransient<IAppHost, AppHost>();
services.AddLogging(builder =>
{
builder.AddNLog("nlog.config");
});
}).Build();
var application = ActivatorUtilities.CreateInstance<AppHost>(host.Services);
application.Run();
}
catch (Exception ex)
{
logger.Error("Stopped program setup with Error. {0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit
NLog.LogManager.Shutdown();
}
}
}
NLog.config
<?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">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<variable name="LogDirectory" value="D:\logs\ApplictionName"/>
<!-- the targets to write to -->
<targets>
<target xsi:type="File"
name="DefaultTarget"
fileName="${LogDirectory}\LogFile.log"
layout="${longdate} | ${callsite} | ${message}"
archiveAboveSize="3145728"
archiveEvery="Day"
archiveFileName = "${LogDirectory}/Archive/{#}.log"
archiveNumbering = "DateAndSequence"
archiveDateFormat = "yyyyMMdd"
maxArchiveFiles = "21"
/>
<target name="ConsoleTarget"
xsi:type="Console"
layout="${longdate} ${logger:shortName=True} ${message} ${onexception:EXCEPTION OCCURRED\:${exception:format=type,message,StackTrace,method:maxInnerExceptionLevel=8:innerFormat=type,message,StackTrace,method}}"
/>
</targets>
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
<logger name="*" minlevel="Debug" writeTo="DefaultTarget,ConsoleTarget" />
</rules>
</nlog>
AppHost.cs
public class AppHost : IAppHost
{
private readonly ILogger<AppHost> _log;
private readonly IConfiguration _configuration;
public AppHost(ILogger<AppHost> log, IConfiguration config)
{
_log = log;
_configuration = config;
}
public void Run()
{
_log.LogInformation("Application START");
try
{
//*** All code goes here ***
}
catch (Exception ex)
{
_log.LogError("Error: {0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
}
_log.LogInformation("Application END");
}
}
这是我将通读的 JSON 文件的一个基本示例。其中一个参数告诉我它将是一个出站文件,这是我将用来将任何日志记录写入 Outbound.log 文件的密钥。入站文件的工作方式相同。
"fileTypes": {
"FileName1":
{
"dayofweek": "MON",
"dayofmonth": "*",
"time": "23:00",
"inputFolder": "\servername\emft\inbound",
"inputFileName": "FileName.pgp",
"maxInputFiles": "1",
"minInputFiles": "1",
"inputDecryptionKey": "d:\PgpKeys\private\keyname.asc",
"outputFolder": "\servername\emft\outbound",
"outputFileName": "outfilename.txt.pgp",
"outputEncryptionKey": "d:\PgpKeys\public\keyname.asc",
"logFileType": "outbound"
}
}
问题更新
如果我的 NLog.config 文件中有多个目标,如下例所示,我该如何告诉 .Net Core 我要定位哪个目标?
例如,使用下面的目标,我如何告诉依赖注入我想创建一个名为 _logOutgoing 的对象以使用“OutgoingTarget”目标,_logIncoming 对象以“IncomingTarget”目标为目标,然后_log 使用“DefaultTarget”?然后,当我在我的控制台应用程序中工作时,如果我正在处理一个传入文件,我会在 _logIncoming 和 _logOutgoing 中写一些东西,如果我正在处理我的传出文件?
我找这样的东西的原因是为了做一份临时报告。 OutgoingTarget 和 IncomingTarget 将用于编写更多非技术报告,我将通过电子邮件将其发送给业务经理,以便他们知道发生了什么,而我将使用 DefaultTarget 供开发人员使用,并提供更多技术细节debugging/support 个原因。
这是我在研究中发现的一个例子。
<target xsi:type="File" name="DefaultTarget" fileName="C:/AVDS/Logs/MyApps/nlog-all-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-all.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
<target xsi:type="File" name="OutgoingTarget" fileName="C:/AVDS/Logs/MyApps/nlog-own-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-own.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
<target xsi:type="File" name="IncomingTarget" fileName="C:/AVDS/Logs/MyApps/nlog-errors-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-errors.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
修复尝试
我一定是漏了什么。我根据下面的示例添加了以下内容,但是 _logIncoming.LogInformation("Testing") 出现错误,提示“ILoggerFactory 不包含 LogInformation 的定义”。我仍然是依赖注入的新手,但我想知道是否需要在 Program.cs 文件中向我的 .ConfigureServices 添加一些内容?
已更新Apphost.cs
public class AppHost : IAppHost
{
private readonly ILogger<AppHost> _log;
private readonly IConfiguration _configuration;
private readonly ILoggerFactory _logIncoming;
private readonly ILoggerFactory _logOutgoing;
public AppHost(ILogger<AppHost> log, ILoggerFactory loggerFactory, IConfiguration config)
{
_log = log;
_logIncoming = (ILoggerFactory)loggerFactory.CreateLogger("IncomingLogger");
_logOutgoing = (ILoggerFactory)loggerFactory.CreateLogger("OutgoingLogger");
_configuration = config;
}
public void Run()
{
_log.LogInformation("Application START");
_logIncoming.LogInformation("Testing Incoming log.");
_logOutgoing.LogInformation("Testing outgoing log.");
}
}
Program.cs
var host = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Path.Combine(AppContext.BaseDirectory));
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
})
.ConfigureServices((context, services) =>
{
services.AddTransient<IAppHost, AppHost>();
services.AddLogging(builder =>
{
builder.AddNLog("nlog.config");
});
}).Build();
不确定我是否理解特定 import/export-files 应该如何影响 NLog 输出。所以我只是在这里随机猜测:
我可能会使用 ILogger.BeginScope
然后使用 NLog ${mdlc}
.
// You can inject several properties into the scope, or use Dictionary<string, object> instead of array
using (logger.BeginScope(new [] { new KeyValuePair<string, object>("ProcessFile", logFileName) }))
{
logger.LogInformation("Processing File ...");
}
然后在 NLog.config 中做这样的事情:
<nlog>
<variable name="LogDirectory" value="D:/logs/ApplictionName"/>
<variable name="LogProcessFile" value="${mdlc:ProcessFile:whenEmpty=LogFile}"/>
<targets>
<target xsi:type="File"
name="DefaultTarget"
fileName="${LogDirectory}/${LogProcessFile}.log"
layout="${longdate}|${message}" />
</targets>
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
<logger name="*" minlevel="Debug" writeTo="DefaultTarget" />
</rules>
</nlog>
然后 ILogger.BeginScope
内发生的所有日志记录都将转到专用文件。您可以让多个线程在各自的 ILogger.BeginScope
.
中同时处理
如果您想将输出重定向到 3 个不同的文件,那么您可以这样做:
public class AppHost : IAppHost
{
private readonly ILogger _log;
private readonly IConfiguration _configuration;
private readonly ILogger _logIncoming;
private readonly ILogger _logOutgoing;
public AppHost(ILoggerFactory loggerFactory, IConfiguration config)
{
_log = loggerFactory.CreateLogger(typeof(AppHost).ToString());
_logIncoming = loggerFactory.CreateLogger("IncomingLogger");
_logOutgoing = loggerFactory.CreateLogger("OutgoingLogger");
_configuration = config;
}
public void Run()
{
_log.LogInformation("Application START");
_logIncoming.LogInformation("IncomingTarget START");
_logOutgoing.LogInformation("OutgoingTarget START");
}
}
然后您可以将 Logger-name 映射到输出目标:
<nlog>
<variable name="LogDirectory" value="D:/logs/ApplictionName"/>
<variable name="LogProcessFile" value="${mdlc:ProcessFile:whenEmpty=LogFile}"/>
<targets>
<target xsi:type="File"
name="DefaultTarget"
fileName="${LogDirectory}/AppLog.log"
layout="${longdate}|${message}" />
<target xsi:type="IncomingTarget"
name="DefaultTarget"
fileName="${LogDirectory}/IncomingTarget.log"
layout="${longdate}|${message}" />
<target xsi:type="File"
name="OutgoingTarget"
fileName="${LogDirectory}/OutgoingTarget.log"
layout="${longdate}|${message}" />
</targets>
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
<logger name="IncomingLogger" minlevel="Debug" writeTo="IncomingTarget" final="true" />
<logger name="OutgoingLogger" minlevel="Debug" writeTo="OutgoingTarget" final="true" />
<logger name="*" minlevel="Debug" writeTo="DefaultTarget" />
</rules>
</nlog>
另请参阅:https://github.com/nlog/nlog/wiki/Configuration-file#rules
我必须编写一个文件实用程序来读取导入文件和创建导出文件。我希望写入不同的 NLog 文件,具体取决于我是在处理导入文件还是创建导出文件。我今天一直在搜索和阅读不同的文章,但我要么没有搜索正确的东西,要么我只是不了解如何使用依赖注入写入不同的日志文件。
这是我正在尝试解决的基本概念。我 运行 一个控制台应用程序,它使用 JSON 文件读取文件设置列表。该文件 setting/config JSON 文件将有一个设置让我知道这是出站文件还是入站文件。因此,假设我正在使用的当前文件是一个出站文件,我会将它的日志记录写入我的 OutboundFiles.log 而不是我的 InboundFiles.log.
目前,我将以下内容与我创建的大多数 .Net Core 控制台应用程序一起使用,它将使用 _log(例如:_log.LogInformation)将其写入单个日志文件。我不明白的是我怎么能说出 _logOutbound.LogInformation 和 _logInbound.LogInformation 我会根据我正在使用的文件时间以及我将如何改变我的 NLog.config 文件用于不同的日志名称和目录。这是我当前用于写入单个文件的代码。
Program.cs
public class Program
{
static void Main(string[] args)
{
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("Initializing Program.Main");
var host = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Path.Combine(AppContext.BaseDirectory));
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
})
.ConfigureServices((context, services) =>
{
services.AddTransient<IAppHost, AppHost>();
services.AddLogging(builder =>
{
builder.AddNLog("nlog.config");
});
}).Build();
var application = ActivatorUtilities.CreateInstance<AppHost>(host.Services);
application.Run();
}
catch (Exception ex)
{
logger.Error("Stopped program setup with Error. {0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit
NLog.LogManager.Shutdown();
}
}
}
NLog.config
<?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">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<variable name="LogDirectory" value="D:\logs\ApplictionName"/>
<!-- the targets to write to -->
<targets>
<target xsi:type="File"
name="DefaultTarget"
fileName="${LogDirectory}\LogFile.log"
layout="${longdate} | ${callsite} | ${message}"
archiveAboveSize="3145728"
archiveEvery="Day"
archiveFileName = "${LogDirectory}/Archive/{#}.log"
archiveNumbering = "DateAndSequence"
archiveDateFormat = "yyyyMMdd"
maxArchiveFiles = "21"
/>
<target name="ConsoleTarget"
xsi:type="Console"
layout="${longdate} ${logger:shortName=True} ${message} ${onexception:EXCEPTION OCCURRED\:${exception:format=type,message,StackTrace,method:maxInnerExceptionLevel=8:innerFormat=type,message,StackTrace,method}}"
/>
</targets>
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
<logger name="*" minlevel="Debug" writeTo="DefaultTarget,ConsoleTarget" />
</rules>
</nlog>
AppHost.cs
public class AppHost : IAppHost
{
private readonly ILogger<AppHost> _log;
private readonly IConfiguration _configuration;
public AppHost(ILogger<AppHost> log, IConfiguration config)
{
_log = log;
_configuration = config;
}
public void Run()
{
_log.LogInformation("Application START");
try
{
//*** All code goes here ***
}
catch (Exception ex)
{
_log.LogError("Error: {0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
}
_log.LogInformation("Application END");
}
}
这是我将通读的 JSON 文件的一个基本示例。其中一个参数告诉我它将是一个出站文件,这是我将用来将任何日志记录写入 Outbound.log 文件的密钥。入站文件的工作方式相同。
"fileTypes": {
"FileName1":
{
"dayofweek": "MON",
"dayofmonth": "*",
"time": "23:00",
"inputFolder": "\servername\emft\inbound",
"inputFileName": "FileName.pgp",
"maxInputFiles": "1",
"minInputFiles": "1",
"inputDecryptionKey": "d:\PgpKeys\private\keyname.asc",
"outputFolder": "\servername\emft\outbound",
"outputFileName": "outfilename.txt.pgp",
"outputEncryptionKey": "d:\PgpKeys\public\keyname.asc",
"logFileType": "outbound"
}
}
问题更新
如果我的 NLog.config 文件中有多个目标,如下例所示,我该如何告诉 .Net Core 我要定位哪个目标?
例如,使用下面的目标,我如何告诉依赖注入我想创建一个名为 _logOutgoing 的对象以使用“OutgoingTarget”目标,_logIncoming 对象以“IncomingTarget”目标为目标,然后_log 使用“DefaultTarget”?然后,当我在我的控制台应用程序中工作时,如果我正在处理一个传入文件,我会在 _logIncoming 和 _logOutgoing 中写一些东西,如果我正在处理我的传出文件?
我找这样的东西的原因是为了做一份临时报告。 OutgoingTarget 和 IncomingTarget 将用于编写更多非技术报告,我将通过电子邮件将其发送给业务经理,以便他们知道发生了什么,而我将使用 DefaultTarget 供开发人员使用,并提供更多技术细节debugging/support 个原因。
这是我在研究中发现的一个例子。
<target xsi:type="File" name="DefaultTarget" fileName="C:/AVDS/Logs/MyApps/nlog-all-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-all.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
<target xsi:type="File" name="OutgoingTarget" fileName="C:/AVDS/Logs/MyApps/nlog-own-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-own.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
<target xsi:type="File" name="IncomingTarget" fileName="C:/AVDS/Logs/MyApps/nlog-errors-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-errors.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
修复尝试
我一定是漏了什么。我根据下面的示例添加了以下内容,但是 _logIncoming.LogInformation("Testing") 出现错误,提示“ILoggerFactory 不包含 LogInformation 的定义”。我仍然是依赖注入的新手,但我想知道是否需要在 Program.cs 文件中向我的 .ConfigureServices 添加一些内容?
已更新Apphost.cs
public class AppHost : IAppHost
{
private readonly ILogger<AppHost> _log;
private readonly IConfiguration _configuration;
private readonly ILoggerFactory _logIncoming;
private readonly ILoggerFactory _logOutgoing;
public AppHost(ILogger<AppHost> log, ILoggerFactory loggerFactory, IConfiguration config)
{
_log = log;
_logIncoming = (ILoggerFactory)loggerFactory.CreateLogger("IncomingLogger");
_logOutgoing = (ILoggerFactory)loggerFactory.CreateLogger("OutgoingLogger");
_configuration = config;
}
public void Run()
{
_log.LogInformation("Application START");
_logIncoming.LogInformation("Testing Incoming log.");
_logOutgoing.LogInformation("Testing outgoing log.");
}
}
Program.cs
var host = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Path.Combine(AppContext.BaseDirectory));
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
})
.ConfigureServices((context, services) =>
{
services.AddTransient<IAppHost, AppHost>();
services.AddLogging(builder =>
{
builder.AddNLog("nlog.config");
});
}).Build();
不确定我是否理解特定 import/export-files 应该如何影响 NLog 输出。所以我只是在这里随机猜测:
我可能会使用 ILogger.BeginScope
然后使用 NLog ${mdlc}
.
// You can inject several properties into the scope, or use Dictionary<string, object> instead of array
using (logger.BeginScope(new [] { new KeyValuePair<string, object>("ProcessFile", logFileName) }))
{
logger.LogInformation("Processing File ...");
}
然后在 NLog.config 中做这样的事情:
<nlog>
<variable name="LogDirectory" value="D:/logs/ApplictionName"/>
<variable name="LogProcessFile" value="${mdlc:ProcessFile:whenEmpty=LogFile}"/>
<targets>
<target xsi:type="File"
name="DefaultTarget"
fileName="${LogDirectory}/${LogProcessFile}.log"
layout="${longdate}|${message}" />
</targets>
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
<logger name="*" minlevel="Debug" writeTo="DefaultTarget" />
</rules>
</nlog>
然后 ILogger.BeginScope
内发生的所有日志记录都将转到专用文件。您可以让多个线程在各自的 ILogger.BeginScope
.
如果您想将输出重定向到 3 个不同的文件,那么您可以这样做:
public class AppHost : IAppHost
{
private readonly ILogger _log;
private readonly IConfiguration _configuration;
private readonly ILogger _logIncoming;
private readonly ILogger _logOutgoing;
public AppHost(ILoggerFactory loggerFactory, IConfiguration config)
{
_log = loggerFactory.CreateLogger(typeof(AppHost).ToString());
_logIncoming = loggerFactory.CreateLogger("IncomingLogger");
_logOutgoing = loggerFactory.CreateLogger("OutgoingLogger");
_configuration = config;
}
public void Run()
{
_log.LogInformation("Application START");
_logIncoming.LogInformation("IncomingTarget START");
_logOutgoing.LogInformation("OutgoingTarget START");
}
}
然后您可以将 Logger-name 映射到输出目标:
<nlog>
<variable name="LogDirectory" value="D:/logs/ApplictionName"/>
<variable name="LogProcessFile" value="${mdlc:ProcessFile:whenEmpty=LogFile}"/>
<targets>
<target xsi:type="File"
name="DefaultTarget"
fileName="${LogDirectory}/AppLog.log"
layout="${longdate}|${message}" />
<target xsi:type="IncomingTarget"
name="DefaultTarget"
fileName="${LogDirectory}/IncomingTarget.log"
layout="${longdate}|${message}" />
<target xsi:type="File"
name="OutgoingTarget"
fileName="${LogDirectory}/OutgoingTarget.log"
layout="${longdate}|${message}" />
</targets>
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
<logger name="IncomingLogger" minlevel="Debug" writeTo="IncomingTarget" final="true" />
<logger name="OutgoingLogger" minlevel="Debug" writeTo="OutgoingTarget" final="true" />
<logger name="*" minlevel="Debug" writeTo="DefaultTarget" />
</rules>
</nlog>
另请参阅:https://github.com/nlog/nlog/wiki/Configuration-file#rules