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

代码配置NLog无法写入数据库且无异常,求原因排查

排查NLog代码配置无法写入数据库且无异常的问题

我来帮你一步步排查这个NLog数据库日志不写入的问题——毕竟这种无异常的静默失败确实头疼,咱们从最常见的配置点开始查:

一、先检查数据库目标的核心配置项

这些是数据库目标工作的基础,缺一个都可能导致静默失败:

  • 连接字符串有效性:
    确保dbTarget2.ConnectionString是完全正确的,包含正确的服务器地址、数据库名、认证方式(比如Windows集成认证还是SQL账号密码)。可以单独用SqlConnection测试连接,比如:

    using (var conn = new SqlConnection("你的连接字符串"))
    {
        try
        {
            conn.Open();
            Console.WriteLine("连接成功");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"连接失败:{ex.Message}");
        }
    }
    

    如果连接本身失败,NLog不会抛出异常,但会在内部日志里记录。

  • SQL命令文本正确性:
    你的CommandText必须和数据库日志表的结构完全匹配,字段名、参数名不能错。举个标准的例子:

    dbTarget2.CommandText = "INSERT INTO Logs (LogLevel, LogMessage, CreatedTime, LoggerName) VALUES (@level, @message, @timestamp, @logger)";
    

    要确保表Logs已经存在,且字段类型对应(比如CreatedTime是datetime2类型,LogMessage是nvarchar(max))。

  • 参数映射是否齐全:
    每个SQL参数都要对应NLog的布局渲染器,不能漏:

    dbTarget2.Parameters.Add(new DatabaseParameterInfo("@level", "${level}"));
    dbTarget2.Parameters.Add(new DatabaseParameterInfo("@message", "${message}"));
    dbTarget2.Parameters.Add(new DatabaseParameterInfo("@timestamp", "${date:format=yyyy-MM-dd HH:mm:ss.fff}"));
    dbTarget2.Parameters.Add(new DatabaseParameterInfo("@logger", "${logger}"));
    

    参数名要和CommandText里的完全一致,大小写敏感(取决于数据库配置)。

二、检查NLog核心配置是否生效

很多时候是配置没正确应用到NLog引擎:

  • 是否将目标添加到配置并设置日志规则:
    你必须把数据库目标添加到LoggingConfiguration,并且创建日志规则指定哪些日志要写入这个目标:

    logConfig.AddTarget("dbTarget", dbTarget2);
    // 规则:所有日志记录器,Info及以上级别写入数据库目标
    logConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, dbTarget2));
    

    如果日志级别设得太高(比如LogLevel.Error),而你只输出了Info级别的日志,自然不会写入。

  • 是否将配置应用到LogManager:
    最后一定要把配置赋值给LogManager.Configuration,否则NLog会用默认配置,完全忽略你的代码配置:

    LogManager.Configuration = logConfig;
    
  • 是否正确使用Logger:
    要确保用LogManager.GetCurrentClassLogger()(或指定名称的记录器)获取Logger,并且输出的日志级别符合规则:

    var logger = LogManager.GetCurrentClassLogger();
    logger.Info("测试数据库日志"); // 这个级别要匹配规则里的级别
    

三、排查“无异常”的关键:开启NLog内部日志

NLog默认不会抛出配置或执行错误的异常,而是把细节记录在内部日志里。这是排查静默失败的核心手段:

添加这段代码在配置NLog之前:

// 开启内部日志,输出到文件
InternalLogger.LogFile = "nlog-internal.log";
// 设置日志级别为Trace,获取最详细的信息
InternalLogger.LogLevel = LogLevel.Trace;

运行程序后,打开nlog-internal.log,里面会清晰显示:

  • 数据库目标的初始化过程
  • 数据库连接尝试的结果
  • SQL语句的执行情况(比如语法错误、权限不足)
  • 任何被静默处理的错误

四、其他常见坑点

  • 数据库权限问题:确保应用程序使用的账号有日志表的INSERT权限。比如用Windows认证时,运行程序的用户需要有对应权限;用SQL账号时,账号要被授予INSERT权限。
  • 异步目标的刷新问题:如果用了AsyncTargetWrapper包装数据库目标,控制台程序结束前要调用LogManager.Shutdown(),确保异步队列里的日志被写入数据库,否则可能丢失日志。
  • 版本兼容性:确保NLog和NLog.Targets.Database的NuGet包版本一致,不同版本可能有配置差异。

完整示例代码

你可以对比自己的代码,看看哪里漏了:

using NLog;
using NLog.Config;
using NLog.Targets;
using System.Data.SqlClient;

namespace Test.Logger
{
    class Program
    {
        static void Main(string[] args)
        {
            // 开启内部日志排查问题
            InternalLogger.LogFile = "nlog-internal.log";
            InternalLogger.LogLevel = LogLevel.Trace;

            var logConfig = new LoggingConfiguration();

            // 配置数据库目标
            var dbTarget2 = new DatabaseTarget("dbTarget")
            {
                ConnectionString = "Server=.;Database=YourLogDB;Integrated Security=True;", // 替换为你的连接字符串
                CommandText = "INSERT INTO Logs (LogLevel, LogMessage, CreatedTime, LoggerName) VALUES (@level, @message, @timestamp, @logger)"
            };

            // 添加参数映射
            dbTarget2.Parameters.Add(new DatabaseParameterInfo("@level", "${level}"));
            dbTarget2.Parameters.Add(new DatabaseParameterInfo("@message", "${message}"));
            dbTarget2.Parameters.Add(new DatabaseParameterInfo("@timestamp", "${date:format=yyyy-MM-dd HH:mm:ss.fff}"));
            dbTarget2.Parameters.Add(new DatabaseParameterInfo("@logger", "${logger}"));

            // 添加目标到配置
            logConfig.AddTarget(dbTarget2);

            // 添加日志规则
            logConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, dbTarget2));

            // 应用配置
            LogManager.Configuration = logConfig;

            var logger = LogManager.GetCurrentClassLogger();
            logger.Info("这是一条测试数据库日志");
            logger.Error("这是一条错误日志");

            // 确保日志被刷新
            LogManager.Shutdown();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:51:27