吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8014|回复: 37
收起左侧

[其他转载] C# 自己封装的高性能日志记录类库

  [复制链接]
zqlovejyc 发表于 2018-11-16 09:08
本帖最后由 zqlovejyc 于 2018-11-16 10:26 编辑

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

[C#] 纯文本查看 复制代码
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?[frames.Length - 1];
            }
            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
    }
}

免费评分

参与人数 6吾爱币 +8 热心值 +6 收起 理由
wwusq + 1 + 1 我很赞同!
Hzming0925 + 1 + 1 用心讨论,共获提升!
孤情冢 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Breathe_ice + 1 + 1 谢谢@Thanks!
苏紫方璇 + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
邓振振 + 1 + 1 可以,虽然没有Log4net功能强大,但是很牛逼,简单粗暴,亲测有效。。。

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

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

只用过C#,C++没有用过
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 05:17

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表