@dexcost/sdk 0.2.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/LICENSE +21 -0
- package/README.md +210 -0
- package/dist/adapters/_netbytes.d.ts +31 -0
- package/dist/adapters/_netbytes.d.ts.map +1 -0
- package/dist/adapters/_netbytes.js +154 -0
- package/dist/adapters/_netbytes.js.map +1 -0
- package/dist/adapters/aws-lambda.d.ts +41 -0
- package/dist/adapters/aws-lambda.d.ts.map +1 -0
- package/dist/adapters/aws-lambda.js +65 -0
- package/dist/adapters/aws-lambda.js.map +1 -0
- package/dist/adapters/browser.d.ts +52 -0
- package/dist/adapters/browser.d.ts.map +1 -0
- package/dist/adapters/browser.js +127 -0
- package/dist/adapters/browser.js.map +1 -0
- package/dist/adapters/compute-wrap.d.ts +33 -0
- package/dist/adapters/compute-wrap.d.ts.map +1 -0
- package/dist/adapters/compute-wrap.js +188 -0
- package/dist/adapters/compute-wrap.js.map +1 -0
- package/dist/adapters/data/aws_lambda_pricing.json +61 -0
- package/dist/adapters/gpu-wrap.d.ts +31 -0
- package/dist/adapters/gpu-wrap.d.ts.map +1 -0
- package/dist/adapters/gpu-wrap.js +147 -0
- package/dist/adapters/gpu-wrap.js.map +1 -0
- package/dist/adapters/http.d.ts +58 -0
- package/dist/adapters/http.d.ts.map +1 -0
- package/dist/adapters/http.js +769 -0
- package/dist/adapters/http.js.map +1 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +12 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/network-accountant.d.ts +63 -0
- package/dist/adapters/network-accountant.d.ts.map +1 -0
- package/dist/adapters/network-accountant.js +153 -0
- package/dist/adapters/network-accountant.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +225 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/scanner.d.ts +39 -0
- package/dist/cli/scanner.d.ts.map +1 -0
- package/dist/cli/scanner.js +480 -0
- package/dist/cli/scanner.js.map +1 -0
- package/dist/clients.d.ts +54 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +240 -0
- package/dist/clients.js.map +1 -0
- package/dist/cloud-detect.d.ts +96 -0
- package/dist/cloud-detect.d.ts.map +1 -0
- package/dist/cloud-detect.js +545 -0
- package/dist/cloud-detect.js.map +1 -0
- package/dist/core/auto-task.d.ts +20 -0
- package/dist/core/auto-task.d.ts.map +1 -0
- package/dist/core/auto-task.js +34 -0
- package/dist/core/auto-task.js.map +1 -0
- package/dist/core/cgroup-reader.d.ts +45 -0
- package/dist/core/cgroup-reader.d.ts.map +1 -0
- package/dist/core/cgroup-reader.js +124 -0
- package/dist/core/cgroup-reader.js.map +1 -0
- package/dist/core/cgroup-walker.d.ts +60 -0
- package/dist/core/cgroup-walker.d.ts.map +1 -0
- package/dist/core/cgroup-walker.js +166 -0
- package/dist/core/cgroup-walker.js.map +1 -0
- package/dist/core/compute-accountant.d.ts +51 -0
- package/dist/core/compute-accountant.d.ts.map +1 -0
- package/dist/core/compute-accountant.js +179 -0
- package/dist/core/compute-accountant.js.map +1 -0
- package/dist/core/compute-runtime.d.ts +42 -0
- package/dist/core/compute-runtime.d.ts.map +1 -0
- package/dist/core/compute-runtime.js +80 -0
- package/dist/core/compute-runtime.js.map +1 -0
- package/dist/core/config.d.ts +44 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +66 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context.d.ts +76 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +91 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/fargate-metadata.d.ts +27 -0
- package/dist/core/fargate-metadata.d.ts.map +1 -0
- package/dist/core/fargate-metadata.js +102 -0
- package/dist/core/fargate-metadata.js.map +1 -0
- package/dist/core/gpu-accountant.d.ts +104 -0
- package/dist/core/gpu-accountant.d.ts.map +1 -0
- package/dist/core/gpu-accountant.js +383 -0
- package/dist/core/gpu-accountant.js.map +1 -0
- package/dist/core/gpu-runtime.d.ts +58 -0
- package/dist/core/gpu-runtime.d.ts.map +1 -0
- package/dist/core/gpu-runtime.js +131 -0
- package/dist/core/gpu-runtime.js.map +1 -0
- package/dist/core/heuristics.d.ts +74 -0
- package/dist/core/heuristics.d.ts.map +1 -0
- package/dist/core/heuristics.js +182 -0
- package/dist/core/heuristics.js.map +1 -0
- package/dist/core/models.d.ts +149 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +226 -0
- package/dist/core/models.js.map +1 -0
- package/dist/core/nvml-reader.d.ts +114 -0
- package/dist/core/nvml-reader.d.ts.map +1 -0
- package/dist/core/nvml-reader.js +323 -0
- package/dist/core/nvml-reader.js.map +1 -0
- package/dist/core/session.d.ts +48 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +123 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/tracker.d.ts +364 -0
- package/dist/core/tracker.d.ts.map +1 -0
- package/dist/core/tracker.js +1073 -0
- package/dist/core/tracker.js.map +1 -0
- package/dist/data/compute_prices.json +180 -0
- package/dist/data/egress_prices.json +418 -0
- package/dist/data/gpu_prices.json +412 -0
- package/dist/data/service_prices.json +2595 -0
- package/dist/dev-console.d.ts +12 -0
- package/dist/dev-console.d.ts.map +1 -0
- package/dist/dev-console.js +60 -0
- package/dist/dev-console.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/instruments/anthropic.d.ts +26 -0
- package/dist/instruments/anthropic.d.ts.map +1 -0
- package/dist/instruments/anthropic.js +242 -0
- package/dist/instruments/anthropic.js.map +1 -0
- package/dist/instruments/bedrock.d.ts +29 -0
- package/dist/instruments/bedrock.d.ts.map +1 -0
- package/dist/instruments/bedrock.js +215 -0
- package/dist/instruments/bedrock.js.map +1 -0
- package/dist/instruments/cohere.d.ts +29 -0
- package/dist/instruments/cohere.d.ts.map +1 -0
- package/dist/instruments/cohere.js +237 -0
- package/dist/instruments/cohere.js.map +1 -0
- package/dist/instruments/gemini.d.ts +30 -0
- package/dist/instruments/gemini.d.ts.map +1 -0
- package/dist/instruments/gemini.js +247 -0
- package/dist/instruments/gemini.js.map +1 -0
- package/dist/instruments/index.d.ts +35 -0
- package/dist/instruments/index.d.ts.map +1 -0
- package/dist/instruments/index.js +54 -0
- package/dist/instruments/index.js.map +1 -0
- package/dist/instruments/mcp.d.ts +24 -0
- package/dist/instruments/mcp.d.ts.map +1 -0
- package/dist/instruments/mcp.js +459 -0
- package/dist/instruments/mcp.js.map +1 -0
- package/dist/instruments/openai.d.ts +26 -0
- package/dist/instruments/openai.d.ts.map +1 -0
- package/dist/instruments/openai.js +221 -0
- package/dist/instruments/openai.js.map +1 -0
- package/dist/instruments/vercel-ai.d.ts +28 -0
- package/dist/instruments/vercel-ai.d.ts.map +1 -0
- package/dist/instruments/vercel-ai.js +192 -0
- package/dist/instruments/vercel-ai.js.map +1 -0
- package/dist/integrations/langchain.d.ts +65 -0
- package/dist/integrations/langchain.d.ts.map +1 -0
- package/dist/integrations/langchain.js +165 -0
- package/dist/integrations/langchain.js.map +1 -0
- package/dist/middleware/express.d.ts +55 -0
- package/dist/middleware/express.d.ts.map +1 -0
- package/dist/middleware/express.js +101 -0
- package/dist/middleware/express.js.map +1 -0
- package/dist/middleware/index.d.ts +6 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +5 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/pricing/compute-pricing.d.ts +57 -0
- package/dist/pricing/compute-pricing.d.ts.map +1 -0
- package/dist/pricing/compute-pricing.js +627 -0
- package/dist/pricing/compute-pricing.js.map +1 -0
- package/dist/pricing/cost_map.json +37665 -0
- package/dist/pricing/egress-pricing.d.ts +55 -0
- package/dist/pricing/egress-pricing.d.ts.map +1 -0
- package/dist/pricing/egress-pricing.js +226 -0
- package/dist/pricing/egress-pricing.js.map +1 -0
- package/dist/pricing/engine.d.ts +24 -0
- package/dist/pricing/engine.d.ts.map +1 -0
- package/dist/pricing/engine.js +148 -0
- package/dist/pricing/engine.js.map +1 -0
- package/dist/pricing/gpu-pricing.d.ts +63 -0
- package/dist/pricing/gpu-pricing.d.ts.map +1 -0
- package/dist/pricing/gpu-pricing.js +484 -0
- package/dist/pricing/gpu-pricing.js.map +1 -0
- package/dist/pricing/rates.d.ts +17 -0
- package/dist/pricing/rates.d.ts.map +1 -0
- package/dist/pricing/rates.js +102 -0
- package/dist/pricing/rates.js.map +1 -0
- package/dist/pricing/service-catalog.d.ts +87 -0
- package/dist/pricing/service-catalog.d.ts.map +1 -0
- package/dist/pricing/service-catalog.js +406 -0
- package/dist/pricing/service-catalog.js.map +1 -0
- package/dist/schema/dexcost-event.v1.json +111 -0
- package/dist/schema/dexcost-task.v1.json +160 -0
- package/dist/schema/validate.d.ts +15 -0
- package/dist/schema/validate.d.ts.map +1 -0
- package/dist/schema/validate.js +87 -0
- package/dist/schema/validate.js.map +1 -0
- package/dist/security/redaction.d.ts +55 -0
- package/dist/security/redaction.d.ts.map +1 -0
- package/dist/security/redaction.js +144 -0
- package/dist/security/redaction.js.map +1 -0
- package/dist/transport/buffer.d.ts +117 -0
- package/dist/transport/buffer.d.ts.map +1 -0
- package/dist/transport/buffer.js +759 -0
- package/dist/transport/buffer.js.map +1 -0
- package/dist/transport/pusher.d.ts +89 -0
- package/dist/transport/pusher.d.ts.map +1 -0
- package/dist/transport/pusher.js +323 -0
- package/dist/transport/pusher.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cgroup v2 file readers (node-only, browser-safe).
|
|
3
|
+
*
|
|
4
|
+
* Fail-silent contract (convention §9): every read returns `null` on missing
|
|
5
|
+
* or malformed input. Non-Linux hosts, cgroup-v1 kernels, browsers, and
|
|
6
|
+
* containers without a cgroup mount all silently return `null` — the caller
|
|
7
|
+
* decides the fallback.
|
|
8
|
+
*
|
|
9
|
+
* Backed file layouts (all under `/sys/fs/cgroup/`):
|
|
10
|
+
*
|
|
11
|
+
* - `cpu.stat` — multi-line; `usage_usec <N>` is the cumulative CPU
|
|
12
|
+
* time consumed (microseconds). Read at task start +
|
|
13
|
+
* end to compute vcpu-seconds for long-running runtimes.
|
|
14
|
+
* - `cpu.max` — single line `<quota|"max"> <period>` (both in
|
|
15
|
+
* microseconds). `quota/period` is the vCPU count
|
|
16
|
+
* enforced on this cgroup; `"max"` means no limit
|
|
17
|
+
* (fall back to `os.cpus().length`).
|
|
18
|
+
* - `memory.peak` — single integer (bytes); the high-water mark since
|
|
19
|
+
* cgroup creation. Available on kernels >= 5.19;
|
|
20
|
+
* absent otherwise.
|
|
21
|
+
* - `memory.max` — single integer (bytes) or `"max"` (unlimited).
|
|
22
|
+
* - `memory.current` — single integer (bytes); the current RSS.
|
|
23
|
+
*
|
|
24
|
+
* Mirrors `python/src/dexcost/cgroup_reader.py`.
|
|
25
|
+
*/
|
|
26
|
+
export interface CpuStat {
|
|
27
|
+
/** Cumulative CPU time consumed (microseconds). */
|
|
28
|
+
usageUsec: number;
|
|
29
|
+
}
|
|
30
|
+
export interface CpuMax {
|
|
31
|
+
/** Period quota in microseconds, or `null` when cgroup is unlimited. */
|
|
32
|
+
quotaUs: number | null;
|
|
33
|
+
/** Period length in microseconds. */
|
|
34
|
+
periodUs: number;
|
|
35
|
+
/** Computed `quotaUs / periodUs`; `os.cpus().length` when unlimited. */
|
|
36
|
+
vcpuCount: number;
|
|
37
|
+
}
|
|
38
|
+
/** Test-only — override the cgroup root. Pass `null` to restore default. */
|
|
39
|
+
export declare function _setCgroupRootForTests(p: string | null): void;
|
|
40
|
+
export declare function readCpuStat(): CpuStat | null;
|
|
41
|
+
export declare function readCpuMax(): CpuMax | null;
|
|
42
|
+
export declare function readMemoryPeak(): number | null;
|
|
43
|
+
export declare function readMemoryMax(): number | null;
|
|
44
|
+
export declare function readMemoryCurrent(): number | null;
|
|
45
|
+
//# sourceMappingURL=cgroup-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cgroup-reader.d.ts","sourceRoot":"","sources":["../../src/core/cgroup-reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAMH,MAAM,WAAW,OAAO;IACtB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,MAAM;IACrB,wEAAwE;IACxE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,4EAA4E;AAC5E,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE7D;AA0BD,wBAAgB,WAAW,IAAI,OAAO,GAAG,IAAI,CAe5C;AAED,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAkB1C;AAED,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAG9C;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAG7C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAGjD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cgroup v2 file readers (node-only, browser-safe).
|
|
3
|
+
*
|
|
4
|
+
* Fail-silent contract (convention §9): every read returns `null` on missing
|
|
5
|
+
* or malformed input. Non-Linux hosts, cgroup-v1 kernels, browsers, and
|
|
6
|
+
* containers without a cgroup mount all silently return `null` — the caller
|
|
7
|
+
* decides the fallback.
|
|
8
|
+
*
|
|
9
|
+
* Backed file layouts (all under `/sys/fs/cgroup/`):
|
|
10
|
+
*
|
|
11
|
+
* - `cpu.stat` — multi-line; `usage_usec <N>` is the cumulative CPU
|
|
12
|
+
* time consumed (microseconds). Read at task start +
|
|
13
|
+
* end to compute vcpu-seconds for long-running runtimes.
|
|
14
|
+
* - `cpu.max` — single line `<quota|"max"> <period>` (both in
|
|
15
|
+
* microseconds). `quota/period` is the vCPU count
|
|
16
|
+
* enforced on this cgroup; `"max"` means no limit
|
|
17
|
+
* (fall back to `os.cpus().length`).
|
|
18
|
+
* - `memory.peak` — single integer (bytes); the high-water mark since
|
|
19
|
+
* cgroup creation. Available on kernels >= 5.19;
|
|
20
|
+
* absent otherwise.
|
|
21
|
+
* - `memory.max` — single integer (bytes) or `"max"` (unlimited).
|
|
22
|
+
* - `memory.current` — single integer (bytes); the current RSS.
|
|
23
|
+
*
|
|
24
|
+
* Mirrors `python/src/dexcost/cgroup_reader.py`.
|
|
25
|
+
*/
|
|
26
|
+
import { readFileSync } from "node:fs";
|
|
27
|
+
import { join } from "node:path";
|
|
28
|
+
import { cpus } from "node:os";
|
|
29
|
+
let _cgroupRoot = "/sys/fs/cgroup";
|
|
30
|
+
/** Test-only — override the cgroup root. Pass `null` to restore default. */
|
|
31
|
+
export function _setCgroupRootForTests(p) {
|
|
32
|
+
_cgroupRoot = p ?? "/sys/fs/cgroup";
|
|
33
|
+
}
|
|
34
|
+
function _isNode() {
|
|
35
|
+
return typeof process !== "undefined" && !!process.versions?.node;
|
|
36
|
+
}
|
|
37
|
+
function _readText(name) {
|
|
38
|
+
if (!_isNode())
|
|
39
|
+
return null;
|
|
40
|
+
try {
|
|
41
|
+
return readFileSync(join(_cgroupRoot, name), "utf-8");
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function _readInt(name) {
|
|
48
|
+
const raw = _readText(name);
|
|
49
|
+
if (raw === null)
|
|
50
|
+
return null;
|
|
51
|
+
const trimmed = raw.trim();
|
|
52
|
+
if (trimmed === "max")
|
|
53
|
+
return null;
|
|
54
|
+
const n = Number(trimmed);
|
|
55
|
+
if (!Number.isFinite(n) || Number.isNaN(n))
|
|
56
|
+
return null;
|
|
57
|
+
if (!/^-?\d+$/.test(trimmed))
|
|
58
|
+
return null;
|
|
59
|
+
return n;
|
|
60
|
+
}
|
|
61
|
+
export function readCpuStat() {
|
|
62
|
+
if (!_isNode())
|
|
63
|
+
return null;
|
|
64
|
+
const raw = _readText("cpu.stat");
|
|
65
|
+
if (raw === null)
|
|
66
|
+
return null;
|
|
67
|
+
for (const line of raw.split("\n")) {
|
|
68
|
+
if (line.startsWith("usage_usec ")) {
|
|
69
|
+
const parts = line.split(/\s+/);
|
|
70
|
+
if (parts.length < 2)
|
|
71
|
+
return null;
|
|
72
|
+
const n = Number(parts[1]);
|
|
73
|
+
if (!Number.isFinite(n) || Number.isNaN(n))
|
|
74
|
+
return null;
|
|
75
|
+
if (!/^-?\d+$/.test(parts[1]))
|
|
76
|
+
return null;
|
|
77
|
+
return { usageUsec: n };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
export function readCpuMax() {
|
|
83
|
+
if (!_isNode())
|
|
84
|
+
return null;
|
|
85
|
+
const raw = _readText("cpu.max");
|
|
86
|
+
if (raw === null)
|
|
87
|
+
return null;
|
|
88
|
+
const parts = raw.trim().split(/\s+/);
|
|
89
|
+
if (parts.length !== 2)
|
|
90
|
+
return null;
|
|
91
|
+
const periodUs = Number(parts[1]);
|
|
92
|
+
if (!Number.isFinite(periodUs) || Number.isNaN(periodUs))
|
|
93
|
+
return null;
|
|
94
|
+
if (!/^-?\d+$/.test(parts[1]))
|
|
95
|
+
return null;
|
|
96
|
+
if (periodUs <= 0)
|
|
97
|
+
return null;
|
|
98
|
+
if (parts[0] === "max") {
|
|
99
|
+
const n = cpus().length || 1;
|
|
100
|
+
return { quotaUs: null, periodUs, vcpuCount: n };
|
|
101
|
+
}
|
|
102
|
+
const quotaUs = Number(parts[0]);
|
|
103
|
+
if (!Number.isFinite(quotaUs) || Number.isNaN(quotaUs))
|
|
104
|
+
return null;
|
|
105
|
+
if (!/^-?\d+$/.test(parts[0]))
|
|
106
|
+
return null;
|
|
107
|
+
return { quotaUs, periodUs, vcpuCount: quotaUs / periodUs };
|
|
108
|
+
}
|
|
109
|
+
export function readMemoryPeak() {
|
|
110
|
+
if (!_isNode())
|
|
111
|
+
return null;
|
|
112
|
+
return _readInt("memory.peak");
|
|
113
|
+
}
|
|
114
|
+
export function readMemoryMax() {
|
|
115
|
+
if (!_isNode())
|
|
116
|
+
return null;
|
|
117
|
+
return _readInt("memory.max");
|
|
118
|
+
}
|
|
119
|
+
export function readMemoryCurrent() {
|
|
120
|
+
if (!_isNode())
|
|
121
|
+
return null;
|
|
122
|
+
return _readInt("memory.current");
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=cgroup-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cgroup-reader.js","sourceRoot":"","sources":["../../src/core/cgroup-reader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cgroup-scope classifier — Phase 2 GPU foundation Decision #1.
|
|
3
|
+
*
|
|
4
|
+
* Reads `/proc/self/cgroup` and classifies the cgroup scope by prefix into
|
|
5
|
+
* one of:
|
|
6
|
+
*
|
|
7
|
+
* - "container" — kubepods.slice / docker / containerd / crio /
|
|
8
|
+
* system.slice/{docker,containerd,crio}-.
|
|
9
|
+
* cgroup.procs enumerates the container's PIDs.
|
|
10
|
+
* - "bare_metal_user_slice" — `/user.slice/...` (systemd user session).
|
|
11
|
+
* Walking would capture every PID in the SSH
|
|
12
|
+
* session, not just dexcost's task. Degrade to
|
|
13
|
+
* self-PID-only at `estimated` confidence with
|
|
14
|
+
* pricing_source suffix :no_container_scope.
|
|
15
|
+
* - "root_cgroup" — `/` (privileged single-tenant host). Ambiguous;
|
|
16
|
+
* degrade to self-PID-only.
|
|
17
|
+
* - "cgroup_v1" — multi-line file (multiple v1 controllers).
|
|
18
|
+
* v1.1 will walk; v1 degrades to self-PID-only.
|
|
19
|
+
* - "unknown" — anything else.
|
|
20
|
+
*
|
|
21
|
+
* **Browser safety**: returns "unknown" off-Node.
|
|
22
|
+
*
|
|
23
|
+
* Mirrors python/src/dexcost/cgroup_walker.py.
|
|
24
|
+
*/
|
|
25
|
+
/** Test-only — override /proc/self/cgroup path. Pass null to restore. */
|
|
26
|
+
export declare function _setProcSelfCgroupPathForTests(p: string | null): void;
|
|
27
|
+
/** Test-only — override the cgroup root. Pass null to restore. */
|
|
28
|
+
export declare function _setCgroupRootForTests(p: string | null): void;
|
|
29
|
+
export declare function _resetWarningStateForTests(): void;
|
|
30
|
+
export type CgroupScopeKind = "container" | "bare_metal_user_slice" | "root_cgroup" | "cgroup_v1" | "unknown";
|
|
31
|
+
export interface CgroupScope {
|
|
32
|
+
kind: CgroupScopeKind;
|
|
33
|
+
/** Unified cgroup-v2 path for `container` scope; null for every other kind. */
|
|
34
|
+
path: string | null;
|
|
35
|
+
}
|
|
36
|
+
export declare function classifyScope(): CgroupScope;
|
|
37
|
+
/**
|
|
38
|
+
* Return the PID set to attribute GPU usage to.
|
|
39
|
+
*
|
|
40
|
+
* - container scope → walk `<cgroupRoot><scope.path>/cgroup.procs`. Returns
|
|
41
|
+
* `null` (NOT empty list) on read failure — signals the caller to log-
|
|
42
|
+
* once `gpu_cgroup_walk_forbidden` and fall back.
|
|
43
|
+
* - every other scope → return `[process.pid]`. Bare-metal-no-container
|
|
44
|
+
* deliberately does NOT walk the systemd user slice (which would capture
|
|
45
|
+
* unrelated user PIDs — the silent-overcount case).
|
|
46
|
+
*
|
|
47
|
+
* Off-Node, returns `[1]` as a non-failing placeholder (matches Python
|
|
48
|
+
* semantics where `os.getpid()` is always available in CPython; in TS the
|
|
49
|
+
* browser doesn't have a PID so we surface a benign sentinel).
|
|
50
|
+
*/
|
|
51
|
+
export declare function enumeratePids(scope: CgroupScope): number[] | null;
|
|
52
|
+
/**
|
|
53
|
+
* Map scope kind to the pricing_source suffix per Decision #1.
|
|
54
|
+
*
|
|
55
|
+
* - container → null (full-fidelity attribution; no suffix)
|
|
56
|
+
* - bare_metal_user_slice / root_cgroup → "no_container_scope"
|
|
57
|
+
* - cgroup_v1 / unknown → "self_pid_only"
|
|
58
|
+
*/
|
|
59
|
+
export declare function fallbackLabelFor(scope: CgroupScope): string | null;
|
|
60
|
+
//# sourceMappingURL=cgroup-walker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cgroup-walker.d.ts","sourceRoot":"","sources":["../../src/core/cgroup-walker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAUH,yEAAyE;AACzE,wBAAgB,8BAA8B,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAErE;AAED,kEAAkE;AAClE,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE7D;AAMD,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAkCD,MAAM,MAAM,eAAe,GACvB,WAAW,GACX,uBAAuB,GACvB,aAAa,GACb,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAID,wBAAgB,aAAa,IAAI,WAAW,CAwC3C;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,IAAI,CA6BjE;AAID;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAMlE"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cgroup-scope classifier — Phase 2 GPU foundation Decision #1.
|
|
3
|
+
*
|
|
4
|
+
* Reads `/proc/self/cgroup` and classifies the cgroup scope by prefix into
|
|
5
|
+
* one of:
|
|
6
|
+
*
|
|
7
|
+
* - "container" — kubepods.slice / docker / containerd / crio /
|
|
8
|
+
* system.slice/{docker,containerd,crio}-.
|
|
9
|
+
* cgroup.procs enumerates the container's PIDs.
|
|
10
|
+
* - "bare_metal_user_slice" — `/user.slice/...` (systemd user session).
|
|
11
|
+
* Walking would capture every PID in the SSH
|
|
12
|
+
* session, not just dexcost's task. Degrade to
|
|
13
|
+
* self-PID-only at `estimated` confidence with
|
|
14
|
+
* pricing_source suffix :no_container_scope.
|
|
15
|
+
* - "root_cgroup" — `/` (privileged single-tenant host). Ambiguous;
|
|
16
|
+
* degrade to self-PID-only.
|
|
17
|
+
* - "cgroup_v1" — multi-line file (multiple v1 controllers).
|
|
18
|
+
* v1.1 will walk; v1 degrades to self-PID-only.
|
|
19
|
+
* - "unknown" — anything else.
|
|
20
|
+
*
|
|
21
|
+
* **Browser safety**: returns "unknown" off-Node.
|
|
22
|
+
*
|
|
23
|
+
* Mirrors python/src/dexcost/cgroup_walker.py.
|
|
24
|
+
*/
|
|
25
|
+
import { readFileSync } from "node:fs";
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
// ─── Module state (testable) ────────────────────────────────────────────────
|
|
28
|
+
let _procSelfCgroupPath = "/proc/self/cgroup";
|
|
29
|
+
let _cgroupRoot = "/sys/fs/cgroup";
|
|
30
|
+
/** Test-only — override /proc/self/cgroup path. Pass null to restore. */
|
|
31
|
+
export function _setProcSelfCgroupPathForTests(p) {
|
|
32
|
+
_procSelfCgroupPath = p ?? "/proc/self/cgroup";
|
|
33
|
+
}
|
|
34
|
+
/** Test-only — override the cgroup root. Pass null to restore. */
|
|
35
|
+
export function _setCgroupRootForTests(p) {
|
|
36
|
+
_cgroupRoot = p ?? "/sys/fs/cgroup";
|
|
37
|
+
}
|
|
38
|
+
// ─── Warn-once state ────────────────────────────────────────────────────────
|
|
39
|
+
const _warnedModes = new Set();
|
|
40
|
+
export function _resetWarningStateForTests() {
|
|
41
|
+
_warnedModes.clear();
|
|
42
|
+
}
|
|
43
|
+
function _warnOnce(mode, message) {
|
|
44
|
+
if (_warnedModes.has(mode))
|
|
45
|
+
return;
|
|
46
|
+
_warnedModes.add(mode);
|
|
47
|
+
// eslint-disable-next-line no-console
|
|
48
|
+
console.warn(message);
|
|
49
|
+
}
|
|
50
|
+
// ─── Browser-safety guard ───────────────────────────────────────────────────
|
|
51
|
+
function _isNode() {
|
|
52
|
+
return typeof process !== "undefined" && !!process.versions?.node;
|
|
53
|
+
}
|
|
54
|
+
// ─── Decision #1 prefix table (priority order) ──────────────────────────────
|
|
55
|
+
const CONTAINER_PREFIXES = [
|
|
56
|
+
"/kubepods.slice/",
|
|
57
|
+
"/kubepods/",
|
|
58
|
+
"/docker/",
|
|
59
|
+
"/system.slice/docker-",
|
|
60
|
+
"/containerd/",
|
|
61
|
+
"/system.slice/containerd-",
|
|
62
|
+
"/crio/",
|
|
63
|
+
"/system.slice/crio-",
|
|
64
|
+
];
|
|
65
|
+
const BARE_METAL_PREFIXES = [
|
|
66
|
+
"/user.slice/",
|
|
67
|
+
];
|
|
68
|
+
// ─── Classification ─────────────────────────────────────────────────────────
|
|
69
|
+
export function classifyScope() {
|
|
70
|
+
if (!_isNode()) {
|
|
71
|
+
return { kind: "unknown", path: null };
|
|
72
|
+
}
|
|
73
|
+
let raw;
|
|
74
|
+
try {
|
|
75
|
+
raw = readFileSync(_procSelfCgroupPath, "utf-8");
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return { kind: "unknown", path: null };
|
|
79
|
+
}
|
|
80
|
+
const lines = raw
|
|
81
|
+
.split("\n")
|
|
82
|
+
.map((l) => l.trim())
|
|
83
|
+
.filter((l) => l.length > 0);
|
|
84
|
+
if (lines.length === 0) {
|
|
85
|
+
return { kind: "unknown", path: null };
|
|
86
|
+
}
|
|
87
|
+
// cgroup v1 → multiple controller lines; cgroup v2 → single "0::/path".
|
|
88
|
+
if (lines.length > 1 || !lines[0].startsWith("0::")) {
|
|
89
|
+
return { kind: "cgroup_v1", path: null };
|
|
90
|
+
}
|
|
91
|
+
const path = lines[0].substring(3); // strip "0::" prefix
|
|
92
|
+
if (path === "/" || path === "") {
|
|
93
|
+
return { kind: "root_cgroup", path: null };
|
|
94
|
+
}
|
|
95
|
+
for (const prefix of CONTAINER_PREFIXES) {
|
|
96
|
+
if (path.startsWith(prefix)) {
|
|
97
|
+
return { kind: "container", path };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
for (const prefix of BARE_METAL_PREFIXES) {
|
|
101
|
+
if (path.startsWith(prefix)) {
|
|
102
|
+
return { kind: "bare_metal_user_slice", path: null };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return { kind: "unknown", path: null };
|
|
106
|
+
}
|
|
107
|
+
// ─── PID enumeration ────────────────────────────────────────────────────────
|
|
108
|
+
/**
|
|
109
|
+
* Return the PID set to attribute GPU usage to.
|
|
110
|
+
*
|
|
111
|
+
* - container scope → walk `<cgroupRoot><scope.path>/cgroup.procs`. Returns
|
|
112
|
+
* `null` (NOT empty list) on read failure — signals the caller to log-
|
|
113
|
+
* once `gpu_cgroup_walk_forbidden` and fall back.
|
|
114
|
+
* - every other scope → return `[process.pid]`. Bare-metal-no-container
|
|
115
|
+
* deliberately does NOT walk the systemd user slice (which would capture
|
|
116
|
+
* unrelated user PIDs — the silent-overcount case).
|
|
117
|
+
*
|
|
118
|
+
* Off-Node, returns `[1]` as a non-failing placeholder (matches Python
|
|
119
|
+
* semantics where `os.getpid()` is always available in CPython; in TS the
|
|
120
|
+
* browser doesn't have a PID so we surface a benign sentinel).
|
|
121
|
+
*/
|
|
122
|
+
export function enumeratePids(scope) {
|
|
123
|
+
if (!_isNode()) {
|
|
124
|
+
return [1];
|
|
125
|
+
}
|
|
126
|
+
if (scope.kind !== "container" || scope.path === null) {
|
|
127
|
+
return [process.pid];
|
|
128
|
+
}
|
|
129
|
+
const cgroupProcsPath = join(_cgroupRoot + scope.path, "cgroup.procs");
|
|
130
|
+
let raw;
|
|
131
|
+
try {
|
|
132
|
+
raw = readFileSync(cgroupProcsPath, "utf-8");
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
_warnOnce("gpu_cgroup_walk_forbidden", `Could not read ${cgroupProcsPath} (${String(err)}); ` +
|
|
136
|
+
`GpuAccountant will degrade to self-PID-only`);
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
const pids = [];
|
|
140
|
+
for (const line of raw.split("\n")) {
|
|
141
|
+
const s = line.trim();
|
|
142
|
+
if (!s)
|
|
143
|
+
continue;
|
|
144
|
+
const n = parseInt(s, 10);
|
|
145
|
+
if (!Number.isNaN(n))
|
|
146
|
+
pids.push(n);
|
|
147
|
+
}
|
|
148
|
+
return pids;
|
|
149
|
+
}
|
|
150
|
+
// ─── Decision #1 confidence labelling ───────────────────────────────────────
|
|
151
|
+
/**
|
|
152
|
+
* Map scope kind to the pricing_source suffix per Decision #1.
|
|
153
|
+
*
|
|
154
|
+
* - container → null (full-fidelity attribution; no suffix)
|
|
155
|
+
* - bare_metal_user_slice / root_cgroup → "no_container_scope"
|
|
156
|
+
* - cgroup_v1 / unknown → "self_pid_only"
|
|
157
|
+
*/
|
|
158
|
+
export function fallbackLabelFor(scope) {
|
|
159
|
+
if (scope.kind === "container")
|
|
160
|
+
return null;
|
|
161
|
+
if (scope.kind === "bare_metal_user_slice" || scope.kind === "root_cgroup") {
|
|
162
|
+
return "no_container_scope";
|
|
163
|
+
}
|
|
164
|
+
return "self_pid_only";
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=cgroup-walker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cgroup-walker.js","sourceRoot":"","sources":["../../src/core/cgroup-walker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-task compute accountant.
|
|
3
|
+
*
|
|
4
|
+
* Holds start cgroup snapshot + runtime context for one dexcost task. At
|
|
5
|
+
* task finalize, emits exactly one `compute_cost` event with
|
|
6
|
+
* `cost_pending: true` — the pricing engine back-fills `cost_usd` via the
|
|
7
|
+
* deferred-cost pattern inherited from network v2 §6.4.
|
|
8
|
+
*
|
|
9
|
+
* Capture §5.3 invariant: at most one event per task per runtime. Idempotent —
|
|
10
|
+
* second call to snapshotEndAndBuild / buildServerlessEvent returns null.
|
|
11
|
+
*
|
|
12
|
+
* TS is single-threaded → freeze flag is sufficient, no mutex needed.
|
|
13
|
+
*
|
|
14
|
+
* Mirrors python/src/dexcost/compute_accountant.py.
|
|
15
|
+
*/
|
|
16
|
+
import { RuntimeKind } from "./compute-runtime.js";
|
|
17
|
+
export interface ComputeAccountantOptions {
|
|
18
|
+
runtime: RuntimeKind;
|
|
19
|
+
lambdaMemoryMb?: number;
|
|
20
|
+
fargateVcpu?: number;
|
|
21
|
+
fargateMemoryMib?: number;
|
|
22
|
+
architecture?: string;
|
|
23
|
+
initializationType?: string;
|
|
24
|
+
region?: string;
|
|
25
|
+
}
|
|
26
|
+
export declare class ComputeAccountant {
|
|
27
|
+
private _frozen;
|
|
28
|
+
private _startCpuUsec;
|
|
29
|
+
readonly runtime: RuntimeKind;
|
|
30
|
+
readonly lambdaMemoryMb: number | undefined;
|
|
31
|
+
readonly fargateVcpu: number | undefined;
|
|
32
|
+
readonly fargateMemoryMib: number | undefined;
|
|
33
|
+
readonly architecture: string;
|
|
34
|
+
readonly initializationType: string | undefined;
|
|
35
|
+
readonly region: string | undefined;
|
|
36
|
+
constructor(opts: ComputeAccountantOptions);
|
|
37
|
+
/** Capture the cgroup CPU counter at task start. Idempotent. */
|
|
38
|
+
snapshotStart(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Capture cgroup CPU/memory at task end and build the event details.
|
|
41
|
+
*
|
|
42
|
+
* Returns null if already frozen (second call) or runtime is unknown.
|
|
43
|
+
*/
|
|
44
|
+
snapshotEndAndBuild(durationMs: number): Record<string, any> | null;
|
|
45
|
+
/**
|
|
46
|
+
* Build a per-invocation event for Lambda / Cloud Run / Cloud Functions /
|
|
47
|
+
* Azure Functions / Vercel.
|
|
48
|
+
*/
|
|
49
|
+
buildServerlessEvent(durationMs: number, memoryBytesPeak: number): Record<string, any> | null;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=compute-accountant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-accountant.d.ts","sourceRoot":"","sources":["../../src/core/compute-accountant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAyCnD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,WAAW,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAuB;IAE5C,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAExB,IAAI,EAAE,wBAAwB;IAe1C,gEAAgE;IAChE,aAAa,IAAI,IAAI;IAMrB;;;;OAIG;IACH,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAwCnE;;;OAGG;IACH,oBAAoB,CAClB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,GACtB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;CAmC9B"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-task compute accountant.
|
|
3
|
+
*
|
|
4
|
+
* Holds start cgroup snapshot + runtime context for one dexcost task. At
|
|
5
|
+
* task finalize, emits exactly one `compute_cost` event with
|
|
6
|
+
* `cost_pending: true` — the pricing engine back-fills `cost_usd` via the
|
|
7
|
+
* deferred-cost pattern inherited from network v2 §6.4.
|
|
8
|
+
*
|
|
9
|
+
* Capture §5.3 invariant: at most one event per task per runtime. Idempotent —
|
|
10
|
+
* second call to snapshotEndAndBuild / buildServerlessEvent returns null.
|
|
11
|
+
*
|
|
12
|
+
* TS is single-threaded → freeze flag is sufficient, no mutex needed.
|
|
13
|
+
*
|
|
14
|
+
* Mirrors python/src/dexcost/compute_accountant.py.
|
|
15
|
+
*/
|
|
16
|
+
import { cpus } from "node:os";
|
|
17
|
+
import { readCpuMax, readCpuStat, readMemoryCurrent, readMemoryMax, readMemoryPeak, } from "./cgroup-reader.js";
|
|
18
|
+
import { RuntimeKind } from "./compute-runtime.js";
|
|
19
|
+
/** Map a RuntimeKind to the details.billing_model discriminator. */
|
|
20
|
+
function billingModelFor(runtime) {
|
|
21
|
+
switch (runtime) {
|
|
22
|
+
case RuntimeKind.Lambda:
|
|
23
|
+
return "lambda";
|
|
24
|
+
case RuntimeKind.Fargate:
|
|
25
|
+
return "fargate";
|
|
26
|
+
case RuntimeKind.Ec2:
|
|
27
|
+
return "ec2";
|
|
28
|
+
case RuntimeKind.Gce:
|
|
29
|
+
return "gce";
|
|
30
|
+
case RuntimeKind.AzureVm:
|
|
31
|
+
return "azure_vm";
|
|
32
|
+
case RuntimeKind.CloudRun:
|
|
33
|
+
return "cloud_run_request";
|
|
34
|
+
case RuntimeKind.CloudFunctions:
|
|
35
|
+
return "cloud_functions";
|
|
36
|
+
case RuntimeKind.AzureFunctions:
|
|
37
|
+
return "azure_functions";
|
|
38
|
+
case RuntimeKind.Vercel:
|
|
39
|
+
return "vercel_fluid";
|
|
40
|
+
case RuntimeKind.K8sPod:
|
|
41
|
+
return "k8s_pod";
|
|
42
|
+
default:
|
|
43
|
+
return "unknown";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function _isNode() {
|
|
47
|
+
return typeof process !== "undefined" && !!process.versions?.node;
|
|
48
|
+
}
|
|
49
|
+
function detectArch() {
|
|
50
|
+
if (!_isNode())
|
|
51
|
+
return "x86_64";
|
|
52
|
+
const a = process.arch;
|
|
53
|
+
if (a === "arm64" || a === "arm")
|
|
54
|
+
return "arm64";
|
|
55
|
+
return "x86_64";
|
|
56
|
+
}
|
|
57
|
+
export class ComputeAccountant {
|
|
58
|
+
_frozen = false;
|
|
59
|
+
_startCpuUsec = null;
|
|
60
|
+
runtime;
|
|
61
|
+
lambdaMemoryMb;
|
|
62
|
+
fargateVcpu;
|
|
63
|
+
fargateMemoryMib;
|
|
64
|
+
architecture;
|
|
65
|
+
initializationType;
|
|
66
|
+
region;
|
|
67
|
+
constructor(opts) {
|
|
68
|
+
this.runtime = opts.runtime;
|
|
69
|
+
this.lambdaMemoryMb = opts.lambdaMemoryMb;
|
|
70
|
+
this.fargateVcpu = opts.fargateVcpu;
|
|
71
|
+
this.fargateMemoryMib = opts.fargateMemoryMib;
|
|
72
|
+
this.architecture = opts.architecture ?? detectArch();
|
|
73
|
+
this.initializationType = opts.initializationType;
|
|
74
|
+
this.region = opts.region;
|
|
75
|
+
}
|
|
76
|
+
// ------------------------------------------------------------------
|
|
77
|
+
// Long-running runtimes (Fargate / EC2 / GCE / Azure VM / K8s pod /
|
|
78
|
+
// Cloud Run instance-based)
|
|
79
|
+
// ------------------------------------------------------------------
|
|
80
|
+
/** Capture the cgroup CPU counter at task start. Idempotent. */
|
|
81
|
+
snapshotStart() {
|
|
82
|
+
if (this._startCpuUsec !== null)
|
|
83
|
+
return;
|
|
84
|
+
const s = readCpuStat();
|
|
85
|
+
this._startCpuUsec = s ? s.usageUsec : 0;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Capture cgroup CPU/memory at task end and build the event details.
|
|
89
|
+
*
|
|
90
|
+
* Returns null if already frozen (second call) or runtime is unknown.
|
|
91
|
+
*/
|
|
92
|
+
snapshotEndAndBuild(durationMs) {
|
|
93
|
+
if (this._frozen)
|
|
94
|
+
return null;
|
|
95
|
+
this._frozen = true;
|
|
96
|
+
const startCpu = this._startCpuUsec ?? 0;
|
|
97
|
+
const end = readCpuStat();
|
|
98
|
+
const cpuMax = readCpuMax();
|
|
99
|
+
// Capture §6 case 6 — memory.peak missing → fall back to memory.current.
|
|
100
|
+
let memPeak = readMemoryPeak();
|
|
101
|
+
if (memPeak === null) {
|
|
102
|
+
memPeak = readMemoryCurrent() ?? 0;
|
|
103
|
+
}
|
|
104
|
+
const memLimit = readMemoryMax() ?? 0;
|
|
105
|
+
let vcpuSecondsUsed = 0;
|
|
106
|
+
if (end !== null && end.usageUsec >= startCpu) {
|
|
107
|
+
vcpuSecondsUsed = (end.usageUsec - startCpu) / 1_000_000;
|
|
108
|
+
}
|
|
109
|
+
const vcpuCount = cpuMax ? cpuMax.vcpuCount : _nproc();
|
|
110
|
+
return {
|
|
111
|
+
billing_model: billingModelFor(this.runtime),
|
|
112
|
+
duration_ms: durationMs,
|
|
113
|
+
memory_bytes_peak: Math.trunc(memPeak),
|
|
114
|
+
memory_bytes_limit: Math.trunc(memLimit),
|
|
115
|
+
vcpu_count: vcpuCount,
|
|
116
|
+
vcpu_seconds_used: vcpuSecondsUsed,
|
|
117
|
+
invocation_count: 0,
|
|
118
|
+
region: this.region ?? null,
|
|
119
|
+
architecture: this.architecture,
|
|
120
|
+
initialization_type: null,
|
|
121
|
+
cost_pending: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// ------------------------------------------------------------------
|
|
125
|
+
// Serverless runtimes
|
|
126
|
+
// ------------------------------------------------------------------
|
|
127
|
+
/**
|
|
128
|
+
* Build a per-invocation event for Lambda / Cloud Run / Cloud Functions /
|
|
129
|
+
* Azure Functions / Vercel.
|
|
130
|
+
*/
|
|
131
|
+
buildServerlessEvent(durationMs, memoryBytesPeak) {
|
|
132
|
+
if (this._frozen)
|
|
133
|
+
return null;
|
|
134
|
+
this._frozen = true;
|
|
135
|
+
let memLimit;
|
|
136
|
+
let vcpuCount;
|
|
137
|
+
if (this.runtime === RuntimeKind.Lambda) {
|
|
138
|
+
// Lambda's AWS_LAMBDA_FUNCTION_MEMORY_SIZE is DECIMAL MB.
|
|
139
|
+
memLimit = (this.lambdaMemoryMb ?? 128) * 1_000_000;
|
|
140
|
+
vcpuCount = vcpuCountFromCgroup();
|
|
141
|
+
}
|
|
142
|
+
else if (this.runtime === RuntimeKind.Fargate) {
|
|
143
|
+
memLimit = (this.fargateMemoryMib ?? 0) * 1024 * 1024;
|
|
144
|
+
vcpuCount =
|
|
145
|
+
this.fargateVcpu !== undefined ? this.fargateVcpu : vcpuCountFromCgroup();
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// Cloud Run / Cloud Functions / Azure Functions / Vercel —
|
|
149
|
+
// cgroup memory.max is the declared limit.
|
|
150
|
+
memLimit = readMemoryMax() ?? memoryBytesPeak;
|
|
151
|
+
vcpuCount = vcpuCountFromCgroup();
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
billing_model: billingModelFor(this.runtime),
|
|
155
|
+
duration_ms: durationMs,
|
|
156
|
+
memory_bytes_peak: memoryBytesPeak,
|
|
157
|
+
memory_bytes_limit: memLimit,
|
|
158
|
+
vcpu_count: vcpuCount,
|
|
159
|
+
vcpu_seconds_used: 0,
|
|
160
|
+
invocation_count: 1,
|
|
161
|
+
region: this.region ?? null,
|
|
162
|
+
architecture: this.architecture,
|
|
163
|
+
initialization_type: this.initializationType ?? null,
|
|
164
|
+
cost_pending: true,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function _nproc() {
|
|
169
|
+
if (!_isNode())
|
|
170
|
+
return 1;
|
|
171
|
+
return cpus().length || 1;
|
|
172
|
+
}
|
|
173
|
+
function vcpuCountFromCgroup() {
|
|
174
|
+
const cpuMax = readCpuMax();
|
|
175
|
+
if (cpuMax !== null)
|
|
176
|
+
return cpuMax.vcpuCount;
|
|
177
|
+
return _nproc();
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=compute-accountant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-accountant.js","sourceRoot":"","sources":["../../src/core/compute-accountant.ts"],"names":[],"mappings":"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"}
|