ASP.NET MVC4中加入Log4Net日志记录功能

前言

在之前的.NET中,微软还没有提供过像样的日志框架,目前能用的一些框架比如Log4Net、NLog、CommonLogging等,虽然多多少少使用起来有点费劲,但这里还是简单分享一下Log4Net的初步使用方法。

在项目中的配置

第一步:首先在项目用引用Log4Net.dll.[管理NuGet程序包中直接搜索就可以啦]

第二步:Web.config文件中进行添加confIGsections的节点

<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  </configSections>
</configuration>

第三步:在configSections下添加Log4Net配置节点[这里将日志分类了,以便于理解与查看对应的日志信息]

<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>
View Code

  在框架的体系里,所有的日志对象都是根日志(root logger)的后代。 因此如果一个日志对象没有在配置文件里显式定义,则框架使用根日志中定义的属性。在<root>标签里,可以定义level级别值和Appender的列表。如果没有定义LEVEL的值,则缺省为DEBUG。可以通过<appender-ref>标签定义日志对象使用的Appender对象。<appender-ref>声明了在其他地方定义的Appender对象的一个引用。在一个logger对象中的设置会覆盖根日志的设置。而对Appender属性来说,子日志对象则会继承父日志对象的Appender列表。这种缺省的行为方式也可以通过显式地设定<logger>标签的additivity属性为false而改变。

在项目中建立自定义Log日志

 

第四步:在文件里配置以下类:ApiTrackerFilter.cs[Api接口日志],TrackerFilter.cs[基本日志类],LoggerHelper.cs[日志信息处理类],MonitorLog.cs[监控日志类](对于监控日志,则根据个人需求是否建立),其中的BookException是自定义的错误,可以省略。

public class LoggerHelper
    {
        private static readonly log4net.ILog LogInfo = log4net.LogManager.GetLogger("LogInfo");
        private static readonly log4net.ILog LogError = log4net.LogManager.GetLogger("LogError");
        private static readonly log4net.ILog LogMonitor = log4net.LogManager.GetLogger("LogMonitor");

        /// <summary>
        /// 记录Error日志
        /// </summary>
        /// <param name="errorMsg"></param>
        /// <param name="ex"></param>
        public static void Error(string errorMsg, Exception ex = null)
        {
            if (ex != null)
            {
                LogError.Error(errorMsg, ex);
            }
            else
            {
                LogError.Error(errorMsg);
            }
        }

        /// <summary>
        /// 记录Info日志
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="ex"></param>
        public static void Info(string msg, Exception ex = null)
        {
            if (ex != null)
            {
                LogInfo.Info(msg, ex);
            }
            else
            {
                LogInfo.Info(msg);
            }
        }

        /// <summary>
        /// 记录Monitor日志
        /// </summary>
        /// <param name="msg"></param>
        public static void Monitor(string msg)
        {
            LogMonitor.Info(msg);
        }
    }
LoggerHelper.cs
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class TrackerFilter : 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[this.key] = monLog;
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            MonitorLog monLog = filterContext.Controller.ViewData[this.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[this.key] as MonitorLog;
            monLog.ExecuteStartTime = DateTime.Now;
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            MonitorLog monLog = filterContext.Controller.ViewData[this.key] as MonitorLog;
            monLog.ExecuteEndTime = DateTime.Now;
            LoggerHelper.Monitor(monLog.GetLogInfo(MonitorLog.MonitorType.View));
            filterContext.Controller.ViewData.Remove(this.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
    }
TrackerFilter.cs
    /// <summary>
    /// 监控日志对象
    /// </summary>
    public class MonitorLog
    {
        public MonitorLog()
        {
            this.Watch = new Stopwatch();
            this.Watch.Start();
        }

        /// <summary>
        /// 监控类型
        /// </summary>
        public enum MonitorType
        {
            /// <summary>
            /// Action
            /// </summary>
            Action = 1,

            /// <summary>
            /// 视图
            /// </summary>
            View = 2
        }

        public string ControllerName { get; set; }

        public string ActionName { get; set; }

        public Stopwatch Watch { 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 string Raw { get; set; }

        /// <summary>
        /// 获取监控指标日志
        /// </summary>
        /// <param name="mtype"></param>
        /// <returns></returns>
        public string GetLogInfo(MonitorType mtype = MonitorType.Action)
        {
            this.Watch.Stop();
            string actionView = "Action执行时间监控:";
            string action = "Action";
            if (mtype == MonitorType.View)
            {
                actionView = "View视图生成时间监控:";
                action = "View";
            }
            string msgContent = string.Format(
                @"
      {0}
      ControllerName:{1}Controller
      {2}Name:{3}
      开始时间:{4}
      结束时间:{5}
      总 时 间:{6}秒",
                actionView,
                this.ControllerName,
                action,
                this.ActionName,
                this.ExecuteStartTime,
                this.ExecuteEndTime,
                this.Watch.ElapsedMilliseconds);

            if (!string.IsNullOrEmpty(this.Raw))
            {
                msgContent += @"
        Raw:" + this.Raw;
            }
            else if (this.FormCollections != null)
            {
                msgContent += @"
        Form:" + this.GetCollections(this.FormCollections);
            }
            else if (this.QueryCollections != null)
            {
                msgContent += @"
        Query:" + this.GetCollections(this.QueryCollections);
            }

            return msgContent;
        }

        /// <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;
            }
            parameters = collections.Keys.Cast<string>()
                .Aggregate(parameters, (current, key) => current + string.Format("{0}={1}&", key, collections[key]));
            if (!string.IsNullOrWhiteSpace(parameters) && parameters.EndsWith("&"))
            {
                parameters = parameters.Substring(0, parameters.Length - 1);
            }
            return parameters;
        }
MonitorLog.cs
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class ApiTrackerFilter : ActionFilterAttribute
    {
        private readonly string key = "_thisOnApiActionMonitorLog_";

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var monLog = new MonitorLog();
            monLog.ExecuteStartTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ffff", DateTimeFormatInfo.InvariantInfo));

            monLog.ControllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            monLog.ActionName = actionContext.ActionDescriptor.ActionName;
            actionContext.Request.Properties[this.key] = monLog;
        }

        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            if (actionExecutedContext.Exception != null)
            {
                string controllerName = string.Format(
                    "{0}Controller",
                    actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName);
                string actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;
                string errorMsg = string.Format("在执行 controller[{0}] 的 action[{1}] 时产生异常", controllerName, actionName);
                if (actionExecutedContext.Exception is BookException)
                {
                    LoggerHelper.Info(errorMsg, actionExecutedContext.Exception);
                }
                else
                {
                    LoggerHelper.Error(errorMsg, actionExecutedContext.Exception);
                }
            }

            if (!actionExecutedContext.Request.Properties.ContainsKey(this.key))
            {
                return;
            }

            var monLog = actionExecutedContext.Request.Properties[this.key] as MonitorLog;
            if (monLog != null)
            {
                monLog.ExecuteEndTime = DateTime.Now;

                monLog.Raw = actionExecutedContext.Request.Content.ReadAsStringAsync().Result;
                LoggerHelper.Monitor(monLog.GetLogInfo());
            }
        }
    }
ApiTrackerFilter.cs

在Global.asax文件中配置以及在MVC的FilterConfig过滤器中配置信息

经过这么多的准备工作,终于最后一步:

1.Global.axax中配置

protected void Application_Start(object sender, EventArgs e)
        {

            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            log4net.Config.XmlConfigurator.Configure();

            GlobalConfiguration.Configuration.Filters.Add(new Log.ApiTrackerFilter());
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

2.在FilterConfig过滤器中配置信息

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            //监控日志
            filters.Add(new Log.TrackerFilter());

            filters.Add(new HandleErrorAttribute());
        }

至此,所有都成功了,最后运行的结果可以在项目根目录下查看相应日期的Log日志信息。

 

posted @ 2015-08-24 15:28  JaminHuang  阅读(5438)  评论(29编辑  收藏  举报