DevTrace is a performance widget for your Rails applications in development. It sits unobtrusively in the corner of your page, just waiting to drop insight on your application:
This kind of insight is powerful. You can see how your app executes, and head off performance issues before they get to production.
But what I want to cover here is how DevTraces stays out of the way — how it’s simultaineously powerful and unassuming.
1) Installed via Gem only
There’s only one thing to install, which is a gem in your application’s Gemfile. Earlier iterations needed a Chrome extension to instrument background Ajax requests. But installing the chrome extension was annoying, and it limited who could use DevTrace. So we figured out a way to instrument Ajax calls in Javascript only, by adding hooks to the browser’s XMLHttpRequest prototype.
2) Visually Lightweight
DevTrace shows up as a small, semi-transparent badge displaying your page load time. It’s placed in the lower left corner of your page, to stay out of the way of navigational elements. Since your eyes natually move from the upper-left to the lower-right of a page, DevTrace is only there if you look for it. Finally, we added subtle animations for Ajax requests — enough to notice, but not enough to be distracting.
3) HTML Hygene
HTML hygene (AKA staying the f* out of your markup as much as possible) is important. We know that — as a developer — you’ll be inspecting your source, and don’t want to see extra cruft from your performance tools.
DevTraces injects as little as possible into your page (we do have to add something though):
- a
<script>
tag to load the needed JavaScript - a
<style>
tag, with classes carefully scoped to our namespace - finally, for HTML pages, a JSON data structure with the trace information for the page
4) Keeping Ajax / JSON Payloads Clean
Modern apps do lots of work via post-pageload Ajax requests, and visibility into those requests is important. DevTrace instruments those calls as well. However, we can’t add profiling information to the payload itself – it would stomp on the expected payload structure. So we have a sneaky side-channel to move traces down to your browser in this case: we add a custom header to Ajax responses containing the trace information, then intercept that header & grab the payload in Javascript. It’s all transparent to you as a user, and it provides critical visibility.
6) Staying out of your Javascript Namespace
Nobody wants to include a tool which litters the Javascript namespace with variables and functions. DevTrace puts exactly one variable into your addressible namespace, which is a reference to a closure containing the entire DevTrace implementation.
The DevTrace widget does a lot visually: rendering its UI, animating the badge on incoming AJAX requests, etc. To enable this UI goodness without polluting your namespace, we place a copy of MinifiedJS (a very lightweight jQuery-type library) inside the closure. MinifiedJS helps make the rest of the widget code concise and maintainable. Completely encapsulating it inside our closure means it can’t interfere with other libraries or JS code on your page. Another key benefit is DevTrace makes no assumptions about which Javascript library your app uses.
6) Development Environment Only
Profiling in development is different from profiling in production. Always-on tracing works in development, because traffic is limited to just you (the developer), and overhead is less of a concern. In contrast, production environments require a smart sampling approach (which we’re perfecting in Scout APM). No need to worry about leaving DevTrace on in the wrong environment: even if you accidently configure it for production, it won’t even insert its rack middleware into your application in a non-development environment.
Staying out of the Way While Giving you What you Need
A Javascript widget needs to be a good houseguest. It doesn’t put its feet up on the furniture or spread its stuff out all over the kitchen. DevTrace goes to great lengths to be a welcome guest in the host application, while also giving you what you need: performance traces at your fingertips, line-of-code tracing, memory usage metrics, and insights on database queries.