badmfck-api-server 3.2.5 → 3.2.7

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.
@@ -95,7 +95,7 @@ async function Initializer(services) {
95
95
  exports.Initializer = Initializer;
96
96
  class APIService extends BaseService_1.BaseService {
97
97
  static nextLogID = 0;
98
- version = "3.2.5";
98
+ version = "3.2.7";
99
99
  options;
100
100
  monitor = null;
101
101
  monitorIndexFile;
@@ -181,6 +181,9 @@ class LogService extends BaseService_1.BaseService {
181
181
  const lastLogItem = this.log[this.log.length - 1];
182
182
  if (lastLogItem && lastLogItem.text === logitem.text && lastLogItem.source === logitem.source && lastLogItem.level === logitem.level) {
183
183
  lastLogItem.repeat++;
184
+ lastLogItem.time = logitem.time;
185
+ lastLogItem.date = logitem.date;
186
+ LogService.nextID--;
184
187
  exports.S_LOG_CREATED.invoke(lastLogItem);
185
188
  return;
186
189
  }
@@ -1,14 +1,9 @@
1
1
  import Signal, { Req } from "badmfck-signal";
2
2
  import { BaseService } from "./BaseService";
3
3
  import { TransferPacketVO } from "./structures/Interfaces";
4
- export interface IEPStat {
5
- success: number;
6
- fail: number;
7
- }
8
4
  export interface ICustomEvent {
9
5
  event: string;
10
6
  data?: any;
11
- project?: string;
12
7
  }
13
8
  export interface IEPStatReqFilter {
14
9
  range?: "minute" | "hour" | "day";
@@ -18,20 +13,47 @@ export interface IEPStatReqFilter {
18
13
  project?: string;
19
14
  event?: string;
20
15
  }
21
- export interface IEPStatResult {
22
- }
23
16
  export declare const S_STAT_REGISTRATE_REQUEST: Signal<TransferPacketVO<any>>;
24
17
  export declare const S_STAT_REGISTRATE_CUSTOM_EVENT: Signal<ICustomEvent>;
25
18
  export declare const S_STAT_REGISTRATE_SERVICE: Signal<string>;
26
- export declare const REQ_EP_STAT: Req<IEPStatReqFilter, IEPStatResult>;
19
+ export declare const REQ_EP_STAT: Req<void, Record<string, IMonitorDaySlot[]>>;
20
+ export declare const REQ_MONITOR_CPU_STAT: Req<void, any>;
21
+ type IMonitorMinutesSlot = {
22
+ count: number;
23
+ yyyymmddhhmm: number;
24
+ };
25
+ type IMonitorHoursSlot = {
26
+ count: number;
27
+ yyyymmddhh: number;
28
+ minutes: IMonitorMinutesSlot[];
29
+ };
30
+ type IMonitorDaySlot = {
31
+ ep: string;
32
+ yyyymmdd: number;
33
+ count: number;
34
+ hours: IMonitorHoursSlot[];
35
+ };
27
36
  export declare class MonitorService extends BaseService {
28
- projects: Map<string, Map<number, Map<string, IEPStat>>>;
37
+ private prevCpu;
38
+ private prevHrTime;
39
+ readonly intervalMs = 10000;
40
+ readonly maxSlots: number;
41
+ private history;
42
+ stat: Map<string, IMonitorDaySlot[]>;
29
43
  constructor();
30
44
  init(): Promise<void>;
31
- getEPStat(req: IEPStatReqFilter): Promise<IEPStatResult>;
45
+ getEPStat(): Promise<Record<string, IMonitorDaySlot[]>>;
32
46
  onStatRegistrate(data: TransferPacketVO): void;
33
- pad(num: number): string;
34
- getMinutes(date: Date): number;
35
- getDate(minutes: number): Date;
36
- getMinutesInMonth(date: Date): number;
47
+ private collectUsage;
48
+ getUsage(): {
49
+ timestamp: number;
50
+ cpu: number;
51
+ memory: {
52
+ rss: number;
53
+ heapUsed: number;
54
+ heapTotal: number;
55
+ external: number;
56
+ };
57
+ }[];
37
58
  }
59
+ export {};
@@ -23,127 +23,102 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.MonitorService = exports.REQ_EP_STAT = exports.S_STAT_REGISTRATE_SERVICE = exports.S_STAT_REGISTRATE_CUSTOM_EVENT = exports.S_STAT_REGISTRATE_REQUEST = void 0;
26
+ exports.MonitorService = exports.REQ_MONITOR_CPU_STAT = exports.REQ_EP_STAT = exports.S_STAT_REGISTRATE_SERVICE = exports.S_STAT_REGISTRATE_CUSTOM_EVENT = exports.S_STAT_REGISTRATE_REQUEST = void 0;
27
27
  const badmfck_signal_1 = __importStar(require("badmfck-signal"));
28
28
  const BaseService_1 = require("./BaseService");
29
+ const YYYYMMDDHH_1 = require("./helper/YYYYMMDDHH");
29
30
  exports.S_STAT_REGISTRATE_REQUEST = new badmfck_signal_1.default();
30
31
  exports.S_STAT_REGISTRATE_CUSTOM_EVENT = new badmfck_signal_1.default();
31
32
  exports.S_STAT_REGISTRATE_SERVICE = new badmfck_signal_1.default();
32
33
  exports.REQ_EP_STAT = new badmfck_signal_1.Req(undefined, "REQ_EP_STAT");
34
+ exports.REQ_MONITOR_CPU_STAT = new badmfck_signal_1.Req(undefined, "REQ_MONITOR_CPU_STAT");
33
35
  class MonitorService extends BaseService_1.BaseService {
34
- projects = new Map();
36
+ prevCpu = process.cpuUsage();
37
+ prevHrTime = process.hrtime();
38
+ intervalMs = 10_000;
39
+ maxSlots = (5 * 60 * 1000) / this.intervalMs;
40
+ history = [];
41
+ stat = new Map();
35
42
  constructor() {
36
43
  super("MonitorService");
37
- exports.S_STAT_REGISTRATE_REQUEST.subscribe(req => this.onStatRegistrate(req));
38
- exports.REQ_EP_STAT.listener = async (req) => this.getEPStat(req);
44
+ exports.S_STAT_REGISTRATE_REQUEST.subscribe((req) => this.onStatRegistrate(req));
45
+ exports.REQ_EP_STAT.listener = async (req) => this.getEPStat();
46
+ exports.REQ_MONITOR_CPU_STAT.listener = async () => this.getUsage();
47
+ setInterval(() => this.collectUsage(), this.intervalMs);
39
48
  }
40
49
  async init() {
41
50
  super.init();
42
51
  }
43
- async getEPStat(req) {
44
- const result = [];
45
- for (let [project, projectSlot] of this.projects) {
46
- if (req.project && req.project !== project)
47
- continue;
48
- let p = result.find(p => p.project === project);
49
- if (!p) {
50
- p = { project, dates: [] };
51
- result.push(p);
52
- }
53
- for (let [minute, minuteSlot] of projectSlot) {
54
- let range = minute + "";
55
- if (req.range === "hour")
56
- range = this.pad(this.getDate(minute).getHours());
57
- else if (req.range === "day")
58
- range = this.pad(this.getDate(minute).getDate());
59
- if (req.from) {
60
- if (range < req.from)
61
- continue;
62
- }
63
- if (req.to) {
64
- if (range > req.to)
65
- continue;
66
- }
67
- let dateSlot = p.dates.find(p => p.date === range);
68
- if (!dateSlot) {
69
- dateSlot = {
70
- date: range,
71
- endpoints: []
72
- };
73
- p.dates.push(dateSlot);
74
- }
75
- for (let [epName, epStatSlot] of minuteSlot) {
76
- let epSlot = dateSlot.endpoints.find(p => p.ep === epName);
77
- if (!epSlot) {
78
- epSlot = {
79
- ep: epName,
80
- success: 0,
81
- fail: 0
82
- };
83
- dateSlot.endpoints.push(epSlot);
84
- }
85
- epSlot.fail += epStatSlot.fail;
86
- epSlot.success += epStatSlot.success;
87
- }
88
- }
89
- }
90
- return { filter: req, result: result };
52
+ async getEPStat() {
53
+ const result = {};
54
+ for (const [ep, slots] of this.stat.entries())
55
+ result[ep] = slots;
56
+ return result;
91
57
  }
92
58
  onStatRegistrate(data) {
93
- const minute = this.getMinutes(new Date());
94
- const project = data.project ?? "unknown";
95
- let projectSlot = this.projects.get(project);
96
- if (!projectSlot) {
97
- projectSlot = new Map();
98
- this.projects.set(project, projectSlot);
99
- }
100
- let minuteSlot = projectSlot.get(minute);
101
- if (!minuteSlot) {
102
- minuteSlot = new Map();
103
- projectSlot.set(minute, minuteSlot);
104
- }
105
- if (!data.endpoint)
106
- data.endpoint = "unknown";
107
- let epSlot = minuteSlot.get(data.endpoint);
59
+ const date = new Date();
60
+ const yyyymmdd = parseInt((0, YYYYMMDDHH_1.YYYYMMDDHH)(date, "yyyymmdd"));
61
+ const yyyymmddhh = parseInt((0, YYYYMMDDHH_1.YYYYMMDDHH)(date, "yyyymmddhh"));
62
+ const yyyymmddhhmm = parseInt((0, YYYYMMDDHH_1.YYYYMMDDHH)(date, "yyyymmddhhmm"));
63
+ const ep = data.endpoint || "unknown";
64
+ let epSlot = this.stat.get(ep);
108
65
  if (!epSlot) {
109
- epSlot = { success: 0, fail: 0 };
110
- minuteSlot.set(data.endpoint, epSlot);
66
+ epSlot = [];
67
+ this.stat.set(ep, epSlot);
111
68
  }
112
- if (data.error) {
113
- epSlot.fail++;
69
+ let slot = epSlot.find((s) => s.yyyymmdd === yyyymmdd && s.ep === ep);
70
+ if (!slot) {
71
+ slot = { ep, yyyymmdd: yyyymmdd, count: 0, hours: [] };
72
+ epSlot.push(slot);
114
73
  }
115
- else {
116
- epSlot.success++;
74
+ slot.count++;
75
+ let slotHour = slot.hours.find((h) => h.yyyymmddhh === yyyymmddhh);
76
+ if (!slotHour) {
77
+ slotHour = {
78
+ count: 0,
79
+ yyyymmddhh,
80
+ minutes: [],
81
+ };
82
+ slot.hours.push(slotHour);
117
83
  }
118
- if (projectSlot.size > 3000) {
119
- const firstItem = projectSlot.keys().next().value;
120
- if (firstItem)
121
- projectSlot.delete(firstItem);
84
+ slotHour.count++;
85
+ let slotMinute = slotHour.minutes.find((m) => m.yyyymmddhhmm === yyyymmddhhmm);
86
+ if (!slotMinute) {
87
+ slotMinute = {
88
+ count: 0,
89
+ yyyymmddhhmm,
90
+ };
91
+ slotHour.minutes.push(slotMinute);
122
92
  }
93
+ slotMinute.count++;
94
+ if (epSlot.length > 7)
95
+ epSlot.unshift();
123
96
  }
124
- pad(num) {
125
- return num.toString().padStart(2, '0');
126
- }
127
- getMinutes(date) {
128
- const year = date.getFullYear();
129
- const month = this.pad(date.getMonth() + 1);
130
- const day = this.pad(date.getDate());
131
- const hours = this.pad(date.getHours());
132
- const minutes = this.pad(date.getMinutes());
133
- return parseInt(`${year}${month}${day}${hours}${minutes}`);
134
- }
135
- getDate(minutes) {
136
- const datetime = minutes.toString();
137
- const year = parseInt(datetime.slice(0, 4));
138
- const month = parseInt(datetime.slice(4, 6)) - 1;
139
- const day = parseInt(datetime.slice(6, 8));
140
- const hours = parseInt(datetime.slice(8, 10));
141
- const min = parseInt(datetime.slice(10, 12));
142
- return new Date(year, month, day, hours, min);
97
+ collectUsage() {
98
+ const currentCpu = process.cpuUsage(this.prevCpu);
99
+ const currentHrTime = process.hrtime(this.prevHrTime);
100
+ this.prevCpu = process.cpuUsage();
101
+ this.prevHrTime = process.hrtime();
102
+ const elapsedMicros = currentHrTime[0] * 1e6 + currentHrTime[1] / 1e3;
103
+ const totalCpu = currentCpu.user + currentCpu.system;
104
+ const cpuPercent = (totalCpu / elapsedMicros) * 100;
105
+ const mem = process.memoryUsage();
106
+ this.history.push({
107
+ timestamp: Date.now(),
108
+ cpu: cpuPercent,
109
+ memory: {
110
+ rss: mem.rss,
111
+ heapUsed: mem.heapUsed,
112
+ heapTotal: mem.heapTotal,
113
+ external: mem.external,
114
+ },
115
+ });
116
+ if (this.history.length > this.maxSlots) {
117
+ this.history.shift();
118
+ }
143
119
  }
144
- getMinutesInMonth(date) {
145
- const daysInMonth = date.getDate();
146
- return daysInMonth * 1440;
120
+ getUsage() {
121
+ return this.history;
147
122
  }
148
123
  }
149
124
  exports.MonitorService = MonitorService;
@@ -120,8 +120,8 @@ class Validator {
120
120
  errors.push("wrong value for field '" + i + "', expected " + expected.join(", ") + " got: " + value);
121
121
  }
122
122
  }
123
- if (typeof structure[i] === "string" && structure[i].includes("regex:")) {
124
- const regex = structure[i].substring(6);
123
+ if (typeof structure[i] === "string" && structure["$__regex_" + i]) {
124
+ const regex = structure["$__regex_" + i];
125
125
  const reg = new RegExp(regex);
126
126
  if (reg.test(object[i]) === false)
127
127
  errors.push("wrong value for field '" + i + "', false mask for: " + object[i]);
@@ -154,6 +154,16 @@ class Validator {
154
154
  }
155
155
  }
156
156
  }
157
+ if (typeof structure[i] === "number" && structure["$__min_" + i]) {
158
+ const min = structure["$__min_" + i];
159
+ if (object[i] < min)
160
+ errors.push("value for field '" + i + "' is too small, expected more than " + min + " got: " + object[i]);
161
+ }
162
+ if (typeof structure[i] === "number" && structure["$__max_" + i]) {
163
+ const max = structure["$__max_" + i];
164
+ if (object[i] > max)
165
+ errors.push("value for field '" + i + "' is too big, expected less than " + max + " got: " + object[i]);
166
+ }
157
167
  foundKeys.push(i);
158
168
  }
159
169
  if (errors.length > 0)
@@ -0,0 +1,2 @@
1
+ export declare function YYYYMMDDHH(date: Date, format?: "yyyymmddhhmm" | "yyyymmddhh" | "yyyymmdd" | "yyyymm"): string;
2
+ export declare function YYYYMMDDHH_toDate(yyyymmddhh: number): Date;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.YYYYMMDDHH_toDate = exports.YYYYMMDDHH = void 0;
4
+ function YYYYMMDDHH(date, format = "yyyymmddhh") {
5
+ const year = date.getFullYear();
6
+ const month = String(date.getMonth() + 1).padStart(2, "0");
7
+ const day = String(date.getDate()).padStart(2, "0");
8
+ const hours = String(date.getHours()).padStart(2, "0");
9
+ const minutes = String(date.getMinutes()).padStart(2, "0");
10
+ switch (format) {
11
+ case "yyyymmddhh":
12
+ return `${year}${month}${day}${hours}`;
13
+ case "yyyymmdd":
14
+ return `${year}${month}${day}`;
15
+ case "yyyymm":
16
+ return `${year}${month}`;
17
+ case "yyyymmddhhmm":
18
+ return `${year}${month}${day}${hours}${minutes}`;
19
+ default:
20
+ return `${year}${month}${day}${hours}`;
21
+ }
22
+ }
23
+ exports.YYYYMMDDHH = YYYYMMDDHH;
24
+ function YYYYMMDDHH_toDate(yyyymmddhh) {
25
+ const str = String(yyyymmddhh);
26
+ const year = parseInt(str.slice(0, 4), 10);
27
+ const month = parseInt(str.slice(4, 6), 10) - 1;
28
+ const day = parseInt(str.slice(6, 8), 10);
29
+ const hours = parseInt(str.slice(8, 10), 10);
30
+ return new Date(year, month, day, hours);
31
+ }
32
+ exports.YYYYMMDDHH_toDate = YYYYMMDDHH_toDate;
@@ -9,7 +9,6 @@ const APIService_1 = require("../APIService");
9
9
  const BaseEndpoint_1 = require("../BaseEndpoint");
10
10
  const LogService_1 = require("../LogService");
11
11
  const crypto_1 = __importDefault(require("crypto"));
12
- const os_1 = __importDefault(require("os"));
13
12
  const DefaultErrors_1 = __importDefault(require("../structures/DefaultErrors"));
14
13
  const MonitorService_1 = require("../MonitorService");
15
14
  const fs_1 = __importDefault(require("fs"));
@@ -163,12 +162,7 @@ class Monitor extends BaseEndpoint_1.BaseEndpoint {
163
162
  }
164
163
  async serverStat(req) {
165
164
  await this.checkAuthentication(req);
166
- let stat = {
167
- cpuUsage: os_1.default.cpus(),
168
- memoryTotal: os_1.default.totalmem(),
169
- memoryUsage: os_1.default.freemem()
170
- };
171
- return { data: stat };
165
+ return { data: MonitorService_1.REQ_MONITOR_CPU_STAT.request() };
172
166
  }
173
167
  async checkAuthentication(req) {
174
168
  const users = await APIService_1.REQ_MONITOR_USERS.request();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badmfck-api-server",
3
- "version": "3.2.5",
3
+ "version": "3.2.7",
4
4
  "description": "Simple API http server based on express",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",