badmfck-api-server 4.1.25 → 4.1.27
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/dist/apiServer/BaseEndpoint.d.ts +26 -0
- package/dist/apiServer/BaseEndpoint.js +58 -0
- package/dist/apiServer/BaseService.d.ts +4 -0
- package/dist/apiServer/BaseService.js +9 -1
- package/dist/apiServer/LogService.d.ts +5 -0
- package/dist/apiServer/LogService.js +47 -0
- package/dist/apiServer/documentation/index.html +46 -46
- package/dist/apiServer/http/Http.d.ts +75 -0
- package/dist/apiServer/http/Http.js +201 -4
- package/dist/apiServer/monitor/Monitor.d.ts +5 -0
- package/dist/apiServer/monitor/Monitor.js +50 -0
- package/dist/apiServer/monitor/ProcessMonitor.d.ts +117 -0
- package/dist/apiServer/monitor/ProcessMonitor.js +308 -0
- package/dist/apiServer/monitor/SystemInfo.d.ts +71 -0
- package/dist/apiServer/monitor/SystemInfo.js +218 -0
- package/dist/apiServer/monitor/index.html +140 -68
- package/package.json +1 -1
|
@@ -13,6 +13,60 @@ export type THttpErr<E = any> = {
|
|
|
13
13
|
details?: any;
|
|
14
14
|
};
|
|
15
15
|
export type THttpResult<T, E = any> = THttpOk<T> | THttpErr<E>;
|
|
16
|
+
export type THttpOutgoingLogItem = {
|
|
17
|
+
id: number;
|
|
18
|
+
created: number;
|
|
19
|
+
time: number;
|
|
20
|
+
method: HttpMethod;
|
|
21
|
+
url: string;
|
|
22
|
+
status?: number;
|
|
23
|
+
ok: boolean;
|
|
24
|
+
attempts: number;
|
|
25
|
+
request: any;
|
|
26
|
+
response: any;
|
|
27
|
+
error?: string;
|
|
28
|
+
};
|
|
29
|
+
export type THttpHostStats = {
|
|
30
|
+
host: string;
|
|
31
|
+
count: number;
|
|
32
|
+
errors: number;
|
|
33
|
+
timeouts: number;
|
|
34
|
+
retries: number;
|
|
35
|
+
avgMs: number;
|
|
36
|
+
minMs: number;
|
|
37
|
+
maxMs: number;
|
|
38
|
+
totalTimeMs: number;
|
|
39
|
+
inFlight: number;
|
|
40
|
+
byStatus: {
|
|
41
|
+
s2xx: number;
|
|
42
|
+
s3xx: number;
|
|
43
|
+
s4xx: number;
|
|
44
|
+
s5xx: number;
|
|
45
|
+
other: number;
|
|
46
|
+
networkErrors: number;
|
|
47
|
+
};
|
|
48
|
+
lastRequestAt: number;
|
|
49
|
+
};
|
|
50
|
+
export type THttpStatusDistribution = {
|
|
51
|
+
s2xx: number;
|
|
52
|
+
s3xx: number;
|
|
53
|
+
s4xx: number;
|
|
54
|
+
s5xx: number;
|
|
55
|
+
other: number;
|
|
56
|
+
networkErrors: number;
|
|
57
|
+
timeouts: number;
|
|
58
|
+
};
|
|
59
|
+
export type THttpStatsSnapshot = {
|
|
60
|
+
totalRequests: number;
|
|
61
|
+
inFlight: {
|
|
62
|
+
current: number;
|
|
63
|
+
peak: number;
|
|
64
|
+
byHost: Record<string, number>;
|
|
65
|
+
};
|
|
66
|
+
statusDistribution: THttpStatusDistribution;
|
|
67
|
+
perHost: THttpHostStats[];
|
|
68
|
+
topSlow: THttpOutgoingLogItem[];
|
|
69
|
+
};
|
|
16
70
|
export type TRetryPolicy = {
|
|
17
71
|
enabled?: boolean;
|
|
18
72
|
maxAttempts?: number;
|
|
@@ -71,6 +125,27 @@ export declare class Http {
|
|
|
71
125
|
private static _activeConnectionsByHost;
|
|
72
126
|
private static _countedSockets;
|
|
73
127
|
private static _socketHostKey;
|
|
128
|
+
private static _outgoingLog;
|
|
129
|
+
private static _nextOutgoingLogID;
|
|
130
|
+
private static _outgoingLogLimit;
|
|
131
|
+
private static _truncate;
|
|
132
|
+
private static _pushOutgoingLog;
|
|
133
|
+
static getOutgoingLogSnapshot(): THttpOutgoingLogItem[];
|
|
134
|
+
private static _totalRequests;
|
|
135
|
+
private static _inFlight;
|
|
136
|
+
private static _peakInFlight;
|
|
137
|
+
private static _inFlightByHost;
|
|
138
|
+
private static _statusDist;
|
|
139
|
+
private static _perHost;
|
|
140
|
+
private static _topSlow;
|
|
141
|
+
private static _topSlowLimit;
|
|
142
|
+
private static _hostFromUrl;
|
|
143
|
+
private static _isTimeoutError;
|
|
144
|
+
private static _incInFlight;
|
|
145
|
+
private static _decInFlight;
|
|
146
|
+
private static _updateStats;
|
|
147
|
+
private static _pushToTopSlow;
|
|
148
|
+
static getHttpStats(): THttpStatsSnapshot;
|
|
74
149
|
private static ensureInit;
|
|
75
150
|
static configure(partial: Partial<THttpConfig>): void;
|
|
76
151
|
static createAgent(opts?: ConstructorParameters<typeof Agent>[0]): Agent;
|
|
@@ -88,6 +88,179 @@ class Http {
|
|
|
88
88
|
static _activeConnectionsByHost = new Map();
|
|
89
89
|
static _countedSockets = new WeakSet();
|
|
90
90
|
static _socketHostKey = new WeakMap();
|
|
91
|
+
static _outgoingLog = [];
|
|
92
|
+
static _nextOutgoingLogID = 0;
|
|
93
|
+
static _outgoingLogLimit = 500;
|
|
94
|
+
static _truncate(v) {
|
|
95
|
+
if (v === undefined || v === null)
|
|
96
|
+
return v;
|
|
97
|
+
if (Buffer.isBuffer(v))
|
|
98
|
+
return `[Buffer ${v.length} bytes]`;
|
|
99
|
+
let json = "";
|
|
100
|
+
try {
|
|
101
|
+
json = JSON.stringify(v, (_, val) => {
|
|
102
|
+
if (typeof val === "string" && val.length > 255)
|
|
103
|
+
return val.slice(0, 255) + `...(${val.length})`;
|
|
104
|
+
if (Buffer.isBuffer(val))
|
|
105
|
+
return `[Buffer ${val.length} bytes]`;
|
|
106
|
+
return val;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return "[unserializable]";
|
|
111
|
+
}
|
|
112
|
+
return json.length > 500 ? json.slice(0, 500) + `...(total ${json.length})` : json;
|
|
113
|
+
}
|
|
114
|
+
static _pushOutgoingLog(item) {
|
|
115
|
+
const entry = { id: this._nextOutgoingLogID++, ...item };
|
|
116
|
+
this._outgoingLog.push(entry);
|
|
117
|
+
if (this._outgoingLog.length > this._outgoingLogLimit)
|
|
118
|
+
this._outgoingLog.shift();
|
|
119
|
+
if (this._nextOutgoingLogID > Number.MAX_SAFE_INTEGER - 1000)
|
|
120
|
+
this._nextOutgoingLogID = 0;
|
|
121
|
+
return entry;
|
|
122
|
+
}
|
|
123
|
+
static getOutgoingLogSnapshot() {
|
|
124
|
+
return this._outgoingLog.slice();
|
|
125
|
+
}
|
|
126
|
+
static _totalRequests = 0;
|
|
127
|
+
static _inFlight = 0;
|
|
128
|
+
static _peakInFlight = 0;
|
|
129
|
+
static _inFlightByHost = new Map();
|
|
130
|
+
static _statusDist = {
|
|
131
|
+
s2xx: 0, s3xx: 0, s4xx: 0, s5xx: 0, other: 0, networkErrors: 0, timeouts: 0,
|
|
132
|
+
};
|
|
133
|
+
static _perHost = new Map();
|
|
134
|
+
static _topSlow = [];
|
|
135
|
+
static _topSlowLimit = 20;
|
|
136
|
+
static _hostFromUrl(url) {
|
|
137
|
+
try {
|
|
138
|
+
return new URL(url).host || "unknown";
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return "unknown";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
static _isTimeoutError(err) {
|
|
145
|
+
if (!err || typeof err !== "object")
|
|
146
|
+
return false;
|
|
147
|
+
const e = err;
|
|
148
|
+
if (e.name === "AbortError")
|
|
149
|
+
return true;
|
|
150
|
+
if (typeof e.code === "string" && e.code.includes("TIMEOUT"))
|
|
151
|
+
return true;
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
static _incInFlight(host) {
|
|
155
|
+
this._inFlight++;
|
|
156
|
+
if (this._inFlight > this._peakInFlight)
|
|
157
|
+
this._peakInFlight = this._inFlight;
|
|
158
|
+
this._inFlightByHost.set(host, (this._inFlightByHost.get(host) ?? 0) + 1);
|
|
159
|
+
}
|
|
160
|
+
static _decInFlight(host) {
|
|
161
|
+
this._inFlight = Math.max(0, this._inFlight - 1);
|
|
162
|
+
const prev = this._inFlightByHost.get(host) ?? 0;
|
|
163
|
+
const next = Math.max(0, prev - 1);
|
|
164
|
+
if (next === 0)
|
|
165
|
+
this._inFlightByHost.delete(host);
|
|
166
|
+
else
|
|
167
|
+
this._inFlightByHost.set(host, next);
|
|
168
|
+
}
|
|
169
|
+
static _updateStats(host, entry, isTimeout) {
|
|
170
|
+
this._totalRequests++;
|
|
171
|
+
if (typeof entry.status === "number") {
|
|
172
|
+
const s = entry.status;
|
|
173
|
+
if (s >= 200 && s < 300)
|
|
174
|
+
this._statusDist.s2xx++;
|
|
175
|
+
else if (s >= 300 && s < 400)
|
|
176
|
+
this._statusDist.s3xx++;
|
|
177
|
+
else if (s >= 400 && s < 500)
|
|
178
|
+
this._statusDist.s4xx++;
|
|
179
|
+
else if (s >= 500 && s < 600)
|
|
180
|
+
this._statusDist.s5xx++;
|
|
181
|
+
else
|
|
182
|
+
this._statusDist.other++;
|
|
183
|
+
}
|
|
184
|
+
else if (entry.error) {
|
|
185
|
+
this._statusDist.networkErrors++;
|
|
186
|
+
if (isTimeout)
|
|
187
|
+
this._statusDist.timeouts++;
|
|
188
|
+
}
|
|
189
|
+
let h = this._perHost.get(host);
|
|
190
|
+
if (!h) {
|
|
191
|
+
h = {
|
|
192
|
+
host,
|
|
193
|
+
count: 0, errors: 0, timeouts: 0, retries: 0,
|
|
194
|
+
avgMs: 0, minMs: Infinity, maxMs: 0, totalTimeMs: 0,
|
|
195
|
+
inFlight: 0,
|
|
196
|
+
byStatus: { s2xx: 0, s3xx: 0, s4xx: 0, s5xx: 0, other: 0, networkErrors: 0 },
|
|
197
|
+
lastRequestAt: 0,
|
|
198
|
+
};
|
|
199
|
+
this._perHost.set(host, h);
|
|
200
|
+
}
|
|
201
|
+
h.count++;
|
|
202
|
+
h.totalTimeMs += entry.time;
|
|
203
|
+
h.avgMs = Math.round((h.totalTimeMs / h.count) * 10) / 10;
|
|
204
|
+
if (entry.time < h.minMs)
|
|
205
|
+
h.minMs = entry.time;
|
|
206
|
+
if (entry.time > h.maxMs)
|
|
207
|
+
h.maxMs = entry.time;
|
|
208
|
+
if (!entry.ok)
|
|
209
|
+
h.errors++;
|
|
210
|
+
if (isTimeout)
|
|
211
|
+
h.timeouts++;
|
|
212
|
+
h.retries += Math.max(0, entry.attempts - 1);
|
|
213
|
+
h.lastRequestAt = Date.now();
|
|
214
|
+
if (typeof entry.status === "number") {
|
|
215
|
+
const s = entry.status;
|
|
216
|
+
if (s >= 200 && s < 300)
|
|
217
|
+
h.byStatus.s2xx++;
|
|
218
|
+
else if (s >= 300 && s < 400)
|
|
219
|
+
h.byStatus.s3xx++;
|
|
220
|
+
else if (s >= 400 && s < 500)
|
|
221
|
+
h.byStatus.s4xx++;
|
|
222
|
+
else if (s >= 500 && s < 600)
|
|
223
|
+
h.byStatus.s5xx++;
|
|
224
|
+
else
|
|
225
|
+
h.byStatus.other++;
|
|
226
|
+
}
|
|
227
|
+
else if (entry.error) {
|
|
228
|
+
h.byStatus.networkErrors++;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
static _pushToTopSlow(entry) {
|
|
232
|
+
if (this._topSlow.length < this._topSlowLimit) {
|
|
233
|
+
this._topSlow.push(entry);
|
|
234
|
+
this._topSlow.sort((a, b) => b.time - a.time);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const slowest_of_top = this._topSlow[this._topSlow.length - 1];
|
|
238
|
+
if (entry.time > slowest_of_top.time) {
|
|
239
|
+
this._topSlow.push(entry);
|
|
240
|
+
this._topSlow.sort((a, b) => b.time - a.time);
|
|
241
|
+
this._topSlow.pop();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
static getHttpStats() {
|
|
245
|
+
const perHost = Array.from(this._perHost.values())
|
|
246
|
+
.map(h => ({
|
|
247
|
+
...h,
|
|
248
|
+
minMs: Number.isFinite(h.minMs) ? h.minMs : 0,
|
|
249
|
+
inFlight: this._inFlightByHost.get(h.host) ?? 0,
|
|
250
|
+
}))
|
|
251
|
+
.sort((a, b) => b.count - a.count);
|
|
252
|
+
return {
|
|
253
|
+
totalRequests: this._totalRequests,
|
|
254
|
+
inFlight: {
|
|
255
|
+
current: this._inFlight,
|
|
256
|
+
peak: this._peakInFlight,
|
|
257
|
+
byHost: Object.fromEntries(this._inFlightByHost),
|
|
258
|
+
},
|
|
259
|
+
statusDistribution: { ...this._statusDist },
|
|
260
|
+
perHost,
|
|
261
|
+
topSlow: this._topSlow.slice(),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
91
264
|
static ensureInit() {
|
|
92
265
|
if (this._inited)
|
|
93
266
|
return;
|
|
@@ -230,6 +403,7 @@ class Http {
|
|
|
230
403
|
static async request(opts) {
|
|
231
404
|
MonitorService_1.S_STAT_REGISTRATE_HTTP_REQUEST.invoke({ url: opts.url });
|
|
232
405
|
this.ensureInit();
|
|
406
|
+
const overallStarted = Date.now();
|
|
233
407
|
const cfg = this.config;
|
|
234
408
|
const retryCfg = {
|
|
235
409
|
enabled: opts.retry?.enabled ?? cfg.retry?.enabled ?? true,
|
|
@@ -263,7 +437,30 @@ class Http {
|
|
|
263
437
|
}
|
|
264
438
|
const responseType = opts.responseType ?? "json";
|
|
265
439
|
const throwOnJsonParseError = opts.throwOnJsonParseError ?? false;
|
|
440
|
+
let attemptsMade = 0;
|
|
441
|
+
const host = Http._hostFromUrl(url);
|
|
442
|
+
Http._incInFlight(host);
|
|
443
|
+
const finish = (result, networkErr) => {
|
|
444
|
+
Http._decInFlight(host);
|
|
445
|
+
const entry = Http._pushOutgoingLog({
|
|
446
|
+
created: overallStarted,
|
|
447
|
+
time: Date.now() - overallStarted,
|
|
448
|
+
method: opts.method,
|
|
449
|
+
url,
|
|
450
|
+
status: result.status,
|
|
451
|
+
ok: result.ok,
|
|
452
|
+
attempts: attemptsMade,
|
|
453
|
+
request: Http._truncate(opts.body),
|
|
454
|
+
response: Http._truncate(result.ok ? result.data : result.error),
|
|
455
|
+
error: networkErr ? String(networkErr?.message ?? networkErr) : undefined,
|
|
456
|
+
});
|
|
457
|
+
const isTimeout = Http._isTimeoutError(networkErr);
|
|
458
|
+
Http._updateStats(host, entry, isTimeout);
|
|
459
|
+
Http._pushToTopSlow(entry);
|
|
460
|
+
return result;
|
|
461
|
+
};
|
|
266
462
|
for (let attempt = 1; attempt <= retryCfg.maxAttempts; attempt++) {
|
|
463
|
+
attemptsMade = attempt;
|
|
267
464
|
const started = Date.now();
|
|
268
465
|
cfg.onRequest?.({ method: opts.method, url, attempt });
|
|
269
466
|
const controller = new AbortController();
|
|
@@ -307,7 +504,7 @@ class Http {
|
|
|
307
504
|
}
|
|
308
505
|
}
|
|
309
506
|
if (status >= 200 && status < 300) {
|
|
310
|
-
return { ok: true, status, data: parsed, headers: hdrs };
|
|
507
|
+
return finish({ ok: true, status, data: parsed, headers: hdrs });
|
|
311
508
|
}
|
|
312
509
|
const retryable = retryCfg.enabled &&
|
|
313
510
|
isRetryableStatus(status, retryCfg.retryOnStatuses) &&
|
|
@@ -317,7 +514,7 @@ class Http {
|
|
|
317
514
|
await sleep(backoff);
|
|
318
515
|
continue;
|
|
319
516
|
}
|
|
320
|
-
return { ok: false, status, error: parsed, details: { headers: hdrs } };
|
|
517
|
+
return finish({ ok: false, status, error: parsed, details: { headers: hdrs } });
|
|
321
518
|
}
|
|
322
519
|
catch (err) {
|
|
323
520
|
const ms = Date.now() - started;
|
|
@@ -331,13 +528,13 @@ class Http {
|
|
|
331
528
|
await sleep(backoff);
|
|
332
529
|
continue;
|
|
333
530
|
}
|
|
334
|
-
return { ok: false, error: err, details: { network: true } };
|
|
531
|
+
return finish({ ok: false, error: err, details: { network: true } }, err);
|
|
335
532
|
}
|
|
336
533
|
finally {
|
|
337
534
|
clearTimeout(t);
|
|
338
535
|
}
|
|
339
536
|
}
|
|
340
|
-
return { ok: false, error: "UNKNOWN" };
|
|
537
|
+
return finish({ ok: false, error: "UNKNOWN" });
|
|
341
538
|
}
|
|
342
539
|
static get(url, opts) {
|
|
343
540
|
return this.request({ ...(opts || {}), method: "GET", url });
|
|
@@ -20,6 +20,11 @@ export declare class Monitor extends BaseEndpoint {
|
|
|
20
20
|
changeLogLevel(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
21
21
|
logs(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
22
22
|
netlog(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
23
|
+
outgoingNetlog(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
24
|
+
sysinfo(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
25
|
+
procinfo(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
26
|
+
httpstats(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
27
|
+
inventory(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
23
28
|
metrics(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
24
29
|
connections(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
25
30
|
db(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
@@ -7,6 +7,7 @@ exports.Monitor = exports.S_MONITOR_REGISTRATE_ACTION = void 0;
|
|
|
7
7
|
const badmfck_signal_1 = require("badmfck-signal");
|
|
8
8
|
const APIService_1 = require("../APIService");
|
|
9
9
|
const BaseEndpoint_1 = require("../BaseEndpoint");
|
|
10
|
+
const BaseService_1 = require("../BaseService");
|
|
10
11
|
const LogService_1 = require("../LogService");
|
|
11
12
|
const crypto_1 = __importDefault(require("crypto"));
|
|
12
13
|
const DefaultErrors_1 = __importDefault(require("../structures/DefaultErrors"));
|
|
@@ -15,6 +16,8 @@ const path_1 = __importDefault(require("path"));
|
|
|
15
16
|
const Http_1 = require("../http/Http");
|
|
16
17
|
const MonitorService_1 = require("../MonitorService");
|
|
17
18
|
const DBService_1 = require("../DBService");
|
|
19
|
+
const SystemInfo_1 = require("./SystemInfo");
|
|
20
|
+
const ProcessMonitor_1 = require("./ProcessMonitor");
|
|
18
21
|
exports.S_MONITOR_REGISTRATE_ACTION = new badmfck_signal_1.Signal();
|
|
19
22
|
const logMap = {
|
|
20
23
|
ALL: 10,
|
|
@@ -39,6 +42,11 @@ class Monitor extends BaseEndpoint_1.BaseEndpoint {
|
|
|
39
42
|
{ ignoreInterceptor: true, endpoint: "html", handler: this.html },
|
|
40
43
|
{ ignoreInterceptor: true, endpoint: "log", handler: this.logs },
|
|
41
44
|
{ ignoreInterceptor: true, endpoint: "netlog", handler: this.netlog },
|
|
45
|
+
{ ignoreInterceptor: true, endpoint: "outgoingnetlog", handler: this.outgoingNetlog },
|
|
46
|
+
{ ignoreInterceptor: true, endpoint: "sysinfo", handler: this.sysinfo },
|
|
47
|
+
{ ignoreInterceptor: true, endpoint: "procinfo", handler: this.procinfo },
|
|
48
|
+
{ ignoreInterceptor: true, endpoint: "inventory", handler: this.inventory },
|
|
49
|
+
{ ignoreInterceptor: true, endpoint: "httpstats", handler: this.httpstats },
|
|
42
50
|
{ ignoreInterceptor: true, endpoint: "metrics", handler: this.metrics, validationModel: {
|
|
43
51
|
range: "",
|
|
44
52
|
$__range_values: ["week", "day", "hour"]
|
|
@@ -120,6 +128,48 @@ class Monitor extends BaseEndpoint_1.BaseEndpoint {
|
|
|
120
128
|
const log = await APIService_1.REQ_HTTP_LOG.request(req.data);
|
|
121
129
|
return { data: log };
|
|
122
130
|
}
|
|
131
|
+
async outgoingNetlog(req) {
|
|
132
|
+
await this.checkAuthentication(req);
|
|
133
|
+
return { data: Http_1.Http.getOutgoingLogSnapshot() };
|
|
134
|
+
}
|
|
135
|
+
async sysinfo(req) {
|
|
136
|
+
await this.checkAuthentication(req);
|
|
137
|
+
return { data: await (0, SystemInfo_1.collectSystemInfo)() };
|
|
138
|
+
}
|
|
139
|
+
async procinfo(req) {
|
|
140
|
+
await this.checkAuthentication(req);
|
|
141
|
+
return { data: await ProcessMonitor_1.ProcessMonitor.getSnapshot() };
|
|
142
|
+
}
|
|
143
|
+
async httpstats(req) {
|
|
144
|
+
await this.checkAuthentication(req);
|
|
145
|
+
return { data: Http_1.Http.getHttpStats() };
|
|
146
|
+
}
|
|
147
|
+
async inventory(req) {
|
|
148
|
+
await this.checkAuthentication(req);
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
const services = BaseService_1.BaseService.allInstances.map(s => ({
|
|
151
|
+
className: s.constructor.name,
|
|
152
|
+
name: s.getName(),
|
|
153
|
+
initialized: s.initializedAt !== null,
|
|
154
|
+
createdAt: s.createdAt,
|
|
155
|
+
initializedAt: s.initializedAt,
|
|
156
|
+
applicationReadyAt: s.applicationReadyAt,
|
|
157
|
+
uptimeSec: s.initializedAt ? Math.round((now - s.initializedAt) / 1000) : null,
|
|
158
|
+
}));
|
|
159
|
+
const endpoints = BaseEndpoint_1.BaseEndpoint.allInstances.map(e => e.getInventory());
|
|
160
|
+
return {
|
|
161
|
+
data: {
|
|
162
|
+
services,
|
|
163
|
+
endpoints,
|
|
164
|
+
counts: {
|
|
165
|
+
services: services.length,
|
|
166
|
+
endpoints: endpoints.length,
|
|
167
|
+
totalHandlers: endpoints.reduce((sum, e) => sum + e.handlerCount, 0),
|
|
168
|
+
},
|
|
169
|
+
entrypoint: BaseEndpoint_1.BaseEndpoint.getEntryPoint(),
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
123
173
|
async metrics(req) {
|
|
124
174
|
await this.checkAuthentication(req);
|
|
125
175
|
const result = await MonitorService_1.REQ_STAT.request(req.data);
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export declare class ProcessMonitor {
|
|
3
|
+
private static _inited;
|
|
4
|
+
private static _eld;
|
|
5
|
+
private static _gcObserver;
|
|
6
|
+
private static _gc;
|
|
7
|
+
private static _prevCpu;
|
|
8
|
+
private static _prevCpuAt;
|
|
9
|
+
private static _cpuPct;
|
|
10
|
+
private static _eluPrev;
|
|
11
|
+
private static _elu;
|
|
12
|
+
private static _processStartedAt;
|
|
13
|
+
static init(): void;
|
|
14
|
+
private static _sampleCpu;
|
|
15
|
+
private static _sampleELU;
|
|
16
|
+
private static _mapGcKind;
|
|
17
|
+
static getSnapshot(): Promise<{
|
|
18
|
+
identity: {
|
|
19
|
+
pid: number;
|
|
20
|
+
ppid: number;
|
|
21
|
+
title: string;
|
|
22
|
+
argv: string[];
|
|
23
|
+
execPath: string;
|
|
24
|
+
cwd: string;
|
|
25
|
+
nodeVersion: string;
|
|
26
|
+
v8Version: string;
|
|
27
|
+
platform: NodeJS.Platform;
|
|
28
|
+
arch: NodeJS.Architecture;
|
|
29
|
+
hostname: string;
|
|
30
|
+
user: {
|
|
31
|
+
uid: number;
|
|
32
|
+
gid: number;
|
|
33
|
+
} | null;
|
|
34
|
+
startedAtUnix: number;
|
|
35
|
+
uptimeSec: number;
|
|
36
|
+
availableParallelism: number;
|
|
37
|
+
};
|
|
38
|
+
memory: {
|
|
39
|
+
rss: number;
|
|
40
|
+
heapTotal: number;
|
|
41
|
+
heapUsed: number;
|
|
42
|
+
external: number;
|
|
43
|
+
arrayBuffers: any;
|
|
44
|
+
heap: {
|
|
45
|
+
sizeLimit: number;
|
|
46
|
+
usedHeap: number;
|
|
47
|
+
totalAvailable: number;
|
|
48
|
+
totalPhysical: number;
|
|
49
|
+
mallocedMemory: number;
|
|
50
|
+
peakMallocedMemory: number;
|
|
51
|
+
numberOfNativeContexts: number;
|
|
52
|
+
numberOfDetachedContexts: number;
|
|
53
|
+
};
|
|
54
|
+
heapSpaces: {
|
|
55
|
+
name: string;
|
|
56
|
+
size: number;
|
|
57
|
+
used: number;
|
|
58
|
+
available: number;
|
|
59
|
+
physical: number;
|
|
60
|
+
}[];
|
|
61
|
+
procStatus: Record<string, number> | null;
|
|
62
|
+
};
|
|
63
|
+
cpu: {
|
|
64
|
+
userPct: number;
|
|
65
|
+
systemPct: number;
|
|
66
|
+
userMicros: number;
|
|
67
|
+
systemMicros: number;
|
|
68
|
+
resource: any;
|
|
69
|
+
};
|
|
70
|
+
eventLoop: {
|
|
71
|
+
minMs: number;
|
|
72
|
+
maxMs: number;
|
|
73
|
+
meanMs: number;
|
|
74
|
+
stddevMs: number;
|
|
75
|
+
p50Ms: number;
|
|
76
|
+
p90Ms: number;
|
|
77
|
+
p99Ms: number;
|
|
78
|
+
utilizationPct: number;
|
|
79
|
+
activeHandles: number;
|
|
80
|
+
activeRequests: number;
|
|
81
|
+
spotLagMs: number;
|
|
82
|
+
} | null;
|
|
83
|
+
gc: {
|
|
84
|
+
totalCount: number;
|
|
85
|
+
totalTimeMs: number;
|
|
86
|
+
maxPauseMs: number;
|
|
87
|
+
byKind: Record<string, {
|
|
88
|
+
count: number;
|
|
89
|
+
timeMs: number;
|
|
90
|
+
}>;
|
|
91
|
+
lastPauses: {
|
|
92
|
+
kind: string;
|
|
93
|
+
ms: number;
|
|
94
|
+
timestamp: number;
|
|
95
|
+
}[];
|
|
96
|
+
};
|
|
97
|
+
fileDescriptors: {
|
|
98
|
+
open: number | null;
|
|
99
|
+
limitSoft: number | null;
|
|
100
|
+
limitHard: number | null;
|
|
101
|
+
};
|
|
102
|
+
io: Record<string, number> | null;
|
|
103
|
+
limits: Record<string, {
|
|
104
|
+
soft: string;
|
|
105
|
+
hard: string;
|
|
106
|
+
unit: string;
|
|
107
|
+
}> | null;
|
|
108
|
+
}>;
|
|
109
|
+
private static _readProcStatus;
|
|
110
|
+
private static _readProcIo;
|
|
111
|
+
private static _readProcLimits;
|
|
112
|
+
private static _countFds;
|
|
113
|
+
private static _parseLimitValue;
|
|
114
|
+
private static _toMsFinite;
|
|
115
|
+
private static _safePercentileMs;
|
|
116
|
+
private static _safeCount;
|
|
117
|
+
}
|