Some users of an MVC 4 app are experiencing sporadic slowness. Presumably not every user reports that problem every time it happens to them.
My thought is to measure the time spent in each controller action and log details of action invocations that exceed a prescribed time to facilitate further analysis (to rule in or rule out a server/code issue).
Is there a convenient way to hook in to perform such measurements so that I can avoid adding instrumentation code to each action? I'm not currently using IOC for this project and would hesitate to introduce it just to solve this issue.
Is there a better way to tackle this type of problem?
Could you create a global action filter? Something like this:
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
}
}
and then add it to your GlobalFilters
collection in `Application_Start()'
GlobalFilters.Filters.Add(new PerformanceTestFilter());
You can get details about the controller being tested from the filterContext
parameter.
UPDATE
Adding the filter to the GlobalFilters
collection directly will create a single instance of the filter for all actions. This, of course, will not work for timing concurrent requests. To create a new instance for each action, create a filter provider:
public class PerformanceTestFilterProvider : IFilterProvider
{
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
return new[] {new Filter(new PerformanceTestFilter(), FilterScope.Global, 0)};
}
}
Then instead of adding the filter directly, rather add the filter provider in Application_Start()
:
FilterProviders.Providers.Add(new PerformanceTestFilterProvider());