由于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()); } } LoggerHelperlog文件的记录采用log4net,log4net是.Net下一个非常优秀的开源日志记录组件。log4net记录日志的功能非常强大。具体配置如下。 1、log4net配置文件log4Net的配置文件名称为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.csusing 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日志、监控日志,并且会按照日期生成日志,方便我们查看。 |
|
来自: ThinkTank_引擎 > 《Log4net》