zoukankan      html  css  js  c++  java
  • log4net 记录MVC监控日志

      由于MVC自身的特点,可以让我们记录每一个Controller下Action的执行时间以及View视图渲染完成的时间,本文采用log4net记录MVC每个Action的执行时间和View视图渲染完成时间,以及请求Action时post或get的数据。这样通过日志记录的时间方便我们定位哪一个Action和View执行的时间过长,进而采取优化的手段。

    监控日志监控的指标如下图

    监控程序实现

      改监控程序主要继承ActionFilterAttribute类,并重写其中的OnActionExecuted、OnActionExecuting、OnResultExecuted、OnResultExecuting几个方法实现。

    1、监控日志对象
    /// <summary>
        /// 监控日志对象
        /// </summary>
        public class MonitorLog
        {
            public string ControllerName
            {
                get;
                set;
            }
            public string ActionName
            {
                get;
                set;
            }
    
            public DateTime ExecuteStartTime
            {
                get;
                set;
            }
            public DateTime ExecuteEndTime
            {
                get;
                set;
            }
            /// <summary>
            /// Form 表单数据
            /// </summary>
            public NameValueCollection FormCollections
            {
                get;
                set;
            }
            /// <summary>
            /// URL 参数
            /// </summary>
            public NameValueCollection QueryCollections
            {
                get;
                set;
            }
            /// <summary>
            /// 监控类型
            /// </summary>
            public enum MonitorType
            {
                Action = 1,
                View = 2
            }
            /// <summary>
            /// 获取监控指标日志
            /// </summary>
            /// <param name="mtype"></param>
            /// <returns></returns>
            public string GetLoginfo(MonitorType mtype = MonitorType.Action)
            {
                string ActionView = "Action执行时间监控:";
                string Name = "Action";
                if (mtype == MonitorType.View)
                {
                    ActionView = "View视图生成时间监控:";
                    Name = "View";
                }
                string Msg = @"
                {0}
                ControllerName:{1}Controller
                {8}Name:{2}
                开始时间:{3}
                结束时间:{4}
                总 时 间:{5}秒
                Form表单数据:{6}
                URL参数:{7}
                        ";
                return string.Format(Msg,
                    ActionView,
                    ControllerName, 
                    ActionName,
                    ExecuteStartTime,
                    ExecuteEndTime, 
                    (ExecuteEndTime - ExecuteStartTime).TotalSeconds,
                    GetCollections(FormCollections),
                    GetCollections(QueryCollections),
                    Name);
            }
    
            /// <summary>
            /// 获取Post 或Get 参数
            /// </summary>
            /// <param name="Collections"></param>
            /// <returns></returns>
            public string GetCollections(NameValueCollection Collections)
            {
                string Parameters = string.Empty;
                if (Collections == null || Collections.Count == 0)
                {
                    return Parameters;
                }
                foreach (string key in Collections.Keys)
                {
                    Parameters += string.Format("{0}={1}&", key, Collections[key]);
                }
                if (!string.IsNullOrWhiteSpace(Parameters) && Parameters.EndsWith("&"))
                {
                    Parameters = Parameters.Substring(0, Parameters.Length - 1);
                }
                return Parameters;
            }
    
        }

    2、监控类

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
        public class StatisticsTrackerAttribute : ActionFilterAttribute,IExceptionFilter
        {
            private readonly string Key = "_thisOnActionMonitorLog_";
    
            #region Action时间监控
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                MonitorLog MonLog = new MonitorLog();
                MonLog.ExecuteStartTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ffff", DateTimeFormatInfo.InvariantInfo));
                MonLog.ControllerName = filterContext.RouteData.Values["controller"] as string;
                MonLog.ActionName = filterContext.RouteData.Values["action"] as string;
    
                filterContext.Controller.ViewData[Key] = MonLog;
            }
    
            public override void OnActionExecuted(ActionExecutedContext filterContext)
            {
                MonitorLog MonLog = filterContext.Controller.ViewData[Key] as MonitorLog;
                MonLog.ExecuteEndTime = DateTime.Now;
                MonLog.FormCollections = filterContext.HttpContext.Request.Form;//form表单提交的数据
                MonLog.QueryCollections = filterContext.HttpContext.Request.QueryString;//Url 参数
                LoggerHelper.Monitor(MonLog.GetLoginfo());
    
            }
            #endregion
    
            #region View 视图生成时间监控
            public override void OnResultExecuting(ResultExecutingContext filterContext)
            {
                MonitorLog MonLog = filterContext.Controller.ViewData[Key] as MonitorLog;
                MonLog.ExecuteStartTime = DateTime.Now;
               
            }
            public override void OnResultExecuted(ResultExecutedContext filterContext)
            {
                MonitorLog MonLog = filterContext.Controller.ViewData[Key] as MonitorLog;
                MonLog.ExecuteEndTime = DateTime.Now;
                LoggerHelper.Monitor(MonLog.GetLoginfo(MonitorLog.MonitorType.View));
                filterContext.Controller.ViewData.Remove(Key);
            }
          
            #endregion
    
            #region 错误日志
    
            public void OnException(ExceptionContext filterContext)
            {
                if (!filterContext.ExceptionHandled)
                {
                    string ControllerName =string.Format("{0}Controller",filterContext.RouteData.Values["controller"] as string);
                    string ActionName = filterContext.RouteData.Values["action"] as string;
                    string ErrorMsg = string.Format("在执行 controller[{0}] 的 action[{1}] 时产生异常", ControllerName, ActionName);
                    LoggerHelper.Error(ErrorMsg, filterContext.Exception);
                }
            }
            #endregion
    
        }

    3、引用监控

    我们可以在每个Controller类上或Action上直接引用 [StatisticsTracker]即可完成对该Controller或Action的监控。

    我们也可以在FilterConfig.cs中注册全局监控,这样我们就可以监控每一个Controller中的Action,代码如下:

    public class FilterConfig
        {
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
                //监控引用
                filters.Add(new StatisticsTrackerAttribute());
            }
        }

    LoggerHelper

      log文件的记录采用log4net,log4net是.Net下一个非常优秀的开源日志记录组件。log4net记录日志的功能非常强大。具体配置如下。

    1、log4net配置文件

      log4Net的配置文件名称为log4net.config,具体配置如下。

    <?xml version="1.0"?>
    <configuration>
      <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
      </configSections>
      <log4net>
        <!--错误日志-->
        <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
          <file value="log\LogError\"/>
          <appendToFile value="true"/>
          <rollingStyle value="Date"/>
          <datePattern value="yyyy\yyyyMM\yyyyMMdd'.txt'"/>
          <staticLogFileName value="false"/>
          <param name="MaxSizeRollBackups" value="100"/>
          <layout type="log4net.Layout.PatternLayout">
            <!--每条日志末尾的文字说明-->
            <!--输出格式-->
            <!--样例:2008-03-26 13:42:32,111 [10] INFO  Log4NetDemo.MainClass [(null)] - info-->
            <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别:  %-5level %n错误描述:%message%newline %n"/>
          </layout>
        </appender>
        <!--Info日志-->
        <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
          <param name="File" value="Log\LogInfo\" />
          <param name="AppendToFile" value="true" />
          <param name="MaxFileSize" value="10240" />
          <param name="MaxSizeRollBackups" value="100" />
          <param name="StaticLogFileName" value="false" />
          <param name="DatePattern" value="yyyy\yyyyMM\yyyyMMdd'.txt'" />
          <param name="RollingStyle" value="Date" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别:  %-5level %n日志描述:%message%newline %n"/>
          </layout>
        </appender>
    
        <!--监控日志-->
        <appender name="MonitorAppender" type="log4net.Appender.RollingFileAppender">
          <param name="File" value="Log\LogMonitor\" />
          <param name="AppendToFile" value="true" />
          <param name="MaxFileSize" value="10240" />
          <param name="MaxSizeRollBackups" value="100" />
          <param name="StaticLogFileName" value="false" />
          <param name="DatePattern" value="yyyy\yyyyMM\yyyyMMdd'.txt'" />
          <param name="RollingStyle" value="Date" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别:  %-5level %n跟踪描述:%message%newline %n"/>
          </layout>
        </appender>
        <!--Error日志-->
        <logger name="logerror">
          <level value="ERROR" />
          <appender-ref ref="RollingLogFileAppender" />
        </logger>
        <!--Info日志-->
        <logger name="loginfo">
          <level value="INFO" />
          <appender-ref ref="InfoAppender" />
        </logger>
        <!--监控日志-->
        <logger name="logmonitor">
          <level value="Monitor" />
          <appender-ref ref="MonitorAppender" />
        </logger>
      </log4net>
    </configuration>
    log4net.config

    2、注册log4net配置文件

      在Global.asax中注册log4net配置文件,代码如下

    protected void Application_Start()
            {
                //注册 log4net
                log4net.Config.XmlConfigurator.Configure(
                   new System.IO.FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\Config\log4net.config")
               );
                AreaRegistration.RegisterAllAreas();
    
                WebApiConfig.Register(GlobalConfiguration.Configuration);
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }

    3、LoggerHelper.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace Monitor.Models.ActionFilters
    {
        public class LoggerHelper
        {
            static readonly log4net.ILog loginfo = log4net.LogManager.GetLogger("loginfo");
            static readonly log4net.ILog logerror = log4net.LogManager.GetLogger("logerror");
            static readonly log4net.ILog logmonitor = log4net.LogManager.GetLogger("logmonitor");
    
            public static void Error(string ErrorMsg, Exception ex = null)
            {
                if (ex != null)
                {
                    logerror.Error(ErrorMsg, ex);
                }
                else
                {
                    logerror.Error(ErrorMsg);
                }
            }
    
            public static void Info(string Msg)
            {
                loginfo.Info(Msg);
            }
    
            public static void Monitor(string Msg)
            {
                logmonitor.Info(Msg);
            }
        }
    }

    4.log4net日志生成的文件目录结构如下图

    目录结构我们区分开了错误日志、Info日志、监控日志,并且会按照日期生成日志,方便我们查看。

     源代码

  • 相关阅读:
    如何写一个邮件模板页面
    java集合List,Set,Map等集合
    参悟python元类(又称metaclass)系列实战(二)
    参悟python元类(又称metaclass)系列实战(一)
    对Python"一切皆对象"的小参悟
    Linux设置ntp客户端
    JMeter BeanShell向文件中写入内容
    JMeter处理接口签名(sign)
    JMeter处理动态的签名内容
    多线程总结,ThreadPoolExecutor创建线程池,
  • 原文地址:https://www.cnblogs.com/lc-chenlong/p/4228639.html
Copyright © 2011-2022 走看看