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

如何将自定义NLog LayoutRenderer传递给Database Target参数?

问题分析与解决方案

你的核心误解在于混淆了LayoutRenderer的职责和日志数据载体的概念:你把自定义的LogMessage同时作为LayoutRenderer(日志渲染组件)和日志数据对象,但NLog的LayoutRenderer实例是由框架创建用于解析日志事件的,和你传入的日志数据对象完全是两个独立的实例,所以你设置的属性不会传递到LayoutRenderer中,最终只会执行Append方法里的固定文本。

下面提供两种可行的解决方案:


方案一:使用结构化日志(推荐,无需自定义LayoutRenderer)

直接将日志数据的属性注入到日志事件的属性集合中,通过NLog内置的${event-properties}布局渲染器读取。

代码修改

internal class Program {
    private static NLog.Logger logger = NLog.LogManager.Setup().GetCurrentClassLogger();
    static void Main(string[] args) {
        var message = new LogMessage() { 
            IncomingOrOutgoing = MessageDirection.Incoming, 
            MessageType = MessageType.TestType, 
            MessageKey = "TestKey", 
            Message = "Test Incoming" 
        };
        // 用结构化日志传递属性
        logger.Info("记录消息", 
            new { 
                MessageKey = message.MessageKey, 
                Message = message.Message, 
                IncomingOrOutgoing = message.IncomingOrOutgoing 
            });
    }
}

// 普通数据类,无需继承LayoutRenderer
public class LogMessage {
    public MessageDirection IncomingOrOutgoing { get; set; }
    public MessageType MessageType { get; set; }
    public string Message { get; set; }
    public string MessageKey { get; set; }
}

NLog配置修改

<target name="db"
        xsi:type="Database"
        connectionString="..."
        commandType="StoredProcedure"
        commandText="[dbo].[IncomingOutgoingMessageLog]">
    <parameter name="@MessageKey" layout="${event-properties:MessageKey}" />
    <parameter name="@Message" layout="${event-properties:Message}" />
    <parameter name="@IncomingOrOutgoing" layout="${event-properties:IncomingOrOutgoing}" />
</target>

方案二:自定义LayoutRenderer解析日志对象

如果坚持要用自定义LayoutRenderer,需要让它从日志事件中提取你传入的LogMessage对象,再根据参数输出对应属性。

代码修改

internal class Program {
    private static NLog.Logger logger = NLog.LogManager.Setup()
        .SetupExtensions(s => s.AutoLoadExtensions().RegisterLayoutRenderer<LogMessageRenderer>())
        .GetCurrentClassLogger();
    static void Main(string[] args) {
        var message = new LogMessage() { 
            IncomingOrOutgoing = MessageDirection.Incoming, 
            MessageType = MessageType.TestType, 
            MessageKey = "TestKey", 
            Message = "Test Incoming" 
        };
        // 直接传入LogMessage对象作为日志消息
        logger.Info(message);
    }
}

// 自定义LayoutRenderer,专门负责解析LogMessage对象
[LayoutRenderer("LogMessage")]
public class LogMessageRenderer : LayoutRenderer {
    [DefaultParameter]
    public string PropertyName { get; set; }

    protected override void Append(StringBuilder builder, LogEventInfo logEvent) {
        // 从日志事件中获取传入的LogMessage对象
        if (logEvent.MessageObject is LogMessage message) {
            switch (PropertyName) {
                case "MessageKey":
                    builder.Append(message.MessageKey);
                    break;
                case "Message":
                    builder.Append(message.Message);
                    break;
                case "IncomingOrOutgoing":
                    builder.Append(message.IncomingOrOutgoing.ToString());
                    break;
                default:
                    builder.Append("未知属性");
                    break;
            }
        }
    }
}

// 普通数据类
public class LogMessage {
    public MessageDirection IncomingOrOutgoing { get; set; }
    public MessageType MessageType { get; set; }
    public string Message { get; set; }
    public string MessageKey { get; set; }
}

NLog配置保持不变

<target name="db"
        xsi:type="Database"
        connectionString="..."
        commandType="StoredProcedure"
        commandText="[dbo].[IncomingOutgoingMessageLog]">
    <parameter name="@MessageKey" layout="${LogMessage:MessageKey}" />
    <parameter name="@Message" layout="${LogMessage:Message}" />
    <parameter name="@IncomingOrOutgoing" layout="${LogMessage:IncomingOrOutgoing}" />
</target>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:57:17