Do you know why most developers don’t manage the performance of their applications? Many will tell you they don’t have the time, but the real reason is probably that they don’t have the right tools. Blackfire fills this gap. Being able to profile applications in development and diagnose problems in production is great, but if the process is manual, developers will stop doing it after a while.
Automation is key to continuously manage application performance.
Automation is also key to avoid performance regressions in production. Blackfire provides a feature that helps developers trigger performance tests on an application and be alerted whenever a problem occurs.
Manually triggering profiles on individual URLs like we did previously works well on development machines, but it does not scale well for production monitoring.
Blackfire scenarios let you run a set of profiles on your application’s main
URLs or API endpoints. Scenarios are defined in
.blackfire.yaml under the
GitList scenarios could look like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
scenarios: | #!blackfire-player scenario name 'Twig on GitList' visit url('/') name 'Homepage' visit url('/Twig') name 'Twig repository' visit url('/Twig/commits') name 'Twig commits' visit url('/Twig/stats') name 'Twig repository stats' visit url('/Twig/newtork') name 'Twig network graph' visit url('/Twig/newtork/1.x') name 'Twig network Ajax' visit url('/Twig/tree/1.x/search?query=loader') name 'Search' method 'POST' # Default samples for POST requests is 1 without warmup. # Here we explicitely use 10 samples aggregation with a warmup request # since this POST request is idempotently safe. samples 10 warmup true
In the example, all scenarios, but the last one, trigger profiles on HTTP
GET requests. For each one of them, Blackfire warms up the URL by hitting
it a few times before generating a profile out of several iterations.
The “Search” scenario is more interesting as it requests a
but a safe one. By default, scenarios for non-GET requests have no warmup and
profiles are generated from only one iteration. But as GitList search is
idempotent, the scenario is explicitly configured to enable warmup (
true) and to generate 10 requests (
samples: 10) for the profile.
Blackfire scenarios have more options as described in the scenarios documentation.
Now that the GitList scenarios are defined, we need a way to trigger them. Blackfire has several ways to trigger them, but the most simple one is to use a periodic build.
Select your Environment, go to the
and click the “Enable periodic builds” button. By default, Blackfire will launch
a new build every 6 hours. But you can fine-tune those settings. Click on the “Edit”
By default, Blackfire will run builds on the endpoint you define when you created the environment, but you can change that. However, periodic builds can target a single endpoint. You’ll need to create multiple environments if you want to periodic run builds on multiple endpoints.
The Enterprise Edition of Blackfire offers all ways to trigger them, such as the webhook.
Go to the Dashboard’s
Builds tab of your environment and click the “Start
a build” button:
Then enter the endpoint (
https://gitlist.demo.blackfire.io/), trigger the
build by submitting the form, and wait for the profiles to finish.
Alternatively, you can also copy and paste the generated URL at the bottom of the form in a console:
1 2 3 4
curl -i -X POST https://blackfire.io/api/v2/builds/env/ENV-UUID/webhook \ --user 'CLIENT-ID:CLIENT-TOKEN' \ -d 'endpoint=https://gitlist.demo.blackfire.io/' \ -d 'title=My First Scenario!'
To use the command above, replace the
ENV-UUID placeholder with the
UUID of one of your Blackfire environments and the
CLIENT-TOKEN placeholders with your client credentials.
If the trigger fired correctly, the JSON output should contain “A new build has been started”. Go to the Blackfire dashboard, then to the “Builds” tab and select the newest build:
With one simple request, we were able to automatically generate 7 profiles in parallel for the main GitList URLs.
The build report displays all profile results, highlights failed scenarios, and provides details for any failed assertions:
As expected, some scenarios fail. Next execute the scenarios on the
branch (from the web or from the console), where our performance patches have
1 2 3 4
curl -i -X POST https://blackfire.io/api/v2/builds/env/ENV-UUID/webhook \ --user 'CLIENT-ID:CLIENT-TOKEN' \ -d 'endpoint=https://fix2-ijtxpsladv67o.eu.platform.sh/' \ -d 'title=Scenario on the fix2 branch'
The results are definitely better, but not as good as we could have hoped. Have a closer look and you will realize that some pages are slower than expected. This is the time to dig into the root causes and try to find more optimizations.
Remember that the main benefits of storing scenarios in a
.blackfire.yaml file alongside your code is to make them specific to
your current work: a pull request, a branch, a specific version of your
code, etc. Whenever you add a new feature, don’t forget to update the
Webhooks are a great way to integrate Blackfire into any tool. Then, once your checks are automated, you will need a way to be alerted when performance degrades.
Blackfire notification channels alert you when a build fails or when a project’s status changes. Blackfire comes with many built-in notification channels, but the simplest one is the email notification channel.
On the dashboard Builds view, add an email notification channel. Configure the email notification channel to receive an email whenever there is a failure or when the build status changes:
In development, update your application scenarios whenever you make significant changes.
Configure your test environment to run the scenarios via the webhook and use the email notification channel to receive a notification whenever a build fails.
But there is more. Builds are also available in the SDK, which opens the door to dynamically building scenarios. The SDK is the best way to leverage Blackfire powerful features, and in the next chapter we will study some advanced usages.