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日志、监控日志,并且会按照日期生成日志,方便我们查看。

源代码

时间: 2024-08-06 21:32:43

log4net 记录MVC监控日志的相关文章

学习总结 之 WebApi服务监控 log4net记录监控日志

在请求WebApi 的时候,我们更想知道在请求数据的时候,调用了哪个接口传了什么参数过来,调用这个Action花了多少时间,有没有人恶意请求.我们可以通过记录日志,对Action进行优化,可以通过日志追踪是哪个用户或ip恶意请求. 在项目中引用log4net.dll 定义一个WebApiMonitorLog ,监控日志对象 /// <summary> /// 监控日志对象 /// </summary> public class WebApiMonitorLog { public s

ASP.NET MVC中Log4Net记录错误日志的使用

第一.在管理NuGet程序包 =>下载 Log4Net 第二.在web.config配置Log4Net 1:在<configuration>节点下 <configSections>节点中 配置log4Net节点引用. <!--log4net日志记录--> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net

Log4Net在MVC下的配置以及运用线程队列记录异常信息

Log4Net是用来记录日志的,可以将程序运行过程中的信息输出到一些地方(文件.数据库.EventLog等),日志就是程序的黑匣子,可以通过日志查看系统的运行过程,从而发现系统的问题.日志的作用:将运行过程的步骤.成功失败记录下来,将关键性的数据记录下来分析系统问题所在.Log4J.对于网站来讲,不能把异常信息显示给用户,异常信息只能记录到日志,出了问题把日志文件发给开发人员,就能知道问题所在. 配置Log4Net环境 (1)新建一个WebApplication (2)添加对log4net.dl

转:使用log4net完成程序异常日志记录(使用SQLite数据库记录和普通文本记录)

http://www.cnblogs.com/kyo-yo/archive/2010/06/11/use-log4net-to-log-exception.html 在前端时间开发的时候由于需要将异常保存到数据库中,所以就到网上搜了下专门的日志记录工具,一搜果然很多,比如:log4net,NLog,EntLib Logging等等,但是还是log4net名气最大,所以就下载下来试用了一番,果然很方便,其涵盖了所有常用的日志记录方式具体的可以看下表: AdoNetAppender 将日志记录到数据

log4net.NoSql +ElasticSearch 实现日志记录

前言: 前两天在查找如何扩展log4net的日志格式时找到一个开源项目Log4net.NoSql,它通过扩展Appender实现了把日志输出到ElasticSearch里面.顺藤摸瓜,发现涉及的项目还挺多,于是打算学习一下,记录在此. 项目一句话简介,详情点击链接去项目主页查看,最后提供打包下载: 1.log4net.nosql A collection of log4net Appenders to NoSQL data stores. Currently only ElasticSearch

C# 使用Log4Net记录程序日志

在之前的博客中,写过使用系统内置的Trace类记录程序日志,具体请参考:C# 使用Trace记录程序日志.这篇博客将介绍如何使用Log4Net记录程序日志. 首先需要引用Log4Net.dll,我们可以使用Visual Studio的NuGet来引入,也可以从官网上面下载.下面是一个简单的LogHelper类, using log4net; [assembly: log4net.Config.XmlConfigurator(Watch = true)] namespace CommonLibra

C# 面向切面编程--监控日志记录方案

背景:现在公司整体在做监控平台,要求把各个部分的细节都记录下来,在前台页面上有所显示,所以现在需要做的就是一个监控日志的记录工作,今天讲的就是渲染监控日志的例子. 现状:当前的渲染程序没有为监控日志记录预留代码接入口,因此要新增加监控日志势必要增加新的代码.但是如果只是单单在已有逻辑中新增日志记录的代码似乎不太合理:因为记录日志的代码很多都是一样的,直接插入代码有很多重复代码:原有代码已经上线并且运行良好,新增代码会破坏原有封装,甚至增加出错的可能:再者从设计的角度来说,记录日志不属于任何一个功

如何有效地记录 Java SQL 日志(转)

在常规项目的开发中可能最容易出问题的地方就在于对数据库的处理了,在大部分的环境下,我们对数据库的操作都是使用流行的框架,比如 Hibernate . MyBatis 等.由于各种原因,我们有时会想知道在这些框架下实际执行的 SQL 究竟是什么. 虽然 Hibernate 可以在配置文件中打开 SHOW SQL 的功能, MyBatis 则可以在 Log4j 的配置文件中配置 SQL 语句的输出,但这些输出是类似这样的 INSERT … ? ? ? 语句,并不是一个完整可以运行的 SQL ,要想知

在Linux上使用logwatch分析监控日志文件

原文:http://seanlook.com/2014/08/23/linux-logwatch-usage/ 1. 介绍 在维护Linux服务器时,经常需要查看系统中各种服务的日志,以检查服务器的运行状态. 如登陆历史.邮件.软件安装等日志.系统管理员一个个去检查会十分不方便:且大多时候,这会是一种被动的检查,即只有在发现系统运行异常时才会想到去查看 日志以获取异常的信息.那么如何主动.集中的分析这些日志,并产生报告,定时发送给管理员就会显得十分重要. logwatch 是一款用 Perl 语