C# ログ出力 その3 Serilog Wrapper

# ラッパークラス
```
using Serilog;
using Serilog.Context;
using System;
using System.Runtime.CompilerServices;

namespace WPF
{
    /// <summary>
    /// Serilogを使用してログを出力するためのラッパークラスです。
    /// </summary>
    public class LoggerWrapper
    {
        private readonly ILogger _logger;
        private static bool _isInitialized = false;

        /// <summary>
        /// ログの出力テンプレート
        /// </summary>
        private const string OutputTemplate = "| {Timestamp:yyyy-MM-dd HH:mm:ss.fff} | {Level:u4} | SourceContext:{SourceContext} | MethodName:{MethodName} | {Message:lj} | {NewLine}{Exception}";

        /// <summary>
        /// Serilogの初期化を行います。
        /// </summary>
        private static void Initialize()
        {
            Log.Logger = new LoggerConfiguration()
                // 最低出力レベル
                .MinimumLevel.Debug()
                // ファイル出力
                .WriteTo.File(
                    // ファイルパス
                    path: @"Logs\.txt",
                    // 出力テンプレート
                    outputTemplate: OutputTemplate,
                    // ファイルの最低出力レベル
                    restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information,
                    // ファイルローリング間隔
                    rollingInterval: RollingInterval.Day,
                    // ファイル保持数
                    retainedFileCountLimit: null,
                    // ファイル保持期間
                    retainedFileTimeLimit: null
                )
                // コンソール出力
                .WriteTo.Console(outputTemplate: OutputTemplate)
                // プロパティ出力用のエンリッチャー
                .Enrich.FromLogContext()
                .CreateLogger();

            _isInitialized = true;
        }

        /// <summary>
        /// <see cref="LoggerWrapper"/> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="classType">クラスの型情報</param>
        public LoggerWrapper(Type classType)
        {
            EnsureInitialized();
            _logger = Log.ForContext(classType);
        }

        /// <summary>
        /// Serilogが初期化されていない場合に初期化します。
        /// </summary>
        private static void EnsureInitialized()
        {
            if (!_isInitialized)
            {
                Initialize();
            }
        }

        /// <summary>
        /// メソッド名をログコンテキストに追加して指定されたログアクションを実行し、ログを出力します。
        /// </summary>
        /// <param name="logAction">ログを出力するアクション</param>
        /// <param name="message">ログメッセージ</param>
        /// <param name="methodName">メソッド名</param>
        private void LogWithMethodName(Action<string> logAction, string message, string methodName)
        {
            // メソッド名をログコンテキストに追加して指定されたログアクションを実行
            using (LogContext.PushProperty("MethodName", methodName))
            {
                logAction(message);
            }
        }

        /// <summary>
        /// Verbose レベルのログを出力します。
        /// </summary>
        public void Verbose(string message, [CallerMemberName] string methodName = "") =>
            LogWithMethodName(_logger.Verbose, message, methodName);

        /// <summary>
        /// Debug レベルのログを出力します。
        /// </summary>
        public void Debug(string message, [CallerMemberName] string methodName = "") =>
            LogWithMethodName(_logger.Debug, message, methodName);

        /// <summary>
        /// Information レベルのログを出力します。
        /// </summary>
        public void Information(string message, [CallerMemberName] string methodName = "") =>
            LogWithMethodName(_logger.Information, message, methodName);

        /// <summary>
        /// Warning レベルのログを出力します。
        /// </summary>
        public void Warning(string message, [CallerMemberName] string methodName = "") =>
            LogWithMethodName(_logger.Warning, message, methodName);

        /// <summary>
        /// Error レベルのログを出力します。
        /// </summary>
        public void Error(Exception exception, string message, [CallerMemberName] string methodName = "") =>
            LogWithMethodName(msg => _logger.Error(exception, msg), message, methodName);

        /// <summary>
        /// Fatal レベルのログを出力します。
        /// </summary>
        public void Fatal(Exception exception, string message, [CallerMemberName] string methodName = "") =>
            LogWithMethodName(msg => _logger.Fatal(exception, msg), message, methodName);
    }
}
```
# ログ出力
```
using System;

namespace WPF
{
    public class MyMainClass
    {
        public static void MainMethod()
        {
            var logger = new LoggerWrapper(typeof(MyMainClass));

            logger.Verbose("Verbose");
            logger.Debug("Debug");
            logger.Information("Information");
            logger.Warning("Warning");
            logger.Error(new Exception("Error"), "Error");
            logger.Fatal(new Exception("Fatal"), "Fatal");
        }
    }
}
```
# コンソール
```
| 2024-02-06 22:36:31.488 | DBUG | SourceContext:WPF.App | MethodName:MainMethod | Debug | 
| 2024-02-06 22:36:31.488 | INFO | SourceContext:WPF.App | MethodName:MainMethod | Information | 
| 2024-02-06 22:36:31.488 | WARN | SourceContext:WPF.App | MethodName:MainMethod | Warning | 
| 2024-02-06 22:36:31.488 | EROR | SourceContext:WPF.App | MethodName:MainMethod | Error | 
System.Exception: Error
| 2024-02-06 22:36:31.489 | FATL | SourceContext:WPF.App | MethodName:MainMethod | Fatal | 
System.Exception: Fatal
```