Feature Focus: “The Metrics”, Episode 1
Metrics are an important part of Blackfire, contributing to a wider awesome feature: Tests
Blog post series index:
Profiling is all about measuring what actually happens within your application. In that regard, the Blackfire probe collects different types of measurements for each function call in your application as it is running:
- Number of times a function is called;
- Wall Time, the global time took by the function itself;
- I/O Wait Time, the time your application is waiting for external components (e.g. the file system, database communication, network…);
- CPU Time, the computation time;
- Memory consumption;
- Network bandwidth consumption.
Each of those dimensions provides a different representation, like a facet, of the profile. While this can be sufficient to spot performance issues, Blackfire also provides the ability to define and use “Metrics”, based on those measurements.
What Metrics are and how they are useful
A Metric is a collection of measurements, based on one or several function calls. We can consider it as a bag where resources costs are put together. This bag can aggregate several functions, has a unique label, and can be stored in another (bigger) bag.
For example, the
symfony.controllers.argument_resolver metric is a child of
symfony.controllers metric, and as such, measurements from the
argument_resolver bubble up to
symfony.controllers as well. Like for function calls, all collected dimensions are available.
Metrics can be used in 2 different situations:
- When defining Tests;
- In the Timeline View.
Evaluating assertions based on metrics
Pretty much like writing unit tests or integration tests, Blackfire enables you to write tests by evaluating assertions against metrics.
Such tests can be, for example, non-regression tests written after having spotted and fixed a performance issue with the help of Blackfire. They can also be more quality or security oriented, to ensure that your application behaves as expected, and meet your technical specifications and requirements.
Tests are defined in
.blackfire.yaml file, which must live at the root of your codebase. It should be versioned with the rest of your code, and shipped into production.
tests: 'All pages are fast': path: '/.*' assertions: - 'main.wall_time < 200ms' - 'main.memory < 10Mb' 'Twig template cache should be enabled in production': path: '/.*' unless: 'is_dev()' assertions: - 'metrics.twig.compile.count == 0' 'Symfony events dispatched': path: '/.*' assertions: - 'metrics.symfony.events.count < 25' 'Not too many SQL queries on the homepage': path: '/(en|fr)/blog/' assertions: - 'metrics.sql.queries.count < 5'
In the example above 👆, metrics are leveraged within assertions using operators.
A very good example of tests is Blackfire Recommendation system. In the background, recommendations actually use the same testing mechanism, evaluating assertions against metrics.
Metrics and the Timeline View
Blackfire Timeline view provides a time-based representation of a profile. It helps understanding the behavior of your application over time. In this view, metrics are used instead of bare function calls in order to give a more intuitive visualisation. Metrics blocks are piled-down, showing how deep your application goes, which can be a good indication for its complexity.
Not all metrics are featured in the Timeline, only the ones considered relevant for such a representation.
Metrics are an important part of Blackfire, especially when using Tests, for which they constitute the smallest entity.
Blackfire comes with hundreds of built-in metrics, which are ready to use in your assertions. But did you know that you could define custom metrics, based on your own codebase? This will be covered by the next Feature Focus episode 😉.