You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NLog中实现类似Log4Net的错误码日志,保留消息与整数错误码

解决方案

问题根源

你的调用logger.Error(3, "消息内容")被C#重载解析匹配到了NLog的Error(object message, params object[] args)方法,导致错误码3被当成了日志消息,第二个参数被当作未使用的格式化参数,最终只输出了3。

无需修改现有代码的解决步骤

1. 全局拦截日志事件,修正内容

在应用启动时添加以下代码,拦截NLog的日志事件,将错误码从消息字段转移到EventId,同时把原参数中的字符串作为日志消息:

using NLog;

// 在应用初始化阶段执行(比如Program.Main或Startup.Configure)
var config = LogManager.Configuration;
foreach (var rule in config.LoggingRules)
{
    foreach (var target in rule.Targets)
    {
        target.BeforeLogEvent += (sender, e) =>
        {
            // 仅处理Error级别的目标调用
            if (e.LogEvent.Level != LogLevel.Error) return;
            
            // 判断是否是错误码+消息的调用模式
            if (int.TryParse(e.LogEvent.Message, out int errorCode) && 
                e.LogEvent.Parameters?.Length == 1 && 
                e.LogEvent.Parameters[0] is string actualMessage)
            {
                // 修正日志事件:设置正确的消息和错误码
                e.LogEvent.Message = actualMessage;
                e.LogEvent.EventId = new EventId(errorCode);
                // 清空参数避免后续格式化干扰
                e.LogEvent.Parameters = Array.Empty<object>();
            }
        };
    }
}
// 重新加载配置使生效
LogManager.ReconfigExistingLoggers();

2. 配置NLog目标,分别存储错误码和消息

根据不同的日志目标调整配置,确保错误码以整数类型存储,消息正常输出:

文件日志示例
<target xsi:type="File" name="fileLog" fileName="logs/${shortdate}.log">
  <layout>${longdate} [${level}] ErrorId: ${eventid:format=D} - ${message}</layout>
</target>
EventLog示例
<target xsi:type="EventLog" name="eventLog" source="YourAppName" log="Application">
  <layout>${message}</layout>
  <eventId>${eventid:format=D}</eventId>
</target>
数据库日志示例(适配预留的错误码列)
<target xsi:type="Database" name="dbLog" connectionString="YourDbConnectionString">
  <commandText>
    INSERT INTO Logs (ErrorId, Message, LogLevel, CreateTime)
    VALUES (@ErrorId, @Message, @LogLevel, @CreateTime)
  </commandText>
  <!-- 错误码列指定为整数类型 -->
  <parameter name="@ErrorId" layout="${eventid:format=D}" dbType="Int32" />
  <parameter name="@Message" layout="${message}" />
  <parameter name="@LogLevel" layout="${level}" />
  <parameter name="@CreateTime" layout="${date:format=yyyy-MM-dd HH:mm:ss}" />
</target>

说明

  • 该方案仅处理Error(int, string)格式的调用,不会影响其他正常日志调用(如logger.Error("普通消息")或带占位符的格式化日志)。
  • 数据库配置中dbType="Int32"确保错误码以整数类型存入预留列,避免字符串转整数的问题。

内容的提问来源于stack exchange,提问作者cr45h0v3rwr173

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 02:01:29