Refactoring Particletree's PHPQuickProfiler
Back in 2009 I was working at a company in De Pere called SparkNET. I was still a fresh developer then, just getting used to working with a team and building on modern web framework principles. One of the tools that they introduced was a profiler from Particletree that kept track of simple application behaviors and offered unobtrusive, on-screen debugging information. This profiler drastically changed how I approached development, forcing me to be aware of problematic queries and memory usage.
These days there are more options for profiling. There is Xdebug, Symfony Web Profiler, New Relic, StatsD, among others. But there isn't anything quite as simple and easy to implement as the old Particletree profiler. I still use it on some of my side projects, including this blog, and enjoy the insights that it gives me on the application. There is one problem, though: it hasn't aged well.
The base profiler throws more than a few PHP warnings and notices. If you use the profiler as a default error display it gets annoying to see errors about the profiler when you're trying to debug the application. Built in 2009 (or earlier) the code does not follow any modern PSR practices or autoloading options and is only installable by dropping a ZIP into your application. Query analysis is tricky to setup and requires some rather drastic changes to your database connection - oh, and it doesn't support param binding, a mainstay for most secure web applications. So I rewrote it.
My initial focus was on registering a modified version of the original release so that it could be served up from Packagist and ensure it can handle PHP 5.6 and PHP 7. As I began to wade into the core I soon realized that there was more to be done. So, writing unit tests along the way to enforce original behavior I broke things down and rebuilt them. I did my best to enforce single-responsibility and injection patterns along the way while preserving the original interface.
I did have to make a few breaking changes. The Console class, which serves as the main storage unit for the logs, was originally built as a global static class that fronted direct calls to $_GLOBALS. This just wouldn't do. It is now instantiated, holding the logs in state, and needs to be injected into PhpQuickProfiler. Previously the styles and scripts files had to be placed in a 'public' folder, which did allow for easier access by the implementing developers. These are now inline to avoid setup overhead. Oh, and there's a new Display class that encapsulates human-friendly formatting, but this really doesn't need to be touched unless extra configuration is desired.
One piece that still gets me is the way profiling works. Originally the Particletree profiler required a single database connection object to include an accessible 'queries' property that was a multi-dimensional array with defined keys. This seemed a bit heavy-handed. Taking a page from Aura.Sql I added the option to inject a separate array of profiled queries, which could be collected from multiple connections or separate classes, though they still need to follow the same defined keys pattern. It'd be great to add a listener somehow, something that eavesdrops on commands sent to the data layer, and have the profiler grab and analyze them as demanded. Oh well.
Anyways, v1 is finally out and is available on packagist. (Did I mention it has 100% test coverage because that's pretty cool.) Moving forward I'm planning on creating a Monolog handler to avoid direct Console::log calls, though I'm not sure if there's an easy way to abstract out the other (memory, speed, error) calls into Monolog. Also, I want to start add some configuration options into the Display class. Simple stuff, like alternate stylesheets/templates or initial load displays. Regardless, I'm pretty excited to have this refactored. It was a lot of fun to work on the original Particletree release, something I've really appreciated over the years, and to make it accessible to modern developers.
Comments (0)