• 十全十美的文本日志类


    十全十美的文本日志类包含几个特点:

    1. 高性能,不卡不拖主进程.

    2. 多线程支持.

    3. 多进程支持.

    4. 灵活分类.

    5. 按不同大小,时间性要求存储.

    6. 备份清理机制.

    1. 高性能,不卡不拖主进程.

        绝对不能因写日志影响到主程序性能.

    2. 多线程支持.

        多线程不冲突,不漏记录.

    3. 多进程支持.

         多线程不冲突,不漏记录.

    4. 灵活分类.

        Error,Warn,Info......

    5. 按不同大小,时间性要求存储.

        可以按每5M写一个文件,按照每小时写一个文件,每天写一个文件.

    6. 备份清理机制.

        不能经常有人找到你说服务器D盘被日志写破了,不能经常有人找到你说怎么昨天的日志没有拉?

    下面的200多行的代码经过测试,仅是我写的一个完美分布式日志系统的一个独立写日志的类.请各大家采用吧,完全开源,敬请保留我的签名.

    1. 10个进程,每个进程最大线程数异步写500万条,一共5000万条 没有sleep的写完一条不漏.

    2. 日PV过亿的高压网上长期运行,不漏不卡不拖不带.

    附代码: Cofnig配置读取类自己写.

    using System;
    using System.IO;
    using System.Text;
    using System.Linq;
    using System.Threading;
    using System.Collections;
    using System.Diagnostics;
    using System.Collections.Generic;
    using System.Collections.Specialized;

    /// <summary>
    /// 作者: cl.carl wopani@gmail.com
    /// 日期:2010-06-02
    /// 完全开源,敬请保留我的签名.
    /// </summary>
    public class Log
    {
    static Encoding encode = Encoding.GetEncoding("GB2312");
    static string logPath = Config.LogPath;
    static string bakPath = Config.LogBakPath;
    static string logName = Config.LogName;
    static double bakLength = Config.LogBakLength;
    static int timedLog = Config.TimedLog;
    static int logAction = Config.LogAction;// (int)(LogAction.Error|LogAction.Info|LogAction.Warn);
    static object o = new object();
    static int refreshTime = Config.LogRefreshTime;
    static double clearHour = Config.LogClearHour;
    static DateTime bakTime = DateTime.Now;
    static DateTime clearTime = DateTime.Now;
    static Dictionary<LogAction, StringBuilder> logs = null;
    static Queue<KeyValuePair<LogAction, string>> logStack = null;
    static readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
    static readonly ReaderWriterLockSlim frwLock = new ReaderWriterLockSlim();
    static Mutex mut = null;
    static Thread proThread = null;
    static Log()
    {
    lock (o)
    {
    Init();
    }
    }

    static void Init()
    {
    try
    {
    if (Config.IsMutex)
    mut = new Mutex(false, "LogMutex");
    if (logAction < 0) return;
    FileInfo f = new FileInfo(logPath);
    if (!f.Directory.Exists) f.Directory.Create();
    Array acs = Enum.GetValues(typeof(LogAction));
    logs = new Dictionary<LogAction, StringBuilder>();
    foreach (LogAction ac in acs)
    {
    if (!logs.ContainsKey(ac)) logs.Add(ac, new StringBuilder());
    if ((logAction & (int)ac) != 0 && ac != LogAction.Write)
    Directory.CreateDirectory(logPath + ac.ToString());
    }
    logStack = new Queue<KeyValuePair<LogAction, string>>();
    if (logAction > -1 && (proThread == null || !proThread.IsAlive))
    {
    proThread = new Thread(WriteLog);
    proThread.IsBackground = true;
    proThread.Start();
    }
    }
    catch (Exception e) { e = null; }
    }

    public static void Write(string msg)
    {
    if (logAction >= 0)
    PushLog(LogAction.Write, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss::fff") + ":" + msg);
    }

    public static void Write(LogAction action, string msg)
    {
    if (logAction >= 0 && (logAction & (int)action) != 0)
    PushLog(action, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss::fff") + ":" + msg);
    }

    public static void Error(string msg)
    {
    if (logAction > -1 && (logAction & (int)LogAction.Error) != 0)
    PushLog(LogAction.Error, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss::fff") + ":" + msg);
    }

    public static void Info(string msg)
    {
    if (logAction > -1 && (logAction & (int)LogAction.Info) != 0)
    PushLog(LogAction.Info, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss::fff") + ":" + msg);
    }

    public static void Warn(string msg)
    {
    if (logAction > -1 && (logAction & (int)LogAction.Warn) != 0)
    PushLog(LogAction.Warn, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss::fff") + ":" + msg);
    }

    private static void PushLog(LogAction action, string msg)
    {
    try
    {
    if (logStack.Count > Config.SecurityMemNumber) return;
    KeyValuePair<LogAction, string> log = new KeyValuePair<LogAction, string>(action, msg);
    rwLock.EnterWriteLock();
    logStack.Enqueue(log);
    }
    catch (Exception e) { e = null; }
    finally { rwLock.ExitWriteLock(); }
    }

    static void WriteLog()
    {
    while (true)
    {
    Thread.Sleep(refreshTime);
    int count = 0;
    try
    {
    rwLock.EnterWriteLock();
    count = logStack.Count;
    int i = count;
    while (i > 0)
    {
    KeyValuePair<LogAction, string> log = logStack.Dequeue();
    i--;
    if (null != log.Value)
    {
    logs[log.Key].AppendLine(log.Value);
    }
    }
    }
    catch (Exception e) { e = null; }
    finally
    {
    rwLock.ExitWriteLock();
    }
    if (count > 0)
    {
    try
    {
    DateTime now = DateTime.Now;
    foreach (LogAction ac in logs.Keys)
    {
    if ((logAction & (int)ac) != 0)
    {
    string path = logPath;
    string bakDir = bakPath;
    string act = (ac != LogAction.Write ? (ac.ToString() + "\\") : "");
    bakDir += act;
    path += act;
    if (timedLog == 1)
    path += now.ToString("yyyy-MM-dd HH-00-00") + ".txt";
    else if (timedLog == 2)
    path += now.ToString("yyyy-MM-dd 00-00-00") + ".txt";
    else path += logName;
    StringBuilder sb = logs[ac];
    if (sb.Length > 0)
    {
    WriteMsg(sb.ToString(), path, Config.IsMutex);
    sb.Length = 0;
    BakLog(path, bakDir);
    }
    }
    }
    }
    catch (Exception e) { e = null; }
    }
    }
    }

    public static void WriteMsg(object msg, string logPath, bool isMutex)
    {
    if (!isMutex)
    {
    try
    {
    frwLock.EnterWriteLock();
    WriteMsg(msg, logPath);
    }
    catch (Exception e) { e = null; Init(); }
    finally
    {
    frwLock.ExitWriteLock();
    }
    return;
    }
    try
    {
    mut.WaitOne();
    WriteMsg(msg, logPath);
    }
    catch (Exception e) { e = null; Init(); }
    finally
    {
    mut.ReleaseMutex();
    }
    }

    public static void WriteMsg(object msg, string logPath)
    {
    try
    {
    using (StreamWriter sw = new StreamWriter(logPath, true, encode))
    {
    sw.Write(msg);
    }
    }
    catch (Exception e) { e = null; Init(); }
    }

    public static void DeleteExpirateFiles(string dir, DateTime expDate)
    {
    List<string> files = Directory.GetFileSystemEntries(dir, "*.txt").ToList().Where(x => ((File.GetLastWriteTime(x) < expDate))).ToList();
    foreach (string f in files)
    {
    File.Delete(f);
    }
    }

    static void BakLog(string logPath, string backDir)
    {
    try
    {
    DateTime now = DateTime.Now;
    TimeSpan span = now - bakTime;
    if (span.Minutes > 5) //每5分钟备份一次
    {
    FileInfo f = new FileInfo(logPath);
    if (f.Length > bakLength)
    {
    string path = backDir + now.ToString("yyyy-MM-dd HH-mm-ss") + ".txt";
    f.MoveTo(path);
    bakTime = DateTime.Now;
    }
    }
    span = now - clearTime;
    if (span.Minutes > 10) //每10分钟清理一次.
    {
    DirectoryInfo dirInfo = new DirectoryInfo(backDir);
    DateTime expDate = now.AddHours(-clearHour);
    DeleteExpirateFiles(backDir, expDate);
    clearTime = DateTime.Now;
    }
    }
    catch (Exception e) { e = null; Init(); }
    }

    }

    /// <summary>
    /// 根据需要扩展日志类型
    /// </summary>
    [Flags]
    public enum LogAction
    {
    Write = 1,
    Info = 2,
    Error = 4,
    Warn = 8,
    Get = 16,
    Set = 32,
    Seria = 64
    }

  • 相关阅读:
    使用片段嵌入进行文档搜索
    详解支持向量机
    使用NLP检测和对抗AI生成的假新闻
    Detectron2 API 之 config | 十五
    用Python可视化卷积神经网络
    六种用于文本分类的开源预训练模型
    解空间树(回溯算法,分支界限法)
    日记2
    C编程(C语言程序设计,大连理工大学MOOC)
    编程题(C/C++程序设计,同济大学mooc)
  • 原文地址:https://www.cnblogs.com/kcitwm/p/log.html
Copyright © 2020-2023  润新知