博主头像
阿柒の站

一名躺平程序员,每天只想着躺平
(┬┬﹏┬┬)

C# 日志记录方案

一个不依赖框架、灵活的日志记录类。

优点:

  • 不依赖其他框架,极简灵活。
  • 分块存储,不怕单文件过大。
  • 写日志时自动检测创建文件,不担心删除文件后写入不了。
  • 随用随调,静态实现,任何地方直接调用就能记录日志。

Logs.cs

public static class Logs
{
    private static readonly ConcurrentQueue<(string Level, string Message, DateTime Time)> LogQueue = new();
    private static readonly CancellationTokenSource TokenSource = new();
    private static readonly string LogRoot = Path.Combine(AppContext.BaseDirectory, "Log"); // 存储路径,默认程序根目录下的Log文件夹下
    private static readonly long MaxFileSize = 5 * 1024 * 1024; // 5MB
    private static DateTime _lastLogTime = DateTime.MinValue;
    private static readonly object WriteLock = new();

    static Logs()
    {
        Task.Factory.StartNew(ProcessQueue, TaskCreationOptions.LongRunning);
    }

    public static void Info(string message) => Enqueue("info", message); // 详情记录
    public static void Error(string message) => Enqueue("error", message); // 错误记录
    // 可继续扩展...

    private static void Enqueue(string level, string message)
    {
        LogQueue.Enqueue((level.ToLower(), message, DateTime.Now));
    }

    private static async Task ProcessQueue()
    {
        while (!TokenSource.IsCancellationRequested)
        {
            while (LogQueue.TryDequeue(out var entry))
            {
                try
                {
                    WriteLog(entry.Level, entry.Message, entry.Time);
                }
                catch
                {
                    // 可扩展重试逻辑或写入到 fallback 文件
                }
            }
            await Task.Delay(100); // 避免空转
        }
    }

    private static void WriteLog(string level, string message, DateTime time)
    {
        var basePath = Path.Combine(LogRoot, time.ToString("yyyy_MM"));
        Directory.CreateDirectory(basePath);

        var filePrefix = Path.Combine(basePath, $"{time:dd}_{level}");
        var filePath = GetAvailableLogFile(filePrefix);

        var content = $"[{time:yyyy-MM-dd HH:mm:ss.fff}] {message}{Environment.NewLine}";

        lock (WriteLock)
        {
            File.AppendAllText(filePath, content, Encoding.UTF8);
        }

        _lastLogTime = time;
    }

    private static string GetAvailableLogFile(string basePath)
    {
        for (int i = 0; i < 1000; i++)
        {
            var filePath = i == 0 ? $"{basePath}.txt" : $"{basePath}_{i}.txt";
            if (!File.Exists(filePath) || new FileInfo(filePath).Length < MaxFileSize)
                return filePath;
        }

        throw new IOException("日志文件已超过最大数量限制");
    }

    public static void Stop()
    {
        TokenSource.Cancel();
    }
}

使用示例:

Logs.Info("记录详情日志");
Logs.Error("记录错误日志");
C# 日志记录方案
https://wc.sb/23
本文作者 阿柒
发布时间 2025-09-11
许可协议 CC BY-NC-SA 4.0
发表新评论