zqlovejyc 发表于 2018-11-16 09:08

C# 自己封装的高性能日志记录类库

本帖最后由 zqlovejyc 于 2018-11-16 10:26 编辑

1.代码如下。测试图就不发了,绝对高性能,支持高并发,更多类库请访问本人的开源项目,网址:https://gitee.com/zqlovejyc/ZqUtils

using System;
using System.Collections.Concurrent;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace Drumbeat.Util.Log
{
    /// <summary>
    /// 日志工具类
    /// </summary>
    public class LogHelper
    {
      #region 私有变量
      /// <summary>
      /// 线程安全队列
      /// </summary>
      private static readonly ConcurrentQueue<LogMessage> _que;

      /// <summary>
      /// 信号
      /// </summary>
      private static readonly ManualResetEvent _mre;

      /// <summary>
      /// 日志写锁
      /// </summary>
      private static readonly ReaderWriterLockSlim _lock;
      #endregion

      #region 构造函数
      /// <summary>
      /// 构造函数
      /// </summary>
      static LogHelper()
      {
            _que = new ConcurrentQueue<LogMessage>();
            _mre = new ManualResetEvent(false);
            _lock = new ReaderWriterLockSlim();
            Task.Run(() => Initialize());
      }
      #endregion

      #region 信息日志
      /// <summary>
      /// 信息日志
      /// </summary>
      /// <param name="message">日志内容</param>
      /// <param name="args">字符串格式化参数</param>
      public static void Info(string message, params object[] args)
      {
            var sf = new StackTrace(true).GetFrame(1);
            var logMessage = new LogMessage
            {
                Level = LogLevel.Info,
                Message = string.Format(Regex.Replace(message?.Replace("{", "{{").Replace("}", "}}") ?? "", @"{{(\d+)}}", "{$1}"), args),
                StackFrame = sf
            };
            _que.Enqueue(logMessage);
            _mre.Set();
      }
      #endregion

      #region 错误日志
      /// <summary>
      /// 错误日志
      /// </summary>
      /// <param name="ex">错误Exception</param>
      /// <param name="message">自定义信息</param>
      /// <param name="args">字符串格式化参数</param>
      public static void Error(string message, params object[] args)
      {
            var sf = new StackTrace(true).GetFrame(1);
            var logMessage = new LogMessage
            {
                Level = LogLevel.Error,
                StackFrame = sf,
                Message = string.Format(Regex.Replace(message?.Replace("{", "{{").Replace("}", "}}") ?? "", @"{{(\d+)}}", "{$1}"), args),
            };
            _que.Enqueue(logMessage);
            _mre.Set();
      }

      /// <summary>
      /// 错误日志
      /// </summary>
      /// <param name="ex">错误Exception</param>
      /// <param name="message">自定义信息</param>
      /// <param name="args">字符串格式化参数</param>
      public static void Error(Exception ex, string message = "", params object[] args)
      {
            StackFrame sf = null;
            if (ex != null)
            {
                var frames = new StackTrace(ex, true).GetFrames();
                sf = frames?;
            }
            else
            {
                sf = new StackTrace(true).GetFrame(1);
            }
            var logMessage = new LogMessage
            {
                Level = LogLevel.Error,
                Exception = ex,
                Message = string.Format(Regex.Replace(message?.Replace("{", "{{").Replace("}", "}}") ?? "", @"{{(\d+)}}", "{$1}"), args),
                StackFrame = sf
            };
            _que.Enqueue(logMessage);
            _mre.Set();
      }
      #endregion

      #region 私有方法/实体
      #region 日志初始化
      /// <summary>
      /// 日志初始化
      /// </summary>
      private static void Initialize()
      {
            while (true)
            {
                //等待信号通知
                _mre.WaitOne();
                //写入日志
                Write();
                //重新设置信号
                _mre.Reset();
                Thread.Sleep(1);
            }
      }
      #endregion

      #region 写入日志
      /// <summary>
      /// 写入日志
      /// </summary>
      private static void Write()
      {
            //获取物理路径
            var infoDir = GetPhysicalPath(ConfigurationManager.AppSettings["logInfo"] ?? @"Logs\Info");
            var errorDir = GetPhysicalPath(ConfigurationManager.AppSettings["logError"] ?? @"Logs\Error");
            //根据当天日期创建日志文件
            var fileName = $"{DateTime.Now.ToString("yyyy-MM-dd")}.log";
            var infoPath = infoDir + fileName;
            var errorPath = errorDir + fileName;
            try
            {
                //进入写锁
                _lock.EnterWriteLock();
                //判断目录是否存在,不存在则重新创建
                if (!Directory.Exists(infoDir)) Directory.CreateDirectory(infoDir);
                if (!Directory.Exists(errorDir)) Directory.CreateDirectory(errorDir);
                //创建StreamWriter
                StreamWriter swInfo = null;
                StreamWriter swError = null;
                if (_que?.ToList().Exists(o => o.Level == LogLevel.Info) == true)
                {
                  swInfo = new StreamWriter(infoPath, true, Encoding.UTF8);
                }
                if (_que?.ToList().Exists(o => o.Level == LogLevel.Error) == true)
                {
                  swError = new StreamWriter(errorPath, true, Encoding.UTF8);
                }
               //判断日志队列中是否有内容,从列队中获取内容,并删除列队中的内容
                while (_que?.Count > 0 && _que.TryDequeue(out LogMessage logMessage))
                {
                  var sf = logMessage.StackFrame;
                  //Info
                  if (swInfo != null && logMessage.Level == LogLevel.Info)
                  {
                        swInfo.WriteLine($"[级别:Info]");
                        swInfo.WriteLine($"[时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}]");
                        swInfo.WriteLine($"[类名:{sf?.GetMethod().DeclaringType.FullName}]");
                        swInfo.WriteLine($"[方法:{sf?.GetMethod().Name}]");
                        swInfo.WriteLine($"[行号:{sf?.GetFileLineNumber()}]");
                        swInfo.WriteLine($"[内容:{logMessage.Message}]");
                        swInfo.WriteLine("------------------------------------------------------------------------------------------");
                        swInfo.WriteLine(string.Empty);
                  }
                  //Error
                  if (swError != null && logMessage.Level == LogLevel.Error)
                  {
                        swError.WriteLine($"[级别:Error]");
                        swError.WriteLine($"[时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}]");
                        swError.WriteLine($"[类名:{sf?.GetMethod().DeclaringType.FullName}]");
                        swError.WriteLine($"[方法:{sf?.GetMethod().Name}]");
                        swError.WriteLine($"[行号:{sf?.GetFileLineNumber()}]");
                        if (!string.IsNullOrEmpty(logMessage.Message))
                        {
                            swError.WriteLine($"[内容:{logMessage.Message}]");
                        }
                        if (logMessage.Exception != null)
                        {
                            swError.WriteLine($"[异常:{logMessage.Exception.ToString()}]");
                        }
                        swError.WriteLine("------------------------------------------------------------------------------------------");
                        swError.WriteLine(string.Empty);
                  }
                }
                //释放并关闭资源
                if (swInfo != null)
                {
                  swInfo.Close();
                  swInfo.Dispose();
                }
                if (swError != null)
                {
                  swError.Close();
                  swError.Dispose();
                }
            }
            finally
            {
                //退出写锁
                _lock.ExitWriteLock();
            }
      }
      #endregion

      #region 获取物理路径
      /// <summary>
      /// 获取物理路径
      /// </summary>
      /// <param name="path"></param>
      /// <returns></returns>
      private static string GetPhysicalPath(string path)
      {
            var physicalPath = AppDomain.CurrentDomain.BaseDirectory;
            if (!string.IsNullOrEmpty(path))
            {
                path = path.Replace("~", "").Replace("/", @"\").TrimStart('\\').TrimEnd('\\');
                var start = path.LastIndexOf('\\') + 1;
                var length = path.Length - start;
                physicalPath = Path.Combine(physicalPath, path.Substring(start, length).Contains(".") ? path : path + @"\");
            }
            return physicalPath;
      }
      #endregion

      #region 日志实体
      /// <summary>
      /// 日志级别
      /// </summary>
      private enum LogLevel
      {
            Info,
            Error
      }

      /// <summary>
      /// 消息实体
      /// </summary>
      private class LogMessage
      {
            /// <summary>
            /// 日志级别
            /// </summary>
            public LogLevel Level { get; set; }

            /// <summary>
            /// 消息内容
            /// </summary>
            public string Message { get; set; }

            /// <summary>
            /// 异常对象
            /// </summary>
            public Exception Exception { get; set; }

            /// <summary>
            /// 堆栈帧信息
            /// </summary>
            public StackFrame StackFrame { get; set; }
      }
      #endregion
      #endregion
    }
}

zjy-geek 发表于 2018-12-9 10:37

你这也叫高性能,,代码写的这么难看,,体现不出编程之美。。真的很低级,,欺负他们看不懂呢??

邓振振 发表于 2018-12-17 17:06

zjy-geek 发表于 2018-12-9 10:37
你这也叫高性能,,代码写的这么难看,,体现不出编程之美。。真的很低级,,欺负他们看不懂呢??

对对对,52上的人都是不会编程的。你说的对。我们都是幼儿园的,不然怎么能体现您是小学生呢?

邓振振 发表于 2018-11-16 09:12

支持一下子,

131415 发表于 2018-11-16 09:32

支持一下,欢迎更多的C# 资料

散与聚 发表于 2018-11-16 09:37

c++有好的日志类吗,c++的日志一直做不好

q285778219 发表于 2018-11-16 09:40

支持下,Log4Net还没熟悉,这个也可以用

hedy16 发表于 2018-11-16 10:00

过来支持下

360安全工程师 发表于 2018-11-16 10:01

很赞,回头用一下。

wangqiustc 发表于 2018-11-16 10:02

楼主厉害

现代文明侠 发表于 2018-11-16 10:20

支持楼主,最近正在学习语言

zqlovejyc 发表于 2018-11-16 10:21

冰霜亚龙 发表于 2018-11-16 10:00
c++有好的日志类吗

只用过C#,C++没有用过
页: [1] 2 3 4
查看完整版本: C# 自己封装的高性能日志记录类库