改进的日志记录类

相对之前发的日志记录来说,此类将程序记录处理与写磁盘操作分离,用户代码部分,将日志放到队列,并通知线程将日志写到文件:

1.公共类:

using System;
using System.IO;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.Diagnostics;

namespace LogWriter
{
    /// <summary>
    /// 日志类型
    /// </summary>
    public enum LogType
    {
        Error,
        Info,
        Waring,
        Success,
        Failure
    }
    /// <summary>
    /// 日志参数信息
    /// </summary>
    internal struct LogInfo
    {
        internal string FileName { get; set; }
        internal string MethodName { get; set; }
        internal int Line { get; set; }
        internal int Column { get; set; }
        internal string LogType { get; set; }
    }
    /// <summary>
    /// 公共日之类
    /// </summary>
    internal  class LogCommon
    {
        static System.Threading.ReaderWriterLockSlim Slim = new System.Threading.ReaderWriterLockSlim(System.Threading.LockRecursionPolicy.SupportsRecursion);
        /// <summary>
        /// 获取日志参数信息
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns></returns>
        internal static LogInfo GetLog(LogType type)
        {
            StackTrace st = new StackTrace(2, true);
            StackFrame sf = st.GetFrame(0);
            LogInfo li = new LogInfo()
            {
                FileName = sf.GetFileName(),
                MethodName = sf.GetMethod().Name,
                Line = sf.GetFileLineNumber(),
                Column = sf.GetFileColumnNumber(),
            };
            string logType = "-Error";

switch (type)
            {
                case LogType.Error:
                    logType = "-Error";
                    break;
                case LogType.Info:
                    logType = "-Info";
                    break;
                case LogType.Waring:
                    logType = "-Waring";
                    break;
                case LogType.Success:
                    logType = "-Success";
                    break;
                case LogType.Failure:
                    logType = "-Failure";
                    break;
                default:
                    logType = "-Error";
                    break;
            }
            li.LogType = logType;
            return li;
        }
        /// <summary>
  /// 写入以小时分割的日志文件
  /// </summary>
  /// <param name="Msg">要记录的消息</param>
  /// <param name="li">日志信息类</param>
  /// <param name="LogPath">日志所在文件夹</param>
  /// <returns></returns>
        internal static string WriteLineToTimeFile(string Msg, LogInfo li,string LogPath)
        {
            if (string.IsNullOrEmpty(Msg))
            {
                return "输入参数Msg为null或者值为空不符合记录要求!";
            }
            StreamWriter sw = null;
            try
            {
                Slim.EnterWriteLock();
               //string Dir = System.Windows.Forms.Application.StartupPath + @"\GLogs\" + DateTime.Now.ToString("yyyy年MM月dd日");
                checkLog(LogPath);
                string file = DateTime.Now.ToString("yyyy年MM月dd日HH时") + ".log";
                checkfile(LogPath, file);
                string fileName = LogPath + "\\" + file;
                sw = File.AppendText(fileName);
                sw.WriteLine("日志时间:" + DateTime.Now.ToString() + ",文件名:" + li.FileName + ",方法名:" + li.MethodName + "行号:" + li.Line + ",列:" + li.Column + ",日志类型:" + li.LogType);
                sw.WriteLine("日志内容:" + Msg);
                return nameof(WriteLineToTimeFile) + "日志记录操作成功!";
            }
            catch (Exception ex)
            {
                return nameof(WriteLineToTimeFile) + "日志记录发生错误:" + ex.Message;
            }
            finally
            {
                sw.Close();
                Slim.ExitWriteLock();
            }
        }
        /// <summary>
        /// 检查日志目录是否存在,不存在则创建
        /// </summary>
        /// <param name="Path">文件夹</param>
        internal static void checkLog(string Path)
        {
            if (!Directory.Exists(Path))
            {
                Directory.CreateDirectory(Path);
            }
        }
        /// <summary>
        /// 传入路径名称和文件名称,创建日志文件
        /// </summary>
        /// <param name="DirName">文件夹</param>
        /// <param name="FileName">文件名</param>
       internal static void checkfile(string DirName, string FileName)
        {
            if (!File.Exists(DirName + @"\" + FileName))
            {
                File.Create(DirName + @"\" + FileName).Close();
            }
        }
    }
}

2.gLog类:

using System;
using System.IO;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LogWriter
{
   
    /// <summary>
    /// 通过队列缓存来提高日志记录速度
    /// </summary>
   public class GLog
    {
       readonly object lockobj = new object();
        TimerCallback tc;
        Timer timer;
        Queue<LogQueueStruct> LogList = new Queue<LogQueueStruct>();
        public string LogPath { get; set; } = System.Windows.Forms.Application.StartupPath + @"\Logs\" + DateTime.Now.ToString("yyyy年MM月dd日");
        public  void RecordLog(LogType type,string msg)
        {
            LogQueueStruct log = new LogQueueStruct()
            {
                info = LogCommon.GetLog(type),
                Msg=msg
            };
            lock (lockobj)
            {
                LogList.Enqueue(log);
            }
            timer.Change(0, Timeout.Infinite);
        }
        public void RegiestLog()
        {
            //开启一个线程用以将队列中的日志记录到文件
         
                tc = new TimerCallback((o) =>
                {
                   
                  timer.Change(Timeout.Infinite, Timeout.Infinite);
                    lock (lockobj)
                    {
                        if (LogList.Count > 0)
                        {
                            LogQueueStruct log = LogList.Dequeue();
                            LogCommon.WriteLineToTimeFile(log.Msg, log.info,LogPath);
                        }
                    }
                });
                timer = new Timer(tc, null, Timeout.Infinite, Timeout.Infinite);           
        }
        public int LogListCount => LogList.Count;
    }
    internal class LogQueueStruct
    {
        internal LogInfo info { get; set; }
        internal string Msg { get; set; }
    }
}

3.调用:

GLog log = new GLog();
            log.RegiestLog();//初始化记录线程(定时器)
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();
           for(int i = 0; i++ < 1000;)
            {
                    log.RecordLog(LogType.Info, $"日志记录测试数据{i}");
            }
            stopwatch.Stop();
            Console.WriteLine(stopwatch.Elapsed.TotalSeconds);
            Console.WriteLine("程序部分操作完成!");
            Console.ReadLine();

相比较TxtLog:

TxtLog log = TxtLog.Instance;
            //初始化记录线程(定时器)
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();
           for(int i = 0; i++ < 1000;)
            {
                    log.WriteLineToFile($"日志记录测试数据{i}", LogType.Info);
            }
            stopwatch.Stop();
            Console.WriteLine($"调用{nameof(TxtLog)}耗时:{stopwatch.Elapsed.TotalSeconds}");
            Console.WriteLine("程序部分操作完成!");
            Console.ReadLine();

程序操作时间相差数倍!这就体现了用户调用部分和后台写磁盘文件部分,分离的好处!

原文地址:https://www.cnblogs.com/gfjin/p/8215337.html

时间: 2024-11-08 22:36:56

改进的日志记录类的相关文章

【个人使用.Net类库】(2)Log日志记录类

开发接口程序时,要保证程序稳定运行就要时刻监控接口程序发送和接收的数据,这就需要一个日志记录的类将需要的信息记录在日志文件中,便于自己维护接口程序.(Web系统也是如此,只是对应的日志实现比这个要复杂一点). 刚开始考虑的比较少,没有加入控制日志文件数量的功能.运行了一段时间,文件夹内的Log文件如下所示: 如果是这样,那运行一年不就三百多个日志文件了,想一想这太可怕了.通过查找资料,发现.Net中的FileInfo存有文件的信息(包括名称,创建时间,文件大小等),那就自己定义一个文件比较器实现

自定义错误日志记录类

引言 这是一个简单的自定义的错误日志记录类,这里我主要用于API接口开发中,APP移动端的入参记录 日志参数 /// <summary> /// 日志参数 /// </summary> public static class LogReq { /// <summary> /// 入参 /// </summary> public static string LogReqStr = ""; /// <summary> /// 加密

C# 创建自己的日志记录类 源码

调试及发布程序时,经常需要将一些信息输出保存,这里写了一个自己的日志记录类,记录信息更方便了.需要的话还可以进行更多的扩展,比如记录异常信息等. using System; using System.IO; namespace WindowsFormsApplication1 { public static class LogerHelper { #region 创建日志 ///-----------------------------------------------------------

使用Line Pos Info 和 Modern C++ 改进打印日志记录

使用Line Pos Info 和 Modern C++ 改进打印日志记录 使用跟踪值:不管自己是多么的精通,可能仍然使用调试的主要方法之一 printf , TRaCE, outputDebugString, 等…然后扫描输出, 同时调试. 添加有关行号和日志消息来源的文件的信息是一种非常有效的方法,可以为你节省大量时间,在这篇文章将描述一个在visual Studio中特别有用的技巧,在其他IDE/编译器中有所帮助. 还将展示现在C++和C++20如何使代码更好. 常规 在调试C++代码时,

日志记录类(明确FileStream\Dictionary等用法)

一个好的程序对于日志的处理是必不可少的.好的日志记录可以帮助我们减少更好的查找错误和系统的维护.今天整理一下自己工作中平时用来记录日志的类,同时也补补基础知识. 功能: 根据程序App.config中配置的路径,创建日志文件并将程序的日志写到相应的文件中. 首先来看一下我之前自己写的一个用于写日志的类,源代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using

日志记录类LogHelper

开源日志log4net使用起来很方便,但是项目中不让用,所以自己重写了一个类,用来记录日志,比较简单. 1.首先是可以把日志分成多个类型,分别记录到不同的文件中 1 /// <summary> 2 /// 日志类型 3 /// </summary> 4 public enum LogType 5 { 6 /// <summary> 7 /// 插入型 8 /// </summary> 9 Insert, 10 /// <summary> 11 /

【C#通用类】日志记录类

using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; namespace KTCommon.LOG { public class TraceLog { /// <summary> /// 全局日志对象 /// </summary> pub

Spring AOP进行日志记录

在java开发中日志的管理有很多种.我一般会使用过滤器,或者是Spring的拦截器进行日志的处理.如果是用过滤器比较简单,只要对所有的.do提交进行拦截,然后获取action的提交路径就可以获取对每个方法的调用.然后进行日志记录.使用过滤器的好处是可以自己选择性的对某一些方法进行过滤,记录日志.但是实现起来有点麻烦. 另外一种就是使用Spring的AOP了.这种方式实现起来非常简单,只要配置一下配置文件就可以了.可是这种方式会拦截下所有的对action的每个操作.使得效率比较低.不过想做详细日志

【测试报告】-TestNG自定义日志记录

我们此前读TestNG的记录和报告提供了不同的选项.现在,让我们了解如何开始使用它们.首先,我们将编写一个示例程序,我们将使用的ITestListener接口,以便进行记录. 创建测试案例类 创建一个Java类为 SampleTest.java 在 C:\ > TestNG_WORKSPACE import org.testng.Assert; import org.testng.annotations.Test; public class SampleTest { @Test public v