@openstatus/health-memory 0.1.4-dev.0

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/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @openstatus/health-memory
2
+
3
+ Memory probe for [`@openstatus/health`](https://jsr.io/@openstatus/health).
4
+ Compares the process's heap in use with the V8 heap limit — and its
5
+ resident set size with a byte budget — and fails the check above either
6
+ threshold, so a leak turns the report `degraded` before the process is
7
+ killed for running out of memory.
8
+
9
+ ```sh
10
+ deno add jsr:@openstatus/health jsr:@openstatus/health-memory
11
+ npm install @openstatus/health @openstatus/health-memory
12
+ ```
13
+
14
+ ```ts
15
+ import { createHealthHandler } from "@openstatus/health";
16
+ import { memoryProbe } from "@openstatus/health-memory";
17
+
18
+ Deno.serve(
19
+ createHealthHandler({
20
+ probes: [memoryProbe({ maxHeapUsedPercent: 90 })],
21
+ }),
22
+ );
23
+ ```
24
+
25
+ The heap percentage is `heapUsed` from `process.memoryUsage()` over
26
+ `heap_size_limit` from `v8.getHeapStatistics()` — the limit V8 will
27
+ actually grow to, which honours `--max-old-space-size`. It is the number
28
+ that predicts an out-of-memory crash. `maxRssBytes` bounds the whole
29
+ resident set instead, which is what a container limit or an OOM killer
30
+ measures; set it a little under that limit. The check fails above
31
+ `maxHeapUsedPercent` (90% by default) or above `maxRssBytes` when that is
32
+ set instead; pass both to enforce both. A failing check throws
33
+ `MemoryPressureError`, which carries the `reading`, and a healthy one
34
+ reports `heapUsedBytes`, `heapLimitBytes`, `heapUsedPercent` and `rssBytes`.
35
+
36
+ ```ts
37
+ memoryProbe({
38
+ maxHeapUsedPercent: 85,
39
+ maxRssBytes: 900 * 1024 * 1024,
40
+ // optional overrides from the Probe contract
41
+ name: "heap",
42
+ critical: true,
43
+ timeoutMs: 100,
44
+ skip: () => env.NODE_ENV !== "production",
45
+ });
46
+ ```
47
+
48
+ Non-critical by default: memory pressure is an alert to act on, and taking
49
+ a leaking instance out of rotation only shifts its traffic onto the others.
50
+ Set `critical: true` when your platform restarts unhealthy instances and
51
+ that is the recovery you want.
52
+
53
+ This probe uses `node:process` and `node:v8`, so it runs on Node.js, Deno
54
+ and Bun but not on edge runtimes. Both readers are typed structurally and
55
+ can be replaced for tests.
56
+
57
+ ## About openstatus
58
+
59
+ [openstatus](https://www.openstatus.dev/) is the open-source uptime monitoring
60
+ and status page platform. This package is part of
61
+ [`@openstatus/health`](https://github.com/openstatusHQ/health), the `/health`
62
+ endpoints behind openstatus's own services, extracted so any JavaScript server
63
+ can expose one. Point an
64
+ [openstatus monitor](https://www.openstatus.dev/docs/reference/http-monitor)
65
+ at the endpoint and assert on `status` in the body to be alerted on
66
+ `degraded` before it becomes `unhealthy`.
67
+
68
+ Source: [github.com/openstatusHQ/health](https://github.com/openstatusHQ/health).
69
+ Issues and PRs welcome.
70
+
71
+ ## License
72
+
73
+ [MIT](https://github.com/openstatusHQ/health/blob/main/LICENSE)
@@ -0,0 +1,30 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+
25
+ Object.defineProperty(exports, '__toESM', {
26
+ enumerable: true,
27
+ get: function () {
28
+ return __toESM;
29
+ }
30
+ });
package/dist/mod.cjs ADDED
@@ -0,0 +1,63 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const node_process = require_rolldown_runtime.__toESM(require("node:process"));
3
+ const node_v8 = require_rolldown_runtime.__toESM(require("node:v8"));
4
+ const __openstatus_health = require_rolldown_runtime.__toESM(require("@openstatus/health"));
5
+
6
+ //#region src/mod.ts
7
+ /** Probe name when `name` is unset. */
8
+ const memoryDefaultName = "memory";
9
+ /** Threshold when neither `maxHeapUsedPercent` nor `maxRssBytes` is set. */
10
+ const memoryDefaultMaxHeapUsedPercent = 90;
11
+ /** Thrown by the probe when usage is above a threshold. */
12
+ var MemoryPressureError = class extends Error {
13
+ /** The reading that crossed the threshold. */
14
+ reading;
15
+ /** Build the error for `reading` against the threshold described by `reason`. */
16
+ constructor(reading, reason) {
17
+ super(reason);
18
+ this.name = "MemoryPressureError";
19
+ this.reading = reading;
20
+ }
21
+ };
22
+ /** A probe that fails above `maxHeapUsedPercent` or `maxRssBytes`; non-critical by default. Throws `ProbeConfigError` for a negative or non-finite threshold. */
23
+ function memoryProbe(options = {}) {
24
+ const maxRssBytes = options.maxRssBytes;
25
+ const maxHeapUsedPercent = options.maxHeapUsedPercent ?? (maxRssBytes == null ? memoryDefaultMaxHeapUsedPercent : void 0);
26
+ for (const [field, value] of [["maxHeapUsedPercent", maxHeapUsedPercent], ["maxRssBytes", maxRssBytes]]) if (value != null && (!Number.isFinite(value) || value < 0)) throw new __openstatus_health.ProbeConfigError("memoryProbe", field, `must be a non-negative number, got ${String(value)}`);
27
+ const memoryUsage = options.memoryUsage ?? (() => node_process.default.memoryUsage());
28
+ const heapStatistics = options.heapStatistics ?? node_v8.getHeapStatistics;
29
+ return {
30
+ name: options.name ?? memoryDefaultName,
31
+ critical: options.critical ?? false,
32
+ timeoutMs: options.timeoutMs,
33
+ skip: options.skip,
34
+ run: () => {
35
+ const reading = read(memoryUsage(), heapStatistics());
36
+ if (maxRssBytes != null && reading.rssBytes > maxRssBytes) throw new MemoryPressureError(reading, `rss ${reading.rssBytes} bytes exceeds ${maxRssBytes}`);
37
+ if (maxHeapUsedPercent != null && reading.heapUsedBytes / reading.heapLimitBytes * 100 > maxHeapUsedPercent) throw new MemoryPressureError(reading, `heap ${reading.heapUsedPercent}% used exceeds ${maxHeapUsedPercent}%`);
38
+ return reading;
39
+ }
40
+ };
41
+ }
42
+ function read(usage, heap) {
43
+ const heapUsedBytes = usage.heapUsed;
44
+ const heapLimitBytes = heap.heap_size_limit;
45
+ const rssBytes = usage.rss;
46
+ if (![
47
+ heapUsedBytes,
48
+ heapLimitBytes,
49
+ rssBytes
50
+ ].every((n) => Number.isFinite(n) && n >= 0) || heapLimitBytes === 0) throw new Error("unexpected memory statistics");
51
+ return {
52
+ heapUsedBytes,
53
+ heapLimitBytes,
54
+ heapUsedPercent: Math.round(heapUsedBytes / heapLimitBytes * 1e3) / 10,
55
+ rssBytes
56
+ };
57
+ }
58
+
59
+ //#endregion
60
+ exports.MemoryPressureError = MemoryPressureError;
61
+ exports.memoryDefaultMaxHeapUsedPercent = memoryDefaultMaxHeapUsedPercent;
62
+ exports.memoryDefaultName = memoryDefaultName;
63
+ exports.memoryProbe = memoryProbe;
package/dist/mod.d.cts ADDED
@@ -0,0 +1,55 @@
1
+ import { Probe, ProbeOverrides } from "@openstatus/health";
2
+
3
+ //#region src/mod.d.ts
4
+
5
+ /** Probe name when `name` is unset. */
6
+ declare const memoryDefaultName = "memory";
7
+ /** Threshold when neither `maxHeapUsedPercent` nor `maxRssBytes` is set. */
8
+ declare const memoryDefaultMaxHeapUsedPercent = 90;
9
+ /** The subset of `process.memoryUsage()` the probe reads. */
10
+ interface MemoryUsageSample {
11
+ /** Bytes of V8 heap in use. */
12
+ readonly heapUsed: number;
13
+ /** Resident set size in bytes. */
14
+ readonly rss: number;
15
+ }
16
+ /** The subset of `v8.getHeapStatistics()` the probe reads. */
17
+ interface HeapStatisticsSample {
18
+ /** The maximum heap size V8 will grow to. */
19
+ readonly heap_size_limit: number;
20
+ }
21
+ /** Options for `memoryProbe()`. */
22
+ interface MemoryProbeOptions extends ProbeOverrides {
23
+ /** Fail when the heap in use exceeds this percentage of the heap limit. Default `memoryDefaultMaxHeapUsedPercent` unless `maxRssBytes` is set. */
24
+ readonly maxHeapUsedPercent?: number;
25
+ /** Fail when the resident set size exceeds this many bytes. */
26
+ readonly maxRssBytes?: number;
27
+ /** Replacement `process.memoryUsage`, for tests. */
28
+ readonly memoryUsage?: () => MemoryUsageSample;
29
+ /** Replacement `v8.getHeapStatistics`, for tests. */
30
+ readonly heapStatistics?: () => HeapStatisticsSample;
31
+ }
32
+ /** What a healthy check resolves with. */
33
+ interface MemoryReading {
34
+ /** Bytes of heap in use. */
35
+ readonly heapUsedBytes: number;
36
+ /** The heap limit in bytes. */
37
+ readonly heapLimitBytes: number;
38
+ /** `heapUsedBytes` as a percentage of `heapLimitBytes`, rounded to one decimal. */
39
+ readonly heapUsedPercent: number;
40
+ /** Resident set size in bytes. */
41
+ readonly rssBytes: number;
42
+ }
43
+ /** Thrown by the probe when usage is above a threshold. */
44
+ declare class MemoryPressureError extends Error {
45
+ /** The reading that crossed the threshold. */
46
+ readonly reading: MemoryReading;
47
+ /** Build the error for `reading` against the threshold described by `reason`. */
48
+ constructor(reading: MemoryReading, reason: string);
49
+ }
50
+ /** A probe that fails above `maxHeapUsedPercent` or `maxRssBytes`; non-critical by default. Throws `ProbeConfigError` for a negative or non-finite threshold. */
51
+ declare function memoryProbe(options?: MemoryProbeOptions): Probe;
52
+ //# sourceMappingURL=mod.d.ts.map
53
+ //#endregion
54
+ export { HeapStatisticsSample, MemoryPressureError, MemoryProbeOptions, MemoryReading, MemoryUsageSample, memoryDefaultMaxHeapUsedPercent, memoryDefaultName, memoryProbe };
55
+ //# sourceMappingURL=mod.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.cts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;AAyEuB,cAhDV,iBAAA,GAgDU,QAAA;;AALuB,cAzCjC,+BAAA,GAyCiC,EAAA;AAa9C;AAA2B,UAnDV,iBAAA,CAmDU;EAAA;EAAiC,SAAG,QAAA,EAAA,MAAA;EAAK;;;;UA3CnD,oBAAA;;;;;UAMA,kBAAA,SAA2B;;;;;;+BAMb;;kCAEG;;;UAIjB,aAAA;;;;;;;;;;;cAYJ,mBAAA,SAA4B,KAAA;;oBAErB;;uBAGG;;;iBAQP,WAAA,WAAqB,qBAA0B"}
package/dist/mod.d.ts ADDED
@@ -0,0 +1,55 @@
1
+ import { Probe, ProbeOverrides } from "@openstatus/health";
2
+
3
+ //#region src/mod.d.ts
4
+
5
+ /** Probe name when `name` is unset. */
6
+ declare const memoryDefaultName = "memory";
7
+ /** Threshold when neither `maxHeapUsedPercent` nor `maxRssBytes` is set. */
8
+ declare const memoryDefaultMaxHeapUsedPercent = 90;
9
+ /** The subset of `process.memoryUsage()` the probe reads. */
10
+ interface MemoryUsageSample {
11
+ /** Bytes of V8 heap in use. */
12
+ readonly heapUsed: number;
13
+ /** Resident set size in bytes. */
14
+ readonly rss: number;
15
+ }
16
+ /** The subset of `v8.getHeapStatistics()` the probe reads. */
17
+ interface HeapStatisticsSample {
18
+ /** The maximum heap size V8 will grow to. */
19
+ readonly heap_size_limit: number;
20
+ }
21
+ /** Options for `memoryProbe()`. */
22
+ interface MemoryProbeOptions extends ProbeOverrides {
23
+ /** Fail when the heap in use exceeds this percentage of the heap limit. Default `memoryDefaultMaxHeapUsedPercent` unless `maxRssBytes` is set. */
24
+ readonly maxHeapUsedPercent?: number;
25
+ /** Fail when the resident set size exceeds this many bytes. */
26
+ readonly maxRssBytes?: number;
27
+ /** Replacement `process.memoryUsage`, for tests. */
28
+ readonly memoryUsage?: () => MemoryUsageSample;
29
+ /** Replacement `v8.getHeapStatistics`, for tests. */
30
+ readonly heapStatistics?: () => HeapStatisticsSample;
31
+ }
32
+ /** What a healthy check resolves with. */
33
+ interface MemoryReading {
34
+ /** Bytes of heap in use. */
35
+ readonly heapUsedBytes: number;
36
+ /** The heap limit in bytes. */
37
+ readonly heapLimitBytes: number;
38
+ /** `heapUsedBytes` as a percentage of `heapLimitBytes`, rounded to one decimal. */
39
+ readonly heapUsedPercent: number;
40
+ /** Resident set size in bytes. */
41
+ readonly rssBytes: number;
42
+ }
43
+ /** Thrown by the probe when usage is above a threshold. */
44
+ declare class MemoryPressureError extends Error {
45
+ /** The reading that crossed the threshold. */
46
+ readonly reading: MemoryReading;
47
+ /** Build the error for `reading` against the threshold described by `reason`. */
48
+ constructor(reading: MemoryReading, reason: string);
49
+ }
50
+ /** A probe that fails above `maxHeapUsedPercent` or `maxRssBytes`; non-critical by default. Throws `ProbeConfigError` for a negative or non-finite threshold. */
51
+ declare function memoryProbe(options?: MemoryProbeOptions): Probe;
52
+ //# sourceMappingURL=mod.d.ts.map
53
+ //#endregion
54
+ export { HeapStatisticsSample, MemoryPressureError, MemoryProbeOptions, MemoryReading, MemoryUsageSample, memoryDefaultMaxHeapUsedPercent, memoryDefaultName, memoryProbe };
55
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;AAyEuB,cAhDV,iBAAA,GAgDU,QAAA;;AALuB,cAzCjC,+BAAA,GAyCiC,EAAA;AAa9C;AAA2B,UAnDV,iBAAA,CAmDU;EAAA;EAAiC,SAAG,QAAA,EAAA,MAAA;EAAK;;;;UA3CnD,oBAAA;;;;;UAMA,kBAAA,SAA2B;;;;;;+BAMb;;kCAEG;;;UAIjB,aAAA;;;;;;;;;;;cAYJ,mBAAA,SAA4B,KAAA;;oBAErB;;uBAGG;;;iBAQP,WAAA,WAAqB,qBAA0B"}
package/dist/mod.js ADDED
@@ -0,0 +1,60 @@
1
+ import process from "node:process";
2
+ import { getHeapStatistics } from "node:v8";
3
+ import { ProbeConfigError } from "@openstatus/health";
4
+
5
+ //#region src/mod.ts
6
+ /** Probe name when `name` is unset. */
7
+ const memoryDefaultName = "memory";
8
+ /** Threshold when neither `maxHeapUsedPercent` nor `maxRssBytes` is set. */
9
+ const memoryDefaultMaxHeapUsedPercent = 90;
10
+ /** Thrown by the probe when usage is above a threshold. */
11
+ var MemoryPressureError = class extends Error {
12
+ /** The reading that crossed the threshold. */
13
+ reading;
14
+ /** Build the error for `reading` against the threshold described by `reason`. */
15
+ constructor(reading, reason) {
16
+ super(reason);
17
+ this.name = "MemoryPressureError";
18
+ this.reading = reading;
19
+ }
20
+ };
21
+ /** A probe that fails above `maxHeapUsedPercent` or `maxRssBytes`; non-critical by default. Throws `ProbeConfigError` for a negative or non-finite threshold. */
22
+ function memoryProbe(options = {}) {
23
+ const maxRssBytes = options.maxRssBytes;
24
+ const maxHeapUsedPercent = options.maxHeapUsedPercent ?? (maxRssBytes == null ? memoryDefaultMaxHeapUsedPercent : void 0);
25
+ for (const [field, value] of [["maxHeapUsedPercent", maxHeapUsedPercent], ["maxRssBytes", maxRssBytes]]) if (value != null && (!Number.isFinite(value) || value < 0)) throw new ProbeConfigError("memoryProbe", field, `must be a non-negative number, got ${String(value)}`);
26
+ const memoryUsage = options.memoryUsage ?? (() => process.memoryUsage());
27
+ const heapStatistics = options.heapStatistics ?? getHeapStatistics;
28
+ return {
29
+ name: options.name ?? memoryDefaultName,
30
+ critical: options.critical ?? false,
31
+ timeoutMs: options.timeoutMs,
32
+ skip: options.skip,
33
+ run: () => {
34
+ const reading = read(memoryUsage(), heapStatistics());
35
+ if (maxRssBytes != null && reading.rssBytes > maxRssBytes) throw new MemoryPressureError(reading, `rss ${reading.rssBytes} bytes exceeds ${maxRssBytes}`);
36
+ if (maxHeapUsedPercent != null && reading.heapUsedBytes / reading.heapLimitBytes * 100 > maxHeapUsedPercent) throw new MemoryPressureError(reading, `heap ${reading.heapUsedPercent}% used exceeds ${maxHeapUsedPercent}%`);
37
+ return reading;
38
+ }
39
+ };
40
+ }
41
+ function read(usage, heap) {
42
+ const heapUsedBytes = usage.heapUsed;
43
+ const heapLimitBytes = heap.heap_size_limit;
44
+ const rssBytes = usage.rss;
45
+ if (![
46
+ heapUsedBytes,
47
+ heapLimitBytes,
48
+ rssBytes
49
+ ].every((n) => Number.isFinite(n) && n >= 0) || heapLimitBytes === 0) throw new Error("unexpected memory statistics");
50
+ return {
51
+ heapUsedBytes,
52
+ heapLimitBytes,
53
+ heapUsedPercent: Math.round(heapUsedBytes / heapLimitBytes * 1e3) / 10,
54
+ rssBytes
55
+ };
56
+ }
57
+
58
+ //#endregion
59
+ export { MemoryPressureError, memoryDefaultMaxHeapUsedPercent, memoryDefaultName, memoryProbe };
60
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","names":["reading: MemoryReading","reason: string","options: MemoryProbeOptions","usage: MemoryUsageSample","heap: HeapStatisticsSample"],"sources":["../src/mod.ts"],"sourcesContent":["/**\n * Memory probe for `@openstatus/health`: compares the process's heap usage\n * with the V8 heap limit, and its resident set size with a byte budget,\n * and fails above either threshold.\n *\n * ```ts\n * import { memoryProbe } from \"@openstatus/health-memory\";\n *\n * const probe = memoryProbe({ maxHeapUsedPercent: 90 });\n * ```\n *\n * Node.js, Deno and Bun only: it uses `node:process` and `node:v8`.\n *\n * @module\n */\n\nimport process from \"node:process\";\nimport { getHeapStatistics } from \"node:v8\";\nimport {\n type Probe,\n ProbeConfigError,\n type ProbeOverrides,\n} from \"@openstatus/health\";\n\n/** Probe name when `name` is unset. */\nexport const memoryDefaultName = \"memory\";\n/** Threshold when neither `maxHeapUsedPercent` nor `maxRssBytes` is set. */\nexport const memoryDefaultMaxHeapUsedPercent = 90;\n\n/** The subset of `process.memoryUsage()` the probe reads. */\nexport interface MemoryUsageSample {\n /** Bytes of V8 heap in use. */\n readonly heapUsed: number;\n /** Resident set size in bytes. */\n readonly rss: number;\n}\n\n/** The subset of `v8.getHeapStatistics()` the probe reads. */\nexport interface HeapStatisticsSample {\n /** The maximum heap size V8 will grow to. */\n readonly heap_size_limit: number;\n}\n\n/** Options for `memoryProbe()`. */\nexport interface MemoryProbeOptions extends ProbeOverrides {\n /** Fail when the heap in use exceeds this percentage of the heap limit. Default `memoryDefaultMaxHeapUsedPercent` unless `maxRssBytes` is set. */\n readonly maxHeapUsedPercent?: number;\n /** Fail when the resident set size exceeds this many bytes. */\n readonly maxRssBytes?: number;\n /** Replacement `process.memoryUsage`, for tests. */\n readonly memoryUsage?: () => MemoryUsageSample;\n /** Replacement `v8.getHeapStatistics`, for tests. */\n readonly heapStatistics?: () => HeapStatisticsSample;\n}\n\n/** What a healthy check resolves with. */\nexport interface MemoryReading {\n /** Bytes of heap in use. */\n readonly heapUsedBytes: number;\n /** The heap limit in bytes. */\n readonly heapLimitBytes: number;\n /** `heapUsedBytes` as a percentage of `heapLimitBytes`, rounded to one decimal. */\n readonly heapUsedPercent: number;\n /** Resident set size in bytes. */\n readonly rssBytes: number;\n}\n\n/** Thrown by the probe when usage is above a threshold. */\nexport class MemoryPressureError extends Error {\n /** The reading that crossed the threshold. */\n readonly reading: MemoryReading;\n\n /** Build the error for `reading` against the threshold described by `reason`. */\n constructor(reading: MemoryReading, reason: string) {\n super(reason);\n this.name = \"MemoryPressureError\";\n this.reading = reading;\n }\n}\n\n/** A probe that fails above `maxHeapUsedPercent` or `maxRssBytes`; non-critical by default. Throws `ProbeConfigError` for a negative or non-finite threshold. */\nexport function memoryProbe(options: MemoryProbeOptions = {}): Probe {\n const maxRssBytes = options.maxRssBytes;\n const maxHeapUsedPercent = options.maxHeapUsedPercent ??\n (maxRssBytes == null ? memoryDefaultMaxHeapUsedPercent : undefined);\n for (\n const [field, value] of [\n [\"maxHeapUsedPercent\", maxHeapUsedPercent],\n [\"maxRssBytes\", maxRssBytes],\n ] as const\n ) {\n if (value != null && (!Number.isFinite(value) || value < 0)) {\n throw new ProbeConfigError(\n \"memoryProbe\",\n field,\n `must be a non-negative number, got ${String(value)}`,\n );\n }\n }\n const memoryUsage = options.memoryUsage ?? (() => process.memoryUsage());\n const heapStatistics = options.heapStatistics ?? getHeapStatistics;\n return {\n name: options.name ?? memoryDefaultName,\n critical: options.critical ?? false,\n timeoutMs: options.timeoutMs,\n skip: options.skip,\n run: () => {\n const reading = read(memoryUsage(), heapStatistics());\n if (maxRssBytes != null && reading.rssBytes > maxRssBytes) {\n throw new MemoryPressureError(\n reading,\n `rss ${reading.rssBytes} bytes exceeds ${maxRssBytes}`,\n );\n }\n if (\n maxHeapUsedPercent != null &&\n (reading.heapUsedBytes / reading.heapLimitBytes) * 100 >\n maxHeapUsedPercent\n ) {\n throw new MemoryPressureError(\n reading,\n `heap ${reading.heapUsedPercent}% used exceeds ${maxHeapUsedPercent}%`,\n );\n }\n return reading;\n },\n };\n}\n\nfunction read(\n usage: MemoryUsageSample,\n heap: HeapStatisticsSample,\n): MemoryReading {\n const heapUsedBytes = usage.heapUsed;\n const heapLimitBytes = heap.heap_size_limit;\n const rssBytes = usage.rss;\n if (\n ![heapUsedBytes, heapLimitBytes, rssBytes].every((n) =>\n Number.isFinite(n) && n >= 0\n ) || heapLimitBytes === 0\n ) {\n throw new Error(\"unexpected memory statistics\");\n }\n return {\n heapUsedBytes,\n heapLimitBytes,\n heapUsedPercent: Math.round((heapUsedBytes / heapLimitBytes) * 1000) / 10,\n rssBytes,\n };\n}\n"],"mappings":";;;;;;AAyBA,MAAa,oBAAoB;;AAEjC,MAAa,kCAAkC;;AAyC/C,IAAa,sBAAb,cAAyC,MAAM;;CAE7C,AAAS;;CAGT,YAAYA,SAAwBC,QAAgB;AAClD,QAAM,OAAO;AACb,OAAK,OAAO;AACZ,OAAK,UAAU;CAChB;AACF;;AAGD,SAAgB,YAAYC,UAA8B,CAAE,GAAS;CACnE,MAAM,cAAc,QAAQ;CAC5B,MAAM,qBAAqB,QAAQ,uBAChC,eAAe,OAAO;AACzB,MACE,MAAM,CAAC,OAAO,MAAM,IAAI,CACtB,CAAC,sBAAsB,kBAAmB,GAC1C,CAAC,eAAe,WAAY,CAC7B,EAED,KAAI,SAAS,UAAU,OAAO,SAAS,MAAM,IAAI,QAAQ,GACvD,OAAM,IAAI,iBACR,eACA,QACC,qCAAqC,OAAO,MAAM,CAAC;CAI1D,MAAM,cAAc,QAAQ,gBAAgB,MAAM,QAAQ,aAAa;CACvE,MAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,UAAU,QAAQ,YAAY;EAC9B,WAAW,QAAQ;EACnB,MAAM,QAAQ;EACd,KAAK,MAAM;GACT,MAAM,UAAU,KAAK,aAAa,EAAE,gBAAgB,CAAC;AACrD,OAAI,eAAe,QAAQ,QAAQ,WAAW,YAC5C,OAAM,IAAI,oBACR,UACC,MAAM,QAAQ,SAAS,iBAAiB,YAAY;AAGzD,OACE,sBAAsB,QACrB,QAAQ,gBAAgB,QAAQ,iBAAkB,MACjD,mBAEF,OAAM,IAAI,oBACR,UACC,OAAO,QAAQ,gBAAgB,iBAAiB,mBAAmB;AAGxE,UAAO;EACR;CACF;AACF;AAED,SAAS,KACPC,OACAC,MACe;CACf,MAAM,gBAAgB,MAAM;CAC5B,MAAM,iBAAiB,KAAK;CAC5B,MAAM,WAAW,MAAM;AACvB,MACG;EAAC;EAAe;EAAgB;CAAS,EAAC,MAAM,CAAC,MAChD,OAAO,SAAS,EAAE,IAAI,KAAK,EAC5B,IAAI,mBAAmB,EAExB,OAAM,IAAI,MAAM;AAElB,QAAO;EACL;EACA;EACA,iBAAiB,KAAK,MAAO,gBAAgB,iBAAkB,IAAK,GAAG;EACvE;CACD;AACF"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@openstatus/health-memory",
3
+ "version": "0.1.4-dev.0",
4
+ "description": "Memory pressure probe for @openstatus/health",
5
+ "keywords": [
6
+ "openstatus",
7
+ "health",
8
+ "healthcheck",
9
+ "memory",
10
+ "heap",
11
+ "rss",
12
+ "system"
13
+ ],
14
+ "license": "MIT",
15
+ "author": {
16
+ "name": "openstatus",
17
+ "url": "https://www.openstatus.dev/"
18
+ },
19
+ "homepage": "https://github.com/openstatusHQ/health",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/openstatusHQ/health.git",
23
+ "directory": "packages/memory/"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/openstatusHQ/health/issues"
27
+ },
28
+ "type": "module",
29
+ "module": "./dist/mod.js",
30
+ "main": "./dist/mod.cjs",
31
+ "types": "./dist/mod.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": {
35
+ "import": "./dist/mod.d.ts",
36
+ "require": "./dist/mod.d.cts"
37
+ },
38
+ "import": "./dist/mod.js",
39
+ "require": "./dist/mod.cjs"
40
+ },
41
+ "./package.json": "./package.json"
42
+ },
43
+ "sideEffects": false,
44
+ "files": [
45
+ "dist/"
46
+ ],
47
+ "engines": {
48
+ "node": ">=22"
49
+ },
50
+ "peerDependencies": {
51
+ "@openstatus/health": "^0.1.4-dev.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": ">=22",
55
+ "tsdown": "^0.12.7",
56
+ "typescript": "^5.8.3"
57
+ },
58
+ "scripts": {
59
+ "build": "tsdown",
60
+ "prepack": "tsdown",
61
+ "test": "node --experimental-transform-types --test"
62
+ }
63
+ }