某些 MVC 4 应用的用户遇到了零星的缓慢问题。可能每个用户并不总是在出现该问题时都会报告。
我的想法是测量每个控制器动作所需的时间,并记录超过预设时间的动作调用详细信息,以便进一步分析(排除服务器/代码问题或确认存在问题)。
是否有一种方便的方法来钩入执行这样的测量,以便我可以避免在每个动作中添加仪器化代码?我目前没有为这个项目使用 IOC,并且会犹豫是否引入它来解决此问题。
是否有更好的方法来解决这种类型的问题?
某些 MVC 4 应用的用户遇到了零星的缓慢问题。可能每个用户并不总是在出现该问题时都会报告。
我的想法是测量每个控制器动作所需的时间,并记录超过预设时间的动作调用详细信息,以便进一步分析(排除服务器/代码问题或确认存在问题)。
是否有一种方便的方法来钩入执行这样的测量,以便我可以避免在每个动作中添加仪器化代码?我目前没有为这个项目使用 IOC,并且会犹豫是否引入它来解决此问题。
是否有更好的方法来解决这种类型的问题?
你能创建一个全局的操作过滤器吗?就像这样:
public class PerformanceTestFilter : IActionFilter
{
private Stopwatch stopWatch = new Stopwatch();
public void OnActionExecuting(ActionExecutingContext filterContext)
{
stopWatch.Reset();
stopWatch.Start();
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
stopWatch.Stop();
var executionTime = stopWatch.ElapsedMilliseconds;
// Do something with the executionTime
}
}
然后将其添加到你的 `Application_Start()` 方法中的 GlobalFilters
集合中。
GlobalFilters.Filters.Add(new PerformanceTestFilter());
你可以从filterContext
参数中获取有关正在测试的控制器的详细信息。
更新
将过滤器直接添加到GlobalFilters
集合中将为所有操作创建一个过滤器实例。 当然,这不适用于计时并发请求。 要为每个操作创建一个新实例,请创建一个过滤器提供程序:public class PerformanceTestFilterProvider : IFilterProvider
{
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
return new[] {new Filter(new PerformanceTestFilter(), FilterScope.Global, 0)};
}
}
那么,不要直接添加筛选器,而是在Application_Start()
中添加筛选器提供程序:
FilterProviders.Providers.Add(new PerformanceTestFilterProvider());
<!-- Page generated in @((DateTime.UtcNow - HttpContext.Current.Timestamp.ToUniversalTime()).TotalSeconds.ToString("F4")) s -->
输出类似于:
<!-- Page generated in 0.4399 s -->
根据文档,这个开始测量时间是在创建HttpContext
时,停止在写入输出之前,因此应该非常准确。
它可能不适用于所有用例(如果您想测量子操作或忽略MVC操作之外的时间等),但很容易粘贴到视图中。
对于更高级的诊断,我过去使用Glimpse。
请尝试使用ASP.NET 4.5页面仪表化。
它可以仪表化页面渲染:您的应用程序可能会在控制器中花费时间,但是在视图渲染中也有很多时间。特别是如果您有许多部分和HTML帮助程序。
更新 - 使用 Install-Package StopWatch 安装我的秒表 NuGet 包, 请参见 Profile and Time your ASP.NET MVC app all the way to Azure。
查看我的教程 Using Asynchronous Methods in ASP.NET MVC 4, 其中包含全局操作筛选器计时器。您可以使用 ELMAH 记录数据。 我的示例 http://msdn.microsoft.com/en-us/library/gg416513(v=vs.98) 也具有相同的计时筛选器,但它是预先 Razor 的。
查找停止表属性以启用计时。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new UseStopwatchAttribute());
}
}
IFilterProvider
。请查看我的更新答案。 - Kevin AenmeyStopwatch
类有Restart
方法。 - user1068352filterContext.HttpContext.Items
来存储你的计时器,并在之后获取它(对于 WebApi 过滤器,可以使用actionContext.Request.Properties
)。 - Guillaume86OnActionExecuted
的末尾放置stopWatch=null
,这样您就可以确保获得一个新实例。如果出现异常,您就知道实例正在被重用。 - Simon_Weaver