@omnitron-dev/omnitron 0.1.2 → 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.
Files changed (268) hide show
  1. package/dist/cli/omnitron.js +32 -1
  2. package/dist/cli/omnitron.js.map +1 -1
  3. package/dist/cluster/leader-election.d.ts.map +1 -1
  4. package/dist/cluster/leader-election.js +0 -2
  5. package/dist/cluster/leader-election.js.map +1 -1
  6. package/dist/commands/env.d.ts.map +1 -1
  7. package/dist/commands/env.js +10 -2
  8. package/dist/commands/env.js.map +1 -1
  9. package/dist/commands/health.d.ts.map +1 -1
  10. package/dist/commands/health.js +10 -2
  11. package/dist/commands/health.js.map +1 -1
  12. package/dist/commands/inspect-graph.d.ts +20 -0
  13. package/dist/commands/inspect-graph.d.ts.map +1 -0
  14. package/dist/commands/inspect-graph.js +78 -0
  15. package/dist/commands/inspect-graph.js.map +1 -0
  16. package/dist/commands/inspect.d.ts.map +1 -1
  17. package/dist/commands/inspect.js +10 -2
  18. package/dist/commands/inspect.js.map +1 -1
  19. package/dist/commands/list.d.ts.map +1 -1
  20. package/dist/commands/list.js +11 -1
  21. package/dist/commands/list.js.map +1 -1
  22. package/dist/commands/logs.d.ts.map +1 -1
  23. package/dist/commands/logs.js +17 -3
  24. package/dist/commands/logs.js.map +1 -1
  25. package/dist/commands/metrics.d.ts.map +1 -1
  26. package/dist/commands/metrics.js +10 -2
  27. package/dist/commands/metrics.js.map +1 -1
  28. package/dist/commands/monit.d.ts.map +1 -1
  29. package/dist/commands/monit.js +9 -0
  30. package/dist/commands/monit.js.map +1 -1
  31. package/dist/commands/output.d.ts +35 -0
  32. package/dist/commands/output.d.ts.map +1 -0
  33. package/dist/commands/output.js +63 -0
  34. package/dist/commands/output.js.map +1 -0
  35. package/dist/commands/stack.d.ts.map +1 -1
  36. package/dist/commands/stack.js +22 -7
  37. package/dist/commands/stack.js.map +1 -1
  38. package/dist/commands/status.d.ts.map +1 -1
  39. package/dist/commands/status.js +17 -0
  40. package/dist/commands/status.js.map +1 -1
  41. package/dist/commands/tor.d.ts +13 -0
  42. package/dist/commands/tor.d.ts.map +1 -0
  43. package/dist/commands/tor.js +100 -0
  44. package/dist/commands/tor.js.map +1 -0
  45. package/dist/commands/up.js +1 -1
  46. package/dist/commands/up.js.map +1 -1
  47. package/dist/config/loader.d.ts.map +1 -1
  48. package/dist/config/loader.js +29 -5
  49. package/dist/config/loader.js.map +1 -1
  50. package/dist/config/types.d.ts +14 -0
  51. package/dist/config/types.d.ts.map +1 -1
  52. package/dist/daemon/daemon-client.d.ts +14 -0
  53. package/dist/daemon/daemon-client.d.ts.map +1 -1
  54. package/dist/daemon/daemon-client.js +4 -0
  55. package/dist/daemon/daemon-client.js.map +1 -1
  56. package/dist/daemon/daemon-entry.js +17 -23
  57. package/dist/daemon/daemon-entry.js.map +1 -1
  58. package/dist/daemon/daemon.d.ts +2 -0
  59. package/dist/daemon/daemon.d.ts.map +1 -1
  60. package/dist/daemon/daemon.js +118 -7
  61. package/dist/daemon/daemon.js.map +1 -1
  62. package/dist/daemon/daemon.module.d.ts.map +1 -1
  63. package/dist/daemon/daemon.module.js +41 -14
  64. package/dist/daemon/daemon.module.js.map +1 -1
  65. package/dist/daemon/daemon.rpc-service.d.ts +19 -0
  66. package/dist/daemon/daemon.rpc-service.d.ts.map +1 -1
  67. package/dist/daemon/daemon.rpc-service.js +14 -0
  68. package/dist/daemon/daemon.rpc-service.js.map +1 -1
  69. package/dist/daemon/pid-manager.d.ts +55 -4
  70. package/dist/daemon/pid-manager.d.ts.map +1 -1
  71. package/dist/daemon/pid-manager.js +123 -16
  72. package/dist/daemon/pid-manager.js.map +1 -1
  73. package/dist/daemon/state-store.d.ts.map +1 -1
  74. package/dist/daemon/state-store.js +43 -1
  75. package/dist/daemon/state-store.js.map +1 -1
  76. package/dist/infrastructure/container-runtime.d.ts +10 -0
  77. package/dist/infrastructure/container-runtime.d.ts.map +1 -1
  78. package/dist/infrastructure/container-runtime.js +111 -36
  79. package/dist/infrastructure/container-runtime.js.map +1 -1
  80. package/dist/infrastructure/infrastructure.service.d.ts +41 -0
  81. package/dist/infrastructure/infrastructure.service.d.ts.map +1 -1
  82. package/dist/infrastructure/infrastructure.service.js +157 -8
  83. package/dist/infrastructure/infrastructure.service.js.map +1 -1
  84. package/dist/infrastructure/phantom-endpoint-janitor.d.ts +72 -0
  85. package/dist/infrastructure/phantom-endpoint-janitor.d.ts.map +1 -0
  86. package/dist/infrastructure/phantom-endpoint-janitor.js +149 -0
  87. package/dist/infrastructure/phantom-endpoint-janitor.js.map +1 -0
  88. package/dist/infrastructure/presets/index.d.ts.map +1 -1
  89. package/dist/infrastructure/presets/index.js +2 -0
  90. package/dist/infrastructure/presets/index.js.map +1 -1
  91. package/dist/infrastructure/presets/postgres.d.ts.map +1 -1
  92. package/dist/infrastructure/presets/postgres.js +9 -3
  93. package/dist/infrastructure/presets/postgres.js.map +1 -1
  94. package/dist/infrastructure/presets/redis.d.ts.map +1 -1
  95. package/dist/infrastructure/presets/redis.js +10 -4
  96. package/dist/infrastructure/presets/redis.js.map +1 -1
  97. package/dist/infrastructure/presets/registry.d.ts.map +1 -1
  98. package/dist/infrastructure/presets/registry.js +12 -0
  99. package/dist/infrastructure/presets/registry.js.map +1 -1
  100. package/dist/infrastructure/presets/tor.d.ts +74 -0
  101. package/dist/infrastructure/presets/tor.d.ts.map +1 -0
  102. package/dist/infrastructure/presets/tor.js +176 -0
  103. package/dist/infrastructure/presets/tor.js.map +1 -0
  104. package/dist/infrastructure/service-resolver.d.ts +31 -0
  105. package/dist/infrastructure/service-resolver.d.ts.map +1 -1
  106. package/dist/infrastructure/service-resolver.js +60 -9
  107. package/dist/infrastructure/service-resolver.js.map +1 -1
  108. package/dist/infrastructure/stack-infra-manager.d.ts +1 -1
  109. package/dist/infrastructure/stack-infra-manager.js +1 -1
  110. package/dist/infrastructure/types.d.ts +17 -0
  111. package/dist/infrastructure/types.d.ts.map +1 -1
  112. package/dist/observability/index.d.ts +4 -0
  113. package/dist/observability/index.d.ts.map +1 -0
  114. package/dist/observability/index.js +3 -0
  115. package/dist/observability/index.js.map +1 -0
  116. package/dist/observability/metrics-bridge.d.ts +87 -0
  117. package/dist/observability/metrics-bridge.d.ts.map +1 -0
  118. package/dist/observability/metrics-bridge.js +295 -0
  119. package/dist/observability/metrics-bridge.js.map +1 -0
  120. package/dist/observability/metrics-server.d.ts +68 -0
  121. package/dist/observability/metrics-server.d.ts.map +1 -0
  122. package/dist/observability/metrics-server.js +146 -0
  123. package/dist/observability/metrics-server.js.map +1 -0
  124. package/dist/orchestrator/app-handle.d.ts +13 -1
  125. package/dist/orchestrator/app-handle.d.ts.map +1 -1
  126. package/dist/orchestrator/app-handle.js +12 -0
  127. package/dist/orchestrator/app-handle.js.map +1 -1
  128. package/dist/orchestrator/bootstrap-process.d.ts +49 -0
  129. package/dist/orchestrator/bootstrap-process.d.ts.map +1 -1
  130. package/dist/orchestrator/bootstrap-process.js +167 -0
  131. package/dist/orchestrator/bootstrap-process.js.map +1 -1
  132. package/dist/orchestrator/build-service.d.ts +50 -3
  133. package/dist/orchestrator/build-service.d.ts.map +1 -1
  134. package/dist/orchestrator/build-service.js +357 -85
  135. package/dist/orchestrator/build-service.js.map +1 -1
  136. package/dist/orchestrator/file-watcher.d.ts.map +1 -1
  137. package/dist/orchestrator/file-watcher.js +60 -38
  138. package/dist/orchestrator/file-watcher.js.map +1 -1
  139. package/dist/orchestrator/orchestrator.service.d.ts +176 -3
  140. package/dist/orchestrator/orchestrator.service.d.ts.map +1 -1
  141. package/dist/orchestrator/orchestrator.service.js +587 -56
  142. package/dist/orchestrator/orchestrator.service.js.map +1 -1
  143. package/dist/orchestrator/process-janitor.d.ts +153 -0
  144. package/dist/orchestrator/process-janitor.d.ts.map +1 -0
  145. package/dist/orchestrator/process-janitor.js +279 -0
  146. package/dist/orchestrator/process-janitor.js.map +1 -0
  147. package/dist/project/config-resolver.d.ts.map +1 -1
  148. package/dist/project/config-resolver.js +38 -12
  149. package/dist/project/config-resolver.js.map +1 -1
  150. package/dist/project/registry.d.ts +1 -0
  151. package/dist/project/registry.d.ts.map +1 -1
  152. package/dist/project/registry.js +30 -0
  153. package/dist/project/registry.js.map +1 -1
  154. package/dist/services/auth.service.d.ts.map +1 -1
  155. package/dist/services/auth.service.js +9 -2
  156. package/dist/services/auth.service.js.map +1 -1
  157. package/dist/services/netron-telemetry-transport.d.ts.map +1 -1
  158. package/dist/services/netron-telemetry-transport.js +0 -4
  159. package/dist/services/netron-telemetry-transport.js.map +1 -1
  160. package/dist/services/node-manager.service.js +1 -1
  161. package/dist/services/node-manager.service.js.map +1 -1
  162. package/dist/services/pipeline.service.d.ts +15 -0
  163. package/dist/services/pipeline.service.d.ts.map +1 -1
  164. package/dist/services/pipeline.service.js +53 -2
  165. package/dist/services/pipeline.service.js.map +1 -1
  166. package/dist/services/project.rpc-service.d.ts +4 -0
  167. package/dist/services/project.rpc-service.d.ts.map +1 -1
  168. package/dist/services/project.rpc-service.js +9 -0
  169. package/dist/services/project.rpc-service.js.map +1 -1
  170. package/dist/services/project.service.d.ts +9 -0
  171. package/dist/services/project.service.d.ts.map +1 -1
  172. package/dist/services/project.service.js +148 -21
  173. package/dist/services/project.service.js.map +1 -1
  174. package/dist/shared/dto/project.d.ts +1 -1
  175. package/dist/shared/dto/project.d.ts.map +1 -1
  176. package/dist/shared/dto/services.d.ts +24 -0
  177. package/dist/shared/dto/services.d.ts.map +1 -1
  178. package/dist/workers/health-monitor.service.d.ts.map +1 -1
  179. package/dist/workers/health-monitor.service.js +4 -1
  180. package/dist/workers/health-monitor.service.js.map +1 -1
  181. package/dist/workers/types.d.ts +3 -0
  182. package/dist/workers/types.d.ts.map +1 -1
  183. package/package.json +19 -18
  184. package/webapp/dist/assets/Badge-D2ZBP5iK.js +1 -0
  185. package/webapp/dist/assets/Card-vO88g06B.js +1 -0
  186. package/webapp/dist/assets/CardActions-C9h7Q2wW.js +1 -0
  187. package/webapp/dist/assets/CardContent-BA_Xmmhk.js +1 -0
  188. package/webapp/dist/assets/CardHeader-ceIs__6x.js +1 -0
  189. package/webapp/dist/assets/Chip-Ckk0xUhK.js +1 -0
  190. package/webapp/dist/assets/DialogActions-BhHM7hov.js +1 -0
  191. package/webapp/dist/assets/DialogContentText-BT2JQRmK.js +1 -0
  192. package/webapp/dist/assets/FormControlLabel-CcQByVS8.js +1 -0
  193. package/webapp/dist/assets/Grid-14PETRQW.js +1 -0
  194. package/webapp/dist/assets/InputAdornment-B8aHIsQ7.js +1 -0
  195. package/webapp/dist/assets/Skeleton-B74-Ds6O.js +37 -0
  196. package/webapp/dist/assets/Switch-DvWD2wh4.js +1 -0
  197. package/webapp/dist/assets/SwitchBase-CDU4nY8O.js +1 -0
  198. package/webapp/dist/assets/Tab-DcCOYYp5.js +1 -0
  199. package/webapp/dist/assets/TableContainer-CzTh4mu-.js +1 -0
  200. package/webapp/dist/assets/TableRow-BySEreZR.js +2 -0
  201. package/webapp/dist/assets/TextField-BLf-BHz2.js +1 -0
  202. package/webapp/dist/assets/alerts-DnRbT41C.js +1 -0
  203. package/webapp/dist/assets/apps-CdR0VH2d.js +1 -0
  204. package/webapp/dist/assets/chunk-DtcAfS_W.js +1 -0
  205. package/webapp/dist/assets/client-DU8I_lDc.js +2 -0
  206. package/webapp/dist/assets/containers-Dw-rRXV1.js +1 -0
  207. package/webapp/dist/assets/dashboard-CzgB0uZz.js +1 -0
  208. package/webapp/dist/assets/dashboard-builder-DsA0yg33.js +1 -0
  209. package/webapp/dist/assets/deployments-DtQAoIcQ.js +1 -0
  210. package/webapp/dist/assets/detail-BJR-G7JG.js +1 -0
  211. package/webapp/dist/assets/detail-nlCeSltl.js +8 -0
  212. package/webapp/dist/assets/index-ByQDwp2r.js +566 -0
  213. package/webapp/dist/assets/isMuiElement-DwF2naaF.js +1 -0
  214. package/webapp/dist/assets/logs-Kn8o4H7k.js +11 -0
  215. package/webapp/dist/assets/metrics-DN8Zu5wT.js +2 -0
  216. package/webapp/dist/assets/nodes-Bgch7AtN.js +7 -0
  217. package/webapp/dist/assets/pipelines-Cry3qm-S.js +4 -0
  218. package/webapp/dist/assets/popper-BJFSj6rc.js +1 -0
  219. package/webapp/dist/assets/preload-helper-DSXbuxSR.js +1 -0
  220. package/webapp/dist/assets/projects-Dym2GI1U.js +1 -0
  221. package/webapp/dist/assets/react-apexcharts.esm-CSGK5Cxn.js +958 -0
  222. package/webapp/dist/assets/react-apexcharts.esm-DEAWOwx5.js +1003 -0
  223. package/webapp/dist/assets/settings-va3zTcow.js +1 -0
  224. package/webapp/dist/assets/sign-in-ik35umbp.js +1 -0
  225. package/webapp/dist/assets/stacks-CVFOnxbF.js +1 -0
  226. package/webapp/dist/assets/system-info-npIXAjX2.js +1 -0
  227. package/webapp/dist/assets/topology-bDe70vLs.js +12 -0
  228. package/webapp/dist/assets/traces-DIIcT8DF.js +1 -0
  229. package/webapp/dist/assets/use-stack-context-DHLwZv1r.js +1 -0
  230. package/webapp/dist/index.html +5 -6
  231. package/webapp/dist/assets/Chip-BySxTjyN.js +0 -1
  232. package/webapp/dist/assets/DialogContentText-YQWiAVrU.js +0 -1
  233. package/webapp/dist/assets/DialogTitle-CDkgUIwp.js +0 -1
  234. package/webapp/dist/assets/FormControlLabel-Bu3CCsBM.js +0 -1
  235. package/webapp/dist/assets/Grid-BFY8hAzL.js +0 -1
  236. package/webapp/dist/assets/InputAdornment-_Dayk-3y.js +0 -3
  237. package/webapp/dist/assets/Skeleton-BGj6Sw8m.js +0 -37
  238. package/webapp/dist/assets/Switch-CA6682vv.js +0 -1
  239. package/webapp/dist/assets/TableContainer-4epq10KJ.js +0 -1
  240. package/webapp/dist/assets/TextField-C73KHMVN.js +0 -1
  241. package/webapp/dist/assets/alerts-JEQALS7Y.js +0 -1
  242. package/webapp/dist/assets/apps-DMPysEKB.js +0 -1
  243. package/webapp/dist/assets/client-DlGPter5.js +0 -110
  244. package/webapp/dist/assets/containers-CvkC7do8.js +0 -1
  245. package/webapp/dist/assets/dashboard-C0Fre9pC.js +0 -1
  246. package/webapp/dist/assets/dashboard-builder-DAghqdpE.js +0 -1
  247. package/webapp/dist/assets/deployments-Cg1lI1uT.js +0 -1
  248. package/webapp/dist/assets/detail-CyFtEson.js +0 -1
  249. package/webapp/dist/assets/detail-DqoSGKT1.js +0 -8
  250. package/webapp/dist/assets/icons-ynIWYfBP.js +0 -3
  251. package/webapp/dist/assets/index-vKrDmEA_.js +0 -259
  252. package/webapp/dist/assets/isMuiElement-BRL3YuCT.js +0 -1
  253. package/webapp/dist/assets/logs-IovIij1C.js +0 -11
  254. package/webapp/dist/assets/metrics-Dufwtwjq.js +0 -1
  255. package/webapp/dist/assets/nodes-Brvu8W3j.js +0 -7
  256. package/webapp/dist/assets/pipelines-t40X4MuC.js +0 -4
  257. package/webapp/dist/assets/prop-types-CvVtHxp4.js +0 -1
  258. package/webapp/dist/assets/react-apexcharts.esm-CLO6gala.js +0 -954
  259. package/webapp/dist/assets/settings-DTAIST3v.js +0 -1
  260. package/webapp/dist/assets/sign-in-DQEAkJum.js +0 -1
  261. package/webapp/dist/assets/stacks-BjM1f45N.js +0 -1
  262. package/webapp/dist/assets/system-info-BQSbSEK-.js +0 -1
  263. package/webapp/dist/assets/topology-6N8-Az_Z.js +0 -12
  264. package/webapp/dist/assets/traces-DVXyb-4m.js +0 -1
  265. package/webapp/dist/assets/use-stack-context-CbE8fxBA.js +0 -1
  266. /package/webapp/dist/assets/{constants-DqFQJ27U.js → constants-BgnT-Xdy.js} +0 -0
  267. /package/webapp/dist/assets/{formatters-J3Xqn6BQ.js → formatters-Do41SRmE.js} +0 -0
  268. /package/webapp/dist/assets/{fs-uP8eiZAR.js → fs-CgZLtHiQ.js} +0 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Omnitron metrics bridge — single point of contact between the daemon's
3
+ * runtime hooks (orchestrator events, ProcessJanitor sweeps,
4
+ * ResilientHandle resets, esbuild rebuilds) and the underlying
5
+ * `IMetricsService` registry from `@omnitron-dev/titan-metrics`.
6
+ *
7
+ * Every issue we've debugged in production was diagnosed REACTIVELY
8
+ * from log greps: postgres connection exhaustion (we found 207 leaked
9
+ * fork-workers only after pg_stat_activity told us to look), esbuild
10
+ * Go sidecar deaths (the build self-heal was silent until we wired up
11
+ * a dedicated log line), RPC name mismatches (only surfaced when an app
12
+ * couldn't talk to its dependency at runtime). The metrics this bridge
13
+ * exposes are what we wished we'd had during each of those incidents.
14
+ *
15
+ * Design notes:
16
+ *
17
+ * - Metrics live in the titan-metrics registry; this bridge is the
18
+ * DAO that types the writes. Callers don't touch the registry
19
+ * directly — they call `metrics.recordEsbuildBuild(...)` etc.
20
+ *
21
+ * - Per-app gauges (`status`, `restart_total`, `uptime_seconds`) are
22
+ * refreshed on every Prometheus scrape via `refreshAppGauges()`.
23
+ * The HTTP server calls it before formatting text. This avoids
24
+ * wiring callbacks into every state mutation in the orchestrator.
25
+ *
26
+ * - Event-driven counters/histograms (orphan kills, esbuild
27
+ * rebuilds, lifecycle phases) are recorded eagerly via the
28
+ * record* helpers, since events are sparse and we don't want to
29
+ * drop them between scrapes.
30
+ */
31
+ // All known statuses; we emit one row per (app, status) so Grafana can
32
+ // pivot. Keeping the list explicit means a typo in OrchestratorService
33
+ // produces a dropped metric instead of a silent new label value.
34
+ const APP_STATUSES = [
35
+ 'stopped',
36
+ 'starting',
37
+ 'online',
38
+ 'stopping',
39
+ 'errored',
40
+ 'crashed',
41
+ ];
42
+ export class MetricsBridge {
43
+ metrics;
44
+ logger;
45
+ orchestrator = null;
46
+ definitionsRegistered = false;
47
+ constructor(metrics, logger) {
48
+ this.metrics = metrics;
49
+ this.logger = logger;
50
+ this.registerDefinitions();
51
+ }
52
+ /** Wire the orchestrator so per-app gauges can be refreshed at scrape time. */
53
+ attachOrchestrator(orchestrator) {
54
+ this.orchestrator = orchestrator;
55
+ }
56
+ /**
57
+ * Refresh per-app gauges. Called by the metrics HTTP server before it
58
+ * formats text — keeps the gauges current without instrumenting every
59
+ * status mutation in the orchestrator.
60
+ */
61
+ refreshAppGauges() {
62
+ if (!this.orchestrator)
63
+ return;
64
+ const apps = this.orchestrator.list();
65
+ for (const app of apps) {
66
+ // One gauge series per (app, status) pair — value 1 if the app
67
+ // is currently in that status, else 0. Lets Grafana plot
68
+ // `omnitron_app_status{status="online"}` as a stacked bar.
69
+ for (const status of APP_STATUSES) {
70
+ this.gauge('omnitron_app_status', { app: app.name, status }, app.status === status ? 1 : 0);
71
+ }
72
+ this.gauge('omnitron_app_restarts', { app: app.name }, app.restarts ?? 0);
73
+ this.gauge('omnitron_app_uptime_seconds', { app: app.name }, app.uptime ?? 0);
74
+ if (typeof app.cpu === 'number') {
75
+ this.gauge('omnitron_app_cpu_percent', { app: app.name }, app.cpu);
76
+ }
77
+ if (typeof app.memory === 'number') {
78
+ this.gauge('omnitron_app_memory_bytes', { app: app.name }, app.memory);
79
+ }
80
+ }
81
+ }
82
+ // -------------------------------------------------------------------------
83
+ // Event-driven recorders
84
+ // -------------------------------------------------------------------------
85
+ /** Record a janitor sweep — gauges current orphan/owned counts + bumps total counter. */
86
+ recordJanitorSweep(m) {
87
+ this.gauge('omnitron_workers_alive', {}, m.forkWorkersAlive);
88
+ this.gauge('omnitron_workers_owned', {}, m.ownedPids);
89
+ this.gauge('omnitron_workers_orphans_pending', {}, m.orphansFound - m.orphansKilled);
90
+ if (m.orphansKilled > 0) {
91
+ this.counter('omnitron_workers_orphans_killed_total', {}, m.orphansKilled);
92
+ }
93
+ if (m.killErrors > 0) {
94
+ this.counter('omnitron_workers_orphan_kill_errors_total', {}, m.killErrors);
95
+ }
96
+ }
97
+ /** Record a ResilientHandle reset — fires once per fatal-error reset across the daemon. */
98
+ recordResilientHandleReset(info) {
99
+ this.counter('resilient_handle_resets_total', { name: info.name }, 1);
100
+ }
101
+ /** Record an esbuild build (initial or rebuild). */
102
+ recordEsbuildBuild(app, kind, durationMs, ok) {
103
+ this.histogram('omnitron_esbuild_duration_seconds', { app, kind }, durationMs / 1000);
104
+ this.counter('omnitron_esbuild_builds_total', { app, kind, outcome: ok ? 'success' : 'failure' }, 1);
105
+ }
106
+ /** Record an app restart event. Called from orchestrator's `app:restart` listener. */
107
+ recordAppRestart(app, attempt, reason) {
108
+ this.counter('omnitron_app_restarts_total', { app, reason }, 1);
109
+ this.gauge('omnitron_app_restart_attempt', { app }, attempt);
110
+ }
111
+ /** Record an app crash. */
112
+ recordAppCrash(app) {
113
+ this.counter('omnitron_app_crashes_total', { app }, 1);
114
+ }
115
+ /** Record an app escalation (max restarts exceeded). */
116
+ recordAppEscalated(app) {
117
+ this.counter('omnitron_app_escalations_total', { app }, 1);
118
+ }
119
+ /** Record a lifecycle controller phase event. */
120
+ recordLifecyclePhase(phase, durationMs, kind) {
121
+ this.histogram('lifecycle_shutdown_phase_duration_seconds', { phase }, durationMs / 1000);
122
+ if (kind === 'timeout') {
123
+ this.counter('lifecycle_shutdown_phase_timeouts_total', { phase }, 1);
124
+ }
125
+ }
126
+ /**
127
+ * Permanently drop every sample for a named app from both the in-memory
128
+ * registry and the storage backend. Use when an app is definitively
129
+ * removed (handle replaced under a different canonical name, app
130
+ * un-registered) so it cannot linger as a "ghost offline" in subsequent
131
+ * snapshots.
132
+ *
133
+ * Best-effort: swallowed errors so an eviction failure can never block
134
+ * the orchestrator's primary lifecycle path.
135
+ */
136
+ evictApp(app) {
137
+ void this.metrics.evictApp(app).catch((err) => {
138
+ this.logger?.warn?.({ app, error: err.message }, 'Failed to evict metrics for app');
139
+ });
140
+ }
141
+ // -------------------------------------------------------------------------
142
+ // Internals
143
+ // -------------------------------------------------------------------------
144
+ /**
145
+ * Pre-register every metric this bridge writes. The titan-metrics
146
+ * registry would auto-register them with default help text on first
147
+ * write, but we want stable, descriptive HELP lines and explicit
148
+ * label sets in the Prometheus output.
149
+ */
150
+ registerDefinitions() {
151
+ if (this.definitionsRegistered)
152
+ return;
153
+ this.definitionsRegistered = true;
154
+ const registry = this.metrics.getRegistry();
155
+ registry.define({
156
+ name: 'omnitron_app_status',
157
+ type: 'gauge',
158
+ help: '1 if the app is currently in the labelled status, else 0',
159
+ labelNames: ['app', 'status'],
160
+ });
161
+ registry.define({
162
+ name: 'omnitron_app_restarts',
163
+ type: 'gauge',
164
+ help: 'Current restart counter for the app (resets on full stop)',
165
+ labelNames: ['app'],
166
+ });
167
+ registry.define({
168
+ name: 'omnitron_app_uptime_seconds',
169
+ type: 'gauge',
170
+ help: 'Seconds since the app last entered the online state',
171
+ labelNames: ['app'],
172
+ });
173
+ registry.define({
174
+ name: 'omnitron_app_cpu_percent',
175
+ type: 'gauge',
176
+ help: 'Last sampled CPU percent for the app',
177
+ labelNames: ['app'],
178
+ });
179
+ registry.define({
180
+ name: 'omnitron_app_memory_bytes',
181
+ type: 'gauge',
182
+ help: 'Last sampled RSS memory for the app',
183
+ labelNames: ['app'],
184
+ });
185
+ registry.define({
186
+ name: 'omnitron_workers_alive',
187
+ type: 'gauge',
188
+ help: 'Total fork-worker processes the daemon can see in `ps`',
189
+ });
190
+ registry.define({
191
+ name: 'omnitron_workers_owned',
192
+ type: 'gauge',
193
+ help: 'Fork-worker pids the daemon has registered as owned',
194
+ });
195
+ registry.define({
196
+ name: 'omnitron_workers_orphans_pending',
197
+ type: 'gauge',
198
+ help: 'Orphan fork-worker pids found in the last sweep but not yet killed',
199
+ });
200
+ registry.define({
201
+ name: 'omnitron_workers_orphans_killed_total',
202
+ type: 'counter',
203
+ help: 'Total fork-worker orphans the janitor has killed',
204
+ });
205
+ registry.define({
206
+ name: 'omnitron_workers_orphan_kill_errors_total',
207
+ type: 'counter',
208
+ help: 'Total errors when the janitor tried to kill an orphan',
209
+ });
210
+ registry.define({
211
+ name: 'resilient_handle_resets_total',
212
+ type: 'counter',
213
+ help: 'ResilientHandle reset count (cached external resource went unhealthy and was re-acquired)',
214
+ labelNames: ['name'],
215
+ });
216
+ registry.define({
217
+ name: 'omnitron_esbuild_duration_seconds',
218
+ type: 'histogram',
219
+ help: 'esbuild build/rebuild duration in seconds',
220
+ labelNames: ['app', 'kind'],
221
+ });
222
+ registry.define({
223
+ name: 'omnitron_esbuild_builds_total',
224
+ type: 'counter',
225
+ help: 'Total esbuild builds and rebuilds, partitioned by outcome',
226
+ labelNames: ['app', 'kind', 'outcome'],
227
+ });
228
+ registry.define({
229
+ name: 'omnitron_app_restarts_total',
230
+ type: 'counter',
231
+ help: 'Total app restarts, partitioned by reason',
232
+ labelNames: ['app', 'reason'],
233
+ });
234
+ registry.define({
235
+ name: 'omnitron_app_restart_attempt',
236
+ type: 'gauge',
237
+ help: 'Most recent restart attempt number for the app',
238
+ labelNames: ['app'],
239
+ });
240
+ registry.define({
241
+ name: 'omnitron_app_crashes_total',
242
+ type: 'counter',
243
+ help: 'Total times the app crashed (process exited with non-zero before going online)',
244
+ labelNames: ['app'],
245
+ });
246
+ registry.define({
247
+ name: 'omnitron_app_escalations_total',
248
+ type: 'counter',
249
+ help: 'Total times the supervisor escalated past max restarts',
250
+ labelNames: ['app'],
251
+ });
252
+ registry.define({
253
+ name: 'lifecycle_shutdown_phase_duration_seconds',
254
+ type: 'histogram',
255
+ help: 'LifecycleController shutdown phase duration in seconds',
256
+ labelNames: ['phase'],
257
+ });
258
+ registry.define({
259
+ name: 'lifecycle_shutdown_phase_timeouts_total',
260
+ type: 'counter',
261
+ help: 'Total LifecycleController phases that hit their timeout',
262
+ labelNames: ['phase'],
263
+ });
264
+ }
265
+ // Thin record helpers — wrap the unified `recordTyped` entry
266
+ // point so every metric the bridge emits appears in BOTH the
267
+ // Prometheus exposition (`/metrics`) AND the storage-backed
268
+ // `querySeries()` API (T#74). Errors are swallowed so a metrics-
269
+ // pipeline hiccup never crashes the broader daemon.
270
+ gauge(name, labels, value) {
271
+ try {
272
+ this.metrics.recordTyped('gauge', name, labels, value);
273
+ }
274
+ catch (err) {
275
+ this.logger?.warn?.({ err, name }, 'metrics-bridge: gauge write failed');
276
+ }
277
+ }
278
+ counter(name, labels, delta) {
279
+ try {
280
+ this.metrics.recordTyped('counter', name, labels, delta);
281
+ }
282
+ catch (err) {
283
+ this.logger?.warn?.({ err, name }, 'metrics-bridge: counter write failed');
284
+ }
285
+ }
286
+ histogram(name, labels, value) {
287
+ try {
288
+ this.metrics.recordTyped('histogram', name, labels, value);
289
+ }
290
+ catch (err) {
291
+ this.logger?.warn?.({ err, name }, 'metrics-bridge: histogram write failed');
292
+ }
293
+ }
294
+ }
295
+ //# sourceMappingURL=metrics-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-bridge.js","sourceRoot":"","sources":["../../src/observability/metrics-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Standalone HTTP server for Prometheus scraping.
3
+ *
4
+ * Bound to a dedicated port (default `httpPort + 3` ≈ 9803) so that
5
+ * scraping is isolated from the main RPC port: a stuck Netron handler
6
+ * can't starve `/metrics`, and scraping can't accidentally generate
7
+ * RPC load. Two routes only:
8
+ *
9
+ * GET /metrics → text/plain Prometheus exposition (refreshes per-app
10
+ * gauges via MetricsBridge.refreshAppGauges() before
11
+ * formatting, so the snapshot is always current).
12
+ * GET /healthz → 200 OK / "ok\n" — used by liveness checks.
13
+ *
14
+ * Anything else returns 404. We deliberately don't expose more — if
15
+ * we ever need richer introspection, it goes through the daemon's RPC
16
+ * surface, which has authentication.
17
+ */
18
+ import type { IMetricsService } from '@omnitron-dev/titan-metrics';
19
+ import type { ILogger } from '@omnitron-dev/titan/module/logger';
20
+ import type { MetricsBridge } from './metrics-bridge.js';
21
+ export interface MetricsServerOptions {
22
+ /** Listen port. */
23
+ port: number;
24
+ /**
25
+ * Bind host. **Default `127.0.0.1` (loopback)** as of T#65. The
26
+ * historical default of `0.0.0.0` exposed `/metrics` on every
27
+ * network interface — internal aggregated traffic counters,
28
+ * per-app health, infrastructure topology — to anyone on the same
29
+ * network. Production scraping by a co-located Prometheus on
30
+ * loopback is unaffected. Remote scraping must opt in by
31
+ * setting host = '0.0.0.0' AND configuring a bearer token via
32
+ * `authToken`.
33
+ */
34
+ host?: string;
35
+ /**
36
+ * Optional bearer token required on `Authorization` header
37
+ * (T#65). When set, requests without `Authorization: Bearer
38
+ * <token>` get 401. `/healthz` is always public so external
39
+ * health probes work; only `/metrics` is gated. Without an
40
+ * `authToken` set, the endpoint is unauthenticated — which is
41
+ * safe ONLY while bound to loopback. The server logs a warning
42
+ * at start when host is non-loopback AND no token is set.
43
+ */
44
+ authToken?: string;
45
+ /** Metric service backing `/metrics`. */
46
+ metrics: IMetricsService;
47
+ /** Bridge for refreshing per-app gauges before formatting. */
48
+ bridge: MetricsBridge;
49
+ /** Logger. */
50
+ logger: ILogger;
51
+ }
52
+ export declare class MetricsServer {
53
+ private server;
54
+ private readonly opts;
55
+ constructor(opts: MetricsServerOptions);
56
+ start(): Promise<{
57
+ port: number;
58
+ }>;
59
+ stop(): Promise<void>;
60
+ private handle;
61
+ /**
62
+ * T#65: constant-time compare against the configured bearer
63
+ * token. Accepts `Authorization: Bearer <token>` only. Returns
64
+ * `true` if the request carries a matching token.
65
+ */
66
+ private authorized;
67
+ }
68
+ //# sourceMappingURL=metrics-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-server.d.ts","sourceRoot":"","sources":["../../src/observability/metrics-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,oBAAoB;IACnC,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,OAAO,EAAE,eAAe,CAAC;IACzB,8DAA8D;IAC9D,MAAM,EAAE,aAAa,CAAC;IACtB,cAAc;IACd,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;gBAEhC,IAAI,EAAE,oBAAoB;IAIhC,KAAK,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAkDlC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAcb,MAAM;IA6CpB;;;;OAIG;IACH,OAAO,CAAC,UAAU;CASnB"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Standalone HTTP server for Prometheus scraping.
3
+ *
4
+ * Bound to a dedicated port (default `httpPort + 3` ≈ 9803) so that
5
+ * scraping is isolated from the main RPC port: a stuck Netron handler
6
+ * can't starve `/metrics`, and scraping can't accidentally generate
7
+ * RPC load. Two routes only:
8
+ *
9
+ * GET /metrics → text/plain Prometheus exposition (refreshes per-app
10
+ * gauges via MetricsBridge.refreshAppGauges() before
11
+ * formatting, so the snapshot is always current).
12
+ * GET /healthz → 200 OK / "ok\n" — used by liveness checks.
13
+ *
14
+ * Anything else returns 404. We deliberately don't expose more — if
15
+ * we ever need richer introspection, it goes through the daemon's RPC
16
+ * surface, which has authentication.
17
+ */
18
+ import http from 'node:http';
19
+ export class MetricsServer {
20
+ server = null;
21
+ opts;
22
+ constructor(opts) {
23
+ this.opts = opts;
24
+ }
25
+ async start() {
26
+ if (this.server) {
27
+ return { port: this.server.address().port };
28
+ }
29
+ const server = http.createServer((req, res) => {
30
+ void this.handle(req, res).catch((err) => {
31
+ this.opts.logger.error({ err, url: req.url }, 'metrics server: handler crash');
32
+ if (!res.headersSent) {
33
+ res.statusCode = 500;
34
+ res.end('internal error\n');
35
+ }
36
+ });
37
+ });
38
+ server.keepAliveTimeout = 5_000;
39
+ server.headersTimeout = 6_000;
40
+ // T#65: default bind to loopback so the metrics endpoint isn't
41
+ // reachable from outside the host without an explicit opt-in.
42
+ const host = this.opts.host ?? '127.0.0.1';
43
+ await new Promise((resolve, reject) => {
44
+ server.once('error', reject);
45
+ server.listen(this.opts.port, host, () => {
46
+ server.off('error', reject);
47
+ resolve();
48
+ });
49
+ });
50
+ this.server = server;
51
+ const address = server.address();
52
+ this.opts.logger.info({ port: address.port, host: address.address, authenticated: Boolean(this.opts.authToken) }, 'metrics server: listening on /metrics');
53
+ // T#65: warn loudly if the operator bound to a non-loopback
54
+ // address WITHOUT setting an auth token. That combination
55
+ // hands `/metrics` to anyone on the network — usually not
56
+ // intended, especially in cloud deploys where the daemon's
57
+ // host is reachable from peer workloads.
58
+ const isLoopback = host === '127.0.0.1' || host === '::1' || host === 'localhost' || host === '127.1';
59
+ if (!isLoopback && !this.opts.authToken) {
60
+ this.opts.logger.warn({ host, port: address.port }, 'metrics server: bound to non-loopback WITHOUT authToken — `/metrics` is publicly readable (T#65)');
61
+ }
62
+ return { port: address.port };
63
+ }
64
+ async stop() {
65
+ if (!this.server)
66
+ return;
67
+ const server = this.server;
68
+ this.server = null;
69
+ await new Promise((resolve) => {
70
+ server.close(() => resolve());
71
+ // close() rejects new connections but waits for in-flight ones to
72
+ // finish naturally. Force close keep-alive connections so we
73
+ // don't drag shutdown out — they hold sockets idle for keepAliveTimeout.
74
+ server.closeIdleConnections?.();
75
+ });
76
+ this.opts.logger.info({}, 'metrics server: stopped');
77
+ }
78
+ async handle(req, res) {
79
+ const url = req.url ?? '/';
80
+ if (req.method !== 'GET') {
81
+ res.statusCode = 405;
82
+ res.setHeader('Allow', 'GET');
83
+ res.end('method not allowed\n');
84
+ return;
85
+ }
86
+ if (url === '/healthz' || url === '/health') {
87
+ res.statusCode = 200;
88
+ res.setHeader('Content-Type', 'text/plain; charset=utf-8');
89
+ res.end('ok\n');
90
+ return;
91
+ }
92
+ if (url === '/metrics' || url.startsWith('/metrics?')) {
93
+ // T#65: gate on bearer token when configured. `/healthz`
94
+ // remains public so external health probes still work; only
95
+ // `/metrics` carries the sensitive aggregate data.
96
+ if (this.opts.authToken && !this.authorized(req)) {
97
+ res.statusCode = 401;
98
+ res.setHeader('WWW-Authenticate', 'Bearer realm="omnitron-metrics"');
99
+ res.end('unauthorized\n');
100
+ return;
101
+ }
102
+ try {
103
+ this.opts.bridge.refreshAppGauges();
104
+ }
105
+ catch (err) {
106
+ this.opts.logger.warn({ err }, 'metrics server: refreshAppGauges threw — emitting last-known values');
107
+ }
108
+ const text = await this.opts.metrics.getPrometheusText();
109
+ res.statusCode = 200;
110
+ res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');
111
+ res.end(text);
112
+ return;
113
+ }
114
+ res.statusCode = 404;
115
+ res.end('not found\n');
116
+ }
117
+ /**
118
+ * T#65: constant-time compare against the configured bearer
119
+ * token. Accepts `Authorization: Bearer <token>` only. Returns
120
+ * `true` if the request carries a matching token.
121
+ */
122
+ authorized(req) {
123
+ const expected = this.opts.authToken;
124
+ if (!expected)
125
+ return true; // no auth configured → public
126
+ const header = req.headers['authorization'];
127
+ if (typeof header !== 'string')
128
+ return false;
129
+ const m = header.match(/^Bearer\s+(.+)$/);
130
+ if (!m)
131
+ return false;
132
+ return timingSafeEqual(m[1], expected);
133
+ }
134
+ }
135
+ function timingSafeEqual(a, b) {
136
+ // Constant-time string compare. Returns false fast on differing
137
+ // length (the length itself isn't a secret in this protocol), and
138
+ // OR-accumulates byte differences across the shorter length.
139
+ if (a.length !== b.length)
140
+ return false;
141
+ let diff = 0;
142
+ for (let i = 0; i < a.length; i++)
143
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
144
+ return diff === 0;
145
+ }
146
+ //# sourceMappingURL=metrics-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-server.js","sourceRoot":"","sources":["../../src/observability/metrics-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAsC7B,MAAM,OAAO,aAAa;IAChB,MAAM,GAAuB,IAAI,CAAC;IACzB,IAAI,CAAuB;IAE5C,YAAY,IAA0B;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,EAAE,IAAI,EAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAkB,CAAC,IAAI,EAAE,CAAC;QAC/D,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC5C,KAAK,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACvC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,+BAA+B,CAAC,CAAC;gBAC/E,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;oBACrB,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAChC,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC;QAE9B,+DAA+D;QAC/D,8DAA8D;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC;QAE3C,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;gBACvC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC5B,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAiB,CAAC;QAChD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CACnB,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAC1F,uCAAuC,CACxC,CAAC;QAEF,4DAA4D;QAC5D,0DAA0D;QAC1D,0DAA0D;QAC1D,2DAA2D;QAC3D,yCAAyC;QACzC,MAAM,UAAU,GACd,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,OAAO,CAAC;QACrF,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CACnB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAC5B,kGAAkG,CACnG,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9B,kEAAkE;YAClE,6DAA6D;YAC7D,yEAAyE;YACzE,MAAM,CAAC,oBAAoB,EAAE,EAAE,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,yBAAyB,CAAC,CAAC;IACvD,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,GAAyB,EAAE,GAAwB;QACtE,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;QAC3B,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YACzB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9B,GAAG,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QAED,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC5C,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,2BAA2B,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAChB,OAAO;QACT,CAAC;QAED,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACtD,yDAAyD;YACzD,4DAA4D;YAC5D,mDAAmD;YACnD,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjD,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;gBACrB,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,iCAAiC,CAAC,CAAC;gBACrE,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACtC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CACnB,EAAE,GAAG,EAAE,EACP,qEAAqE,CACtE,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;YACzD,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,0CAA0C,CAAC,CAAC;YAC1E,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACd,OAAO;QACT,CAAC;QAED,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACK,UAAU,CAAC,GAAyB;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACrC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,CAAC,8BAA8B;QAC1D,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC5C,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC7C,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC1C,IAAI,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACrB,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;CACF;AAED,SAAS,eAAe,CAAC,CAAS,EAAE,CAAS;IAC3C,gEAAgE;IAChE,kEAAkE;IAClE,6DAA6D;IAC7D,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -5,7 +5,7 @@
5
5
  * along with app-level metadata.
6
6
  */
7
7
  import type { ChildProcess } from 'node:child_process';
8
- import type { IProcessMetrics, IHealthStatus } from '@omnitron-dev/titan-pm';
8
+ import type { IProcessMetrics, IHealthStatus, IProcessPool } from '@omnitron-dev/titan-pm';
9
9
  import type { ProcessSupervisor } from '@omnitron-dev/titan-pm';
10
10
  import type { AppStatus, IEcosystemAppEntry, IProcessEntry } from '../config/types.js';
11
11
  import type { ServiceRouter } from './service-router.js';
@@ -29,6 +29,18 @@ export declare class AppHandle {
29
29
  serviceRouter: ServiceRouter | null;
30
30
  /** Process topology entries from defineSystem() */
31
31
  topologyProcesses: IProcessEntry[] | null;
32
+ /**
33
+ * Pool refs keyed by topology entry `name` (only for entries with
34
+ * `instances > 1` — single-instance topology runs as a supervisor
35
+ * child instead). Populated when the pool is created in
36
+ * `OrchestratorService.startBootstrapApp`; consumed by `getInfo()`
37
+ * so per-pool status reflects actual worker count instead of
38
+ * defaulting to 'stopped' (supervisor knows nothing about pool
39
+ * workers, so without this map the orchestrator would always
40
+ * report pool-managed topology entries as stopped even when they
41
+ * have N live workers).
42
+ */
43
+ topologyPools: Map<string, IProcessPool<unknown>>;
32
44
  /** Timer for classic-mode crash restart backoff (cleared on explicit stop) */
33
45
  crashRestartTimer: ReturnType<typeof setTimeout> | null;
34
46
  /** Stdout/stderr log buffer (ring buffer) */
@@ -1 +1 @@
1
- {"version":3,"file":"app-handle.d.ts","sourceRoot":"","sources":["../../src/orchestrator/app-handle.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,qBAAa,SAAS;aAgCF,KAAK,EAAE,kBAAkB;aACzB,IAAI,EAAE,SAAS,GAAG,WAAW;IAhCxC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC1B,MAAM,EAAE,SAAS,CAAa;IAC9B,SAAS,EAAE,MAAM,CAAK;IACtB,QAAQ,EAAE,MAAM,CAAK;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3B,WAAW,EAAE,eAAe,GAAG,IAAI,CAAQ;IAC3C,UAAU,EAAE,aAAa,GAAG,IAAI,CAAQ;IAE/C,mEAAmE;IAC5D,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IAEnD,6DAA6D;IACtD,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAEhD,iCAAiC;IAC1B,aAAa,EAAE,MAAM,CAAK;IAEjC,gDAAgD;IACzC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAQ;IAElD,mDAAmD;IAC5C,iBAAiB,EAAE,aAAa,EAAE,GAAG,IAAI,CAAQ;IAExD,8EAA8E;IACvE,iBAAiB,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAQ;IAEtE,6CAA6C;IAC7C,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;gBAGlB,KAAK,EAAE,kBAAkB,EACzB,IAAI,EAAE,SAAS,GAAG,WAAW;IAG/C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,MAAM,IAAI,MAAM,CAGnB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO7B,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAKjC,YAAY,IAAI,IAAI;IAKpB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,YAAY,IAAI,IAAI;IAIpB,WAAW,IAAI,IAAI;IAWnB,WAAW,IAAI,IAAI;IAInB,WAAW,IAAI,IAAI;CAIpB"}
1
+ {"version":3,"file":"app-handle.d.ts","sourceRoot":"","sources":["../../src/orchestrator/app-handle.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,qBAAa,SAAS;aA6CF,KAAK,EAAE,kBAAkB;aACzB,IAAI,EAAE,SAAS,GAAG,WAAW;IA7CxC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC1B,MAAM,EAAE,SAAS,CAAa;IAC9B,SAAS,EAAE,MAAM,CAAK;IACtB,QAAQ,EAAE,MAAM,CAAK;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3B,WAAW,EAAE,eAAe,GAAG,IAAI,CAAQ;IAC3C,UAAU,EAAE,aAAa,GAAG,IAAI,CAAQ;IAE/C,mEAAmE;IAC5D,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IAEnD,6DAA6D;IACtD,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAEhD,iCAAiC;IAC1B,aAAa,EAAE,MAAM,CAAK;IAEjC,gDAAgD;IACzC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAQ;IAElD,mDAAmD;IAC5C,iBAAiB,EAAE,aAAa,EAAE,GAAG,IAAI,CAAQ;IAExD;;;;;;;;;;OAUG;IACI,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAa;IAErE,8EAA8E;IACvE,iBAAiB,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAQ;IAEtE,6CAA6C;IAC7C,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;gBAGlB,KAAK,EAAE,kBAAkB,EACzB,IAAI,EAAE,SAAS,GAAG,WAAW;IAG/C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,MAAM,IAAI,MAAM,CAGnB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO7B,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAKjC,YAAY,IAAI,IAAI;IAKpB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,YAAY,IAAI,IAAI;IAIpB,WAAW,IAAI,IAAI;IAWnB,WAAW,IAAI,IAAI;IAInB,WAAW,IAAI,IAAI;CAIpB"}
@@ -24,6 +24,18 @@ export class AppHandle {
24
24
  serviceRouter = null;
25
25
  /** Process topology entries from defineSystem() */
26
26
  topologyProcesses = null;
27
+ /**
28
+ * Pool refs keyed by topology entry `name` (only for entries with
29
+ * `instances > 1` — single-instance topology runs as a supervisor
30
+ * child instead). Populated when the pool is created in
31
+ * `OrchestratorService.startBootstrapApp`; consumed by `getInfo()`
32
+ * so per-pool status reflects actual worker count instead of
33
+ * defaulting to 'stopped' (supervisor knows nothing about pool
34
+ * workers, so without this map the orchestrator would always
35
+ * report pool-managed topology entries as stopped even when they
36
+ * have N live workers).
37
+ */
38
+ topologyPools = new Map();
27
39
  /** Timer for classic-mode crash restart backoff (cleared on explicit stop) */
28
40
  crashRestartTimer = null;
29
41
  /** Stdout/stderr log buffer (ring buffer) */
@@ -1 +1 @@
1
- {"version":3,"file":"app-handle.js","sourceRoot":"","sources":["../../src/orchestrator/app-handle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app-handle.js","sourceRoot":"","sources":["../../src/orchestrator/app-handle.ts"],"names":[],"mappings":"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"}