Serilog EventSink 客製化

Serilog 本身提供的 Sinks 已很足夠,可寫入多種標的,然而還是有全客製化的需求。查到可用【Serilog.Sinks.PeriodicBatching】來客製化寫入的標的。

開發環境

IDE:Visual Studio 2022

.NET6

Blazor Server App

參考文件

自訂 Serilog Sink

源碼紀錄

自訂Serilog

using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Configuration;
using Serilog.Events;
using Serilog.Sinks.PeriodicBatching;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;

namespace YourProject.Models;

/// <summary>
/// 客製化 Serilog 寫入對象
/// </summary>
/// <see cref="[Serilog.Sinks.PeriodicBatching](https://github.com/serilog/serilog-sinks-periodicbatching)"/>
class CustomSerilogEventSink : IBatchedLogEventSink
{
    readonly Uri _actionLogUri;
    public CustomSerilogEventSink(IConfiguration Configuration)
    {
        _actionLogUri = new Uri(Configuration["ActionLogUri"]);
    }

    Task IBatchedLogEventSink.EmitBatchAsync(IEnumerable<LogEvent> batch)
    {
        foreach (var logEvent in batch)
            DoPostActionLog(logEvent);

        return Task.CompletedTask;
    }

    /// 自訂 log 寫入標的
    void DoPostActionLog(LogEvent info)
    {
        try
        {
            var restrictedToMinimumLevel = LogEventLevel.Information;
            if (info.Level < restrictedToMinimumLevel)
                return;            

            var actLog = new ActionLog {info...} 
            
            var http = new HttpClient();
            http.PostAsJsonAsync<ActionLog>(_actionLogUri, actLog);
        }
        catch { /* 寫入log失敗也要繼續執行。 */ }
    }

    Task IBatchedLogEventSink.OnEmptyBatchAsync()
    {
        return Task.CompletedTask;   
    }
}

/// 自訂 Serilog Event Sink 組態的位置
public static class CustomSerilogEventSinkConfiguration
{
    public static LoggerConfiguration CustomSerilogSink(this LoggerSinkConfiguration loggerSinkConfiguration, IConfiguration Configuration)
    {
        var batchSink = new CustomSerilogEventSink(Configuration);

        var batchingOptions = new PeriodicBatchingSinkOptions
        {
            BatchSizeLimit = 100,
            Period = TimeSpan.FromSeconds(2),
            EagerlyEmitFirstEvent = true,
            QueueLimit = 10000
        };

        var batchingSink = new PeriodicBatchingSink(batchSink, batchingOptions);

        return loggerSinkConfiguration.Sink(batchingSink);
    }
}

系統初始化

public class Program
{
  public static void Main(string[] args)
  {
    #region Serilog configuration.
    ... 
    Log.Logger = new LoggerConfiguration()
      .WriteTo.Async(cfg =>
      {
        //# 文字檔
        cfg.File("Log/applog.txt",
        	rollingInterval: RollingInterval.Day,
        	restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information);
        //# JSON 檔
        cfg.File(new Serilog.Formatting.Json.JsonFormatter(), "Log/applog.json",
        	rollingInterval: RollingInterval.Day,
        	restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information);

        //# 自訂 Serilog Logger Sink
        cfg.CustomSerilogSink(Configuration);

      }).CreateLogger();
    #endregion
    ...
    ...
    ...
  }	
}

Last updated