server-timing
Advanced tools
Comparing version 3.1.2 to 3.2.0
@@ -5,4 +5,5 @@ declare module "server-timing" { | ||
total?: boolean; | ||
enabled?: boolean; | ||
enabled?: boolean | IsEnabledCheck; | ||
autoEnd?: boolean; | ||
precision?: number; | ||
}; | ||
@@ -15,3 +16,4 @@ const _default: (opts?: Options) => e.RequestHandler; | ||
}; | ||
export type IsEnabledCheck = (req: e.Request, res: e.Response) => boolean | ||
export type SeverTimingResponse = e.Response & Response; | ||
} |
34
index.js
@@ -10,5 +10,6 @@ 'use strict' | ||
enabled: true, | ||
autoEnd: true | ||
autoEnd: true, | ||
precision: +Infinity | ||
}, options) | ||
return (_, res, next) => { | ||
return (req, res, next) => { | ||
const headers = [] | ||
@@ -22,3 +23,3 @@ const timer = new Timer() | ||
res.setMetric = setMetric(headers) | ||
res.setMetric = setMetric(headers, opts) | ||
res.startTime = startTime(timer) | ||
@@ -28,16 +29,20 @@ res.endTime = endTime(timer, res) | ||
onHeaders(res, () => { | ||
if (opts.autoEnd) { | ||
const keys = timer.keys() | ||
for (const key of keys) { | ||
res.endTime(key) | ||
} | ||
} | ||
if (opts.total) { | ||
const diff = process.hrtime(startAt) | ||
const timeSec = (diff[0] * 1E3) + (diff[1] * 1e-6) | ||
if (opts.autoEnd) { | ||
const keys = timer.keys() | ||
for (const key of keys) { | ||
res.endTime(key) | ||
} | ||
} | ||
headers.push(`total; dur=${timeSec}; desc="Total Response Time"`) | ||
res.setMetric('total', timeSec, 'Total Response Time') | ||
} | ||
timer.clear() | ||
if (opts.enabled) { | ||
const enabled = typeof opts.enabled === 'function' | ||
? opts.enabled(req, res) : opts.enabled | ||
if (enabled) { | ||
const existingHeaders = res.getHeader('Server-Timing') | ||
@@ -54,3 +59,3 @@ | ||
function setMetric (headers) { | ||
function setMetric (headers, opts) { | ||
return (name, value, description) => { | ||
@@ -64,4 +69,7 @@ if (typeof name !== 'string') { | ||
const dur = Number.isFinite(opts.precision) | ||
? value.toFixed(opts.precision) : value | ||
const metric = typeof description !== 'string' || !description | ||
? `${name}; dur=${value}` : `${name}; dur=${value}; desc="${description}"` | ||
? `${name}; dur=${dur}` : `${name}; dur=${dur}; desc="${description}"` | ||
@@ -68,0 +76,0 @@ headers.push(metric) |
{ | ||
"name": "server-timing", | ||
"version": "3.1.2", | ||
"version": "3.2.0", | ||
"description": "This module can add `ServerTiming` Header to http response, and be able to use express middleware", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -50,2 +50,15 @@ # server-timing | ||
## Conditionally enabled | ||
```javascript | ||
const express = require('express'); | ||
const serverTiming = require('server-timing'); | ||
const app = express(); | ||
app.use(serverTiming({ | ||
// Only send metrics if query parameter `debug` is set to `true` | ||
enabled: (req, res) => req.query.debug === 'true' | ||
})); | ||
``` | ||
# API | ||
@@ -56,4 +69,5 @@ | ||
- options.total: boolean, default `true`, add total response time | ||
- options.enabled: boolean, default `true`, enable server timing header | ||
- options.enabled: boolean | function, default `true`, enable server timing header. If a function is passed, it will be called with two arguments, `request` and `response`, and should return a boolean. | ||
- options.autoEnd: boolean, default `true` automatically endTime is called if timer is not finished. | ||
- options.precision: number, default `+Infinity`, number of decimals to use for timings. | ||
@@ -60,0 +74,0 @@ # Result |
@@ -93,1 +93,44 @@ 'use strict' | ||
}) | ||
test('express stop automatic timer (without total)', () => { | ||
const app = express() | ||
app.use(serverTiming({total: false})) | ||
app.use((req, res, next) => { | ||
res.startTime('hello', 'hello') | ||
res.send('hello') | ||
}) | ||
const server = app.listen(0, () => { | ||
http.get(`http://localhost:${server.address().port}/`, mustCall((res) => { | ||
const assertStream = new AssertStream() | ||
assertStream.expect('hello') | ||
res.pipe(assertStream) | ||
assert(/hello; dur=.*; desc="hello"$/.test(res.headers['server-timing'])) | ||
server.close() | ||
})) | ||
}) | ||
}) | ||
test('express specify precision', () => { | ||
const app = express() | ||
app.use(serverTiming({precision: 2})) | ||
app.use((req, res, next) => { | ||
res.setMetric('manual', 100 / 3) | ||
res.startTime('auto') | ||
process.nextTick(() => { | ||
res.endTime('auto') | ||
res.send('hello') | ||
}) | ||
}) | ||
const server = app.listen(0, () => { | ||
http.get(`http://localhost:${server.address().port}/`, mustCall((res) => { | ||
const assertStream = new AssertStream() | ||
assertStream.expect('hello') | ||
res.pipe(assertStream) | ||
const timingHeader = res.headers['server-timing'] | ||
assert(/total; dur=\d+\.\d{2}[;,]/.test(timingHeader)) | ||
assert(/manual; dur=\d+\.\d{2}[;,]/.test(timingHeader)) | ||
assert(/auto; dur=\d+\.\d{2}[;,]/.test(timingHeader)) | ||
server.close() | ||
})) | ||
}) | ||
}) |
@@ -5,2 +5,3 @@ 'use strict' | ||
const http = require('http') | ||
const {URL} = require('url') | ||
const serverTiming = require('../.') | ||
@@ -120,2 +121,30 @@ const assert = require('assert') | ||
test('success: no response (conditional)', () => { | ||
const server = http.createServer((req, res) => { | ||
serverTiming({ | ||
enabled: req => { | ||
const url = new URL(req.url, `http://${req.headers.host}`) | ||
return url.searchParams.get("debug") === "true" | ||
} | ||
})(req, res) | ||
res.setMetric('foo', 100.0) | ||
res.end('hello') | ||
}).listen(0, () => { | ||
http.get(`http://localhost:${server.address().port}/?debug=true`, mustCall((res) => { | ||
const assertStream = new AssertStream() | ||
assertStream.expect('hello') | ||
res.pipe(assertStream) | ||
assert(res.headers['server-timing']) | ||
http.get(`http://localhost:${server.address().port}/?debug=false`, mustCall((res) => { | ||
const assertStream = new AssertStream() | ||
assertStream.expect('hello') | ||
res.pipe(assertStream) | ||
assert(!res.headers['server-timing']) | ||
server.close() | ||
})) | ||
})) | ||
}) | ||
}) | ||
test('success: stop automatically timer', () => { | ||
@@ -132,3 +161,4 @@ const server = http.createServer((req, res) => { | ||
assert(res.headers['server-timing']) | ||
console.log(res.headers) | ||
assert(res.headers['server-timing'].includes('foo; dur=')) | ||
assert(res.headers['server-timing'].includes('total; dur=')) | ||
server.close() | ||
@@ -138,1 +168,43 @@ })) | ||
}) | ||
test('success: stop automatically timer (without total)', () => { | ||
const server = http.createServer((req, res) => { | ||
serverTiming({total: false})(req, res) | ||
res.startTime('foo', 'foo') | ||
res.end('hello') | ||
}).listen(0, () => { | ||
http.get(`http://localhost:${server.address().port}/`, mustCall((res) => { | ||
const assertStream = new AssertStream() | ||
assertStream.expect('hello') | ||
res.pipe(assertStream) | ||
assert(res.headers['server-timing']) | ||
assert(res.headers['server-timing'].includes('foo; dur=')) | ||
assert(!res.headers['server-timing'].includes('total; dur=')) | ||
server.close() | ||
})) | ||
}) | ||
}) | ||
test('success: specify precision', () => { | ||
const server = http.createServer((req, res) => { | ||
serverTiming({precision: 3})(req, res) | ||
res.setMetric('manual', 100 / 3) | ||
res.startTime('auto') | ||
process.nextTick(() => { | ||
res.endTime('auto') | ||
res.end('hello') | ||
}) | ||
}).listen(0, () => { | ||
http.get(`http://localhost:${server.address().port}/`, mustCall((res) => { | ||
const assertStream = new AssertStream() | ||
assertStream.expect('hello') | ||
res.pipe(assertStream) | ||
const timingHeader = res.headers['server-timing'] | ||
assert(timingHeader) | ||
assert(/total; dur=\d+\.\d{3}[;,]/.test(timingHeader)) | ||
assert(/manual; dur=\d+\.\d{3}[;,]/.test(timingHeader)) | ||
assert(/auto; dur=\d+\.\d{3}[;,]/.test(timingHeader)) | ||
server.close() | ||
})) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24783
638
75