这是我第一次使用 NLog 包进行日志记录,但到目前为止,它使用起来很棒。
在我的场景中,我需要以编程方式初始化我的 NLog 日志记录配置设置,而不是通过更典型的配置文件方案。我已经对此进行了测试,并默认按照我想要的方式工作。但是,我将如何在运行时以编程方式修改我的设置呢?
这里最常见的情况可能是应用程序的默认日志记录级别设置为 ERROR,但特定模块中出现错误,我想将日志记录级别切换为更详细以跟踪错误。
我想写一个小的 Web 界面,这样我就可以在运行时轻松调整这些设置,但我想确保我采取了正确的方法。
我迟到了一年,但我刚刚遇到了类似的情况,我需要为用户提供记录器的动态控制。幸运的是,这对于 nlog 来说相对容易。在这里,我只是为已经创建的记录器启用跟踪级别日志记录,但显然您可以做任何您想做的事情,包括添加新的目标/规则,或者只是将记录器配置完全替换为以编程方式生成的记录器配置。
Basic ColoredConsole nlog.config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="ColoredConsole" name="c"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="c" />
</rules>
</nlog>
简单的控制台应用程序:
public class Program
{
//Initialize default Logger from config file
private static readonly Logger m_log = LogManager.GetCurrentClassLogger();
public static Logger Log
{
get { return m_log; }
}
public static void Main(string[] args)
{
Log.Trace("You won't see me because config is at LogLevel.Error");
EnabledTraceForAllRules();
Log.Trace("You will see me now though!");
//Pause console window
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
/* Prints:
2013-05-07 16:04:22.7050 TRACE You will see me now though!
Press any key to continue...
*/
}
public static void EnabledTraceForAllRules()
{
foreach(var rule in LogManager.Configuration.LoggingRules)
{
rule.EnableLoggingForLevel(LogLevel.Trace);
}
//Call to update existing Loggers created with GetLogger() or
//GetCurrentClassLogger()
LogManager.ReconfigExistingLoggers();
}
}
如果您需要从进程外部更改日志记录配置,并且必须以编程方式完成,我建议使用 WCF。您可以从应用程序或网站公开一个小型 WCF 服务,该服务提供用于重新配置 nlog 的方法。
我在NLog文档(https://github.com/NLog/NLog/wiki/Configure-from-code)中找到了"配置API",可能对您有所帮助。也看看NLog程序集中的NLog.Config命名空间。
另请参阅:https://github.com/NLog/NLog/wiki/Reinitialize-NLog-configuration
NLog 4.6.7引入了在LoggingRules中使用布局逻辑的功能。因此,您可以拥有一个带有日志记录规则的 NLog.config,这些规则可以在运行时轻松调整:
<nlog>
<variable name='myLevel' value='Warn'/>
<rules>
<logger minLevel='${var:myLevel}' writeTo="your-target-name" />
</rules>
</nlog>
然后可以在运行时更新myLevel
:
LogManager.Configuration.Variables["myLevel"] = "Debug";
LogManager.ReconfigExistingLoggers();
另请参阅:https://github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules
我看到答案一次启用一个级别,但是如果要镜像NLog.config文件的行为,其中设置单个级别也会启用所有较高优先级的级别(并禁用较低优先级的级别),则需要使用如下SetLoggingLevels
启用一系列级别:
NLog.config:
<rules>
<logger name="*" minlevel="Trace" writeTo="your-target-name" />
</rules>
法典:
public static void SetLogLevel(LogLevel newLogLevel)
{
foreach (var rule in LogManager.Configuration.LoggingRules)
{
foreach (var target in rule.Targets)
{
if (target.Name == "your-target-name")
{
rule.SetLoggingLevels(newLogLevel, LogLevel.Fatal);
}
}
}
LogManager.ReconfigExistingLoggers();
}
来自 NLog 文档:
public void SetLoggingLevels(LogLevel minLevel, LogLevel maxLevel);
允许记录(包含的)
minLevel
和 之间的级别maxLevel
.所有其他级别将被禁用。
using NLog;
private void SetLogLevel(LogLevel level)
{
LogManager.GlobalThreshold = level;
}
NLog教程页面上给出了一个编程初始设置示例,我在下面进行了介绍。(这里有一个稍微广泛的版本。
public static void Startup()
{
var config = new NLog.Config.LoggingConfiguration();
// Targets where to log to: File and Console
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "file.txt" };
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
// Rules for mapping loggers to targets
config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole);
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
// Apply config
NLog.LogManager.Configuration = config;
LogManager.ReconfigExistingLoggers();
}
然后,要更改日志级别(其中logconsole
是要更改的目标),请执行以下操作:
public static void SetConsoleLogLevel(LogLevel level)
{
foreach (var rule in LogManager.Configuration.LoggingRules)
{
foreach (var ruleTarget in rule.Targets)
{
if (ruleTarget != logconsole) continue;
DisableLoggingForLevels(rule, LogLevel.Trace, level);
rule.EnableLoggingForLevels(level, LogLevel.Fatal);
LogManager.GetCurrentClassLogger().Log(level, "Changed logger level to {0}", level);
}
}
LogManager.ReconfigExistingLoggers();
}
其中DisableLoggingForLevels
是一个与NLog.Config.LoggingRule.EnableLoggingForLevels
完全相同的私有方法,只是它禁用:
private static void DisableLoggingForLevels(LoggingRule rule, LogLevel minLevel, LogLevel maxLevel)
{
for (var ordinal = minLevel.Ordinal; ordinal <= maxLevel.Ordinal; ++ordinal)
rule.DisableLoggingForLevel(LogLevel.FromOrdinal(ordinal));
}
NLog 的大多数示例都使用某种 NLog 配置文件,但我希望拥有完全可重新配置的编程解决方案,如果您使用纯代码执行此操作 - 它可能看起来像这样:
var conf = new NLog.Config.LoggingConfiguration();
var consoletarget = new ColoredConsoleTarget() { Layout = "${message}" };
conf.AddTarget("console", consoletarget);
//conf.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Debug, consoletarget));
//conf.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Info, consoletarget));
conf.AddRuleForAllLevels(consoletarget);
NLog.LogManager.Configuration = conf;
var log = NLog.LogManager.GetLogger("hello");
log.Trace("trace");
log.Debug("debug");
log.Info("info");
log.Warn("warn");
log.Error("error");
log.Fatal("fatal");
我留下了一些注释的代码,以防万一您想重新配置将向最终用户显示的日志级别。(默认情况下将显示所有内容)