Profiling WebAPI’s in AngularJS-app with MiniProfiler

with 1 Comment

Profiling is an important part of developing software, but its often overlooked during development.

When we write complex web applications knowledge about how our application performs is crucial:

  • How many requests is my application making to my backend?
  • What is the average time for these requests?
  • If the request is using a database:
    • How many SQL-statements is executed?
    • What is the time for these statements?
    • Is the statement (often generated by Entity Framework) a performant one?
    • Can we adjust our backend code to produce a better statement?

I’ve used MiniProfiler for this purpose in several projects. MiniProfiler can be found on nuget and easily integrates into your asp.net MVC-application:

First, download MiniProfiler from nuget into your MVC-project (links to nuget packages found here: http://miniprofiler.com).

Second, adjust your Global.asax.cs:

Third, in your _Layout.cshtml file:

The result is something like this:

demo

Piece of cake! (clicking on a sql-link gives you information about the sql-statements executed

So how does this magic work?

This is the life of a simple xhr-post is being made to the server:

  1. Application_Start is excuted. MiniProfiler is set to profile all Entity Framework’s sql-statements.
  2. Begin_Request is executed. MiniProfiler gets the current and previous profiling-ids not yet communicated to the client. These ids are added to the header of the response
  3. The xhr-request completed callback is called and the MiniProfiler javascript kicks in (see below for jquery-calls).
  4. The MiniProfiler client calls the server on /mini-profiler-resources/results/ once per Id, this returns profiling from the MiniProfiler instance.
  5. Magic is displayed for your pleasure.

So how about MiniProfiler for multiple WebAPI endpoints and one (angular) application:

This is a bit harder:

  1. Adjust Global.asax.cs for all your WebAPI’s so that MiniProfiler is run in all applications (this is _NOT_ enough since MiniProfiler cant talk between applications).
  2. Change MiniProfiler.Settings.Storage to a storage where all applications can reach.

Our implementation looks something like this:

 

Adjustment for Angular (1.3.10) (not needed if you are using another library for your XHR-needs)

MiniProfiler does this to XMLHttpRequest to be able to intercept all XHR-calls for angular

Well, Angular never sets xhr.onreadystatechange so we need to adjust this in a harmless way:

This is our approach to solving the performance-questions specified at the start. So far so good!

Hope you take the time to implement a similar solution to improve your applications performance, before release!

One Response

  1. sandy
    | Reply

    Hi ,
    great info !!
    I am working on similar prob. where my mvc web site and web api are is different servers . and I have to save all the profiled info into a database . can you please share your thoughts and if possible above working code example .

    Thanks,
    Sandy

Leave a Reply