ハロの外部記憶インターフェイス

そろそろ覚える努力が必要かも…

Microsoft.Extensions.Logging実装

Logger実装を試す、一旦、MS提供のLoggingクラスを実装してみた。 参考:C# でのログ記録 - .NET | Microsoft Learn

ILoggerには3つの実装処理があるが、一旦、Logだけにする。

IDisposable? BeginScope<TState>(TState state);
bool IsEnabled(LogLevel logLevel)
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
using Microsoft.Extensions.Logging;
    public class Logger(string name) : ILogger
    {
        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            LogFileWriter.AddQueue(_name, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{logLevel}] {formatter(state, exception)}");
        }
    }

※未実装のBeginScope、IsEnabledは省略している。

LogFileWriterについて

ファイルにログを記録する処理として、スレッドセーフで記載可能にする。

internal static class LogFileWriter
{
    private static ConcurrentQueue _queue = new();
    private static StreamWriter _writer;
    private static bool _isBusy = false;
}

タイマーにより、1秒ごとにPrint()処理を実行する。

private static Timer? _timer;
public static void StartAutoPrint()
{
    if (_timer == null) _timer = new Timer(_ => Print(), null, 0, 1000); // 1秒ごとにPrint
}

AddQueue:呼び元ごとにLogファイルを用意している。

public static void AddQueue(string sender, string msg)
{
    _queue[sender].Enqueue(msg);
    // タイマーが停止している場合は開始する
    if (_timer == null) StartAutoPrint(); 
}

Print():重複実行はスキップし、

public static void Print()
{
    if (_isBusy) return; // すでに実行中の場合は何もしない
    _isBusy = true;

    if (_writer == null)
    {
        _writer = new StreamWriter($"TestLogger.log", true, Encoding.UTF8);
    }
    
    while (_queue[key].TryDequeue(out string? o))
    {
        _writer[key].WriteLine(o);
    }
    _isBusy = false;
}

テスト

Logger logger = new Logger("TestLogger");
logger.LogDebug("This is a debug log message.");
logger.LogInformation("This is an information log message.");
logger.LogWarning("This is a warning log message.");
logger.LogError(new Exception("Test exception"), "This is an error log message.");
logger.LogCritical("This is a critical log message.");
logger.LogTrace("This is a trace log message.");

出力された!(TestLogger.log)

2025-06-13 17:39:21 [Debug] This is a debug log message.
2025-06-13 17:39:21 [Information] This is an information log message.
2025-06-13 17:39:21 [Warning] This is a warning log message.
2025-06-13 17:39:21 [Error] This is an error log message.
2025-06-13 17:39:21 [Critical] This is a critical log message.
2025-06-13 17:39:21 [Trace] This is a trace log message.