Recently I was tasked with troubleshooting a problem with one of our Kentico MVC projects that we were working on. The issue was that, at a high load, the performance of the front end MVC live site was not scaling very well. This was an issue that I had not really seen before in our Kentico MVC projects because typically Kentico’s API caching system does a really great job at making sure sites are very high performing.
As long as you follow best practices for Kentico MVC development you are usually pretty good on the performance side, well, that is until a client loads a 5 MB image file on the home page, but alas, that is a different story for a different blog post.
The root issue seemed to be that the Time to first byte (TTFB) was relatively high in the first few tests and didn’t efficiently drop as much as we would like on the primed cache hits. This was a clue that it was something to do on the server-side rendering of the page, before the HTTP response was even being sent down to the browser. And with any asp.net database backed CMS, this usually points to something being up with the SQL database calls that it takes to render the page.
What Is a Kentico MVC Developer To Do
Naturally I decided to enable SQL Debugging in Kentico and take a look at what was going on behind the scenes to generate the page in question. And even though I thought this would just work, I was brought to a completely empty Debug app screen in the Kentico admin interface (and yes, before you ask, I did clear the cache…twice… for good measure). I thought, “Well that is just not very helpful is it…”.
After some quick googling for the official answer on if SQL Debugging was supported in Kentico MVC, I stumbled across the Debugging SQL queries with Glimpse on MVC sites article. “That’s right, Glimpse!” I proclaimed in my head.
If you are not familiar, Glimpse is a an open source diagnostics platform that has been built to support ASP.NET MVC debugging. It is actually quite popular in the ASP.NET community with even the likes of Scott Hanselman singing its praises.
The cool thing here is that Kentico has embraced Glimpse, and the product team has added direct support for Kentico developers to easily use it with Kentico via the Kentico.Glimpse NuGet package. It is one of the Kentico MVC integration packages which is part of 8 things developers should know about Kentico MVC. The Kentico.Glimpse integration with Kentico MVC is what allows you to see SQL query debug information right on your MVC live site.
Now if you had started your project by using the Kentico MVC starter site template, you would already have the package in your site and it would look like this:
However, starting with the Dancing Goat site is not a best practice. It is a much better idea to start from a blank slate and just create a whole new project(s) in your Visual Studio solution that connects to the Kentico admin interface project (CMSApp.csproj) as detailed out in the Kentico documentation. Since this is the route that we had taken with our project, the package was not there.
Basically, the instructions in the documentation make it very clear and straightforward on what you need to do to get Kentico.Glimpse running. Read that doc first, and then come back. I will walk through it here, to make it crystal clear and give a few tips.
Since your Visual Studio solution may have multiple projects, the first directions of just install the NuGet packages could be a bit clearer. What Kentico means here is that you should select your MVC live site project as the project to install these NuGet packages on, and NOT the CMSApp project.
Next up you will note that if you search for Kentico.Glimpse in the NuGet Package Manager, it will default to the latest stable version of the package. Right now, at time of writing this post, that would be version 3.0.0. This version of the package supports Kentico 11.0 which is what you would want if you were starting a new project.
For my issue, however, we are using Kentico 10.0. That means if I were to simply click the install button without looking, I could totally screw up the dependencies of my project. So be careful! The thing to take note is at the bottom of the screen where it mentions the package Dependencies. Switching the package version to 2.0.0 is what I needed. This switches the version to install Kentico.Glimpse so that it supports Kentico 10.0.
Don’t forget you do actually need to next install the latest version of the Glimpse.MVC5 package as the Kentico docs mention. Once both packages are installed, you can rebuild your project. This will restore the packages and dependencies to what you need and you should be good to run/debug your website locally with Glimpse installed.
The last step is to navigate to the special hidden Glimpse configuration handler, found at ~/glimpse.axd. That page should come right up and clicking on the Turn Glimpse On button should enable the debugger.
There biggest value that you get from Kentico’s Glimpse implementation is the Kentico SQL tab (the one in purple).
This tab shows you the same information as the Kentico Debug app does. The key here is that you can see which queries are run, how long they take, and if any duplicate queries show up, you know you have some issues to fix. Just like Kentico normally does, the long running or largest sized queries are highlighted in red. There is also more that Glimpse does from a debugging standpoint, but you can check out the Glimpse documentation on that. This link via Microsoft is pretty helpful as well.
Opening the stack trace of a query shows you how that query actually got run (which API called it) where possible.
One more reminder, don’t forget to disable Glimpse when you are done! It is going to affect performance as well if left on, just like the standard Kentico debugging tools. Luckily it is meant to run locally only, and running it remotely is disabled by default as well.
My Issue Easily Shown via Kentico.Glimpse
Below is a screen shot that really showed the power of this tool to me:
Glimpse showed us that we were moving 1.2 MB of data across the wire, on this page load and it was not being cached. Each and every time this page was run that amount of data was being returned, simply to generate the name and URL of the attachment that could be downloaded from the header of the page. We didn’t even actually need the contents of the file!
PRO Tip: If you don’t need the binary of an attachment make sure you use AttachmentInfoProvider.GetAttachmentInfoWithoutBinary if you don’t want the binary returned from the database call, and not AttachmentInfoProvider.GetAttachmentInfo if you do. The difference matters when it comes to performance.