我们知道 NLog 4.6.7 添加了对使用 NLog Layout 的支持,例如${gdc:globalLevel}
to 在运行时动态更改级别属性 https://github.com/nlog/NLog/wiki/Configure-from-code。更好的解决方案是如果可能的话升级您的 NLog。
更新:新解决方案
我在 4.5 版本上尝试了这段代码,效果很好。看来你不需要升级你的NLog版本。在这种情况下,所有配置均以编程方式设置。您可以在标题中发送您想要的级别:loglevel
。如果您发送loglevel
在标题中,它将被使用。否则,logLevel 将为Error
. See here https://github.com/NLog/NLog/wiki/Tutorial#configure-nlog-targets-for-output, 请。
注意:只需使用using NLog;
。你不需要using Microsoft.Extensions.Logging;
[Route("api/[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly Logger _log = LogManager.GetCurrentClassLogger();
[HttpGet]
public async Task<IEnumerable<string>> Get()
{
var requestLogLevel = Request.Headers.SingleOrDefault(x => x.Key == "loglevel");
LogLevel logLevel = LogLevel.Error;
switch (requestLogLevel.Value.ToString().ToLower())
{
case "trace":
logLevel = LogLevel.Trace;
break;
case "debug":
logLevel = LogLevel.Debug;
break;
case "info":
logLevel = LogLevel.Info;
break;
case "warn":
case "warning":
logLevel = LogLevel.Warn;
break;
case "error":
logLevel = LogLevel.Error;
break;
case "fatal":
logLevel = LogLevel.Fatal;
break;
}
var config = new NLog.Config.LoggingConfiguration();
var defaultMode = new NLog.Targets.FileTarget("defaultlog") { FileName = "log.txt" };
config.AddRule(logLevel, LogLevel.Fatal, defaultMode);
NLog.LogManager.Configuration = config;
_log.Trace("Some logs");
return new string[] { "value1", "value2" };
}
}
解决方案1)升级NLog到4.6.7或更高版本:
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;
解决方案 2) 以编程方式更改配置文件:因为你的版本NLog
不支持自动更改配置,我们将以编程方式更改它:
[Route("api/[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly Logger _log = LogManager.GetCurrentClassLogger();
// Special Authorization needed
public bool ChangeToDebugMode()
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(AppDomain.CurrentDomain.BaseDirectory + "nlog.config");
XmlNode root = doc.DocumentElement;
XmlNode myNode = root["include"].Attributes["file"];
myNode.Value = "debugmode.config";
doc.Save(AppDomain.CurrentDomain.BaseDirectory + "nlog.config");
}
catch (Exception)
{
return false;
}
return true;
}
// Special Authorization needed
public bool RestToDefault()
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(AppDomain.CurrentDomain.BaseDirectory + "nlog.config");
XmlNode root = doc.DocumentElement;
XmlNode myNode = root["include"].Attributes["file"];
myNode.Value = "defaultmode.config";
doc.Save(AppDomain.CurrentDomain.BaseDirectory + "nlog.config");
}
catch (Exception)
{
return false;
}
return true;
}
[HttpGet]
public async Task<IEnumerable<string>> Get()
{
_log.Trace("Some logs");
return new string[] { "value1", "value2" };
}
}
在这种情况下,您需要对配置文件进行一些更改。
你需要添加autoReload=true
到配置。现在,当任何配置发生更改时,NLog 会自动重新加载配置,您无需重新启动应用程序。你需要看看autoReload
and include
here https://github.com/nlog/NLog/wiki/Configure-from-code
nlog配置文件
<?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">
<include file="defaultmode.config" />
</nlog>
默认模式配置
<?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">
<targets>
<target name="logfile" xsi:type="File" fileName="file.txt" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
<!-- ... -->
</nlog>
调试模式配置
<?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">
<targets>
<target name="logfile" xsi:type="File" fileName="file.txt" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />
</rules>
<!-- ... -->
</nlog>
我制作了另外两个配置文件。debugmode.config
and defaultmode.config
。默认情况下nlog.config
file, deafultmode.config
已经包括了。什么时候ChangeToDebugMode
被调用,它变为debugmode.config
什么时候RestToDefault
被调用,它变为defaultmode.config
。我用了include
为了简单起见,将配置分成两个文件。
解决方案3)根据您的问题:在这种情况下,我使用了您在问题中提供的代码。如果您在请求标头中发送日志级别,它将被考虑。如果您不发送,它将使用您在配置中设置的默认值。因此,您无需在客户端更改应用程序。效果很好。调试时只需发送您想要的日志级别即可。
[Route("api/[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly Logger _log = LogManager.GetCurrentClassLogger();
[HttpGet]
public async Task<IEnumerable<string>> Get()
{
var requestLogLevel = Request.Headers.SingleOrDefault(x => x.Key == "loglevel");
LogLevel logLevel = LogLevel.Error;
switch (requestLogLevel.Value.ToString().ToLower())
{
case "trace":
logLevel = LogLevel.Trace;
break;
case "debug":
logLevel = LogLevel.Debug;
break;
case "info":
logLevel = LogLevel.Info;
break;
case "warn":
case "warning":
logLevel = LogLevel.Warn;
break;
case "error":
logLevel = LogLevel.Error;
break;
case "fatal":
logLevel = LogLevel.Fatal;
break;
}
SetMinLogLevel(logLevel);
_log.Trace("Some logs.");
return new string[] { "value1", "value2" };
}
public static void SetMinLogLevel(LogLevel NewLogLevel)
{
foreach (var rule in LogManager.Configuration.LoggingRules)
{
rule.EnableLoggingForLevel(NewLogLevel);
}
//Call to update existing Loggers created with GetLogger() or
//GetCurrentClassLogger()
LogManager.ReconfigExistingLoggers();
}
}
The problem is, this situation needs to send the log level every time.
In these screenshots, you see how to send log level in debugging mode.