【问题标题】:How to use ActionFilterAttribute to log running times?如何使用 ActionFilterAttribute 记录运行时间?
【发布时间】:2014-04-27 11:20:05
【问题描述】:

我创建了一个动作过滤器,用于测量 Web API v2 中每个动作的运行时间。

public class RunningTimeAttribute : ActionFilterAttribute
    {
        private readonly ILogFactory _logFactory;
        private readonly ITimerFactory _timerFactory;
        private ITimer _timer;
        private ILogger _logger;

        public RunningTimeAttribute(ILogFactory logFactory, ITimerFactory timerFactory) {
            if(logFactory == null)
                throw new ArgumentNullException("logFactory");
            if(timerFactory == null)
                throw new ArgumentNullException("timerFactory");

            _logFactory = logFactory;
            _timerFactory = timerFactory;
        }

        public override void OnActionExecuting(HttpActionContext actionContext) {
            base.OnActionExecuting(actionContext);
            OnBeforeAction(actionContext);
        }

        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) {
            OnAfterAction(actionExecutedContext);
            base.OnActionExecuted(actionExecutedContext);
        }

        private void OnBeforeAction(HttpActionContext actionContext) {
            var controllerName = actionContext.ControllerContext.Controller.GetType().FullName;
            var actionName = actionContext.ActionDescriptor.ActionName;

            _logger = _logFactory.Create(controllerName);
            _logger.Trace("Action \"{0}\" begins execution", actionName);

            _timer = _timerFactory.Create();
            _timer.Start();
        }

        private void OnAfterAction(HttpActionExecutedContext actionExecutedContext) {
            var actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;

            _timer.Stop();
            _logger.Trace("Time elapsed for action \"{0}\": {1} msec", actionName, _timer.ElapsedMilliseconds);
        }

}

但是,动作过滤器充当单例,因此当OnActionExecuted 运行时,我不能确定_logger_timer 是否对应于为相同的动作OnActionExecuting 创建的 .

例如。

  1. 动作 Foo1 开始执行。 _logger = "logger1", _timer = "timer1".
  2. 动作 Foo2 开始执行。 _logger = "logger2"_timer = "timer2"(它们被覆盖)
  3. 动作 Foo1 结束执行。它停止计时器并记录经过的时间,这是无意义的(end1-start2)。

问题:有没有办法让我知道OnActionExecuted 对应的OnActionExecuting?如果有一些唯一的动作标识符,我可以将它用作字典的键来存储任何与动作相关的对象,例如记录器和计时器。有没有?还是其他解决方案?

【问题讨论】:

    标签: c# asp.net-mvc logging asp.net-web-api action-filter


    【解决方案1】:

    就 Web API 而言,System.Web.HttpContext.Current 并不总是得到保证。这取决于您是否使用 Web API 自托管。这就是在覆盖 System.Web.Http.Filters.ActionFilterAttribute.OnActionExecuting 时您没有在 HttpActionContext 参数上获得 httpcontext 属性的主要原因(在 AspNet MVC 中您可以)。

    最好的方法是使用actionContext.Request.Properties 字典。

    也检查这个答案here

    【讨论】:

      【解决方案2】:

      System.Web.HttpContext.Current.Items 是每个请求的缓存存储。
      您可以安全地在 OnBeforeAction 方法中的 Items 中添加计时器对象,并从 OnAfterAction 方法中的 Items 中检索此计时器对象

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-22
        • 2011-12-25
        • 1970-01-01
        • 2016-05-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多