Измерение времени вызова действий контроллера ASP.NET MVC

Некоторые пользователи приложения MVC 4 испытывают спорадическую медлительность. Предположительно, не каждый пользователь сообщает об этой проблеме каждый раз, когда это происходит с ним.

Моя мысль состоит в том, чтобы измерить время, затрачиваемое на каждое действие контроллера, и зарегистрировать детали вызовов действий, которые превышают предписанное время, чтобы облегчить дальнейший анализ (чтобы исключить или исключить проблему с сервером / кодом).

Есть ли удобный способ подключиться к выполнению таких измерений, чтобы избежать добавления инструментария к каждому действию? В настоящее время я не использую МОК для этого проекта и не хотел бы представлять его только для решения этой проблемы.

Есть ли лучший способ решения этой проблемы?

4 ответа

Решение

Не могли бы вы создать глобальный фильтр действий? Что-то вроде этого:

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
    }
}

а затем добавить его в свой GlobalFilters коллекция в `Application_Start()'

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());

Я обычно добавляю этот простой код в конец моего представления Layout:

<!-- 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 Page Инструментарий

Это инструменты рендеринга страницы: время вашего приложения может быть потрачено в контроллере, но есть много раз, когда оно тратится на визуализацию. Особенно, если у вас есть много частичных и HTML-помощников.

Обновление - установите мой пакет секундомера NuGet с помощью Install-Package StopWatch, см. Профиль и время вашего приложения ASP.NET MVC вплоть до Azure.

См. Мое руководство Использование асинхронных методов в ASP.NET MVC 4, в котором есть глобальный таймер фильтра действий. Вы можете использовать ELMAH для регистрации данных. Мой образец Мой образец http://msdn.microsoft.com/en-us/library/gg416513(v=vs.98) также имеет тот же фильтр синхронизации и является более простым, но это pre-Razor.

Ищите атрибут секундомера, чтобы включить синхронизацию.

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new UseStopwatchAttribute());
    }
}
Другие вопросы по тегам