badmfck-api-server 4.1.59 → 5.0.2

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.
@@ -60,6 +60,10 @@ class Validator {
60
60
  }
61
61
  if (s_options.ignore_in_documentation === undefined && structure[k + "ignore_in_documentation"] !== undefined)
62
62
  s_options.ignore_in_documentation = structure[k + "ignore_in_documentation"];
63
+ if (s_options.values === undefined && structure[k + "values"] !== undefined)
64
+ s_options.values = structure[k + "values"];
65
+ if (s_options.values === undefined && typeof structure[key] === "string" && structure[key].includes(","))
66
+ s_options.values = structure[key].split(",").map((v) => v.trim()).filter((v) => v.length > 0);
63
67
  if (s_options.min && isNaN(s_options.min))
64
68
  s_options.min = undefined;
65
69
  if (s_options.max == undefined || isNaN(s_options.max)) {
@@ -35,6 +35,9 @@ export type THttpHostStats = {
35
35
  avgMs: number;
36
36
  minMs: number;
37
37
  maxMs: number;
38
+ p50Ms: number;
39
+ p95Ms: number;
40
+ p99Ms: number;
38
41
  totalTimeMs: number;
39
42
  inFlight: number;
40
43
  byStatus: {
@@ -144,6 +147,10 @@ export declare class Http {
144
147
  private static _incInFlight;
145
148
  private static _decInFlight;
146
149
  private static _updateStats;
150
+ private static _LAT_CAP;
151
+ private static _latency;
152
+ private static _recordLatency;
153
+ private static _percentiles;
147
154
  private static _pushToTopSlow;
148
155
  static getHttpStats(): THttpStatsSnapshot;
149
156
  private static ensureInit;
@@ -217,7 +217,7 @@ class Http {
217
217
  h = {
218
218
  host,
219
219
  count: 0, errors: 0, timeouts: 0, retries: 0,
220
- avgMs: 0, minMs: Infinity, maxMs: 0, totalTimeMs: 0,
220
+ avgMs: 0, minMs: Infinity, maxMs: 0, p50Ms: 0, p95Ms: 0, p99Ms: 0, totalTimeMs: 0,
221
221
  inFlight: 0,
222
222
  byStatus: { s2xx: 0, s3xx: 0, s4xx: 0, s5xx: 0, other: 0, networkErrors: 0 },
223
223
  lastRequestAt: 0,
@@ -231,6 +231,7 @@ class Http {
231
231
  h.minMs = entry.time;
232
232
  if (entry.time > h.maxMs)
233
233
  h.maxMs = entry.time;
234
+ this._recordLatency(host, entry.time);
234
235
  if (!entry.ok)
235
236
  h.errors++;
236
237
  if (isTimeout)
@@ -254,6 +255,27 @@ class Http {
254
255
  h.byStatus.networkErrors++;
255
256
  }
256
257
  }
258
+ static _LAT_CAP = 1024;
259
+ static _latency = new Map();
260
+ static _recordLatency(host, ms) {
261
+ let r = this._latency.get(host);
262
+ if (!r) {
263
+ r = { s: new Array(this._LAT_CAP), pos: 0, n: 0 };
264
+ this._latency.set(host, r);
265
+ }
266
+ r.s[r.pos] = ms;
267
+ r.pos = (r.pos + 1) % this._LAT_CAP;
268
+ if (r.n < this._LAT_CAP)
269
+ r.n++;
270
+ }
271
+ static _percentiles(host) {
272
+ const r = this._latency.get(host);
273
+ if (!r || r.n === 0)
274
+ return { p50: 0, p95: 0, p99: 0 };
275
+ const arr = r.s.slice(0, r.n).sort((a, b) => a - b);
276
+ const pick = (p) => arr[Math.min(arr.length - 1, Math.max(0, Math.ceil((p / 100) * arr.length) - 1))];
277
+ return { p50: pick(50), p95: pick(95), p99: pick(99) };
278
+ }
257
279
  static _pushToTopSlow(entry) {
258
280
  if (this._topSlow.length < this._topSlowLimit) {
259
281
  this._topSlow.push(entry);
@@ -269,11 +291,15 @@ class Http {
269
291
  }
270
292
  static getHttpStats() {
271
293
  const perHost = Array.from(this._perHost.values())
272
- .map(h => ({
273
- ...h,
274
- minMs: Number.isFinite(h.minMs) ? h.minMs : 0,
275
- inFlight: this._inFlightByHost.get(h.host) ?? 0,
276
- }))
294
+ .map(h => {
295
+ const p = this._percentiles(h.host);
296
+ return {
297
+ ...h,
298
+ minMs: Number.isFinite(h.minMs) ? h.minMs : 0,
299
+ p50Ms: p.p50, p95Ms: p.p95, p99Ms: p.p99,
300
+ inFlight: this._inFlightByHost.get(h.host) ?? 0,
301
+ };
302
+ })
277
303
  .sort((a, b) => b.count - a.count);
278
304
  return {
279
305
  totalRequests: this._totalRequests,
@@ -494,6 +520,7 @@ class Http {
494
520
  const isTimeout = Http._isTimeoutError(networkErr);
495
521
  Http._updateStats(host, entry, isTimeout);
496
522
  Http._pushToTopSlow(entry);
523
+ MonitorService_1.S_STAT_REGISTRATE_HTTP_RESULT.invoke({ host, ok: result.ok, ms: entry.time });
497
524
  return result;
498
525
  };
499
526
  for (let attempt = 1; attempt <= retryCfg.maxAttempts; attempt++) {
@@ -34,6 +34,8 @@ export declare class Monitor extends BaseEndpoint {
34
34
  httpstats(req: HTTPRequestVO): Promise<TransferPacketVO>;
35
35
  inventory(req: HTTPRequestVO): Promise<TransferPacketVO>;
36
36
  metrics(req: HTTPRequestVO): Promise<TransferPacketVO>;
37
+ metricsWeeks(req: HTTPRequestVO): Promise<TransferPacketVO>;
38
+ metricsWeek(req: HTTPRequestVO): Promise<TransferPacketVO>;
37
39
  connections(req: HTTPRequestVO): Promise<TransferPacketVO>;
38
40
  db(req: HTTPRequestVO): Promise<TransferPacketVO>;
39
41
  checkAuthentication(req: HTTPRequestVO): Promise<string>;
@@ -56,6 +56,10 @@ class Monitor extends BaseEndpoint_1.BaseEndpoint {
56
56
  range: "",
57
57
  $__range_values: ["week", "day", "hour"]
58
58
  } },
59
+ { ignoreInterceptor: true, endpoint: "metricsWeeks", handler: this.metricsWeeks },
60
+ { ignoreInterceptor: true, endpoint: "metricsWeek", handler: this.metricsWeek, validationModel: {
61
+ weekKey: ""
62
+ } },
59
63
  { ignoreInterceptor: true, endpoint: "connections", handler: this.connections },
60
64
  { ignoreInterceptor: true, endpoint: "db", handler: this.db, validationModel: {
61
65
  range: "",
@@ -201,6 +205,14 @@ class Monitor extends BaseEndpoint_1.BaseEndpoint {
201
205
  const result = await MonitorService_1.REQ_STAT.request(req.data);
202
206
  return { data: result };
203
207
  }
208
+ async metricsWeeks(req) {
209
+ await this.checkAuthentication(req);
210
+ return { data: await MonitorService_1.REQ_STAT_WEEKS.request() };
211
+ }
212
+ async metricsWeek(req) {
213
+ await this.checkAuthentication(req);
214
+ return { data: await MonitorService_1.REQ_STAT_WEEK.request({ weekKey: req.data.weekKey }) };
215
+ }
204
216
  async connections(req) {
205
217
  await this.checkAuthentication(req);
206
218
  return { data: Http_1.Http.getActiveConnectionsSnapshot() };