Allow you add metrics via Server-Timing header
npm install server-timing-headerThis is middleware for Express that allow you monitor server-side performance in the browser with use of Service-Timing headers.
- Great for identifying server-side performance issues.
- Supported in Chrome, Safari and Mozilla.
- _1.52 KB_ with all dependencies, minified and gzipped.
- Tested.
Step 1: install package.
npm i -S server-timing-header
Step 2: add middleware.
``diff javascript
+ const serverTimingMiddleware = require('server-timing-header');
const express = require('express');
const app = express();
+ app.use(serverTimingMiddleware({sendHeaders: (process.env.NODE_ENV !== 'production')}));
`
Step 3: measure how long take to get data.
`diff javascript`
app.get('/', function (req, res, next) {
+ req.serverTiming.from('db');
// fetching data from database
+ req.serverTiming.to('db');
// …
});
Step 4: check Server-Timing in the network tab of Chrome DevTools.
Measure time between two points
Most common use-case — measure time between two points.
`javascriptExample app listening on port ${port}!
const express = require('express');
const serverTimingMiddleware = require('server-timing-header');
const port = 3000;
const app = express();
app.use(serverTimingMiddleware({sendHeaders: (process.env.NODE_ENV !== 'production')}));
app.get('/', function (req, res, next) {
req.serverTiming.from('db');
// fetching data from database
req.serverTiming.to('db');
});
app.listen(port, () => console.log());`
Add metric manually
In case we recieve timing from external source we may just add metric we need.
`javascriptExample app listening on port ${port}!
const express = require('express');
const serverTimingMiddleware = require('server-timing-header');
const port = 3000;
const app = express();
app.use(serverTimingMiddleware());
app.get('/', function (req, res, next) {
// You got time metric from the external source
req.serverTiming.add('cache', 'Cache Read', 23.2);
});
app.listen(port, () => console.log());`
Add hook to modify data before send
In some cases you may need to modify data before send it to browser. In example bellow we can't separate time of rendering and time of acquiring data. To make render time more precise we may devide time we use to get data from the rendering time.
`javascriptExample app listening on port ${port}!
const express = require('express');
const serverTimingMiddleware = require('server-timing-header');
const port = 3000;
const app = express();
app.use(serverTimingMiddleware());
app.get('/', function (req, res, next) {
req.serverTiming.from('render');
req.serverTiming.from('data');
// fetching data from database
req.serverTiming.to('data');
req.serverTiming.to('render');
});
app.use(function (req, res, next) {
// If one measurement include other inside you may substract times
req.serverTiming.addHook('substractDataTimeFromRenderTime', function (metrics) {
const updated = { ...metrics };
if (updated.data && updated.render) {
const renderDuration = req.serverTiming.calculateDurationSmart(updated.render);
const dataDuration = req.serverTiming.calculateDurationSmart(updated.data);
updated.render.duration = Math.abs(renderDuration - dataDuration);
}
return updated;
});
});
app.listen(port, () => console.log());`
Result in the Chrome DevTools
Result in the Safari DevTools
Access metrics values from JavaScript on a client
You may access data from JavaScript with help of PerformanceServerTiming.
`javascript`
['navigation', 'resource']
.forEach(function(entryType) {
performance.getEntriesByType(entryType).forEach(function({name: url, serverTiming}) {
serverTiming.forEach(function({name, duration, description}) {
console.info('expressjs middleware =',
JSON.stringify({url, entryType, name, duration, description}, null, 2))
})
})
})
- Chrome v.60
- FF v.63
- Safari v.12.1 _(no api support)_
- ServerTiming
- addHook
- Parameters
- Examples
- removeHook
- Parameters
- from
- Parameters
- Examples
- to
- Parameters
- Examples
- description
- Parameters
- duration
- Parameters
- add
- Parameters
- Examples
- calculateDurationSmart
- Parameters
- oldStyle
- Parameters
- newStyle
- Parameters
- index
- Parameters
- Examples
- See:
Middleware for express.js to add Server Timing headers
Meta
- author: Anton Nemtsev <thesilentimp@gmail.com>
Add callback to modify data before create and send headers
#### Parameters
- name string — hook namecallback
- function — function that may modify data before send headerscallbackIndex
- number index that will be used to sort callbacks before execution
#### Examples
Add hook to mutate the metrics
`javascriptExample app listening on port ${port}!
const express = require('express');
const serverTimingMiddleware = require('server-timing-header');
const port = 3000;
const app = express();
app.use(serverTimingMiddleware());
app.use(function (req, res, next) {
// If one measurement include other inside you may substract times
req.serverTiming.addHook('substractDataTimeFromRenderTime', function (metrics) {
const updated = { ...metrics };
if (updated.data && updated.render) {
const renderDuration = req.serverTiming.calculateDurationSmart(updated.render);
const dataDuration = req.serverTiming.calculateDurationSmart(updated.data);
updated.render.duration = Math.abs(renderDuration - dataDuration);
}
return updated;
});
});
app.listen(port, () => console.log());`
Remove callback with specific name
#### Parameters
- name string — hook name
Set start time for metric
#### Parameters
- name string — metric namedescription
- string? — description of the metric
#### Examples
You may define only start time for metric
`javascriptExample app listening on port ${port}!
const express = require('express');
const serverTimingMiddleware = require('server-timing-header');
const port = 3000;
const app = express();
app.use(serverTimingMiddleware());
app.get('/', function (req, res, next) {
// If you define only start time for metric,
// then as the end time will be used header sent time
req.serverTiming.from('metric', 'metric description');
// fetching data from database
});
app.listen(port, () => console.log());`
Set end time for metric
#### Parameters
- name string — metric namedescription
- string? — description of the metric
#### Examples
You may define only end time for metric
`javascriptExample app listening on port ${port}!
const express = require('express');
const serverTimingMiddleware = require('server-timing-header');
const port = 3000;
const app = express();
app.use(serverTimingMiddleware());
app.get('/', function (req, res, next) {
// fetching data from database
// If you define only end time for metric,
// then as the start time will be used middleware initialization time
req.serverTiming.to('metric');
});
app.listen(port, () => console.log());`
Add description to specific metric
#### Parameters
- name string — metric namedescription
- string — description of the metric
Add duration to specific metric
#### Parameters
- name string — metric nameduration
- float — duration of the metric
Add metric
#### Parameters
- name string metric namedescription
- string — metric descriptionduration
- number — metric duration (optional, default 0.0)
#### Examples
Add metric
`javascriptExample app listening on port ${port}!
const express = require('express');
const serverTimingMiddleware = require('server-timing-header');
const port = 3000;
const app = express();
app.use(serverTimingMiddleware());
app.get('/', function (req, res, next) {
// You got time metric from the external source
req.serverTiming.add('metric', 'metric description', 52.3);
});
app.listen(port, () => console.log());`
Calculate duration between two timestamps, if from or two is undefined — will use initialization time and current time to replace
#### Parameters
- metric object — object that contain metric informationmetric.name
- string — metric namemetric.description
- string — metric descriptionmetric.from
- Array<integer> — start time [seconds, nanoseconds], if undefined, initialization time will be usedmetric.to
- Array<integer> — end time [seconds, nanoseconds], if undefined, current timestamp will be usedmetric.duration
- integer — time in milliseconds, if not undefined method will just return durations
Returns integer duration in milliseconds
Build server-timing header value by old specification
#### Parameters
- name string metric namedescription
- string metric descriptionduration
- string metric duration
Returns string — server-timing header value
Build server-timing header value by current specification
#### Parameters
- name string metric namedescription
- string metric descriptionduration
- string metric duration
Returns string — server-timing header value
Express middleware add serverTiming to request and
make sure that we will send this headers before express finish request
- options object? — middleware options (optional, default {})options.sendHeaders
- boolean? should middleware send headers (may be disabled for some environments) (optional, default true)
How to add middleware
`javascriptExample app listening on port ${port}!
const express = require('express');
const serverTimingMiddleware = require('server-timing-header');
const port = 3000;
const app = express();
app.use(serverTimingMiddleware());
app.get('/', function (req, res, next) {
req.serverTiming.from('db');
// fetching data from database
req.serverTiming.to('db');
});
app.listen(port, () => console.log());``
Returns function return express middleware