@spinajs/telemetry 2.0.482

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 (214) hide show
  1. package/README.md +482 -0
  2. package/lib/cjs/InMemoryPerfSink.d.ts +51 -0
  3. package/lib/cjs/InMemoryPerfSink.d.ts.map +1 -0
  4. package/lib/cjs/InMemoryPerfSink.js +100 -0
  5. package/lib/cjs/InMemoryPerfSink.js.map +1 -0
  6. package/lib/cjs/PromMetricSink.d.ts +26 -0
  7. package/lib/cjs/PromMetricSink.d.ts.map +1 -0
  8. package/lib/cjs/PromMetricSink.js +68 -0
  9. package/lib/cjs/PromMetricSink.js.map +1 -0
  10. package/lib/cjs/bootstrap.d.ts +13 -0
  11. package/lib/cjs/bootstrap.d.ts.map +1 -0
  12. package/lib/cjs/bootstrap.js +57 -0
  13. package/lib/cjs/bootstrap.js.map +1 -0
  14. package/lib/cjs/config/telemetry.d.ts +63 -0
  15. package/lib/cjs/config/telemetry.d.ts.map +1 -0
  16. package/lib/cjs/config/telemetry.js +78 -0
  17. package/lib/cjs/config/telemetry.js.map +1 -0
  18. package/lib/cjs/controllers/Metrics.d.ts +26 -0
  19. package/lib/cjs/controllers/Metrics.d.ts.map +1 -0
  20. package/lib/cjs/controllers/Metrics.js +63 -0
  21. package/lib/cjs/controllers/Metrics.js.map +1 -0
  22. package/lib/cjs/controllers/Telemetry.d.ts +92 -0
  23. package/lib/cjs/controllers/Telemetry.d.ts.map +1 -0
  24. package/lib/cjs/controllers/Telemetry.js +226 -0
  25. package/lib/cjs/controllers/Telemetry.js.map +1 -0
  26. package/lib/cjs/dto/index.d.ts +21 -0
  27. package/lib/cjs/dto/index.d.ts.map +1 -0
  28. package/lib/cjs/dto/index.js +64 -0
  29. package/lib/cjs/dto/index.js.map +1 -0
  30. package/lib/cjs/endpoints.d.ts +32 -0
  31. package/lib/cjs/endpoints.d.ts.map +1 -0
  32. package/lib/cjs/endpoints.js +38 -0
  33. package/lib/cjs/endpoints.js.map +1 -0
  34. package/lib/cjs/health.d.ts +55 -0
  35. package/lib/cjs/health.d.ts.map +1 -0
  36. package/lib/cjs/health.js +111 -0
  37. package/lib/cjs/health.js.map +1 -0
  38. package/lib/cjs/index.d.ts +16 -0
  39. package/lib/cjs/index.d.ts.map +1 -0
  40. package/lib/cjs/index.js +32 -0
  41. package/lib/cjs/index.js.map +1 -0
  42. package/lib/cjs/metrics.d.ts +16 -0
  43. package/lib/cjs/metrics.d.ts.map +1 -0
  44. package/lib/cjs/metrics.js +32 -0
  45. package/lib/cjs/metrics.js.map +1 -0
  46. package/lib/cjs/middleware.d.ts +81 -0
  47. package/lib/cjs/middleware.d.ts.map +1 -0
  48. package/lib/cjs/middleware.js +210 -0
  49. package/lib/cjs/middleware.js.map +1 -0
  50. package/lib/cjs/package.json +1 -0
  51. package/lib/cjs/policies/PublicPolicy.d.ts +16 -0
  52. package/lib/cjs/policies/PublicPolicy.d.ts.map +1 -0
  53. package/lib/cjs/policies/PublicPolicy.js +34 -0
  54. package/lib/cjs/policies/PublicPolicy.js.map +1 -0
  55. package/lib/cjs/policies/TelemetryTokenPolicy.d.ts +19 -0
  56. package/lib/cjs/policies/TelemetryTokenPolicy.d.ts.map +1 -0
  57. package/lib/cjs/policies/TelemetryTokenPolicy.js +65 -0
  58. package/lib/cjs/policies/TelemetryTokenPolicy.js.map +1 -0
  59. package/lib/cjs/requestStats.d.ts +81 -0
  60. package/lib/cjs/requestStats.d.ts.map +1 -0
  61. package/lib/cjs/requestStats.js +134 -0
  62. package/lib/cjs/requestStats.js.map +1 -0
  63. package/lib/cjs/responses.d.ts +23 -0
  64. package/lib/cjs/responses.d.ts.map +1 -0
  65. package/lib/cjs/responses.js +35 -0
  66. package/lib/cjs/responses.js.map +1 -0
  67. package/lib/cjs/routeStats.d.ts +43 -0
  68. package/lib/cjs/routeStats.d.ts.map +1 -0
  69. package/lib/cjs/routeStats.js +59 -0
  70. package/lib/cjs/routeStats.js.map +1 -0
  71. package/lib/cjs/schemas/HealthResponse.schema.d.ts +30 -0
  72. package/lib/cjs/schemas/HealthResponse.schema.d.ts.map +1 -0
  73. package/lib/cjs/schemas/HealthResponse.schema.js +15 -0
  74. package/lib/cjs/schemas/HealthResponse.schema.js.map +1 -0
  75. package/lib/cjs/schemas/PerfResponse.schema.d.ts +56 -0
  76. package/lib/cjs/schemas/PerfResponse.schema.d.ts.map +1 -0
  77. package/lib/cjs/schemas/PerfResponse.schema.js +36 -0
  78. package/lib/cjs/schemas/PerfResponse.schema.js.map +1 -0
  79. package/lib/cjs/schemas/ReadyResponse.schema.d.ts +36 -0
  80. package/lib/cjs/schemas/ReadyResponse.schema.d.ts.map +1 -0
  81. package/lib/cjs/schemas/ReadyResponse.schema.js +23 -0
  82. package/lib/cjs/schemas/ReadyResponse.schema.js.map +1 -0
  83. package/lib/cjs/schemas/RequestStatsSnapshot.schema.d.ts +79 -0
  84. package/lib/cjs/schemas/RequestStatsSnapshot.schema.d.ts.map +1 -0
  85. package/lib/cjs/schemas/RequestStatsSnapshot.schema.js +30 -0
  86. package/lib/cjs/schemas/RequestStatsSnapshot.schema.js.map +1 -0
  87. package/lib/cjs/schemas/RoutesResponse.schema.d.ts +100 -0
  88. package/lib/cjs/schemas/RoutesResponse.schema.d.ts.map +1 -0
  89. package/lib/cjs/schemas/RoutesResponse.schema.js +25 -0
  90. package/lib/cjs/schemas/RoutesResponse.schema.js.map +1 -0
  91. package/lib/cjs/schemas/StatsResponse.schema.d.ts +158 -0
  92. package/lib/cjs/schemas/StatsResponse.schema.d.ts.map +1 -0
  93. package/lib/cjs/schemas/StatsResponse.schema.js +19 -0
  94. package/lib/cjs/schemas/StatsResponse.schema.js.map +1 -0
  95. package/lib/cjs/schemas/TimelineResponse.schema.d.ts +109 -0
  96. package/lib/cjs/schemas/TimelineResponse.schema.d.ts.map +1 -0
  97. package/lib/cjs/schemas/TimelineResponse.schema.js +28 -0
  98. package/lib/cjs/schemas/TimelineResponse.schema.js.map +1 -0
  99. package/lib/cjs/store.d.ts +58 -0
  100. package/lib/cjs/store.d.ts.map +1 -0
  101. package/lib/cjs/store.js +108 -0
  102. package/lib/cjs/store.js.map +1 -0
  103. package/lib/cjs/timeline.d.ts +48 -0
  104. package/lib/cjs/timeline.d.ts.map +1 -0
  105. package/lib/cjs/timeline.js +70 -0
  106. package/lib/cjs/timeline.js.map +1 -0
  107. package/lib/mjs/InMemoryPerfSink.d.ts +51 -0
  108. package/lib/mjs/InMemoryPerfSink.d.ts.map +1 -0
  109. package/lib/mjs/InMemoryPerfSink.js +97 -0
  110. package/lib/mjs/InMemoryPerfSink.js.map +1 -0
  111. package/lib/mjs/PromMetricSink.d.ts +26 -0
  112. package/lib/mjs/PromMetricSink.d.ts.map +1 -0
  113. package/lib/mjs/PromMetricSink.js +65 -0
  114. package/lib/mjs/PromMetricSink.js.map +1 -0
  115. package/lib/mjs/bootstrap.d.ts +13 -0
  116. package/lib/mjs/bootstrap.d.ts.map +1 -0
  117. package/lib/mjs/bootstrap.js +54 -0
  118. package/lib/mjs/bootstrap.js.map +1 -0
  119. package/lib/mjs/config/telemetry.d.ts +63 -0
  120. package/lib/mjs/config/telemetry.d.ts.map +1 -0
  121. package/lib/mjs/config/telemetry.js +76 -0
  122. package/lib/mjs/config/telemetry.js.map +1 -0
  123. package/lib/mjs/controllers/Metrics.d.ts +26 -0
  124. package/lib/mjs/controllers/Metrics.d.ts.map +1 -0
  125. package/lib/mjs/controllers/Metrics.js +60 -0
  126. package/lib/mjs/controllers/Metrics.js.map +1 -0
  127. package/lib/mjs/controllers/Telemetry.d.ts +92 -0
  128. package/lib/mjs/controllers/Telemetry.d.ts.map +1 -0
  129. package/lib/mjs/controllers/Telemetry.js +223 -0
  130. package/lib/mjs/controllers/Telemetry.js.map +1 -0
  131. package/lib/mjs/dto/index.d.ts +21 -0
  132. package/lib/mjs/dto/index.d.ts.map +1 -0
  133. package/lib/mjs/dto/index.js +58 -0
  134. package/lib/mjs/dto/index.js.map +1 -0
  135. package/lib/mjs/endpoints.d.ts +32 -0
  136. package/lib/mjs/endpoints.d.ts.map +1 -0
  137. package/lib/mjs/endpoints.js +34 -0
  138. package/lib/mjs/endpoints.js.map +1 -0
  139. package/lib/mjs/health.d.ts +55 -0
  140. package/lib/mjs/health.d.ts.map +1 -0
  141. package/lib/mjs/health.js +107 -0
  142. package/lib/mjs/health.js.map +1 -0
  143. package/lib/mjs/index.d.ts +16 -0
  144. package/lib/mjs/index.d.ts.map +1 -0
  145. package/lib/mjs/index.js +16 -0
  146. package/lib/mjs/index.js.map +1 -0
  147. package/lib/mjs/metrics.d.ts +16 -0
  148. package/lib/mjs/metrics.d.ts.map +1 -0
  149. package/lib/mjs/metrics.js +16 -0
  150. package/lib/mjs/metrics.js.map +1 -0
  151. package/lib/mjs/middleware.d.ts +81 -0
  152. package/lib/mjs/middleware.d.ts.map +1 -0
  153. package/lib/mjs/middleware.js +207 -0
  154. package/lib/mjs/middleware.js.map +1 -0
  155. package/lib/mjs/package.json +1 -0
  156. package/lib/mjs/policies/PublicPolicy.d.ts +16 -0
  157. package/lib/mjs/policies/PublicPolicy.d.ts.map +1 -0
  158. package/lib/mjs/policies/PublicPolicy.js +31 -0
  159. package/lib/mjs/policies/PublicPolicy.js.map +1 -0
  160. package/lib/mjs/policies/TelemetryTokenPolicy.d.ts +19 -0
  161. package/lib/mjs/policies/TelemetryTokenPolicy.d.ts.map +1 -0
  162. package/lib/mjs/policies/TelemetryTokenPolicy.js +62 -0
  163. package/lib/mjs/policies/TelemetryTokenPolicy.js.map +1 -0
  164. package/lib/mjs/requestStats.d.ts +81 -0
  165. package/lib/mjs/requestStats.d.ts.map +1 -0
  166. package/lib/mjs/requestStats.js +130 -0
  167. package/lib/mjs/requestStats.js.map +1 -0
  168. package/lib/mjs/responses.d.ts +23 -0
  169. package/lib/mjs/responses.d.ts.map +1 -0
  170. package/lib/mjs/responses.js +30 -0
  171. package/lib/mjs/responses.js.map +1 -0
  172. package/lib/mjs/routeStats.d.ts +43 -0
  173. package/lib/mjs/routeStats.d.ts.map +1 -0
  174. package/lib/mjs/routeStats.js +55 -0
  175. package/lib/mjs/routeStats.js.map +1 -0
  176. package/lib/mjs/schemas/HealthResponse.schema.d.ts +30 -0
  177. package/lib/mjs/schemas/HealthResponse.schema.d.ts.map +1 -0
  178. package/lib/mjs/schemas/HealthResponse.schema.js +13 -0
  179. package/lib/mjs/schemas/HealthResponse.schema.js.map +1 -0
  180. package/lib/mjs/schemas/PerfResponse.schema.d.ts +56 -0
  181. package/lib/mjs/schemas/PerfResponse.schema.d.ts.map +1 -0
  182. package/lib/mjs/schemas/PerfResponse.schema.js +34 -0
  183. package/lib/mjs/schemas/PerfResponse.schema.js.map +1 -0
  184. package/lib/mjs/schemas/ReadyResponse.schema.d.ts +36 -0
  185. package/lib/mjs/schemas/ReadyResponse.schema.d.ts.map +1 -0
  186. package/lib/mjs/schemas/ReadyResponse.schema.js +21 -0
  187. package/lib/mjs/schemas/ReadyResponse.schema.js.map +1 -0
  188. package/lib/mjs/schemas/RequestStatsSnapshot.schema.d.ts +79 -0
  189. package/lib/mjs/schemas/RequestStatsSnapshot.schema.d.ts.map +1 -0
  190. package/lib/mjs/schemas/RequestStatsSnapshot.schema.js +28 -0
  191. package/lib/mjs/schemas/RequestStatsSnapshot.schema.js.map +1 -0
  192. package/lib/mjs/schemas/RoutesResponse.schema.d.ts +100 -0
  193. package/lib/mjs/schemas/RoutesResponse.schema.d.ts.map +1 -0
  194. package/lib/mjs/schemas/RoutesResponse.schema.js +20 -0
  195. package/lib/mjs/schemas/RoutesResponse.schema.js.map +1 -0
  196. package/lib/mjs/schemas/StatsResponse.schema.d.ts +158 -0
  197. package/lib/mjs/schemas/StatsResponse.schema.d.ts.map +1 -0
  198. package/lib/mjs/schemas/StatsResponse.schema.js +14 -0
  199. package/lib/mjs/schemas/StatsResponse.schema.js.map +1 -0
  200. package/lib/mjs/schemas/TimelineResponse.schema.d.ts +109 -0
  201. package/lib/mjs/schemas/TimelineResponse.schema.d.ts.map +1 -0
  202. package/lib/mjs/schemas/TimelineResponse.schema.js +23 -0
  203. package/lib/mjs/schemas/TimelineResponse.schema.js.map +1 -0
  204. package/lib/mjs/store.d.ts +58 -0
  205. package/lib/mjs/store.d.ts.map +1 -0
  206. package/lib/mjs/store.js +105 -0
  207. package/lib/mjs/store.js.map +1 -0
  208. package/lib/mjs/timeline.d.ts +48 -0
  209. package/lib/mjs/timeline.d.ts.map +1 -0
  210. package/lib/mjs/timeline.js +66 -0
  211. package/lib/mjs/timeline.js.map +1 -0
  212. package/lib/tsconfig.cjs.tsbuildinfo +1 -0
  213. package/lib/tsconfig.mjs.tsbuildinfo +1 -0
  214. package/package.json +69 -0
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.TelemetryController = void 0;
16
+ const http_1 = require("@spinajs/http");
17
+ const di_1 = require("@spinajs/di");
18
+ const configuration_1 = require("@spinajs/configuration");
19
+ const exceptions_1 = require("@spinajs/exceptions");
20
+ const store_js_1 = require("./../store.js");
21
+ const InMemoryPerfSink_js_1 = require("./../InMemoryPerfSink.js");
22
+ const health_js_1 = require("./../health.js");
23
+ const responses_js_1 = require("./../responses.js");
24
+ // Importing the DTO barrel runs the @Schema decorators, which is what makes the
25
+ // response schemas resolvable by name in the generated OpenAPI document.
26
+ require("./../dto/index.js");
27
+ // Same reason, for security rather than documentation: importing the policy
28
+ // modules runs their @Injectable decorators, which is what puts the classes in
29
+ // the DI container under the names the routes below name as STRINGS ( via
30
+ // `telemetry.auth.policies.*` ). Nothing else forces them to load — this
31
+ // controller is mounted by the config-declared directory scan, and that
32
+ // configuration is auto-discovered from node_modules, so an app never has to
33
+ // import the package barrel. And http FAILS OPEN on an unresolvable policy name
34
+ // ( it logs `No policy named ...`, drops it, and a route left with no policies
35
+ // calls next() ), which would serve these endpoints unauthenticated.
36
+ require("./../policies/TelemetryTokenPolicy.js");
37
+ require("./../policies/PublicPolicy.js");
38
+ /**
39
+ * JSON telemetry API. Machine-facing — consumed by dashboards, uptime monitors
40
+ * and orchestrator probes.
41
+ *
42
+ * The prometheus scrape endpoint deliberately lives on its own controller at
43
+ * the bare `/metrics` path, not under this prefix.
44
+ */
45
+ let TelemetryController = class TelemetryController extends http_1.BaseController {
46
+ /**
47
+ * Lifetime request statistics plus the rolling timeline.
48
+ *
49
+ * @returns {StatsResponse} Lifetime stats and the per-bucket timeline
50
+ * @response 403 Access token missing or invalid
51
+ */
52
+ async getStats() {
53
+ const stats = this.Store.RequestStats;
54
+ // Rates are not maintained on the hot path — they are derived here, over the
55
+ // whole collection window, or `req_rate` / `err_rate` would always read 0.
56
+ stats.updateRates(Date.now() - this.Store.StartedAt);
57
+ return new http_1.Ok({
58
+ all: stats.toJSON(),
59
+ timeline: this.Store.Timeline.toJSON(),
60
+ });
61
+ }
62
+ /**
63
+ * The rolling timeline alone, with each bucket annotated with the wall-clock
64
+ * window it covers so consumers do not have to reverse the bucket key.
65
+ *
66
+ * @param buckets - how many of the most recent buckets to return; all of them when omitted
67
+ * @returns {TimelineResponse} The annotated timeline
68
+ * @response 400 `buckets` was not a positive integer
69
+ * @response 403 Access token missing or invalid
70
+ */
71
+ async getTimeline(buckets) {
72
+ const timeline = this.Store.Timeline;
73
+ const snapshot = timeline.toJSON();
74
+ let keys = Object.keys(snapshot)
75
+ .map((k) => Number(k))
76
+ .sort((a, b) => a - b);
77
+ // Only a genuinely ABSENT `buckets` means "all of them". An explicitly empty
78
+ // `?buckets=` is a supplied value that is not a positive integer, so it is
79
+ // rejected like every other invalid one rather than silently meaning "all".
80
+ if (buckets !== undefined && buckets !== null) {
81
+ // Taken as a string and parsed here rather than declared `number` and left
82
+ // to the decorator's schema: a query value arrives as a string, and how the
83
+ // framework coerces a non-numeric one ( `Number( 'abc' )` -> NaN, rejected
84
+ // by the arg validator with a generic message ) is not something this
85
+ // endpoint's contract should depend on.
86
+ //
87
+ // `Number( '' )` is 0, not NaN, so the empty string falls through to the
88
+ // `count < 1` rejection below on its own.
89
+ const count = Number(buckets);
90
+ if (!Number.isInteger(count) || count < 1) {
91
+ throw new exceptions_1.BadRequest('buckets must be a positive integer');
92
+ }
93
+ // The most recent N — the tail of an ascending key order.
94
+ keys = keys.slice(-count);
95
+ }
96
+ return new http_1.Ok({
97
+ bucketMs: timeline.bucketMs,
98
+ length: timeline.length,
99
+ buckets: keys.map((key) => ({
100
+ key,
101
+ from: key * timeline.bucketMs,
102
+ to: (key + 1) * timeline.bucketMs,
103
+ stats: snapshot[String(key)],
104
+ })),
105
+ });
106
+ }
107
+ /**
108
+ * Per method+route request breakdown.
109
+ *
110
+ * No percentiles — query them from prometheus against the `route`-labelled
111
+ * `http_request_duration_ms` histogram, which carries the same label values.
112
+ *
113
+ * @returns {RoutesResponse} Per-route request statistics
114
+ * @response 403 Access token missing or invalid
115
+ */
116
+ async getRoutes() {
117
+ return new http_1.Ok(this.Store.RouteStats.toJSON());
118
+ }
119
+ /**
120
+ * Aggregated performance measurements collected through the `Perf` facade —
121
+ * every `Perf.measure`, `@Measure`, `Perf.count` and `Perf.value` in the
122
+ * process, including the ORM's `orm.query` spans.
123
+ *
124
+ * @returns {PerfResponse} Aggregated spans and events
125
+ * @response 403 Access token missing or invalid
126
+ */
127
+ async getPerf() {
128
+ return new http_1.Ok(this.PerfSink.toJSON());
129
+ }
130
+ /**
131
+ * Liveness. Runs no checks, so it can never be made slow or flaky by a
132
+ * dependency — if this answers, the process is alive.
133
+ *
134
+ * @returns {HealthResponse} Process liveness information
135
+ */
136
+ async getHealth() {
137
+ const uptimeMs = Math.round(process.uptime() * 1000);
138
+ return new http_1.Ok({
139
+ status: 'up',
140
+ startedAt: Date.now() - uptimeMs,
141
+ uptimeMs,
142
+ pid: process.pid,
143
+ node: process.version,
144
+ // omitted rather than reported as null when `telemetry.health.version` is unset
145
+ ...(this.Version ? { version: this.Version } : {}),
146
+ });
147
+ }
148
+ /**
149
+ * Readiness. Runs every registered `HealthCheck`, each raced against
150
+ * `telemetry.health.timeoutMs`.
151
+ *
152
+ * @returns {ReadyResponse} Overall readiness and the per-check results
153
+ * @response 503 At least one check is down ( or degraded, when `telemetry.health.failOnDegraded` is set )
154
+ */
155
+ async getReady() {
156
+ const report = await this.Health.run();
157
+ if (this.Health.isFailing(report.status)) {
158
+ return new responses_js_1.ServiceUnavailable(report);
159
+ }
160
+ return new http_1.Ok(report);
161
+ }
162
+ };
163
+ exports.TelemetryController = TelemetryController;
164
+ __decorate([
165
+ (0, di_1.Autoinject)(store_js_1.TelemetryStore),
166
+ __metadata("design:type", store_js_1.TelemetryStore)
167
+ ], TelemetryController.prototype, "Store", void 0);
168
+ __decorate([
169
+ (0, di_1.Autoinject)(InMemoryPerfSink_js_1.InMemoryPerfSink),
170
+ __metadata("design:type", InMemoryPerfSink_js_1.InMemoryPerfSink)
171
+ ], TelemetryController.prototype, "PerfSink", void 0);
172
+ __decorate([
173
+ (0, di_1.Autoinject)(health_js_1.HealthCheckRunner),
174
+ __metadata("design:type", health_js_1.HealthCheckRunner)
175
+ ], TelemetryController.prototype, "Health", void 0);
176
+ __decorate([
177
+ (0, configuration_1.Config)('telemetry.health.version'),
178
+ __metadata("design:type", String)
179
+ ], TelemetryController.prototype, "Version", void 0);
180
+ __decorate([
181
+ (0, http_1.Get)('stats'),
182
+ (0, http_1.Policy)('telemetry.auth.policies.stats'),
183
+ __metadata("design:type", Function),
184
+ __metadata("design:paramtypes", []),
185
+ __metadata("design:returntype", Promise)
186
+ ], TelemetryController.prototype, "getStats", null);
187
+ __decorate([
188
+ (0, http_1.Get)('timeline'),
189
+ (0, http_1.Policy)('telemetry.auth.policies.timeline'),
190
+ __param(0, (0, http_1.Query)()),
191
+ __metadata("design:type", Function),
192
+ __metadata("design:paramtypes", [String]),
193
+ __metadata("design:returntype", Promise)
194
+ ], TelemetryController.prototype, "getTimeline", null);
195
+ __decorate([
196
+ (0, http_1.Get)('routes'),
197
+ (0, http_1.Policy)('telemetry.auth.policies.routes'),
198
+ __metadata("design:type", Function),
199
+ __metadata("design:paramtypes", []),
200
+ __metadata("design:returntype", Promise)
201
+ ], TelemetryController.prototype, "getRoutes", null);
202
+ __decorate([
203
+ (0, http_1.Get)('perf'),
204
+ (0, http_1.Policy)('telemetry.auth.policies.perf'),
205
+ __metadata("design:type", Function),
206
+ __metadata("design:paramtypes", []),
207
+ __metadata("design:returntype", Promise)
208
+ ], TelemetryController.prototype, "getPerf", null);
209
+ __decorate([
210
+ (0, http_1.Get)('health'),
211
+ (0, http_1.Policy)('telemetry.auth.policies.health'),
212
+ __metadata("design:type", Function),
213
+ __metadata("design:paramtypes", []),
214
+ __metadata("design:returntype", Promise)
215
+ ], TelemetryController.prototype, "getHealth", null);
216
+ __decorate([
217
+ (0, http_1.Get)('ready'),
218
+ (0, http_1.Policy)('telemetry.auth.policies.ready'),
219
+ __metadata("design:type", Function),
220
+ __metadata("design:paramtypes", []),
221
+ __metadata("design:returntype", Promise)
222
+ ], TelemetryController.prototype, "getReady", null);
223
+ exports.TelemetryController = TelemetryController = __decorate([
224
+ (0, http_1.BasePath)('telemetry')
225
+ ], TelemetryController);
226
+ //# sourceMappingURL=Telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Telemetry.js","sourceRoot":"","sources":["../../../src/controllers/Telemetry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Response shapes for the telemetry endpoints.
3
+ *
4
+ * These classes are never instantiated — they exist so `@Schema` registers each
5
+ * JSON schema under the class name, which is how http-swagger resolves a
6
+ * `@returns {StatsResponse}` JSDoc tag into a `#/components/schemas/...`
7
+ * component. The controller imports this module so the decorators run.
8
+ */
9
+ export declare class StatsResponse {
10
+ }
11
+ export declare class TimelineResponse {
12
+ }
13
+ export declare class RoutesResponse {
14
+ }
15
+ export declare class PerfResponse {
16
+ }
17
+ export declare class HealthResponse {
18
+ }
19
+ export declare class ReadyResponse {
20
+ }
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dto/index.ts"],"names":[],"mappings":"AASA;;;;;;;GAOG;AAEH,qBACa,aAAa;CAAG;AAE7B,qBACa,gBAAgB;CAAG;AAEhC,qBACa,cAAc;CAAG;AAE9B,qBACa,YAAY;CAAG;AAE5B,qBACa,cAAc;CAAG;AAE9B,qBACa,aAAa;CAAG"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ReadyResponse = exports.HealthResponse = exports.PerfResponse = exports.RoutesResponse = exports.TimelineResponse = exports.StatsResponse = void 0;
13
+ const validation_1 = require("@spinajs/validation");
14
+ const StatsResponse_schema_js_1 = __importDefault(require("./../schemas/StatsResponse.schema.js"));
15
+ const TimelineResponse_schema_js_1 = __importDefault(require("./../schemas/TimelineResponse.schema.js"));
16
+ const RoutesResponse_schema_js_1 = __importDefault(require("./../schemas/RoutesResponse.schema.js"));
17
+ const PerfResponse_schema_js_1 = __importDefault(require("./../schemas/PerfResponse.schema.js"));
18
+ const HealthResponse_schema_js_1 = __importDefault(require("./../schemas/HealthResponse.schema.js"));
19
+ const ReadyResponse_schema_js_1 = __importDefault(require("./../schemas/ReadyResponse.schema.js"));
20
+ /**
21
+ * Response shapes for the telemetry endpoints.
22
+ *
23
+ * These classes are never instantiated — they exist so `@Schema` registers each
24
+ * JSON schema under the class name, which is how http-swagger resolves a
25
+ * `@returns {StatsResponse}` JSDoc tag into a `#/components/schemas/...`
26
+ * component. The controller imports this module so the decorators run.
27
+ */
28
+ let StatsResponse = class StatsResponse {
29
+ };
30
+ exports.StatsResponse = StatsResponse;
31
+ exports.StatsResponse = StatsResponse = __decorate([
32
+ (0, validation_1.Schema)(StatsResponse_schema_js_1.default)
33
+ ], StatsResponse);
34
+ let TimelineResponse = class TimelineResponse {
35
+ };
36
+ exports.TimelineResponse = TimelineResponse;
37
+ exports.TimelineResponse = TimelineResponse = __decorate([
38
+ (0, validation_1.Schema)(TimelineResponse_schema_js_1.default)
39
+ ], TimelineResponse);
40
+ let RoutesResponse = class RoutesResponse {
41
+ };
42
+ exports.RoutesResponse = RoutesResponse;
43
+ exports.RoutesResponse = RoutesResponse = __decorate([
44
+ (0, validation_1.Schema)(RoutesResponse_schema_js_1.default)
45
+ ], RoutesResponse);
46
+ let PerfResponse = class PerfResponse {
47
+ };
48
+ exports.PerfResponse = PerfResponse;
49
+ exports.PerfResponse = PerfResponse = __decorate([
50
+ (0, validation_1.Schema)(PerfResponse_schema_js_1.default)
51
+ ], PerfResponse);
52
+ let HealthResponse = class HealthResponse {
53
+ };
54
+ exports.HealthResponse = HealthResponse;
55
+ exports.HealthResponse = HealthResponse = __decorate([
56
+ (0, validation_1.Schema)(HealthResponse_schema_js_1.default)
57
+ ], HealthResponse);
58
+ let ReadyResponse = class ReadyResponse {
59
+ };
60
+ exports.ReadyResponse = ReadyResponse;
61
+ exports.ReadyResponse = ReadyResponse = __decorate([
62
+ (0, validation_1.Schema)(ReadyResponse_schema_js_1.default)
63
+ ], ReadyResponse);
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/dto/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA6C;AAE7C,mGAAuE;AACvE,yGAA6E;AAC7E,qGAAyE;AACzE,iGAAqE;AACrE,qGAAyE;AACzE,mGAAuE;AAEvE;;;;;;;GAOG;AAGI,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAM,EAAC,iCAAmB,CAAC;GACf,aAAa,CAAG;AAGtB,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAAG,CAAA;AAAnB,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAM,EAAC,oCAAsB,CAAC;GAClB,gBAAgB,CAAG;AAGzB,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAM,EAAC,kCAAoB,CAAC;GAChB,cAAc,CAAG;AAGvB,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAM,EAAC,gCAAkB,CAAC;GACd,YAAY,CAAG;AAGrB,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAM,EAAC,kCAAoB,CAAC;GAChB,cAAc,CAAG;AAGvB,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAM,EAAC,iCAAmB,CAAC;GACf,aAAa,CAAG"}
@@ -0,0 +1,32 @@
1
+ import { Metrics } from './metrics.js';
2
+ import { TelemetryStore } from './store.js';
3
+ /**
4
+ * Minimal request/response shapes the endpoint handlers rely on. Kept
5
+ * intentionally structural ( `setHeader` / `end` ) so the handlers are not
6
+ * coupled to express beyond what a plain Node `ServerResponse` provides.
7
+ */
8
+ export interface IMinimalResponse {
9
+ setHeader(name: string, value: string): void;
10
+ statusCode?: number;
11
+ end(body?: string): void;
12
+ }
13
+ export type MinimalRequest = unknown;
14
+ /**
15
+ * Build the Prometheus `/metrics` scrape handler.
16
+ *
17
+ * Sets `Content-Type` from the registry and writes the ( async-rendered )
18
+ * exposition text.
19
+ */
20
+ export declare function metricsHandler(metrics: Metrics): (req: MinimalRequest, res: IMinimalResponse) => Promise<void>;
21
+ /**
22
+ * Build the JSON stats handler.
23
+ *
24
+ * Writes `{ all: RequestStats.toJSON(), timeline: Timeline.toJSON() }` read
25
+ * from the shared telemetry store — the same counters `GET /telemetry/stats`
26
+ * serves. The rate fields differ though: only the controller endpoint calls
27
+ * `RequestStats.updateRates( ... )`, and because that MUTATES the shared
28
+ * `RequestStats`, the `req_rate` / `err_rate` this handler emits are whatever
29
+ * the last `/telemetry/stats` call left behind ( `0` if nobody has called it ).
30
+ */
31
+ export declare function statsHandler(store: TelemetryStore): (req: MinimalRequest, res: IMinimalResponse) => void;
32
+ //# sourceMappingURL=endpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../../src/endpoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC;AAErC;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAM9G;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,gBAAgB,KAAK,IAAI,CASxG"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.metricsHandler = metricsHandler;
4
+ exports.statsHandler = statsHandler;
5
+ /**
6
+ * Build the Prometheus `/metrics` scrape handler.
7
+ *
8
+ * Sets `Content-Type` from the registry and writes the ( async-rendered )
9
+ * exposition text.
10
+ */
11
+ function metricsHandler(metrics) {
12
+ return async (_req, res) => {
13
+ const body = await metrics.render();
14
+ res.setHeader('Content-Type', metrics.contentType());
15
+ res.end(body);
16
+ };
17
+ }
18
+ /**
19
+ * Build the JSON stats handler.
20
+ *
21
+ * Writes `{ all: RequestStats.toJSON(), timeline: Timeline.toJSON() }` read
22
+ * from the shared telemetry store — the same counters `GET /telemetry/stats`
23
+ * serves. The rate fields differ though: only the controller endpoint calls
24
+ * `RequestStats.updateRates( ... )`, and because that MUTATES the shared
25
+ * `RequestStats`, the `req_rate` / `err_rate` this handler emits are whatever
26
+ * the last `/telemetry/stats` call left behind ( `0` if nobody has called it ).
27
+ */
28
+ function statsHandler(store) {
29
+ return (_req, res) => {
30
+ const body = JSON.stringify({
31
+ all: store.RequestStats.toJSON(),
32
+ timeline: store.Timeline.toJSON(),
33
+ });
34
+ res.setHeader('Content-Type', 'application/json');
35
+ res.end(body);
36
+ };
37
+ }
38
+ //# sourceMappingURL=endpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoints.js","sourceRoot":"","sources":["../../src/endpoints.ts"],"names":[],"mappings":";;AAsBA,wCAMC;AAYD,oCASC;AAjCD;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,OAAgB;IAC7C,OAAO,KAAK,EAAE,IAAoB,EAAE,GAAqB,EAAiB,EAAE;QAC1E,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;QACpC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAAC,KAAqB;IAChD,OAAO,CAAC,IAAoB,EAAE,GAAqB,EAAQ,EAAE;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,GAAG,EAAE,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE;YAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE;SAClC,CAAC,CAAC;QACH,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAClD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { AsyncService } from '@spinajs/di';
2
+ /** Outcome of a single health check. */
3
+ export type HealthStatus = 'up' | 'degraded' | 'down';
4
+ /** What a {@link HealthCheck} returns. */
5
+ export interface IHealthResult {
6
+ status: HealthStatus;
7
+ message?: string;
8
+ data?: Record<string, unknown>;
9
+ }
10
+ /** One check's line in the readiness report. */
11
+ export interface IHealthCheckReport extends IHealthResult {
12
+ name: string;
13
+ /** How long the check took, in ms. */
14
+ durationMs: number;
15
+ }
16
+ /** The body served by `GET /telemetry/ready`. */
17
+ export interface IReadyReport {
18
+ status: HealthStatus;
19
+ checks: IHealthCheckReport[];
20
+ }
21
+ /**
22
+ * A readiness probe for one dependency.
23
+ *
24
+ * Register a concrete subclass with `@Injectable( HealthCheck )` and it is
25
+ * discovered by {@link HealthCheckRunner} via `Array.ofType( HealthCheck )`.
26
+ * `@spinajs/telemetry` deliberately ships NO concrete checks — a database check
27
+ * belongs where the database dependency already is, not in the observability
28
+ * package.
29
+ *
30
+ * `check()` may throw; a throw counts as `down`.
31
+ */
32
+ export declare abstract class HealthCheck extends AsyncService {
33
+ /** Stable identifier for this check, used as the report key. */
34
+ abstract Name: string;
35
+ abstract check(): Promise<IHealthResult>;
36
+ }
37
+ /**
38
+ * Runs every registered {@link HealthCheck} concurrently, each raced against a
39
+ * per-check timeout, and reduces the results to one overall status.
40
+ *
41
+ * The timeout is the point of the class: a readiness endpoint that can hang is
42
+ * worse than no readiness endpoint, because a kubelet probe blocks on it.
43
+ */
44
+ export declare class HealthCheckRunner {
45
+ protected Checks: HealthCheck[];
46
+ protected TimeoutMs: number;
47
+ protected FailOnDegraded: boolean;
48
+ /**
49
+ * True when the overall status should be served as HTTP 503.
50
+ */
51
+ isFailing(status: HealthStatus): boolean;
52
+ run(): Promise<IReadyReport>;
53
+ private runOne;
54
+ }
55
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqC,MAAM,aAAa,CAAC;AAG9E,wCAAwC;AACxC,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC;AAEtD,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,gDAAgD;AAChD,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,8BAAsB,WAAY,SAAQ,YAAY;IACpD,gEAAgE;IAChE,SAAgB,IAAI,EAAE,MAAM,CAAC;aAEb,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC;CAChD;AAkBD;;;;;;GAMG;AACH,qBAEa,iBAAiB;IAE5B,SAAS,CAAC,MAAM,EAAG,WAAW,EAAE,CAAC;IAGjC,SAAS,CAAC,SAAS,EAAG,MAAM,CAAC;IAG7B,SAAS,CAAC,cAAc,EAAG,OAAO,CAAC;IAEnC;;OAEG;IACI,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAKlC,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC;YAe3B,MAAM;CAqBrB"}
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.HealthCheckRunner = exports.HealthCheck = void 0;
13
+ const di_1 = require("@spinajs/di");
14
+ const configuration_1 = require("@spinajs/configuration");
15
+ /**
16
+ * A readiness probe for one dependency.
17
+ *
18
+ * Register a concrete subclass with `@Injectable( HealthCheck )` and it is
19
+ * discovered by {@link HealthCheckRunner} via `Array.ofType( HealthCheck )`.
20
+ * `@spinajs/telemetry` deliberately ships NO concrete checks — a database check
21
+ * belongs where the database dependency already is, not in the observability
22
+ * package.
23
+ *
24
+ * `check()` may throw; a throw counts as `down`.
25
+ */
26
+ class HealthCheck extends di_1.AsyncService {
27
+ }
28
+ exports.HealthCheck = HealthCheck;
29
+ const RANK = { up: 0, degraded: 1, down: 2 };
30
+ /**
31
+ * Severity of one check's status, for the reduction in {@link HealthCheckRunner.run}.
32
+ *
33
+ * An unrecognised value ranks as `down`, not as harmless: `HealthStatus` is only
34
+ * enforced at compile time, so a JS consumer ( or a check that forwards a status
35
+ * from somewhere else ) can return `'DOWN'` or `'UNHEALTHY'`. A plain
36
+ * `RANK[status] > RANK[worst]` reads `undefined` for those, and `undefined > n`
37
+ * is false, so a genuinely failing dependency would leave the overall status at
38
+ * `up` and `/telemetry/ready` would answer 200.
39
+ */
40
+ function rank(status) {
41
+ return RANK[status] ?? RANK.down;
42
+ }
43
+ /**
44
+ * Runs every registered {@link HealthCheck} concurrently, each raced against a
45
+ * per-check timeout, and reduces the results to one overall status.
46
+ *
47
+ * The timeout is the point of the class: a readiness endpoint that can hang is
48
+ * worse than no readiness endpoint, because a kubelet probe blocks on it.
49
+ */
50
+ let HealthCheckRunner = class HealthCheckRunner {
51
+ /**
52
+ * True when the overall status should be served as HTTP 503.
53
+ */
54
+ isFailing(status) {
55
+ if (status === 'down')
56
+ return true;
57
+ return status === 'degraded' && this.FailOnDegraded === true;
58
+ }
59
+ async run() {
60
+ const checks = await Promise.all((this.Checks ?? []).map((c) => this.runOne(c)));
61
+ let worst = 'up';
62
+ for (const c of checks) {
63
+ // The unrecognised status is reduced AS `down`, but the check's own line in
64
+ // the report keeps the string the check actually returned — that value is
65
+ // the only clue an operator has that a check is misbehaving, and rewriting
66
+ // it would hide the misconfiguration behind a correct-looking report.
67
+ if (rank(c.status) > rank(worst))
68
+ worst = RANK[c.status] !== undefined ? c.status : 'down';
69
+ }
70
+ return { status: worst, checks };
71
+ }
72
+ async runOne(check) {
73
+ const startedAt = Date.now();
74
+ const timeoutMs = this.TimeoutMs ?? 2000;
75
+ let timer;
76
+ try {
77
+ const result = await Promise.race([
78
+ check.check(),
79
+ new Promise((_, reject) => {
80
+ timer = setTimeout(() => reject(new Error(`health check timed out after ${timeoutMs}ms`)), timeoutMs);
81
+ }),
82
+ ]);
83
+ return { name: check.Name, status: result.status, message: result.message, data: result.data, durationMs: Date.now() - startedAt };
84
+ }
85
+ catch (err) {
86
+ return { name: check.Name, status: 'down', message: err?.message ?? String(err), durationMs: Date.now() - startedAt };
87
+ }
88
+ finally {
89
+ if (timer)
90
+ clearTimeout(timer);
91
+ }
92
+ }
93
+ };
94
+ exports.HealthCheckRunner = HealthCheckRunner;
95
+ __decorate([
96
+ (0, di_1.Autoinject)(HealthCheck),
97
+ __metadata("design:type", Array)
98
+ ], HealthCheckRunner.prototype, "Checks", void 0);
99
+ __decorate([
100
+ (0, configuration_1.Config)('telemetry.health.timeoutMs', { defaultValue: 2000 }),
101
+ __metadata("design:type", Number)
102
+ ], HealthCheckRunner.prototype, "TimeoutMs", void 0);
103
+ __decorate([
104
+ (0, configuration_1.Config)('telemetry.health.failOnDegraded', { defaultValue: false }),
105
+ __metadata("design:type", Boolean)
106
+ ], HealthCheckRunner.prototype, "FailOnDegraded", void 0);
107
+ exports.HealthCheckRunner = HealthCheckRunner = __decorate([
108
+ (0, di_1.Singleton)(),
109
+ (0, di_1.Injectable)()
110
+ ], HealthCheckRunner);
111
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/health.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oCAA8E;AAC9E,0DAAgD;AAyBhD;;;;;;;;;;GAUG;AACH,MAAsB,WAAY,SAAQ,iBAAY;CAKrD;AALD,kCAKC;AAED,MAAM,IAAI,GAAiC,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAE3E;;;;;;;;;GASG;AACH,SAAS,IAAI,CAAC,MAAoB;IAChC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AAGI,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAU5B;;OAEG;IACI,SAAS,CAAC,MAAoB;QACnC,IAAI,MAAM,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QACnC,OAAO,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC;IAC/D,CAAC;IAEM,KAAK,CAAC,GAAG;QACd,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjF,IAAI,KAAK,GAAiB,IAAI,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,4EAA4E;YAC5E,0EAA0E;YAC1E,2EAA2E;YAC3E,sEAAsE;YACtE,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;gBAAE,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAC7F,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,KAAkB;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;QAEzC,IAAI,KAAiC,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;gBAChC,KAAK,CAAC,KAAK,EAAE;gBACb,IAAI,OAAO,CAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;oBACvC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,SAAS,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;gBACxG,CAAC,CAAC;aACH,CAAC,CAAC;YAEH,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;QACrI,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAG,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;QACnI,CAAC;gBAAS,CAAC;YACT,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;CACF,CAAA;AAtDY,8CAAiB;AAElB;IADT,IAAA,eAAU,EAAC,WAAW,CAAC;;iDACS;AAGvB;IADT,IAAA,sBAAM,EAAC,4BAA4B,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;;oDAChC;AAGnB;IADT,IAAA,sBAAM,EAAC,iCAAiC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;;yDAChC;4BARxB,iBAAiB;IAF7B,IAAA,cAAS,GAAE;IACX,IAAA,eAAU,GAAE;GACA,iBAAiB,CAsD7B"}
@@ -0,0 +1,16 @@
1
+ export * from './metrics.js';
2
+ export * from './bootstrap.js';
3
+ export * from './InMemoryPerfSink.js';
4
+ export * from './requestStats.js';
5
+ export * from './timeline.js';
6
+ export * from './routeStats.js';
7
+ export * from './store.js';
8
+ export * from './middleware.js';
9
+ export * from './endpoints.js';
10
+ export * from './PromMetricSink.js';
11
+ export * from './policies/TelemetryTokenPolicy.js';
12
+ export * from './policies/PublicPolicy.js';
13
+ export * from './responses.js';
14
+ export * from './health.js';
15
+ export * from './dto/index.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./metrics.js"), exports);
18
+ __exportStar(require("./bootstrap.js"), exports);
19
+ __exportStar(require("./InMemoryPerfSink.js"), exports);
20
+ __exportStar(require("./requestStats.js"), exports);
21
+ __exportStar(require("./timeline.js"), exports);
22
+ __exportStar(require("./routeStats.js"), exports);
23
+ __exportStar(require("./store.js"), exports);
24
+ __exportStar(require("./middleware.js"), exports);
25
+ __exportStar(require("./endpoints.js"), exports);
26
+ __exportStar(require("./PromMetricSink.js"), exports);
27
+ __exportStar(require("./policies/TelemetryTokenPolicy.js"), exports);
28
+ __exportStar(require("./policies/PublicPolicy.js"), exports);
29
+ __exportStar(require("./responses.js"), exports);
30
+ __exportStar(require("./health.js"), exports);
31
+ __exportStar(require("./dto/index.js"), exports);
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,iDAA+B;AAC/B,wDAAsC;AACtC,oDAAkC;AAClC,gDAA8B;AAC9B,kDAAgC;AAChC,6CAA2B;AAC3B,kDAAgC;AAChC,iDAA+B;AAC/B,sDAAoC;AACpC,qEAAmD;AACnD,6DAA2C;AAC3C,iDAA+B;AAC/B,8CAA4B;AAC5B,iDAA+B"}