badmfck-api-server 2.8.4 → 2.8.6
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/APIService.d.ts +7 -8
- package/dist/apiServer/APIService.js +8 -37
- package/dist/apiServer/MonitorService.d.ts +27 -0
- package/dist/apiServer/MonitorService.js +137 -0
- package/dist/apiServer/monitor/Monitor.d.ts +6 -30
- package/dist/apiServer/monitor/Monitor.js +47 -230
- package/package.json +1 -1
@@ -5,6 +5,10 @@ import { IBaseEndpoint } from './BaseEndpoint';
|
|
5
5
|
import { HTTPRequestVO, IError, TransferPacketVO } from './structures/Interfaces';
|
6
6
|
import { Req } from "badmfck-signal";
|
7
7
|
import http from 'http';
|
8
|
+
export interface IMonitorUser {
|
9
|
+
login: string;
|
10
|
+
password: string;
|
11
|
+
}
|
8
12
|
export interface APIServiceNetworkLogItem {
|
9
13
|
id: number;
|
10
14
|
created: number;
|
@@ -30,10 +34,7 @@ export interface APIServiceOptions {
|
|
30
34
|
interceptor?: IBaseEndpoint;
|
31
35
|
postproducer?: (req: HTTPRequestVO | undefined | null, res: Response, data: TransferPacketVO<any>, requestTime: number, endpoint?: string, log?: APIServiceNetworkLogItem | null) => Promise<TransferPacketVO>;
|
32
36
|
preproducer?: (req: HTTPRequestVO | undefined | null) => any;
|
33
|
-
monitor?:
|
34
|
-
login: string;
|
35
|
-
password: string;
|
36
|
-
}[];
|
37
|
+
monitor?: IMonitorUser[];
|
37
38
|
appVersion?: string;
|
38
39
|
fileTempDir: string;
|
39
40
|
fileLimit: number;
|
@@ -47,15 +48,13 @@ export declare const REQ_HTTP_SERVER: Req<void, {
|
|
47
48
|
http: http.Server;
|
48
49
|
}>;
|
49
50
|
export declare const REQ_INTERNAL_CALL: Req<HTTPRequestVO, IError | any>;
|
50
|
-
export declare const REQ_MONITOR_USERS: Req<
|
51
|
-
authorization: string;
|
52
|
-
}, any>;
|
51
|
+
export declare const REQ_MONITOR_USERS: Req<void, IMonitorUser[]>;
|
53
52
|
export declare function Initializer(services: IBaseService[]): Promise<void>;
|
54
53
|
export declare class APIService extends BaseService {
|
55
54
|
private static nextLogID;
|
56
55
|
private version;
|
57
56
|
private options;
|
58
|
-
private monitor
|
57
|
+
private monitor;
|
59
58
|
private monitorIndexFile?;
|
60
59
|
private started;
|
61
60
|
private requestsCount;
|
@@ -46,6 +46,7 @@ const http_1 = __importDefault(require("http"));
|
|
46
46
|
const MysqlService_1 = require("./MysqlService");
|
47
47
|
const StatService_1 = require("./StatService");
|
48
48
|
const ExternalServiceEndpoint_1 = require("./external/ExternalServiceEndpoint");
|
49
|
+
const MonitorService_1 = require("./MonitorService");
|
49
50
|
function getDefaultOptions() {
|
50
51
|
return {
|
51
52
|
port: 8091,
|
@@ -74,7 +75,6 @@ exports.REQ_HTTP_SERVER = new badmfck_signal_1.Req(undefined, "REQ_HTTP_SERVER")
|
|
74
75
|
exports.REQ_INTERNAL_CALL = new badmfck_signal_1.Req(undefined, "REQ_INTERNAL_CALL");
|
75
76
|
exports.REQ_MONITOR_USERS = new badmfck_signal_1.Req(undefined, "REQ_MONITOR_USERS");
|
76
77
|
const activeServices = [];
|
77
|
-
const entryPoints = [];
|
78
78
|
async function Initializer(services) {
|
79
79
|
services.push(new StatService_1.StatService());
|
80
80
|
for (let i of services) {
|
@@ -88,9 +88,9 @@ async function Initializer(services) {
|
|
88
88
|
exports.Initializer = Initializer;
|
89
89
|
class APIService extends BaseService_1.BaseService {
|
90
90
|
static nextLogID = 0;
|
91
|
-
version = "2.8.
|
91
|
+
version = "2.8.6";
|
92
92
|
options;
|
93
|
-
monitor;
|
93
|
+
monitor = null;
|
94
94
|
monitorIndexFile;
|
95
95
|
started = new Date();
|
96
96
|
requestsCount = 0;
|
@@ -105,24 +105,9 @@ class APIService extends BaseService_1.BaseService {
|
|
105
105
|
if (!this.options.corsHostWhiteList.find(val => val === self))
|
106
106
|
this.options.corsHostWhiteList.push();
|
107
107
|
if (this.options.monitor && this.options.monitor.length > 0) {
|
108
|
-
|
109
|
-
this.
|
110
|
-
|
111
|
-
console.warn("monitor links:");
|
112
|
-
for (let i of this.options.monitor) {
|
113
|
-
const hash = crypto_1.default.createHash("sha256").update(i.login + i.password).digest().toString("hex");
|
114
|
-
console.warn("Monitor link for: " + i.login + " -> /sm-" + hash);
|
115
|
-
}
|
116
|
-
exports.REQ_MONITOR_USERS.listener = async (req) => {
|
117
|
-
const result = [];
|
118
|
-
if (this.options.monitor) {
|
119
|
-
for (let i of this.options.monitor) {
|
120
|
-
const hash = crypto_1.default.createHash("sha256").update(i.login + i.password).digest().toString("hex");
|
121
|
-
result.push(hash);
|
122
|
-
}
|
123
|
-
}
|
124
|
-
return result;
|
125
|
-
};
|
108
|
+
exports.REQ_MONITOR_USERS.listener = async () => this.options.monitor ?? [];
|
109
|
+
this.monitor = new MonitorService_1.MonitorService();
|
110
|
+
this.options.endpoints.push(new Monitor_1.Monitor());
|
126
111
|
}
|
127
112
|
this.options.endpoints.push(new ExternalServiceEndpoint_1.ExternalServiceEndpoint());
|
128
113
|
this.options.endpoints.push(new Liveness_1.Liveness(this.started), new Readiness_1.Readiness(this.started));
|
@@ -299,8 +284,6 @@ class APIService extends BaseService_1.BaseService {
|
|
299
284
|
httpRequest.interceptorResult = interceptorResult;
|
300
285
|
}
|
301
286
|
}
|
302
|
-
if (i === this.monitor)
|
303
|
-
httpRequest.precheck = { data: this.options.monitor };
|
304
287
|
const precheck = await i.precheck(httpRequest);
|
305
288
|
if (precheck && precheck.error) {
|
306
289
|
this.sendResponse(req.get("Referer") ?? "", res, precheck, tme, ep, log, httpRequest);
|
@@ -313,8 +296,6 @@ class APIService extends BaseService_1.BaseService {
|
|
313
296
|
console.error(e);
|
314
297
|
if (this.options.onError)
|
315
298
|
this.options.onError(e);
|
316
|
-
if (this.monitor)
|
317
|
-
this.monitor.registrateFatalError(ep);
|
318
299
|
let data = {
|
319
300
|
error: {
|
320
301
|
code: 10002,
|
@@ -388,8 +369,6 @@ class APIService extends BaseService_1.BaseService {
|
|
388
369
|
this.options.onNetworkLog(log);
|
389
370
|
return;
|
390
371
|
}
|
391
|
-
if (req && req.stream) {
|
392
|
-
}
|
393
372
|
if (this.options.postproducer) {
|
394
373
|
try {
|
395
374
|
data = await this.options.postproducer(req, res, data, requestTime, endpoint, log);
|
@@ -409,15 +388,12 @@ class APIService extends BaseService_1.BaseService {
|
|
409
388
|
log.time = data.responseTime;
|
410
389
|
log.referer = ref;
|
411
390
|
}
|
412
|
-
|
413
|
-
this.monitor.registrateResponse(data.endpoint, data.responseTime);
|
391
|
+
MonitorService_1.S_STAT_REGISTRATE_REQUEST.invoke(data);
|
414
392
|
if (res.destroyed || res.closed) {
|
415
393
|
if (log)
|
416
394
|
log.error = "Connection already closed, can't send response for: " + data.endpoint;
|
417
395
|
if (this.options.onError)
|
418
396
|
this.options.onError("Connection already closed, can't send response: " + data.endpoint, data);
|
419
|
-
if (this.monitor)
|
420
|
-
this.monitor.registrateError(data.endpoint);
|
421
397
|
}
|
422
398
|
else {
|
423
399
|
try {
|
@@ -426,8 +402,6 @@ class APIService extends BaseService_1.BaseService {
|
|
426
402
|
if (err) {
|
427
403
|
if (log)
|
428
404
|
log.error = "Can't send file: " + data.file;
|
429
|
-
if (this.monitor && data.endpoint)
|
430
|
-
this.monitor.registrateAPIError(data.endpoint);
|
431
405
|
this.sendResponse(ref, res, {
|
432
406
|
error: DefaultErrors_1.default.CANT_SEND_FILE,
|
433
407
|
data: null,
|
@@ -460,8 +434,7 @@ class APIService extends BaseService_1.BaseService {
|
|
460
434
|
res.send(data);
|
461
435
|
if (log)
|
462
436
|
log.response = this.checkDataLength(data);
|
463
|
-
if (data.error
|
464
|
-
this.monitor.registrateAPIError(data.endpoint);
|
437
|
+
if (data.error) {
|
465
438
|
if (log)
|
466
439
|
log.error = data.error.message;
|
467
440
|
}
|
@@ -473,8 +446,6 @@ class APIService extends BaseService_1.BaseService {
|
|
473
446
|
this.options.onError("Can't send response", e);
|
474
447
|
if (log)
|
475
448
|
log.error = "Can't send response";
|
476
|
-
if (this.monitor)
|
477
|
-
this.monitor.registrateError(data.endpoint);
|
478
449
|
}
|
479
450
|
}
|
480
451
|
if (log && log.error && this.options.onError) {
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import Signal, { Req } from "badmfck-signal";
|
2
|
+
import { BaseService } from "./BaseService";
|
3
|
+
import { TransferPacketVO } from "./structures/Interfaces";
|
4
|
+
export interface IEPStat {
|
5
|
+
success: number;
|
6
|
+
fail: number;
|
7
|
+
}
|
8
|
+
export interface IEPStatReqFilter {
|
9
|
+
range: "minute" | "hour" | "day";
|
10
|
+
from: string;
|
11
|
+
to: string;
|
12
|
+
ep: string;
|
13
|
+
}
|
14
|
+
export interface IEPStatResult {
|
15
|
+
}
|
16
|
+
export declare const S_STAT_REGISTRATE_REQUEST: Signal<TransferPacketVO<any>>;
|
17
|
+
export declare const REQ_EP_STAT: Req<IEPStatReqFilter, IEPStatResult>;
|
18
|
+
export declare class MonitorService extends BaseService {
|
19
|
+
endpoints: Map<number, Map<string, IEPStat>>;
|
20
|
+
constructor();
|
21
|
+
getEPStat(req: IEPStatReqFilter): Promise<IEPStatResult>;
|
22
|
+
onStatRegistrate(data: TransferPacketVO): void;
|
23
|
+
pad(num: number): string;
|
24
|
+
getMinutes(date: Date): number;
|
25
|
+
getDate(minutes: number): Date;
|
26
|
+
getMinutesInMonth(date: Date): number;
|
27
|
+
}
|
@@ -0,0 +1,137 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
+
if (mod && mod.__esModule) return mod;
|
20
|
+
var result = {};
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
+
__setModuleDefault(result, mod);
|
23
|
+
return result;
|
24
|
+
};
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
26
|
+
exports.MonitorService = exports.REQ_EP_STAT = exports.S_STAT_REGISTRATE_REQUEST = void 0;
|
27
|
+
const badmfck_signal_1 = __importStar(require("badmfck-signal"));
|
28
|
+
const BaseService_1 = require("./BaseService");
|
29
|
+
exports.S_STAT_REGISTRATE_REQUEST = new badmfck_signal_1.default();
|
30
|
+
exports.REQ_EP_STAT = new badmfck_signal_1.Req(undefined, "REQ_EP_STAT");
|
31
|
+
class MonitorService extends BaseService_1.BaseService {
|
32
|
+
endpoints = new Map();
|
33
|
+
constructor() {
|
34
|
+
super("MonitorService");
|
35
|
+
exports.S_STAT_REGISTRATE_REQUEST.subscribe(this.onStatRegistrate);
|
36
|
+
exports.REQ_EP_STAT.listener = async (req) => this.getEPStat(req);
|
37
|
+
}
|
38
|
+
async getEPStat(req) {
|
39
|
+
const result = new Map();
|
40
|
+
if (req.range === "hour") {
|
41
|
+
for (let [minute, minuteSlot] of this.endpoints) {
|
42
|
+
const date = this.getDate(minute);
|
43
|
+
let range = minute + "";
|
44
|
+
if (req.range === "hour")
|
45
|
+
range = this.pad(this.getDate(minute).getHours());
|
46
|
+
else if (req.range === "day")
|
47
|
+
range = this.pad(this.getDate(minute).getDate());
|
48
|
+
if (req.from) {
|
49
|
+
if (range < req.from)
|
50
|
+
continue;
|
51
|
+
}
|
52
|
+
if (req.to) {
|
53
|
+
if (range > req.to)
|
54
|
+
continue;
|
55
|
+
}
|
56
|
+
let resultSlot = result.get(range);
|
57
|
+
if (!resultSlot) {
|
58
|
+
resultSlot = new Map();
|
59
|
+
result.set(range, resultSlot);
|
60
|
+
}
|
61
|
+
let epSlot = resultSlot.get(req.ep);
|
62
|
+
if (!epSlot) {
|
63
|
+
epSlot = { success: 0, fail: 0 };
|
64
|
+
resultSlot.set(req.ep, epSlot);
|
65
|
+
}
|
66
|
+
for (let [ep, stat] of minuteSlot) {
|
67
|
+
epSlot.success += stat.success;
|
68
|
+
epSlot.fail += stat.fail;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
const endResult = [];
|
73
|
+
for (let [date, obj] of result) {
|
74
|
+
const stat = {
|
75
|
+
date,
|
76
|
+
data: []
|
77
|
+
};
|
78
|
+
for (let [ep, s] of obj) {
|
79
|
+
const r = { ep, ...s };
|
80
|
+
stat.data.push(r);
|
81
|
+
}
|
82
|
+
endResult.push(stat);
|
83
|
+
}
|
84
|
+
return { filter: req, result: endResult };
|
85
|
+
}
|
86
|
+
onStatRegistrate(data) {
|
87
|
+
const minute = this.getMinutes(new Date());
|
88
|
+
let minuteSlot = this.endpoints.get(minute);
|
89
|
+
if (!minuteSlot) {
|
90
|
+
minuteSlot = new Map();
|
91
|
+
this.endpoints.set(minute, minuteSlot);
|
92
|
+
}
|
93
|
+
if (!data.endpoint)
|
94
|
+
data.endpoint = "unknown";
|
95
|
+
let epSlot = minuteSlot.get(data.endpoint);
|
96
|
+
if (!epSlot) {
|
97
|
+
epSlot = { success: 0, fail: 0 };
|
98
|
+
minuteSlot.set(data.endpoint, epSlot);
|
99
|
+
}
|
100
|
+
if (data.error) {
|
101
|
+
epSlot.fail++;
|
102
|
+
}
|
103
|
+
else {
|
104
|
+
epSlot.success++;
|
105
|
+
}
|
106
|
+
if (this.endpoints.size > 3000) {
|
107
|
+
const firstItem = this.endpoints.keys().next().value;
|
108
|
+
if (firstItem)
|
109
|
+
this.endpoints.delete(firstItem);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
pad(num) {
|
113
|
+
return num.toString().padStart(2, '0');
|
114
|
+
}
|
115
|
+
getMinutes(date) {
|
116
|
+
const year = date.getFullYear();
|
117
|
+
const month = this.pad(date.getMonth() + 1);
|
118
|
+
const day = this.pad(date.getDate());
|
119
|
+
const hours = this.pad(date.getHours());
|
120
|
+
const minutes = this.pad(date.getMinutes());
|
121
|
+
return parseInt(`${year}${month}${day}${hours}${minutes}`);
|
122
|
+
}
|
123
|
+
getDate(minutes) {
|
124
|
+
const datetime = minutes.toString();
|
125
|
+
const year = parseInt(datetime.slice(0, 4));
|
126
|
+
const month = parseInt(datetime.slice(4, 6)) - 1;
|
127
|
+
const day = parseInt(datetime.slice(6, 8));
|
128
|
+
const hours = parseInt(datetime.slice(8, 10));
|
129
|
+
const min = parseInt(datetime.slice(10, 12));
|
130
|
+
return new Date(year, month, day, hours, min);
|
131
|
+
}
|
132
|
+
getMinutesInMonth(date) {
|
133
|
+
const daysInMonth = date.getDate();
|
134
|
+
return daysInMonth * 1440;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
exports.MonitorService = MonitorService;
|
@@ -10,39 +10,15 @@ interface IStatObject {
|
|
10
10
|
fatalErrors: Map<string, number>;
|
11
11
|
apiErrors: Map<string, number>;
|
12
12
|
}
|
13
|
-
interface ISystemStat {
|
14
|
-
cpuUsage: any;
|
15
|
-
memoryTotal: number;
|
16
|
-
memoryUsage: any;
|
17
|
-
}
|
18
13
|
export declare const S_MONITOR_REGISTRATE_ACTION: Signal<IUserAction>;
|
19
14
|
export declare class Monitor extends BaseEndpoint {
|
20
15
|
ignoreHttpLogging: boolean;
|
21
|
-
|
22
|
-
private systemStat;
|
23
|
-
private userActions;
|
24
|
-
private registeredActions;
|
16
|
+
users: Map<string, IStatObject>;
|
25
17
|
constructor();
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
registrateResponse(endpoint: string, responseTime: number): void;
|
32
|
-
increaseStat(statObject: Map<string, number>, endpoint: string): void;
|
33
|
-
createStatObj(): IStatObject;
|
34
|
-
createSystemStatObj(): ISystemStat;
|
35
|
-
getDateIndex(d: Date): number;
|
36
|
-
getHourMinuteIndex(d: Date): string;
|
37
|
-
leadZero(i: number): string;
|
38
|
-
precheck(req: HTTPRequestVO): Promise<TransferPacketVO<any> | null>;
|
39
|
-
logs(req: HTTPRequestVO): Promise<TransferPacketVO<any>>;
|
40
|
-
netlog(req: HTTPRequestVO): Promise<TransferPacketVO<any>>;
|
41
|
-
metrics(req: HTTPRequestVO): Promise<TransferPacketVO<any>>;
|
42
|
-
serverStat(req: HTTPRequestVO): Promise<TransferPacketVO<any>>;
|
43
|
-
mapToKeyValue(map: Map<string, string | number>): {
|
44
|
-
name: string;
|
45
|
-
value: string | number;
|
46
|
-
}[];
|
18
|
+
logs(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
19
|
+
netlog(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
20
|
+
metrics(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
21
|
+
serverStat(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
22
|
+
checkAuthentication(req: HTTPRequestVO): Promise<boolean>;
|
47
23
|
}
|
48
24
|
export {};
|
@@ -10,254 +10,71 @@ const BaseEndpoint_1 = require("../BaseEndpoint");
|
|
10
10
|
const LogService_1 = require("../LogService");
|
11
11
|
const crypto_1 = __importDefault(require("crypto"));
|
12
12
|
const os_1 = __importDefault(require("os"));
|
13
|
+
const DefaultErrors_1 = __importDefault(require("../structures/DefaultErrors"));
|
14
|
+
const MonitorService_1 = require("../MonitorService");
|
13
15
|
exports.S_MONITOR_REGISTRATE_ACTION = new badmfck_signal_1.Signal();
|
14
16
|
class Monitor extends BaseEndpoint_1.BaseEndpoint {
|
15
17
|
ignoreHttpLogging = true;
|
16
|
-
|
17
|
-
systemStat = new Map();
|
18
|
-
userActions = new Map();
|
19
|
-
registeredActions = 0;
|
18
|
+
users = new Map();
|
20
19
|
constructor() {
|
21
|
-
super("sys-monitor");
|
22
|
-
exports.S_MONITOR_REGISTRATE_ACTION.subscribe(data => this.registrateAction(data));
|
20
|
+
super("--sys-monitor");
|
23
21
|
this.registerEndpoints([
|
24
22
|
{ ignoreInterceptor: true, endpoint: "log", handler: this.logs },
|
25
23
|
{ ignoreInterceptor: true, endpoint: "netlog", handler: this.netlog },
|
26
24
|
{ ignoreInterceptor: true, endpoint: "metrics", handler: this.metrics },
|
27
|
-
{ ignoreInterceptor: true, endpoint: "server
|
25
|
+
{ ignoreInterceptor: true, endpoint: "server", handler: this.serverStat }
|
28
26
|
]);
|
29
|
-
setInterval(() => {
|
30
|
-
this.addSystemStat();
|
31
|
-
}, 1000 * 60 * 10);
|
32
|
-
this.addSystemStat();
|
33
|
-
}
|
34
|
-
registrateAction(data) {
|
35
|
-
if (!data.action)
|
36
|
-
return;
|
37
|
-
if (typeof data.action !== "string")
|
38
|
-
return;
|
39
|
-
if (data.action.length > 20)
|
40
|
-
data.action = data.action.substring(0, 20);
|
41
|
-
const d = new Date();
|
42
|
-
const doy = this.getDateIndex(d);
|
43
|
-
let day = this.userActions.get(doy);
|
44
|
-
if (!day) {
|
45
|
-
day = new Map();
|
46
|
-
this.userActions.set(doy, day);
|
47
|
-
if (this.userActions.size > 7) {
|
48
|
-
for (let i of this.userActions) {
|
49
|
-
this.userActions.delete(i[0]);
|
50
|
-
break;
|
51
|
-
}
|
52
|
-
}
|
53
|
-
}
|
54
|
-
const minute = this.getHourMinuteIndex(d);
|
55
|
-
let m = day.get(minute);
|
56
|
-
if (!m) {
|
57
|
-
m = new Map();
|
58
|
-
day.set(minute, m);
|
59
|
-
}
|
60
|
-
let cnt = m.get(data.action);
|
61
|
-
if (!cnt)
|
62
|
-
cnt = 0;
|
63
|
-
cnt++;
|
64
|
-
m.set(data.action, cnt);
|
65
|
-
}
|
66
|
-
addSystemStat() {
|
67
|
-
const so = this.createSystemStatObj();
|
68
|
-
so.memoryUsage = process.memoryUsage();
|
69
|
-
so.memoryTotal = os_1.default.totalmem();
|
70
|
-
}
|
71
|
-
registrateError(endpoint) {
|
72
|
-
const so = this.createStatObj();
|
73
|
-
this.increaseStat(so.errors, endpoint);
|
74
|
-
}
|
75
|
-
registrateFatalError(endpoint) {
|
76
|
-
const so = this.createStatObj();
|
77
|
-
this.increaseStat(so.fatalErrors, endpoint);
|
78
|
-
}
|
79
|
-
registrateAPIError(endpoint) {
|
80
|
-
const so = this.createStatObj();
|
81
|
-
this.increaseStat(so.apiErrors, endpoint);
|
82
|
-
}
|
83
|
-
registrateResponse(endpoint, responseTime) {
|
84
|
-
const so = this.createStatObj();
|
85
|
-
this.increaseStat(so.requests, endpoint);
|
86
|
-
}
|
87
|
-
increaseStat(statObject, endpoint) {
|
88
|
-
let reqep = statObject.get(endpoint);
|
89
|
-
if (!reqep)
|
90
|
-
reqep = 0;
|
91
|
-
reqep += 1;
|
92
|
-
statObject.set(endpoint, reqep);
|
93
|
-
this.registeredActions++;
|
94
|
-
}
|
95
|
-
createStatObj() {
|
96
|
-
const d = new Date();
|
97
|
-
const dtm = this.getDateIndex(d);
|
98
|
-
let day = this.httpRequests.get(dtm);
|
99
|
-
if (!day) {
|
100
|
-
day = new Map();
|
101
|
-
this.httpRequests.set(dtm, day);
|
102
|
-
if (this.httpRequests.size > 7) {
|
103
|
-
for (let i of this.httpRequests) {
|
104
|
-
this.httpRequests.delete(i[0]);
|
105
|
-
break;
|
106
|
-
}
|
107
|
-
}
|
108
|
-
}
|
109
|
-
const hourMinute = this.getHourMinuteIndex(d);
|
110
|
-
let hm = day.get(hourMinute);
|
111
|
-
if (!hm) {
|
112
|
-
hm = {
|
113
|
-
errors: new Map(),
|
114
|
-
requests: new Map(),
|
115
|
-
fatalErrors: new Map(),
|
116
|
-
apiErrors: new Map()
|
117
|
-
};
|
118
|
-
day.set(hourMinute, hm);
|
119
|
-
}
|
120
|
-
return hm;
|
121
|
-
}
|
122
|
-
createSystemStatObj() {
|
123
|
-
const d = new Date();
|
124
|
-
const dtm = this.getDateIndex(d);
|
125
|
-
let day = this.systemStat.get(dtm);
|
126
|
-
if (!day) {
|
127
|
-
day = new Map();
|
128
|
-
this.systemStat.set(dtm, day);
|
129
|
-
if (this.systemStat.size > 7) {
|
130
|
-
for (let i of this.systemStat) {
|
131
|
-
this.systemStat.delete(i[0]);
|
132
|
-
break;
|
133
|
-
}
|
134
|
-
}
|
135
|
-
}
|
136
|
-
const hourMinute = this.getHourMinuteIndex(d);
|
137
|
-
let hm = day.get(hourMinute);
|
138
|
-
if (!hm) {
|
139
|
-
hm = {
|
140
|
-
cpuUsage: 0,
|
141
|
-
memoryTotal: 0,
|
142
|
-
memoryUsage: {}
|
143
|
-
};
|
144
|
-
day.set(hourMinute, hm);
|
145
|
-
}
|
146
|
-
return hm;
|
147
|
-
}
|
148
|
-
getDateIndex(d) {
|
149
|
-
const dtm = d;
|
150
|
-
return parseInt(dtm.getFullYear().toString().substring(2) + this.leadZero(dtm.getMonth() + 1) + this.leadZero(dtm.getDate()));
|
151
|
-
}
|
152
|
-
getHourMinuteIndex(d) {
|
153
|
-
const dtm = d;
|
154
|
-
return this.leadZero(dtm.getHours()) + this.leadZero(dtm.getMinutes());
|
155
|
-
}
|
156
|
-
leadZero(i) {
|
157
|
-
if (i > 9)
|
158
|
-
return i + "";
|
159
|
-
return "0" + i;
|
160
|
-
}
|
161
|
-
async precheck(req) {
|
162
|
-
if (!req.headers)
|
163
|
-
return { error: { code: 10001, message: "No authorization", httpStatus: 400 } };
|
164
|
-
if (!req.headers['authorization'])
|
165
|
-
return { error: { code: 10002, message: "No authorization found", httpStatus: 400 } };
|
166
|
-
const auth = req.headers['authorization'];
|
167
|
-
if (!req.precheck || !Array.isArray(req.precheck.data)) {
|
168
|
-
return { error: { code: 10003, message: "No authorization records found", httpStatus: 400 } };
|
169
|
-
}
|
170
|
-
let authorized = false;
|
171
|
-
for (let i of req.precheck.data) {
|
172
|
-
let expectationStr = "";
|
173
|
-
expectationStr += req.endpoint;
|
174
|
-
expectationStr += JSON.stringify(i);
|
175
|
-
expectationStr += JSON.stringify(req.method);
|
176
|
-
expectationStr += JSON.stringify(req.data);
|
177
|
-
expectationStr += JSON.stringify(req.params);
|
178
|
-
const expectation = "sha256 " + crypto_1.default.createHash("sha256").update(expectationStr).digest().toString("hex");
|
179
|
-
if (auth === expectation) {
|
180
|
-
authorized = true;
|
181
|
-
break;
|
182
|
-
}
|
183
|
-
}
|
184
|
-
if (!authorized) {
|
185
|
-
console.error("Wrong token: " + auth);
|
186
|
-
return { error: { code: 10004, message: "Unauthorized access", httpStatus: 401 } };
|
187
|
-
}
|
188
|
-
return null;
|
189
27
|
}
|
190
28
|
async logs(req) {
|
191
|
-
|
192
|
-
|
29
|
+
this.checkAuthentication(req);
|
30
|
+
const services = await LogService_1.REQ_LOG_UNIQUE_SERVICES.request();
|
31
|
+
const log = await LogService_1.REQ_LOG.request({
|
32
|
+
lastID: req.data.lastID ?? 0
|
33
|
+
});
|
34
|
+
return {
|
35
|
+
data: {
|
36
|
+
services,
|
37
|
+
log
|
38
|
+
}
|
39
|
+
};
|
193
40
|
}
|
194
41
|
async netlog(req) {
|
195
|
-
|
196
|
-
return {
|
42
|
+
this.checkAuthentication(req);
|
43
|
+
return {};
|
197
44
|
}
|
198
45
|
async metrics(req) {
|
199
|
-
|
200
|
-
const
|
201
|
-
|
202
|
-
let result = [];
|
203
|
-
if (stat) {
|
204
|
-
for (let minutes of stat) {
|
205
|
-
result.push({
|
206
|
-
m: minutes[0],
|
207
|
-
ae: this.mapToKeyValue(minutes[1].apiErrors),
|
208
|
-
e: this.mapToKeyValue(minutes[1].errors),
|
209
|
-
r: this.mapToKeyValue(minutes[1].requests),
|
210
|
-
fe: this.mapToKeyValue(minutes[1].fatalErrors),
|
211
|
-
});
|
212
|
-
}
|
213
|
-
}
|
214
|
-
const ua = this.userActions.get(di);
|
215
|
-
let uaResult = [];
|
216
|
-
if (ua) {
|
217
|
-
for (let i of ua) {
|
218
|
-
const minutes = i[1];
|
219
|
-
const mArray = [];
|
220
|
-
for (let j of i[0]) {
|
221
|
-
mArray.push({
|
222
|
-
action: j[0],
|
223
|
-
count: j[1]
|
224
|
-
});
|
225
|
-
}
|
226
|
-
result.push({
|
227
|
-
m: i[0],
|
228
|
-
data: mArray
|
229
|
-
});
|
230
|
-
}
|
231
|
-
}
|
232
|
-
return { data: { stat: result, date: +date, userActions: uaResult } };
|
46
|
+
this.checkAuthentication(req);
|
47
|
+
const result = await MonitorService_1.REQ_EP_STAT.request(req.data);
|
48
|
+
return { data: result };
|
233
49
|
}
|
234
50
|
async serverStat(req) {
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
}
|
51
|
+
this.checkAuthentication(req);
|
52
|
+
let stat = {
|
53
|
+
cpuUsage: os_1.default.cpus(),
|
54
|
+
memoryTotal: os_1.default.totalmem(),
|
55
|
+
memoryUsage: os_1.default.freemem()
|
56
|
+
};
|
57
|
+
return { data: stat };
|
58
|
+
}
|
59
|
+
async checkAuthentication(req) {
|
60
|
+
const users = await APIService_1.REQ_MONITOR_USERS.request();
|
61
|
+
const header = req.headers['authorization'];
|
62
|
+
if (!header)
|
63
|
+
throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "No authorization header found" };
|
64
|
+
for (let i of users) {
|
65
|
+
let hashStr = "";
|
66
|
+
hashStr += req.endpoint;
|
67
|
+
hashStr += JSON.stringify(i);
|
68
|
+
hashStr += JSON.stringify(req.method.toUpperCase());
|
69
|
+
hashStr += JSON.stringify(req.data ?? {});
|
70
|
+
hashStr += JSON.stringify(req.params ?? {});
|
71
|
+
let token = null;
|
72
|
+
token = "sha256 " + crypto_1.default.createHash('sha256').update(hashStr).digest('hex');
|
73
|
+
if (token == header) {
|
74
|
+
return true;
|
75
|
+
}
|
248
76
|
}
|
249
|
-
|
250
|
-
registeredActions: this.registeredActions,
|
251
|
-
uptime: process.uptime(),
|
252
|
-
osUptime: os_1.default.uptime(),
|
253
|
-
stat: result
|
254
|
-
} };
|
255
|
-
}
|
256
|
-
mapToKeyValue(map) {
|
257
|
-
const res = [];
|
258
|
-
for (let i of map)
|
259
|
-
res.push({ name: i[0], value: i[1] });
|
260
|
-
return res;
|
77
|
+
throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "Invalid token" };
|
261
78
|
}
|
262
79
|
}
|
263
80
|
exports.Monitor = Monitor;
|