如何让NLog选择性地将日志记录到两个不同的MemoryTarget?
解决NLog每个类实例绑定专属MemoryTarget的问题
你遇到的问题根源在于SimpleConfigurator.ConfigureForTargetLogging是全局配置——每次调用它都会替换NLog的全局日志配置,所以最后一次初始化会覆盖之前所有的设置,导致所有日志器都指向最后一个MemoryTarget。
要实现每个类实例的日志单独发送到自己的MemoryTarget,我们需要为每个实例创建独立的日志器标识和专属的路由规则,而不是依赖全局配置。下面是具体的实现步骤和代码示例:
核心思路
- 给每个实例的MemoryTarget分配唯一名称(比如结合实例ID、GUID或自定义标识)
- 为每个实例创建独立的NLog配置,添加对应的MemoryTarget和仅匹配当前实例日志器的路由规则
- 使用这个专属配置初始化当前实例的日志器,确保日志只会流向自己的MemoryTarget
代码实现示例
using NLog; using NLog.Targets; using System.Collections.Generic; public class LoggedService { // 当前实例专属的MemoryTarget private readonly MemoryTarget _instanceMemoryTarget; // 当前实例专属的日志器 private readonly Logger _instanceLogger; // 构造函数接收实例标识,确保每个实例的目标和日志器唯一 public LoggedService(string instanceIdentifier) { // 1. 初始化带唯一名称的MemoryTarget _instanceMemoryTarget = new MemoryTarget { Name = $"InstanceMemoryTarget_{instanceIdentifier}", Layout = "${date:format=HH:mm:ss} ${level:uppercase=true} ${message}" // 自定义日志格式 }; // 2. 创建专属的日志配置 var instanceConfig = new LoggingConfiguration(); // 将当前实例的MemoryTarget添加到配置中 instanceConfig.AddTarget(_instanceMemoryTarget.Name, _instanceMemoryTarget); // 3. 创建路由规则:仅匹配当前实例的日志器名称,将所有级别的日志发送到专属目标 var loggerUniqueName = $"LoggedService_{instanceIdentifier}"; var loggingRule = new LoggingRule(loggerUniqueName, LogLevel.Trace, _instanceMemoryTarget); instanceConfig.LoggingRules.Add(loggingRule); // 4. 使用专属配置初始化日志器 _instanceLogger = LogManager.GetLogger(loggerUniqueName, instanceConfig); } // 示例日志方法 public void LogOperation(string operationDetails) { _instanceLogger.Info($"执行操作:{operationDetails}"); } // 获取当前实例的所有日志 public List<string> GetInstanceLogs() { return _instanceMemoryTarget.Logs.ToList(); } }
关键细节解释
- 唯一标识:通过
instanceIdentifier确保每个实例的MemoryTarget名称和日志器名称不重复,避免规则冲突 - 独立配置:每个实例的
LoggingConfiguration是独立的,不会影响全局配置或其他实例的配置 - 精准路由:
LoggingRule指定了仅匹配当前实例的日志器名称,所以只有这个日志器输出的日志会被路由到对应的MemoryTarget
使用示例
// 创建两个不同的实例 var service1 = new LoggedService("Service_001"); var service2 = new LoggedService("Service_002"); // 各自记录日志 service1.LogOperation("用户登录"); service2.LogOperation("数据导出"); // 获取各自的日志,互相独立 var logs1 = service1.GetInstanceLogs(); var logs2 = service2.GetInstanceLogs();
这样每个实例的日志都会单独存储在自己的MemoryTarget中,不会出现互相覆盖的问题。
内容的提问来源于stack exchange,提问作者Pinco Pallino
相关产品推荐
相关产品推荐

