Measure Server Timing Metrics with Server-Timing Header in SilverStripe
In a world where the speed of web applications is imperative for user experience and Search Engine Optimisation (SEO) purposes, the ability to measure and identify potential performance bottlenecks is crucial.
This is where the Server-Timing header can help developers identify and resolve bottlenecks to improve overall website performance.
What is the Server-Timing API?
The Server Timing API is a W3C supported specification which helps expose timing information from within an application to the front-end client-side.
The Server-Timing API does not directly measure the timing of different server events but instead enables metrics to be surfaced to the browser, once the metrics themselves have been measured.
The Time-To-First-Byte metric is commonly used to define how long the browser takes between making a request to the server and receiving a HTTP response. A number of different tasks are usually completed before a response is sent back to the client-side. Tasks such as reading data from a database, rendering the response in a template, or connecting to other APIS . In order to optimise this process, a developer needs to first identify where bottlenecks are occurring by measuring these tasks using either some 3rd-party tooling or via custom code.
Once the event timings have been measured, the Server-Timing API communicates these back-end server-timing metrics to the client-side in a set of HTTP response headers. These headers can then be seen in either the developer tools of a user’s browser or retrieved via the PerformanceServerTiming interface.
Server-timing metrics communicated by the Server-Timing header can be in different formats including:
- metric name only
- metric with value
- metric with value and description
- metric with description:
The following shows an example of how different server metrics can be formatted:
// Single metric without value
// Single metric (called cpu) with value
// Single metric (metric is called cache)with description and value
Server-Timing: cache;desc="Cache Read";dur=23.2
// Two metrics with value - db and app
Server-Timing: db;dur=53, app;dur=47.2
--- response body ---
// Overall response time
The Internetrix Server Timing module for SilverStripe Framework
Internetrix has built an open-source Server Timing module for SilverStripe Framework which acts as a middleware for developers to easily measure custom timing metrics and add them to the headers of a response.
The module can simply be installed via Composer:
composer require internetrix/silverstripe-server-timing
When configuring the module's middleware, the \Internetrix\Control\Middleware\ServerTimingMiddleware::class should be added to the top of the SilverStripe Framework middleware execution pipeline before the SilverStripe Framework has been fully bootstrapped, to allow for the most accurate measuring of server-timings.
The instructions to do so can be found in the Configuration section of the module’s README file.
Default timing metrics
Once the module has been installed and configured, the web application will automatically start measuring the following metrics out-of-the-box and add them to the Server-Timing header for all HTTP responses:
- Bootstrap: Time until it takes for the ServerTimingMiddleware to be called
- Application: Time it takes to receive a response from the SilverStripe Franemwork application.
- Total: The total duration being a request being sent to the server until right before a response being sent back to the client-side.
The following shows how the default server-timing metrics appears in the developer tools of Chrome when selecting the web request for the current page in the NETWORK tab:
Custom timing metrics
If you're looking to go above and beyond the default metrics, you can easily add more server-side timing metrics to understand what is slowing down the response from the server.
You will first need to identify 2 points in the custom code where you would like to measure the timing for (i.e the time it takes from the 1st point to the 2nd point).
Once you have identified the section of the application that they would like to measure, you will need to call the start() and end() methods on the Internetrix\ServerTiming\Helper\ServerTiming::class:
ServerTiming::start('Custom Metric to Measure'); // do something in the code ServerTiming::end('Custom Metric to Measure');
Alternatively, you can also measure the duration it took from the start of the request to reach a certain point in the application’s execution by calling the addMetric() method on the same ServerTiming class:
ServerTiming::addMetric('Metric to Add');
Client-Side Analytics Integration
It is important to note when using the PerformanceServerTiming interface that it is restricted to the same origin and only available in secure contexts (HTTPS) for some browsers. This means that server-timing information will not be retrievable using the PerformanceServerTiming interface on any environments without SSL. The server-timing information will still however be visible using the developer tools of a browser.