under-pressure
Advanced tools
Comparing version 3.2.1 to 5.0.0
@@ -1,3 +0,4 @@ | ||
import * as http from "http"; | ||
import * as fastify from "fastify"; | ||
import { | ||
FastifyPlugin | ||
} from "fastify"; | ||
@@ -14,3 +15,3 @@ declare namespace underPressure { | ||
sampleInterval?: number; | ||
exposeStatusRoute?: boolean | string | {routeOpts: object; url?: string}; | ||
exposeStatusRoute?: boolean | string | { routeOpts: object; url?: string }; | ||
} | ||
@@ -20,14 +21,11 @@ } | ||
declare module "fastify" { | ||
interface FastifyInstance<HttpServer, HttpRequest, HttpResponse> { | ||
memoryUsage: () => string; | ||
interface FastifyInstance { | ||
memoryUsage(): string; | ||
} | ||
} | ||
declare let underPressure: fastify.Plugin< | ||
http.Server, | ||
http.IncomingMessage, | ||
http.ServerResponse, | ||
declare let underPressure: FastifyPlugin< | ||
underPressure.UnderPressureOptions | ||
>; | ||
export = underPressure; | ||
export default underPressure; |
38
index.js
@@ -5,7 +5,15 @@ 'use strict' | ||
const assert = require('assert') | ||
const { monitorEventLoopDelay } = require('perf_hooks') | ||
function getSampleInterval (value, eventLoopResolution) { | ||
const defaultValue = monitorEventLoopDelay ? 1000 : 5 | ||
const sampleInterval = value || defaultValue | ||
return monitorEventLoopDelay ? Math.max(eventLoopResolution, sampleInterval) : sampleInterval | ||
} | ||
async function underPressure (fastify, opts) { | ||
opts = opts || {} | ||
const sampleInterval = opts.sampleInterval || 5 | ||
const resolution = 10 | ||
const sampleInterval = getSampleInterval(opts.sampleInterval, resolution) | ||
const maxEventLoopDelay = opts.maxEventLoopDelay || 0 | ||
@@ -24,3 +32,12 @@ const maxHeapUsedBytes = opts.maxHeapUsedBytes || 0 | ||
var eventLoopDelay = 0 | ||
var lastCheck = now() | ||
var lastCheck | ||
var histogram | ||
if (monitorEventLoopDelay) { | ||
histogram = monitorEventLoopDelay({ resolution }) | ||
histogram.enable() | ||
} else { | ||
lastCheck = now() | ||
} | ||
const timer = setInterval(updateMemoryUsage, sampleInterval) | ||
@@ -100,2 +117,13 @@ timer.unref() | ||
function updateEventLoopDelay () { | ||
if (histogram) { | ||
eventLoopDelay = Math.max(0, histogram.mean / 1e6 - resolution) | ||
histogram.reset() | ||
} else { | ||
const toCheck = now() | ||
eventLoopDelay = Math.max(0, toCheck - lastCheck - sampleInterval) | ||
lastCheck = toCheck | ||
} | ||
} | ||
function updateMemoryUsage () { | ||
@@ -105,5 +133,3 @@ var mem = process.memoryUsage() | ||
rssBytes = mem.rss | ||
var toCheck = now() | ||
eventLoopDelay = toCheck - lastCheck - sampleInterval | ||
lastCheck = toCheck | ||
updateEventLoopDelay() | ||
} | ||
@@ -178,4 +204,4 @@ | ||
module.exports = fp(underPressure, { | ||
fastify: '>=2.0.0', | ||
fastify: '3.x', | ||
name: 'under-pressure' | ||
}) |
{ | ||
"name": "under-pressure", | ||
"version": "3.2.1", | ||
"version": "5.0.0", | ||
"description": "Measure process load with automatic handling of 'Service Unavailable' plugin for Fastify.", | ||
@@ -8,5 +8,5 @@ "main": "index.js", | ||
"lint": "standard | snazzy", | ||
"unit": "tap test.js --no-coverage", | ||
"unit": "tap test.js", | ||
"test": "npm run lint && npm run unit && npm run typescript", | ||
"typescript": "tsc --project ./tsconfig.json" | ||
"typescript": "tsd" | ||
}, | ||
@@ -30,17 +30,18 @@ "repository": { | ||
"dependencies": { | ||
"fastify-plugin": "^1.5.0" | ||
"fastify-plugin": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^12.7.3", | ||
"fastify": "^2.3.0", | ||
"@types/node": "^13.13.2", | ||
"fastify": "^3.0.0-rc.1", | ||
"pre-commit": "^1.2.2", | ||
"simple-get": "^3.0.3", | ||
"simple-get": "^3.1.0", | ||
"snazzy": "^8.0.0", | ||
"standard": "^14.0.0", | ||
"tap": "^14.2.4", | ||
"tsd": "^0.11.0", | ||
"typescript": "^3.6.2" | ||
}, | ||
"engines": { | ||
"node": ">=8" | ||
"node": ">=10" | ||
} | ||
} |
# under-pressure | ||
[](https://greenkeeper.io/) | ||
[](https://github.com/fastify/under-pressure/actions) | ||
[](http://standardjs.com/) | ||
[](https://travis-ci.org/fastify/under-pressure) | ||
@@ -111,3 +110,19 @@ Measure process load with automatic handling of *"Service Unavailable"* plugin for Fastify. | ||
``` | ||
<a name="sample-interval"></a> | ||
#### Sample interval | ||
You can set a custom value for sampling the metrics returned by `memoryUsage` using the `sampleInterval` option, which accepts a number that represents the interval in milliseconds. | ||
The default value is different depending on which Node version is used. On version 8 and 10 it is `5`, while on version 11.10.0 and up it is `1000`. This difference is due to the fact that from version 11.10.0 the event loop delay can be sampled with [`monitorEventLoopDelay`](https://nodejs.org/docs/latest-v12.x/api/perf_hooks.html#perf_hooks_perf_hooks_monitoreventloopdelay_options) and this allows to increase the interval value. | ||
```js | ||
const fastify = require('fastify')() | ||
fastify.register(require('under-pressure'), { | ||
sampleInterval: <your custom sample interval in ms> | ||
}) | ||
``` | ||
<a name="acknowledgements"></a> | ||
@@ -114,0 +129,0 @@ ## Acknowledgements |
102
test.js
'use strict' | ||
const t = require('tap') | ||
const test = t.test | ||
const { test } = require('tap') | ||
const { promisify } = require('util') | ||
const sget = require('simple-get').concat | ||
const Fastify = require('fastify') | ||
const { monitorEventLoopDelay } = require('perf_hooks') | ||
const underPressure = require('./index') | ||
const wait = promisify(setTimeout) | ||
test('Should return 503 on maxEventLoopDelay', t => { | ||
@@ -14,3 +17,3 @@ t.plan(5) | ||
fastify.register(underPressure, { | ||
maxEventLoopDelay: 50 | ||
maxEventLoopDelay: 15 | ||
}) | ||
@@ -22,8 +25,15 @@ | ||
fastify.listen(0, (err, address) => { | ||
fastify.listen(0, async (err, address) => { | ||
t.error(err) | ||
fastify.server.unref() | ||
// If using monitorEventLoopDelay give it time to collect | ||
// some samples | ||
if (monitorEventLoopDelay) { | ||
await wait(500) | ||
} | ||
// Increased to prevent Travis to fail | ||
process.nextTick(() => sleep(1000)) | ||
process.nextTick(() => block(1000)) | ||
sget({ | ||
@@ -62,3 +72,4 @@ method: 'GET', | ||
process.nextTick(() => sleep(500)) | ||
process.nextTick(() => block(monitorEventLoopDelay ? 1500 : 500)) | ||
sget({ | ||
@@ -96,3 +107,5 @@ method: 'GET', | ||
fastify.server.unref() | ||
process.nextTick(() => sleep(500)) | ||
process.nextTick(() => block(monitorEventLoopDelay ? 1500 : 500)) | ||
sget({ | ||
@@ -120,3 +133,3 @@ method: 'GET', | ||
fastify.register(underPressure, { | ||
maxEventLoopDelay: 50, | ||
maxRssBytes: 1, | ||
message: 'Under pressure!', | ||
@@ -134,3 +147,4 @@ retryAfter: 50 | ||
process.nextTick(() => sleep(500)) | ||
process.nextTick(() => block(monitorEventLoopDelay ? 1500 : 500)) | ||
sget({ | ||
@@ -170,3 +184,3 @@ method: 'GET', | ||
fastify.listen(0, (err, address) => { | ||
fastify.listen(0, async (err, address) => { | ||
t.error(err) | ||
@@ -176,3 +190,10 @@ t.is(typeof fastify.memoryUsage, 'function') | ||
process.nextTick(() => sleep(500)) | ||
// If using monitorEventLoopDelay give it time to collect | ||
// some samples | ||
if (monitorEventLoopDelay) { | ||
await wait(500) | ||
} | ||
process.nextTick(() => block(monitorEventLoopDelay ? 1500 : 500)) | ||
sget({ | ||
@@ -203,3 +224,3 @@ method: 'GET', | ||
fastify.listen(0, (err, address) => { | ||
fastify.listen(0, async (err, address) => { | ||
t.error(err) | ||
@@ -209,3 +230,10 @@ t.is(typeof fastify.memoryUsage, 'function') | ||
process.nextTick(() => sleep(500)) | ||
// If using monitorEventLoopDelay give it time to collect | ||
// some samples | ||
if (monitorEventLoopDelay) { | ||
await wait(500) | ||
} | ||
process.nextTick(() => block(monitorEventLoopDelay ? 1500 : 500)) | ||
sget({ | ||
@@ -235,3 +263,4 @@ method: 'GET', | ||
process.nextTick(() => sleep(500)) | ||
process.nextTick(() => block(monitorEventLoopDelay ? 1500 : 500)) | ||
sget({ | ||
@@ -282,2 +311,12 @@ method: 'GET', | ||
const fastify = Fastify() | ||
fastify.addHook('onRoute', (routeOptions) => { | ||
fastify.server.unref() | ||
process.nextTick(() => block(500)) | ||
t.strictEqual(routeOptions.url, '/alive') | ||
t.strictEqual(routeOptions.logLevel, 'silent', 'log level not set') | ||
t.deepEqual(routeOptions.config, customConfig, 'config not set') | ||
fastify.close() | ||
}) | ||
fastify.register(underPressure, { | ||
@@ -293,18 +332,18 @@ exposeStatusRoute: { | ||
fastify.ready() | ||
}) | ||
test('Expose status route with additional route options and default url', t => { | ||
t.plan(2) | ||
const fastify = Fastify() | ||
fastify.addHook('onRoute', (routeOptions) => { | ||
fastify.server.unref() | ||
process.nextTick(() => sleep(500)) | ||
t.strictEqual(routeOptions.url, '/alive') | ||
process.nextTick(() => block(500)) | ||
t.strictEqual(routeOptions.url, '/status') | ||
t.strictEqual(routeOptions.logLevel, 'silent', 'log level not set') | ||
t.deepEqual(routeOptions.config, customConfig, 'config not set') | ||
fastify.close() | ||
}) | ||
fastify.listen() | ||
}) | ||
test('Expose status route with additional route options and default url', t => { | ||
t.plan(2) | ||
const fastify = Fastify() | ||
fastify.register(underPressure, { | ||
@@ -317,11 +356,4 @@ exposeStatusRoute: { | ||
}) | ||
fastify.addHook('onRoute', (routeOptions) => { | ||
fastify.server.unref() | ||
process.nextTick(() => sleep(500)) | ||
t.strictEqual(routeOptions.url, '/status') | ||
t.strictEqual(routeOptions.logLevel, 'silent', 'log level not set') | ||
fastify.close() | ||
}) | ||
fastify.listen() | ||
fastify.ready() | ||
}) | ||
@@ -455,3 +487,3 @@ | ||
healthCheck: async () => { | ||
await new Promise(resolve => setTimeout(() => resolve(), 100)) | ||
await wait(100) | ||
t.false(called) | ||
@@ -544,5 +576,5 @@ called = true | ||
function sleep (msec) { | ||
function block (msec) { | ||
const start = Date.now() | ||
while (Date.now() - start < msec) {} | ||
while (Date.now() - start < msec) { } | ||
} |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
28274
11
734
136
9
2
+ Addedfastify-plugin@2.3.4(transitive)
+ Addedsemver@7.7.1(transitive)
- Removedfastify-plugin@1.6.1(transitive)
- Removedsemver@6.3.1(transitive)
Updatedfastify-plugin@^2.0.0