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日志、監控日志,並且會按照日期生成日志,方便我們查看。

 源代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM