@tramvai/module-request-limiter 5.24.0 → 5.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser.js +1 -1
- package/lib/requestLimiter.d.ts +12 -1
- package/lib/requestLimiter.es.js +24 -9
- package/lib/requestLimiter.js +24 -9
- package/lib/server.es.js +54 -4
- package/lib/server.js +53 -2
- package/lib/tokens.browser.js +2 -1
- package/lib/tokens.d.ts +4 -1
- package/lib/tokens.es.js +2 -1
- package/lib/tokens.js +2 -0
- package/package.json +6 -5
package/lib/browser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
2
|
import { Module } from '@tramvai/core';
|
|
3
|
-
export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN } from './tokens.browser.js';
|
|
3
|
+
export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_METRICS_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN } from './tokens.browser.js';
|
|
4
4
|
|
|
5
5
|
let RequestLimiterModule = class RequestLimiterModule {
|
|
6
6
|
};
|
package/lib/requestLimiter.d.ts
CHANGED
|
@@ -18,6 +18,14 @@ export interface RequestLimiterOptions {
|
|
|
18
18
|
message: string;
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
+
export type RequestQueuedResult = 'drop' | 'take';
|
|
22
|
+
export interface RequestsLimiterMetrics {
|
|
23
|
+
collectQueueSize: (v: number) => void;
|
|
24
|
+
collectQueueLimit: (v: number) => void;
|
|
25
|
+
collectCurrentRequests: (v: number) => void;
|
|
26
|
+
collectCurrentRequestsLimit: (v: number) => void;
|
|
27
|
+
collectRequestsQueuedTime: (result: RequestQueuedResult, duration: number) => void;
|
|
28
|
+
}
|
|
21
29
|
export interface RequestLimiterRequest {
|
|
22
30
|
req: FastifyRequest;
|
|
23
31
|
res: FastifyReply;
|
|
@@ -33,8 +41,11 @@ export declare class RequestLimiter {
|
|
|
33
41
|
private minimalActiveRequestLimit;
|
|
34
42
|
private maxEventLoopDelay;
|
|
35
43
|
private eventLoopHistogram;
|
|
36
|
-
|
|
44
|
+
private metrics;
|
|
45
|
+
constructor(options: RequestLimiterOptions, metrics: RequestsLimiterMetrics);
|
|
37
46
|
onResponse(): void;
|
|
47
|
+
private updateCurrentActiveRequests;
|
|
48
|
+
private updateActiveRequestLimit;
|
|
38
49
|
private nextTick;
|
|
39
50
|
add(request: RequestLimiterRequest): void;
|
|
40
51
|
private loop;
|
package/lib/requestLimiter.es.js
CHANGED
|
@@ -12,7 +12,7 @@ const DEFAULT_OPTIONS = {
|
|
|
12
12
|
};
|
|
13
13
|
const resolution = 10;
|
|
14
14
|
class RequestLimiter {
|
|
15
|
-
constructor(options) {
|
|
15
|
+
constructor(options, metrics) {
|
|
16
16
|
this.currentActive = 0;
|
|
17
17
|
this.eventLoopDelay = 0;
|
|
18
18
|
this.queue = new DoubleLinkedList();
|
|
@@ -22,15 +22,25 @@ class RequestLimiter {
|
|
|
22
22
|
this.queueLimit = queue;
|
|
23
23
|
this.error = error;
|
|
24
24
|
this.maxEventLoopDelay = maxEventLoopDelay;
|
|
25
|
+
this.metrics = metrics;
|
|
26
|
+
this.metrics.collectQueueLimit(this.queueLimit);
|
|
25
27
|
this.eventLoopHistogram = monitorEventLoopDelay({ resolution });
|
|
26
28
|
this.eventLoopHistogram.enable();
|
|
27
29
|
const timer = setInterval(() => this.nextTick(), 1000);
|
|
28
30
|
timer.unref();
|
|
29
31
|
}
|
|
30
32
|
onResponse() {
|
|
31
|
-
this.currentActive
|
|
33
|
+
this.updateCurrentActiveRequests(this.currentActive - 1);
|
|
32
34
|
this.loop();
|
|
33
35
|
}
|
|
36
|
+
updateCurrentActiveRequests(value) {
|
|
37
|
+
this.currentActive = value;
|
|
38
|
+
this.metrics.collectCurrentRequests(value);
|
|
39
|
+
}
|
|
40
|
+
updateActiveRequestLimit(value) {
|
|
41
|
+
this.activeRequestLimit = value;
|
|
42
|
+
this.metrics.collectCurrentRequestsLimit(value);
|
|
43
|
+
}
|
|
34
44
|
// General idea is change limits every second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
|
|
35
45
|
nextTick() {
|
|
36
46
|
this.eventLoopDelay = Math.max(0, this.eventLoopHistogram.mean / 1e6 - resolution);
|
|
@@ -39,12 +49,12 @@ class RequestLimiter {
|
|
|
39
49
|
this.eventLoopHistogram.reset();
|
|
40
50
|
if (this.eventLoopDelay <= this.maxEventLoopDelay) {
|
|
41
51
|
if (this.currentActive >= this.activeRequestLimit) {
|
|
42
|
-
this.activeRequestLimit
|
|
52
|
+
this.updateActiveRequestLimit(this.activeRequestLimit + 1);
|
|
43
53
|
}
|
|
44
54
|
// We need to have minimalActiveRequestLimit
|
|
45
55
|
}
|
|
46
56
|
else if (this.activeRequestLimit > this.minimalActiveRequestLimit) {
|
|
47
|
-
this.activeRequestLimit
|
|
57
|
+
this.updateActiveRequestLimit(this.activeRequestLimit - 1);
|
|
48
58
|
}
|
|
49
59
|
}
|
|
50
60
|
add(request) {
|
|
@@ -53,19 +63,24 @@ class RequestLimiter {
|
|
|
53
63
|
return;
|
|
54
64
|
}
|
|
55
65
|
if (this.queue.length >= this.queueLimit) {
|
|
56
|
-
const
|
|
57
|
-
|
|
66
|
+
const { requestLimiterRequest, timestamp } = this.queue.shift();
|
|
67
|
+
requestLimiterRequest.next(new HttpError(this.error));
|
|
68
|
+
this.metrics.collectRequestsQueuedTime('drop', Date.now() - timestamp);
|
|
58
69
|
}
|
|
59
|
-
this.queue.push(request);
|
|
70
|
+
this.queue.push({ requestLimiterRequest: request, timestamp: Date.now() });
|
|
71
|
+
this.metrics.collectQueueSize(this.queue.size());
|
|
60
72
|
}
|
|
61
73
|
loop() {
|
|
62
74
|
while (this.queue.length > 0 && this.currentActive < this.activeRequestLimit) {
|
|
63
75
|
// better if we start with new requests. Because more opportunity to answer before client cancel request
|
|
64
|
-
this.
|
|
76
|
+
const { requestLimiterRequest, timestamp } = this.queue.pop();
|
|
77
|
+
this.run(requestLimiterRequest);
|
|
78
|
+
this.metrics.collectRequestsQueuedTime('take', Date.now() - timestamp);
|
|
79
|
+
this.metrics.collectQueueSize(this.queue.size());
|
|
65
80
|
}
|
|
66
81
|
}
|
|
67
82
|
run({ next, res }) {
|
|
68
|
-
this.currentActive
|
|
83
|
+
this.updateCurrentActiveRequests(this.currentActive + 1);
|
|
69
84
|
// onFinished doesn't work OK in DEV mode. Just stuck with high load without any reasons
|
|
70
85
|
// fastify: it only works this way with on-finished, as using hook `onRequest` is not enough to handle all of the requests
|
|
71
86
|
// and some of the failed requests are getting disappeared
|
package/lib/requestLimiter.js
CHANGED
|
@@ -21,7 +21,7 @@ const DEFAULT_OPTIONS = {
|
|
|
21
21
|
};
|
|
22
22
|
const resolution = 10;
|
|
23
23
|
class RequestLimiter {
|
|
24
|
-
constructor(options) {
|
|
24
|
+
constructor(options, metrics) {
|
|
25
25
|
this.currentActive = 0;
|
|
26
26
|
this.eventLoopDelay = 0;
|
|
27
27
|
this.queue = new doubleLinkedList.DoubleLinkedList();
|
|
@@ -31,15 +31,25 @@ class RequestLimiter {
|
|
|
31
31
|
this.queueLimit = queue;
|
|
32
32
|
this.error = error;
|
|
33
33
|
this.maxEventLoopDelay = maxEventLoopDelay;
|
|
34
|
+
this.metrics = metrics;
|
|
35
|
+
this.metrics.collectQueueLimit(this.queueLimit);
|
|
34
36
|
this.eventLoopHistogram = perf_hooks.monitorEventLoopDelay({ resolution });
|
|
35
37
|
this.eventLoopHistogram.enable();
|
|
36
38
|
const timer = setInterval(() => this.nextTick(), 1000);
|
|
37
39
|
timer.unref();
|
|
38
40
|
}
|
|
39
41
|
onResponse() {
|
|
40
|
-
this.currentActive
|
|
42
|
+
this.updateCurrentActiveRequests(this.currentActive - 1);
|
|
41
43
|
this.loop();
|
|
42
44
|
}
|
|
45
|
+
updateCurrentActiveRequests(value) {
|
|
46
|
+
this.currentActive = value;
|
|
47
|
+
this.metrics.collectCurrentRequests(value);
|
|
48
|
+
}
|
|
49
|
+
updateActiveRequestLimit(value) {
|
|
50
|
+
this.activeRequestLimit = value;
|
|
51
|
+
this.metrics.collectCurrentRequestsLimit(value);
|
|
52
|
+
}
|
|
43
53
|
// General idea is change limits every second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
|
|
44
54
|
nextTick() {
|
|
45
55
|
this.eventLoopDelay = Math.max(0, this.eventLoopHistogram.mean / 1e6 - resolution);
|
|
@@ -48,12 +58,12 @@ class RequestLimiter {
|
|
|
48
58
|
this.eventLoopHistogram.reset();
|
|
49
59
|
if (this.eventLoopDelay <= this.maxEventLoopDelay) {
|
|
50
60
|
if (this.currentActive >= this.activeRequestLimit) {
|
|
51
|
-
this.activeRequestLimit
|
|
61
|
+
this.updateActiveRequestLimit(this.activeRequestLimit + 1);
|
|
52
62
|
}
|
|
53
63
|
// We need to have minimalActiveRequestLimit
|
|
54
64
|
}
|
|
55
65
|
else if (this.activeRequestLimit > this.minimalActiveRequestLimit) {
|
|
56
|
-
this.activeRequestLimit
|
|
66
|
+
this.updateActiveRequestLimit(this.activeRequestLimit - 1);
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
69
|
add(request) {
|
|
@@ -62,19 +72,24 @@ class RequestLimiter {
|
|
|
62
72
|
return;
|
|
63
73
|
}
|
|
64
74
|
if (this.queue.length >= this.queueLimit) {
|
|
65
|
-
const
|
|
66
|
-
|
|
75
|
+
const { requestLimiterRequest, timestamp } = this.queue.shift();
|
|
76
|
+
requestLimiterRequest.next(new errors.HttpError(this.error));
|
|
77
|
+
this.metrics.collectRequestsQueuedTime('drop', Date.now() - timestamp);
|
|
67
78
|
}
|
|
68
|
-
this.queue.push(request);
|
|
79
|
+
this.queue.push({ requestLimiterRequest: request, timestamp: Date.now() });
|
|
80
|
+
this.metrics.collectQueueSize(this.queue.size());
|
|
69
81
|
}
|
|
70
82
|
loop() {
|
|
71
83
|
while (this.queue.length > 0 && this.currentActive < this.activeRequestLimit) {
|
|
72
84
|
// better if we start with new requests. Because more opportunity to answer before client cancel request
|
|
73
|
-
this.
|
|
85
|
+
const { requestLimiterRequest, timestamp } = this.queue.pop();
|
|
86
|
+
this.run(requestLimiterRequest);
|
|
87
|
+
this.metrics.collectRequestsQueuedTime('take', Date.now() - timestamp);
|
|
88
|
+
this.metrics.collectQueueSize(this.queue.size());
|
|
74
89
|
}
|
|
75
90
|
}
|
|
76
91
|
run({ next, res }) {
|
|
77
|
-
this.currentActive
|
|
92
|
+
this.updateCurrentActiveRequests(this.currentActive + 1);
|
|
78
93
|
// onFinished doesn't work OK in DEV mode. Just stuck with high load without any reasons
|
|
79
94
|
// fastify: it only works this way with on-finished, as using hook `onRequest` is not enough to handle all of the requests
|
|
80
95
|
// and some of the failed requests are getting disappeared
|
package/lib/server.es.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
2
|
import { Module, provide, Scope } from '@tramvai/core';
|
|
3
|
+
import { METRICS_MODULE_TOKEN } from '@tramvai/tokens-metrics';
|
|
3
4
|
import { ENV_USED_TOKEN, ENV_MANAGER_TOKEN } from '@tramvai/tokens-common';
|
|
4
5
|
import { WEB_FASTIFY_APP_LIMITER_TOKEN } from '@tramvai/tokens-server-private';
|
|
5
6
|
import { DEFAULT_OPTIONS, RequestLimiter, fastifyRequestsLimiter } from './requestLimiter.es.js';
|
|
6
7
|
export { DEFAULT_OPTIONS, RequestLimiter, fastifyRequestsLimiter } from './requestLimiter.es.js';
|
|
7
|
-
import { REQUESTS_LIMITER_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_ACTIVATE_TOKEN } from './tokens.es.js';
|
|
8
|
-
export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN } from './tokens.es.js';
|
|
8
|
+
import { REQUESTS_LIMITER_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_METRICS_TOKEN } from './tokens.es.js';
|
|
9
|
+
export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_METRICS_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN } from './tokens.es.js';
|
|
9
10
|
|
|
10
11
|
let RequestLimiterModule = class RequestLimiterModule {
|
|
11
12
|
};
|
|
@@ -33,7 +34,7 @@ RequestLimiterModule = __decorate([
|
|
|
33
34
|
provide({
|
|
34
35
|
provide: REQUESTS_LIMITER_TOKEN,
|
|
35
36
|
scope: Scope.SINGLETON,
|
|
36
|
-
useFactory: ({ options, featureEnable, envManager }) => {
|
|
37
|
+
useFactory: ({ options, featureEnable, envManager, metrics }) => {
|
|
37
38
|
if (featureEnable === false) {
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
@@ -48,12 +49,13 @@ RequestLimiterModule = __decorate([
|
|
|
48
49
|
: options?.maxEventLoopDelay ?? DEFAULT_OPTIONS.maxEventLoopDelay,
|
|
49
50
|
error: options?.error ?? DEFAULT_OPTIONS.error,
|
|
50
51
|
};
|
|
51
|
-
return new RequestLimiter(resultOptions);
|
|
52
|
+
return new RequestLimiter(resultOptions, metrics);
|
|
52
53
|
},
|
|
53
54
|
deps: {
|
|
54
55
|
options: { token: REQUESTS_LIMITER_OPTIONS_TOKEN, optional: true },
|
|
55
56
|
featureEnable: { token: REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
|
|
56
57
|
envManager: ENV_MANAGER_TOKEN,
|
|
58
|
+
metrics: REQUESTS_LIMITER_METRICS_TOKEN,
|
|
57
59
|
},
|
|
58
60
|
}),
|
|
59
61
|
provide({
|
|
@@ -72,6 +74,54 @@ RequestLimiterModule = __decorate([
|
|
|
72
74
|
featureEnable: { token: REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
|
|
73
75
|
},
|
|
74
76
|
}),
|
|
77
|
+
provide({
|
|
78
|
+
provide: REQUESTS_LIMITER_METRICS_TOKEN,
|
|
79
|
+
scope: Scope.SINGLETON,
|
|
80
|
+
useFactory: ({ metrics }) => {
|
|
81
|
+
const queueSizeGauge = metrics.gauge({
|
|
82
|
+
name: 'http_requests_limiter_queue_size',
|
|
83
|
+
help: 'Number of requests in the queue',
|
|
84
|
+
});
|
|
85
|
+
const queueLimitGauge = metrics.gauge({
|
|
86
|
+
name: 'http_requests_limiter_queue_limit',
|
|
87
|
+
help: 'Maximum number of requests in the queue',
|
|
88
|
+
});
|
|
89
|
+
const currentRequestsGauge = metrics.gauge({
|
|
90
|
+
name: 'http_requests_limiter_current_requests',
|
|
91
|
+
help: 'Number of currently active requests',
|
|
92
|
+
});
|
|
93
|
+
const currentRequestsLimitGauge = metrics.gauge({
|
|
94
|
+
name: 'http_requests_limiter_current_requests_limit',
|
|
95
|
+
help: 'Maximum number of active requests',
|
|
96
|
+
});
|
|
97
|
+
const requestsQueuedTimeHistogram = metrics.histogram({
|
|
98
|
+
name: 'http_requests_limiter_requests_queued_seconds',
|
|
99
|
+
help: 'Number of seconds requests were in the queue',
|
|
100
|
+
labelNames: ['result'],
|
|
101
|
+
buckets: [0.01, 0.05, 0.1, 0.3, 0.5, 1, 2.5, 4, 5, 8, 10, 20],
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
collectQueueLimit: (value) => {
|
|
105
|
+
queueLimitGauge.set(value);
|
|
106
|
+
},
|
|
107
|
+
collectQueueSize: (value) => {
|
|
108
|
+
queueSizeGauge.set(value);
|
|
109
|
+
},
|
|
110
|
+
collectCurrentRequests: (value) => {
|
|
111
|
+
currentRequestsGauge.set(value);
|
|
112
|
+
},
|
|
113
|
+
collectCurrentRequestsLimit: (value) => {
|
|
114
|
+
currentRequestsLimitGauge.set(value);
|
|
115
|
+
},
|
|
116
|
+
collectRequestsQueuedTime: (result, durationMS) => {
|
|
117
|
+
requestsQueuedTimeHistogram.observe({ result }, durationMS / 1000);
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
deps: {
|
|
122
|
+
metrics: METRICS_MODULE_TOKEN,
|
|
123
|
+
},
|
|
124
|
+
}),
|
|
75
125
|
],
|
|
76
126
|
})
|
|
77
127
|
], RequestLimiterModule);
|
package/lib/server.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var tslib = require('tslib');
|
|
6
6
|
var core = require('@tramvai/core');
|
|
7
|
+
var tokensMetrics = require('@tramvai/tokens-metrics');
|
|
7
8
|
var tokensCommon = require('@tramvai/tokens-common');
|
|
8
9
|
var tokensServerPrivate = require('@tramvai/tokens-server-private');
|
|
9
10
|
var requestLimiter = require('./requestLimiter.js');
|
|
@@ -35,7 +36,7 @@ exports.RequestLimiterModule = tslib.__decorate([
|
|
|
35
36
|
core.provide({
|
|
36
37
|
provide: tokens.REQUESTS_LIMITER_TOKEN,
|
|
37
38
|
scope: core.Scope.SINGLETON,
|
|
38
|
-
useFactory: ({ options, featureEnable, envManager }) => {
|
|
39
|
+
useFactory: ({ options, featureEnable, envManager, metrics }) => {
|
|
39
40
|
if (featureEnable === false) {
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
@@ -50,12 +51,13 @@ exports.RequestLimiterModule = tslib.__decorate([
|
|
|
50
51
|
: options?.maxEventLoopDelay ?? requestLimiter.DEFAULT_OPTIONS.maxEventLoopDelay,
|
|
51
52
|
error: options?.error ?? requestLimiter.DEFAULT_OPTIONS.error,
|
|
52
53
|
};
|
|
53
|
-
return new requestLimiter.RequestLimiter(resultOptions);
|
|
54
|
+
return new requestLimiter.RequestLimiter(resultOptions, metrics);
|
|
54
55
|
},
|
|
55
56
|
deps: {
|
|
56
57
|
options: { token: tokens.REQUESTS_LIMITER_OPTIONS_TOKEN, optional: true },
|
|
57
58
|
featureEnable: { token: tokens.REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
|
|
58
59
|
envManager: tokensCommon.ENV_MANAGER_TOKEN,
|
|
60
|
+
metrics: tokens.REQUESTS_LIMITER_METRICS_TOKEN,
|
|
59
61
|
},
|
|
60
62
|
}),
|
|
61
63
|
core.provide({
|
|
@@ -74,6 +76,54 @@ exports.RequestLimiterModule = tslib.__decorate([
|
|
|
74
76
|
featureEnable: { token: tokens.REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
|
|
75
77
|
},
|
|
76
78
|
}),
|
|
79
|
+
core.provide({
|
|
80
|
+
provide: tokens.REQUESTS_LIMITER_METRICS_TOKEN,
|
|
81
|
+
scope: core.Scope.SINGLETON,
|
|
82
|
+
useFactory: ({ metrics }) => {
|
|
83
|
+
const queueSizeGauge = metrics.gauge({
|
|
84
|
+
name: 'http_requests_limiter_queue_size',
|
|
85
|
+
help: 'Number of requests in the queue',
|
|
86
|
+
});
|
|
87
|
+
const queueLimitGauge = metrics.gauge({
|
|
88
|
+
name: 'http_requests_limiter_queue_limit',
|
|
89
|
+
help: 'Maximum number of requests in the queue',
|
|
90
|
+
});
|
|
91
|
+
const currentRequestsGauge = metrics.gauge({
|
|
92
|
+
name: 'http_requests_limiter_current_requests',
|
|
93
|
+
help: 'Number of currently active requests',
|
|
94
|
+
});
|
|
95
|
+
const currentRequestsLimitGauge = metrics.gauge({
|
|
96
|
+
name: 'http_requests_limiter_current_requests_limit',
|
|
97
|
+
help: 'Maximum number of active requests',
|
|
98
|
+
});
|
|
99
|
+
const requestsQueuedTimeHistogram = metrics.histogram({
|
|
100
|
+
name: 'http_requests_limiter_requests_queued_seconds',
|
|
101
|
+
help: 'Number of seconds requests were in the queue',
|
|
102
|
+
labelNames: ['result'],
|
|
103
|
+
buckets: [0.01, 0.05, 0.1, 0.3, 0.5, 1, 2.5, 4, 5, 8, 10, 20],
|
|
104
|
+
});
|
|
105
|
+
return {
|
|
106
|
+
collectQueueLimit: (value) => {
|
|
107
|
+
queueLimitGauge.set(value);
|
|
108
|
+
},
|
|
109
|
+
collectQueueSize: (value) => {
|
|
110
|
+
queueSizeGauge.set(value);
|
|
111
|
+
},
|
|
112
|
+
collectCurrentRequests: (value) => {
|
|
113
|
+
currentRequestsGauge.set(value);
|
|
114
|
+
},
|
|
115
|
+
collectCurrentRequestsLimit: (value) => {
|
|
116
|
+
currentRequestsLimitGauge.set(value);
|
|
117
|
+
},
|
|
118
|
+
collectRequestsQueuedTime: (result, durationMS) => {
|
|
119
|
+
requestsQueuedTimeHistogram.observe({ result }, durationMS / 1000);
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
deps: {
|
|
124
|
+
metrics: tokensMetrics.METRICS_MODULE_TOKEN,
|
|
125
|
+
},
|
|
126
|
+
}),
|
|
77
127
|
],
|
|
78
128
|
})
|
|
79
129
|
], exports.RequestLimiterModule);
|
|
@@ -82,5 +132,6 @@ exports.DEFAULT_OPTIONS = requestLimiter.DEFAULT_OPTIONS;
|
|
|
82
132
|
exports.RequestLimiter = requestLimiter.RequestLimiter;
|
|
83
133
|
exports.fastifyRequestsLimiter = requestLimiter.fastifyRequestsLimiter;
|
|
84
134
|
exports.REQUESTS_LIMITER_ACTIVATE_TOKEN = tokens.REQUESTS_LIMITER_ACTIVATE_TOKEN;
|
|
135
|
+
exports.REQUESTS_LIMITER_METRICS_TOKEN = tokens.REQUESTS_LIMITER_METRICS_TOKEN;
|
|
85
136
|
exports.REQUESTS_LIMITER_OPTIONS_TOKEN = tokens.REQUESTS_LIMITER_OPTIONS_TOKEN;
|
|
86
137
|
exports.REQUESTS_LIMITER_TOKEN = tokens.REQUESTS_LIMITER_TOKEN;
|
package/lib/tokens.browser.js
CHANGED
|
@@ -5,5 +5,6 @@ const REQUESTS_LIMITER_TOKEN = createToken('requestsLimiterToken', {
|
|
|
5
5
|
});
|
|
6
6
|
const REQUESTS_LIMITER_ACTIVATE_TOKEN = createToken('requestsLimiterActivateToken', { scope: Scope.SINGLETON });
|
|
7
7
|
const REQUESTS_LIMITER_OPTIONS_TOKEN = createToken('requestsLimiterOptionsToken', { scope: Scope.SINGLETON });
|
|
8
|
+
const REQUESTS_LIMITER_METRICS_TOKEN = createToken('requestsLimiterMetricsToken', { scope: Scope.SINGLETON });
|
|
8
9
|
|
|
9
|
-
export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN };
|
|
10
|
+
export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_METRICS_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN };
|
package/lib/tokens.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RequestLimiter, RequestLimiterOptions } from './requestLimiter';
|
|
1
|
+
import type { RequestLimiter, RequestLimiterOptions, RequestsLimiterMetrics } from './requestLimiter';
|
|
2
2
|
export declare const REQUESTS_LIMITER_TOKEN: RequestLimiter & {
|
|
3
3
|
__type?: "base token";
|
|
4
4
|
};
|
|
@@ -10,4 +10,7 @@ export declare const REQUESTS_LIMITER_ACTIVATE_TOKEN: (false & {
|
|
|
10
10
|
export declare const REQUESTS_LIMITER_OPTIONS_TOKEN: RequestLimiterOptions & {
|
|
11
11
|
__type?: "base token";
|
|
12
12
|
};
|
|
13
|
+
export declare const REQUESTS_LIMITER_METRICS_TOKEN: RequestsLimiterMetrics & {
|
|
14
|
+
__type?: "base token";
|
|
15
|
+
};
|
|
13
16
|
//# sourceMappingURL=tokens.d.ts.map
|
package/lib/tokens.es.js
CHANGED
|
@@ -5,5 +5,6 @@ const REQUESTS_LIMITER_TOKEN = createToken('requestsLimiterToken', {
|
|
|
5
5
|
});
|
|
6
6
|
const REQUESTS_LIMITER_ACTIVATE_TOKEN = createToken('requestsLimiterActivateToken', { scope: Scope.SINGLETON });
|
|
7
7
|
const REQUESTS_LIMITER_OPTIONS_TOKEN = createToken('requestsLimiterOptionsToken', { scope: Scope.SINGLETON });
|
|
8
|
+
const REQUESTS_LIMITER_METRICS_TOKEN = createToken('requestsLimiterMetricsToken', { scope: Scope.SINGLETON });
|
|
8
9
|
|
|
9
|
-
export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN };
|
|
10
|
+
export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_METRICS_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN };
|
package/lib/tokens.js
CHANGED
|
@@ -9,7 +9,9 @@ const REQUESTS_LIMITER_TOKEN = dippy.createToken('requestsLimiterToken', {
|
|
|
9
9
|
});
|
|
10
10
|
const REQUESTS_LIMITER_ACTIVATE_TOKEN = dippy.createToken('requestsLimiterActivateToken', { scope: dippy.Scope.SINGLETON });
|
|
11
11
|
const REQUESTS_LIMITER_OPTIONS_TOKEN = dippy.createToken('requestsLimiterOptionsToken', { scope: dippy.Scope.SINGLETON });
|
|
12
|
+
const REQUESTS_LIMITER_METRICS_TOKEN = dippy.createToken('requestsLimiterMetricsToken', { scope: dippy.Scope.SINGLETON });
|
|
12
13
|
|
|
13
14
|
exports.REQUESTS_LIMITER_ACTIVATE_TOKEN = REQUESTS_LIMITER_ACTIVATE_TOKEN;
|
|
15
|
+
exports.REQUESTS_LIMITER_METRICS_TOKEN = REQUESTS_LIMITER_METRICS_TOKEN;
|
|
14
16
|
exports.REQUESTS_LIMITER_OPTIONS_TOKEN = REQUESTS_LIMITER_OPTIONS_TOKEN;
|
|
15
17
|
exports.REQUESTS_LIMITER_TOKEN = REQUESTS_LIMITER_TOKEN;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/module-request-limiter",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.40.0",
|
|
4
4
|
"description": "Enable different rendering modes for pages",
|
|
5
5
|
"main": "lib/server.js",
|
|
6
6
|
"module": "lib/server.es.js",
|
|
@@ -25,14 +25,15 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@tinkoff/errors": "0.6.2",
|
|
27
27
|
"fastify-plugin": "^4.2.1",
|
|
28
|
-
"on-finished": "^2.3.0"
|
|
28
|
+
"on-finished": "^2.3.0",
|
|
29
|
+
"@tramvai/tokens-metrics": "5.40.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {},
|
|
31
32
|
"peerDependencies": {
|
|
32
33
|
"@tinkoff/dippy": "0.11.3",
|
|
33
|
-
"@tramvai/core": "5.
|
|
34
|
-
"@tramvai/tokens-common": "5.
|
|
35
|
-
"@tramvai/tokens-server-private": "5.
|
|
34
|
+
"@tramvai/core": "5.40.0",
|
|
35
|
+
"@tramvai/tokens-common": "5.40.0",
|
|
36
|
+
"@tramvai/tokens-server-private": "5.40.0",
|
|
36
37
|
"fastify": "^4.6.0",
|
|
37
38
|
"tslib": "^2.4.0"
|
|
38
39
|
}
|