winform 基于log4net的日志框架封装

没有日志,问题单难收敛,开发兄弟天天擦屁股还擦不干净...

 超短期把这套东西补全委实困难,此处基于log4net,简单封装了日志框架。一切本着易用原则。

log4net系apache 2.0协议,无开源风险。

【演示】

程序运行目录下生成log.log文件及其备份

日志效果图


【使用步骤】

1 把log4net.dll加入到程序目录下,并引用它

2.把日志配置文件放到程序运行目录下

主要配置——文件按大小滚动备份

 <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="./Log/log.log" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="20" />
      <maximumFileSize value="10M" />
      <staticLogFileName value="true" />
      
      <!--<datePattern value="yyyy-MM-dd".log""/> -->
      <layout type="log4net.Layout.PatternLayout">
        <!--<footer value="" />-->
        <!--输出格式-->
        <!--%date [%t] %-5p [%c] - %m%n-->
        <!--样例:2008-03-26 13:42:32,111 [10] INFO  Log4NetDemo.MainClass [(null)] - info-->
        <conversionPattern value="%date [%t] %-5p - %m%n" />
      </layout>
    </appender>

3. 封装一个日志单态类,封装了log4net基本输出日志方法,对外暴露日志输出函数DebugLog,FuncEntryLog(用以标记函数入口)等

amespace agri.logger
{
    public class Log
    {
        #region 私有内容    
        private static log4net.ILog _logger = null;
        private static object _locker = new object();

        static Log()
        {
            string path = string.Format("{0}log.config", AppDomain.CurrentDomain.BaseDirectory);
            if (File.Exists(path))
            {
                log4net.Config.XmlConfigurator.Configure(new FileInfo(path));
            }
            else
            {
                RollingFileAppender appender = new RollingFileAppender();
                appender.Name = "LogFileAppender";
                appender.File = "./Log/log.log";
                appender.AppendToFile = true;
                appender.RollingStyle = RollingFileAppender.RollingMode.Size;
                appender.MaximumFileSize = "10M";
                appender.MaxSizeRollBackups = 20;
                log4net.Layout.PatternLayout layout =
                    new log4net.Layout.PatternLayout("%date [%t] %-5p - %m%n"); 
                appender.Layout = layout;
                BasicConfigurator.Configure(appender);
                appender.ActivateOptions();
            }
        }

        private static log4net.ILog instance
        {
            get
            {
                if (null == _logger)
                {
                    lock (_locker)
                    {
                        if (null == _logger)
                        {                        
                            _logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
                        }
                    }
                }

                return _logger;
            }
        }

        private static void log_by_level(Level level, int hierarchy, string format, params object[] args)
        {
            hierarchy += 1;
            MethodBase method = get_method_from_stack(hierarchy);

            string strHeadFmt = string.Format("[{0}][{1}] ", method.DeclaringType, method.Name);
            strHeadFmt += format;

            if (level.Equals(Level.Debug))
            {
                Log.instance.DebugFormat(strHeadFmt, args);
            }
            else if (level.Equals(Level.Info))
            {
                Log.instance.InfoFormat(strHeadFmt, args);
            }
            else if (level.Equals(Level.Warn))
            {
                Log.instance.WarnFormat(strHeadFmt, args);
            }
            else if (level.Equals(Level.Error))
            {
                Log.instance.ErrorFormat(strHeadFmt, args);
            }
            else if (level.Equals(Level.Fatal))
            {
                Log.instance.FatalFormat(strHeadFmt, args);
            }
            else
            {
                Log.instance.InfoFormat(strHeadFmt, args);
            }
        }

        private static MethodBase get_method_from_stack(int hierarchy)
        {
            hierarchy += 1; // 这个函数本身也算一层 
            StackTrace strace = new StackTrace(true);
            int nFrameIndex = strace.FrameCount > hierarchy ? hierarchy : 0; // hierachy从0开始计数
            MethodBase method = strace.GetFrame(nFrameIndex).GetMethod();
            return method;
        }
        #endregion 私有内容

        #region 对外暴露的方法
        public static void DebugLog(string format, params object[] args)
        {         
            log_by_level(Level.Debug, 1, format, args);
        }

        public static void InfoLog(string format, params object[] args)
        {
            log_by_level(Level.Info, 1, format, args);
        }

        public static void WarnLog(string format, params object[] args)
        {
            log_by_level(Level.Warn, 1, format, args);
        }

        public static void ErrorLog(string format, params object[] args)
        {
            log_by_level(Level.Error, 1, format, args);
        }

        public static void FatalLog(string format, params object[] args)
        {
            log_by_level(Level.Fatal, 1, format, args);
        }

        /// <summary>
        /// 函数入口日志,Info级别
        /// </summary>
        /// <param name="args"></param>
        public static void FuncEntryLog(params object[] args)
        {
            // 不晓得怎么使用 profiling API.或反射机制实现获取调用函数的参数值,
            //>因此这里只能笨笨的让用户程序把参数带过来了,待优化
            StringBuilder sbMsg = new StringBuilder("Function Enterd...(");
            for (int i = 0; i < args.Length; i++)
            {
                sbMsg.Append("<arg");
                sbMsg.Append(i);
                sbMsg.Append(":");
                sbMsg.Append(args[i]);
                sbMsg.Append(">");
                if (i != args.Length - 1)
                {
                    sbMsg.Append(", ");
                }
            }
            sbMsg.Append(")");

            log_by_level(Level.Info, 1, sbMsg.ToString());

            // 知识点:C++写得话,可以在此处调用个宏,此宏创建个临时变量,该变量的析构函数调用FuncExit()函数。
            //>外面的函数执行结束后,该变量生命周期结束时,就会调用其析构函数,进而调用FuncExit()。
            //>因此,只要在函数入口调用FuncEntry()就能实现函数出口时的日志输出了。
        }

        public static void FuncExitLog()
        {            
            log_by_level(Level.Info, 1, "Function Exited...");
        }

        // 待重载符号<<,以实现"DEBUG << MSG1 << MSG2 << ..."形式的调用
        #endregion 对外暴露的方法
    }
}
4. 测试程序

        private void m_btnChangeWnd_Click(object sender, EventArgs e)
        {
            Log.FuncEntryLog(sender, e); // 函数入口日志,新代码要求每个函数入口必打日志
            
            _Task.Stop();

            Form subform = new SubForm();            
            Random random = new Random();
            int rdNum = random.Next(10);
            Log.DebugLog("生成一个随机数:{0},看看是不是{1}的整数倍", rdNum, 2);
            if (0 == rdNum % 2)
            {
                subform.BackColor = Color.Black;
                Log.ErrorLog("给你个黑框框");       
            }
            subform.Show();            
          
            Log.FuncExitLog(); // 函数出口日志,不强制要求
        }

转载请注明出处:http://blog.csdn.net/shineych/article/details/8134954


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值