@maioradv/nestjs-core 2.0.3 → 2.0.4

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.
@@ -4,22 +4,30 @@ export type ResourceGuardOptions = {
4
4
  cpuLimit?: number;
5
5
  /** Memory limit in MB (RSS). Optional. */
6
6
  memoryLimitMb?: number;
7
- /** Interval in ms to check CPU/memory. Default: 2000 */
7
+ /** Interval in ms to check CPU/memory. Default: 2000 ms */
8
8
  sampleIntervalMs?: number;
9
- /** How long in ms the limit must be exceeded before shutdown. Default: 10000 */
9
+ /** How long in ms the limit must be exceeded before shutdown. Default: 10000ms */
10
10
  sustainForMs?: number;
11
- /** Maximum time in ms to wait for shutdownFn before hard kill. Default: 5000 */
11
+ /** Maximum time in ms to wait for shutdownFn before hard kill. Default: 5000ms */
12
12
  hardKillAfterMs?: number;
13
13
  /** Optional async shutdown function. If provided, will be called before hard exit. */
14
14
  shutdownFn?: () => Promise<void>;
15
15
  /** Optional NestJS LoggerService to use for logging. */
16
16
  logger?: LoggerService;
17
+ /** Optional peak logging options: log when CPU/memory exceed thresholds for a sustained period. Default sustain: 3000ms */
18
+ logPeaks?: {
19
+ cpuThreshold?: number;
20
+ memoryThresholdMb?: number;
21
+ sustainMs?: number;
22
+ };
17
23
  };
18
24
  export declare class ResourceGuard {
19
25
  private readonly opts;
20
26
  private lastCpu;
21
27
  private lastTime;
22
28
  private overSince;
29
+ private peakCpuSince;
30
+ private peakMemSince;
23
31
  private shuttingDown;
24
32
  constructor(opts: ResourceGuardOptions);
25
33
  /** Start monitoring CPU and memory */
@@ -7,14 +7,19 @@ class ResourceGuard {
7
7
  this.lastCpu = process.cpuUsage();
8
8
  this.lastTime = Date.now();
9
9
  this.overSince = null;
10
+ this.peakCpuSince = null;
11
+ this.peakMemSince = null;
10
12
  this.shuttingDown = false;
11
13
  this.opts.sampleIntervalMs ??= 2000;
12
14
  this.opts.sustainForMs ??= 10000;
13
15
  this.opts.hardKillAfterMs ??= 5000;
16
+ if (this.opts.logPeaks) {
17
+ this.opts.logPeaks.sustainMs ??= 3000;
18
+ }
14
19
  }
15
20
  /** Start monitoring CPU and memory */
16
21
  start() {
17
- if (!this.opts.cpuLimit && !this.opts.memoryLimitMb)
22
+ if (!this.opts.cpuLimit && !this.opts.memoryLimitMb && !this.opts.logPeaks)
18
23
  return;
19
24
  setInterval(() => this.check(), this.opts.sampleIntervalMs).unref();
20
25
  }
@@ -25,18 +30,21 @@ class ResourceGuard {
25
30
  let over = false;
26
31
  let currentCpuPercent = null;
27
32
  let currentMemMb = null;
28
- if (this.opts.cpuLimit) {
33
+ // compute CPU percent if needed for shutdown or peak logging
34
+ const needCpu = !!this.opts.cpuLimit || !!this.opts.logPeaks?.cpuThreshold;
35
+ if (needCpu) {
29
36
  const now = process.cpuUsage(this.lastCpu);
30
37
  const elapsedMs = nowTime - this.lastTime;
31
38
  const cpuMs = (now.user + now.system) / 1000;
32
39
  currentCpuPercent = (cpuMs / elapsedMs) * 100;
33
- if (currentCpuPercent > this.opts.cpuLimit)
40
+ if (this.opts.cpuLimit && currentCpuPercent > this.opts.cpuLimit)
34
41
  over = true;
35
42
  this.lastCpu = process.cpuUsage();
36
43
  }
37
- if (this.opts.memoryLimitMb) {
44
+ const needMem = !!this.opts.memoryLimitMb || !!this.opts.logPeaks?.memoryThresholdMb;
45
+ if (needMem) {
38
46
  currentMemMb = process.memoryUsage().rss / 1024 / 1024;
39
- if (currentMemMb > this.opts.memoryLimitMb)
47
+ if (this.opts.memoryLimitMb && currentMemMb > this.opts.memoryLimitMb)
40
48
  over = true;
41
49
  }
42
50
  this.lastTime = nowTime;
@@ -50,6 +58,44 @@ class ResourceGuard {
50
58
  else {
51
59
  this.overSince = null;
52
60
  }
61
+ const log = (msg) => {
62
+ if (this.opts.logger)
63
+ this.opts.logger.warn(`${msg}`);
64
+ else
65
+ console.warn(`${msg}`);
66
+ };
67
+ // Peak logging (non-shutdown): CPU
68
+ if (this.opts.logPeaks?.cpuThreshold && currentCpuPercent !== null) {
69
+ if (currentCpuPercent > this.opts.logPeaks.cpuThreshold) {
70
+ if (!this.peakCpuSince)
71
+ this.peakCpuSince = nowTime;
72
+ const sustainMs = this.opts.logPeaks.sustainMs;
73
+ if (nowTime - this.peakCpuSince >= sustainMs) {
74
+ const msg = `CPU: ${currentCpuPercent.toFixed(1)}% (${this.opts.logPeaks.cpuThreshold}%) ${nowTime - this.peakCpuSince}ms`;
75
+ log(msg);
76
+ this.peakCpuSince = null; // avoid repeated logging until it drops below
77
+ }
78
+ }
79
+ else {
80
+ this.peakCpuSince = null;
81
+ }
82
+ }
83
+ // Peak logging: Memory
84
+ if (this.opts.logPeaks?.memoryThresholdMb && currentMemMb !== null) {
85
+ if (currentMemMb > this.opts.logPeaks.memoryThresholdMb) {
86
+ if (!this.peakMemSince)
87
+ this.peakMemSince = nowTime;
88
+ const sustainMs = this.opts.logPeaks.sustainMs;
89
+ if (nowTime - this.peakMemSince >= sustainMs) {
90
+ const msg = `MEM: ${currentMemMb.toFixed(0)}MB (${this.opts.logPeaks.memoryThresholdMb}MB) ${nowTime - this.peakMemSince}ms`;
91
+ log(msg);
92
+ this.peakMemSince = null;
93
+ }
94
+ }
95
+ else {
96
+ this.peakMemSince = null;
97
+ }
98
+ }
53
99
  }
54
100
  async shutdown(currentCpu, currentMem) {
55
101
  if (this.shuttingDown)
@@ -63,7 +109,7 @@ class ResourceGuard {
63
109
  };
64
110
  const overTimeMs = this.overSince ? Date.now() - this.overSince : 0;
65
111
  const cpuMsg = this.opts.cpuLimit ? ` CPU: ${currentCpu?.toFixed(1)}% (${this.opts.cpuLimit}%)` : '';
66
- const memMsg = this.opts.memoryLimitMb ? ` Memory: ${currentMem?.toFixed(0)}MB (${this.opts.memoryLimitMb}MB)` : '';
112
+ const memMsg = this.opts.memoryLimitMb ? ` MEM: ${currentMem?.toFixed(0)}MB (${this.opts.memoryLimitMb}MB)` : '';
67
113
  const append = [cpuMsg, memMsg, ` Exceeded for: ${overTimeMs}ms (${this.opts.sustainForMs}ms)`].filter(Boolean).join(';');
68
114
  log(`LIMIT EXCEEDED → initiating shutdown;${append}`);
69
115
  const hardKill = setTimeout(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maioradv/nestjs-core",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "NestJS helpers by MaiorADV",
5
5
  "repository": "https://github.com/maioradv/nestjs-core.git",
6
6
  "author": "Maior ADV Srl",