@teamscala/service-boot 0.23.295 → 0.23.296
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/package.json +1 -1
- package/src/register-static-assets.ts +14 -33
package/package.json
CHANGED
|
@@ -14,6 +14,8 @@ import { join } from "node:path";
|
|
|
14
14
|
import type { Hono } from "hono";
|
|
15
15
|
import { etag } from "hono/etag";
|
|
16
16
|
import { buildErrorReport } from "@teamscala/os/errors/error-report";
|
|
17
|
+
import { collectHeapReport } from "@teamscala/os/observability/heap-report";
|
|
18
|
+
import { isLoopbackHost } from "@teamscala/os/observability/loopback-host";
|
|
17
19
|
import { handleAssetProxy } from "./asset-proxy";
|
|
18
20
|
import { resolveBrandFaviconPath, warmBrandFaviconCache } from "./resolve-brand-favicon";
|
|
19
21
|
|
|
@@ -37,41 +39,20 @@ export async function registerStaticAssets(
|
|
|
37
39
|
}),
|
|
38
40
|
);
|
|
39
41
|
|
|
40
|
-
// Localhost-gated heap-attribution probe —
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
//
|
|
42
|
+
// Localhost-gated heap-attribution probe — the heapSize-vs-RSS split (JS heap
|
|
43
|
+
// vs native: OTel/Prisma-engine/buffers/compiled code) plus the top object
|
|
44
|
+
// types by count. Read-only, no secrets; gated to a localhost Host so it never
|
|
45
|
+
// answers over the public domain. Registered here (before auth + page routes)
|
|
46
|
+
// so it is reachable on every service kind, like /health
|
|
47
|
+
// (`verify-via-127.0.0.1`, sibling of `runtime-metrics-via-railway-cli`).
|
|
48
|
+
//
|
|
49
|
+
// The payload shape lives in @teamscala/os so standalone `Bun.serve` daemons
|
|
50
|
+
// (scala-guard) answer this probe identically — `scala-tools heap <slug>` must
|
|
51
|
+
// not mean different things depending on which process replied.
|
|
47
52
|
app.get("/_heap", async (c) => {
|
|
48
|
-
|
|
49
|
-
const isLocal =
|
|
50
|
-
host.startsWith("127.0.0.1") || host.startsWith("localhost") || host.startsWith("[::1]");
|
|
51
|
-
if (!isLocal) return c.json({ error: "localhost only" }, 403);
|
|
53
|
+
if (!isLoopbackHost(c.req.header("host"))) return c.json({ error: "localhost only" }, 403);
|
|
52
54
|
try {
|
|
53
|
-
|
|
54
|
-
const s = heapStats() as unknown as {
|
|
55
|
-
heapSize: number;
|
|
56
|
-
heapCapacity: number;
|
|
57
|
-
objectCount: number;
|
|
58
|
-
objectTypeCounts?: Record<string, number>;
|
|
59
|
-
};
|
|
60
|
-
const rss = process.memoryUsage.rss();
|
|
61
|
-
const topObjectTypes = Object.fromEntries(
|
|
62
|
-
Object.entries(s.objectTypeCounts ?? {})
|
|
63
|
-
.sort((a, b) => b[1] - a[1])
|
|
64
|
-
.slice(0, 40),
|
|
65
|
-
);
|
|
66
|
-
return c.json({
|
|
67
|
-
service: serviceSlug,
|
|
68
|
-
rss,
|
|
69
|
-
heapSize: s.heapSize,
|
|
70
|
-
heapCapacity: s.heapCapacity,
|
|
71
|
-
objectCount: s.objectCount,
|
|
72
|
-
nativeApprox: Math.max(0, rss - s.heapSize),
|
|
73
|
-
topObjectTypes,
|
|
74
|
-
});
|
|
55
|
+
return c.json(await collectHeapReport(serviceSlug));
|
|
75
56
|
} catch (err) {
|
|
76
57
|
const report = buildErrorReport(err, { service: serviceSlug, url: c.req.url });
|
|
77
58
|
return new Response(JSON.stringify(report.http.body), {
|