需求是这样,客户说在调试阶段需要随时跟踪日志,上线阶段需要关闭一些日志
但是几年前由于客户在开发的时候,没有严格的安装一些日志等级来使用 NLog,所以 log.Info("xxx") 这种随处可见。从今天的角度来说,调试的日志应该使用 log.Debug("xxx"),但是从代码的规模来说,已经不便于再去修改每一处地方。
好在 客户要关掉的日志有一些明显的特征
logger.Info($"Tx: {hex}");
比如像上面这样以 “Tx:” 开头的
在Nlog 初始化之前,可以使用他自己的配置文件来忽略掉这个日志
<nlog>
<rules>
<logger name="*" minlevel="Trace" writeTo="file">
<filters>
<when condition="starts-with('${message}', 'Tx:')" action="Ignore" />
</filters>
</logger>
</rules>
</nlog>
但是这样一来,我在服务端想要随时的打开和关闭这个设置就尤为麻烦了,尤其是这种配置如果放在 Android App 里面,修改配置还要修改 App 本地的文件,着显然是行不通的。所以目的是放在服务器端的数据库,通过远程的配置来刷新本地 App,这个时候需要从远程的服务器读取配置,在运行时改变 NLog 的行为。
下面写一个帮助类和一个控制台程序来测试这个功能
using Newtonsoft.Json.Linq;
using NLog;
using NLog.Config;
using NLog.Filters;
using NLog.Targets;
namespace Bestrane.Common
{
public class NLogConfigurator
{
public static void ConfigureGlobalLoggingRules(Target target, string loggerName, string jsonConfig)
{
// Get NLog configuration
LoggingConfiguration config = LogManager.Configuration;
// Parse the JSON configuration text
JObject configObject = JObject.Parse(jsonConfig);
string logLevel = configObject["LoggingLevel"].Value<string>();
LogLevel level = LogLevel.FromString(logLevel);
bool ignoreSwitch = configObject["LogIgnore"].Value<bool>();
JArray ignoreConditions = (JArray)configObject["LogIgnoreConditions"];
// Create a new rule
var rule = new LoggingRule(loggerName, level, target);
// Add condition filters based on the IgnoreSwitch value
if (ignoreSwitch)
{
foreach (var condition in ignoreConditions)
{
// Create a new condition filter
var conditionFilter = new ConditionBasedFilter
{
Condition = condition.ToString(),
Action = FilterResult.Ignore
};
rule.Filters.Add(conditionFilter);
}
}
// Add the new rule to the configuration
config.LoggingRules.Add(rule);
// Reconfigure NLog
LogManager.Configuration = config;
}
}
}
控制台程序
jsonConfig 是模拟配置文件的 Json字符串,可以从服务端的数据库读取出来
LoggingLevel 为当前使用的日志级别,例如设置为 Info ,那么下面 Debug 的日志就不会打印出来了
LogIgnore 为是否忽略,为True就会开启 LogIgnoreConditions 的条件过滤,那么满足条件的日志就不会打印出来,反正如果设置为 False,那么就不会按条件过滤了
至于 starts-with('${message}', 'Tx:') 这样的写法,不是我实现的解析,而是 NLog 自身支持的,需要时,自行去查阅 NLog 的资料
using System;
using Bestrane.Common;
using NLog.Targets;
namespace Bestrane.LoggingConsole
{
class Program
{
static void Main(string[] args)
{
string loggerName = "LcpApi";
string jsonConfig = @"
{
""LoggingLevel"": ""Info"",
""LogIgnore"": true,
""LogIgnoreConditions"": [
""starts-with('${message}', 'Tx:')"",
""starts-with('${message}', 'Rx:')"",
]
}";
var consoleTarget = new ConsoleTarget();
consoleTarget.Layout = "[${uppercase:${level}}] ${logger} - ${message}";
// Call the global logging rule configuration method at application startup
NLogConfigurator.ConfigureGlobalLoggingRules(consoleTarget, loggerName, jsonConfig);
NLog.Logger logger = NLog.LogManager.GetLogger(loggerName);
logger.Info("Info: start");
logger.Info("Tx: Info Sample log message");
logger.Info("Rx: Info Sample log message");
logger.Info("Info: end");
logger.Debug("Debug: start");
logger.Debug("Tx: Debug Sample log message");
logger.Debug("Rx: Debug Sample log message");
logger.Debug("Debug: end");
Console.ReadKey();
}
}
}