如何使用ActionFilterAttribute来记录运行时间

本文关键字:记录 运行时间 ActionFilterAttribute 何使用 | 更新日期: 2023-09-27 17:51:03

我创建了一个操作过滤器,用于测量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);
        }
}

但是,操作筛选器充当singleton,因此当OnActionExecuted运行时,我不能确定_logger_timer是否与为相同操作OnActionExecuting创建的对应。

例如。

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

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

如何使用ActionFilterAttribute来记录运行时间

就Web API而言,System.Web.HttpContext.Current并不总是有保证的。这取决于您是否使用Web API自托管。这就是在重写System.Web.Http.Filters.ActionFilterAttribute.OnActionExecuting时,您不会在HttpActionContext参数上获得httpcontext属性的主要原因(在AspNetMVC中,您会获得(。

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

也可以在这里检查这个答案

系统。网状物HttpContext。现在的Items是一个按请求的缓存存储
您可以安全地在OnBeforeAction方法的Items中添加计时器对象,并从OnAfterAction方法中的Items检索此计时器对象