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

如何为Serilog自定义Sink实现outputTemplate参数并支持通用模板配置

Great question! Adding outputTemplate support to your custom Serilog sink is totally doable, and you can reuse Serilog's built-in template rendering logic to keep behavior consistent with official sinks like the Console sink. Here's how to implement it step by step:

Step 1: Add Required Usings

First, include these Serilog namespaces to access the template parsing and formatting utilities:

using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Display;
using System.IO;
Step 2: Update Your MySink Class

Instead of manually parsing the template string, use Serilog's MessageTemplateTextFormatter—this is the same class the official Console sink uses, so it handles all standard template syntax (like {Timestamp}, {Exception}, and format modifiers) out of the box.

Here's the revised sink code:

public class MySink : ILogEventSink
{
    private readonly MessageTemplateTextFormatter _templateFormatter;

    // Constructor accepts the output template and format provider
    public MySink(string outputTemplate, IFormatProvider formatProvider = null)
    {
        // Initialize the built-in formatter to handle template rendering
        _templateFormatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
    }

    public void Emit(LogEvent logEvent)
    {
        // Use a StringWriter to capture the formatted log output
        using var stringWriter = new StringWriter();
        
        // Let the formatter render the log event into the writer
        _templateFormatter.Format(logEvent, stringWriter);
        
        // Get the final formatted string
        string formattedLogEntry = stringWriter.ToString();

        // Replace this with your sink's actual output logic (e.g., write to file, API, etc.)
        Console.WriteLine(formattedLogEntry);
    }
}

What's Changed?

  • We replaced the raw outputTemplate string with a pre-initialized MessageTemplateTextFormatter—this parses the template once at sink creation (instead of every log event) for better performance.
  • The formatter handles all Serilog template rules, so your sink will behave consistently with official sinks.
  • In Emit, we use a StringWriter to capture the formatted log, then pass that string to your custom output logic.
Step 3: Add Extension Method for LoggerConfiguration

To enable the clean .WriteTo.MySink(outputTemplate: "...") syntax users expect, add an extension method for LoggerConfiguration:

public static class MySinkExtensions
{
    // Use the same default template as Serilog's Console sink for consistency
    private const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}";

    public static LoggerConfiguration MySink(
        this LoggerSinkConfiguration sinkConfiguration,
        string outputTemplate = DefaultOutputTemplate,
        IFormatProvider formatProvider = null)
    {
        // Validate input parameters
        if (sinkConfiguration == null)
            throw new ArgumentNullException(nameof(sinkConfiguration));
        if (string.IsNullOrWhiteSpace(outputTemplate))
            throw new ArgumentNullException(nameof(outputTemplate));

        // Create the sink instance and add it to the logger configuration
        var sink = new MySink(outputTemplate, formatProvider);
        return sinkConfiguration.Sink(sink);
    }
}

This method:

  • Provides a sensible default template (matching the Console sink) so users don't have to specify one.
  • Validates inputs to avoid common errors.
  • Wires up your custom sink to Serilog's configuration pipeline.
Step 4: Use Your Custom Sink

Now you can use your sink exactly like the official Console sink:

var logger = new LoggerConfiguration()
    .WriteTo.MySink(outputTemplate: "{Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}")
    .CreateLogger();

logger.Information("Hello from my custom sink!");
logger.Error(new InvalidOperationException("Test error"), "Something went wrong");
Key Takeaways
  • Consistency: Reusing MessageTemplateTextFormatter ensures your sink follows Serilog's standard template rules—users won't need to learn new syntax.
  • Performance: Parsing the template once at initialization is far more efficient than parsing it for every log event.
  • Flexibility: You can add custom logic (like filtering, enrichment, or sending to a unique destination) after rendering the formatted log string.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:47:31