-
Notifications
You must be signed in to change notification settings - Fork 15
/
index.js
executable file
·114 lines (76 loc) · 3.22 KB
/
index.js
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
'use strict';
const Boom = require('@hapi/boom');
const Hoek = require('@hapi/hoek');
const Joi = require('@hapi/joi');
const internals = {};
internals.schema = Joi.object({
sampleInterval: Joi.number().min(0),
maxHeapUsedBytes: Joi.number().min(0),
maxEventLoopDelay: Joi.number().min(0),
maxRssBytes: Joi.number().min(0)
})
.unknown();
internals.defaults = {
sampleInterval: 0, // Frequency of load sampling in milliseconds (zero is no sampling)
maxHeapUsedBytes: 0, // Reject requests when V8 heap is over size in bytes (zero is no max)
maxRssBytes: 0, // Reject requests when process RSS is over size in bytes (zero is no max)
maxEventLoopDelay: 0 // Milliseconds of delay after which requests are rejected (zero is no max)
};
exports = module.exports = internals.Heavy = function (options) {
options = options || {};
Joi.assert(options, internals.schema, 'Invalid load monitoring options');
this.settings = Hoek.applyToDefaults(internals.defaults, options);
Hoek.assert(this.settings.sampleInterval || (!this.settings.maxEventLoopDelay && !this.settings.maxHeapUsedBytes && !this.settings.maxRssBytes), 'Load sample interval must be set to enable load limits');
this._eventLoopTimer = null;
this._loadBench = new Hoek.Bench();
this.load = {
eventLoopDelay: 0,
heapUsed: 0,
rss: 0
};
};
internals.Heavy.prototype.start = function () {
if (!this.settings.sampleInterval) {
return;
}
const loopSample = () => {
this._loadBench.reset();
const measure = () => {
const mem = process.memoryUsage();
// Retain the same this.load object to keep external references valid
this.load.eventLoopDelay = (this._loadBench.elapsed() - this.settings.sampleInterval);
this.load.heapUsed = mem.heapUsed;
this.load.rss = mem.rss;
loopSample();
};
this._eventLoopTimer = setTimeout(measure, this.settings.sampleInterval);
};
loopSample();
};
internals.Heavy.prototype.stop = function () {
clearTimeout(this._eventLoopTimer);
this._eventLoopTimer = null;
};
internals.Heavy.prototype.check = function () {
if (!this.settings.sampleInterval) {
return;
}
Hoek.assert(this._eventLoopTimer, 'Cannot check load when sampler is not started');
const elapsed = this._loadBench.elapsed();
const load = this.load;
if (elapsed > this.settings.sampleInterval) {
load.eventLoopDelay = Math.max(load.eventLoopDelay, elapsed - this.settings.sampleInterval);
}
if (this.settings.maxEventLoopDelay &&
load.eventLoopDelay > this.settings.maxEventLoopDelay) {
throw Boom.serverUnavailable('Server under heavy load (event loop)', load);
}
if (this.settings.maxHeapUsedBytes &&
load.heapUsed > this.settings.maxHeapUsedBytes) {
throw Boom.serverUnavailable('Server under heavy load (heap)', load);
}
if (this.settings.maxRssBytes &&
load.rss > this.settings.maxRssBytes) {
throw Boom.serverUnavailable('Server under heavy load (rss)', load);
}
};