@powerhousedao/switchboard 6.0.0-dev.93 → 6.0.0-dev.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## 6.0.0-dev.95 (2026-03-17)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **switchboard:** add OTel metrics export via OTEL_EXPORTER_OTLP_ENDPOINT ([52f34aa1f](https://github.com/powerhouse-inc/powerhouse/commit/52f34aa1f))
6
+
7
+ ### 🩹 Fixes
8
+
9
+ - **codegen:** added missing deps to boilerplate ([721dcb581](https://github.com/powerhouse-inc/powerhouse/commit/721dcb581))
10
+ - **switchboard:** derive exportTimeoutMillis from exportIntervalMillis ([775a77f3b](https://github.com/powerhouse-inc/powerhouse/commit/775a77f3b))
11
+ - **switchboard:** set exportTimeoutMillis to stay under shutdown deadline ([341d88d9e](https://github.com/powerhouse-inc/powerhouse/commit/341d88d9e))
12
+ - **switchboard:** address further OTel metrics review feedback ([dee185ba8](https://github.com/powerhouse-inc/powerhouse/commit/dee185ba8))
13
+ - **switchboard:** address OTel metrics review feedback ([c5ac016fc](https://github.com/powerhouse-inc/powerhouse/commit/c5ac016fc))
14
+
15
+ ### ❤️ Thank You
16
+
17
+ - acaldas @acaldas
18
+ - Samuel Hawksby-Robinson @Samyoul
19
+
20
+ ## 6.0.0-dev.94 (2026-03-17)
21
+
22
+ ### 🩹 Fixes
23
+
24
+ - **common:** added missing runtime dependencies ([b0f647f75](https://github.com/powerhouse-inc/powerhouse/commit/b0f647f75))
25
+
26
+ ### ❤️ Thank You
27
+
28
+ - acaldas @acaldas
29
+
1
30
  ## 6.0.0-dev.93 (2026-03-17)
2
31
 
3
32
  This was a version bump only for @powerhousedao/switchboard to align it with other projects, there were no code changes.
package/dist/src/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import * as Sentry from "@sentry/node";
3
3
  import { childLogger } from "document-drive";
4
4
  import { config } from "./config.js";
5
+ import { setupMetricsFromEnv } from "./metrics.js";
5
6
  import { initProfilerFromEnv } from "./profiler.js";
6
7
  import { startSwitchboard } from "./server.js";
7
8
  const logger = childLogger(["switchboard"]);
@@ -17,10 +18,20 @@ function ensureNodeVersion(minVersion = "24") {
17
18
  }
18
19
  // Ensure minimum Node.js version
19
20
  ensureNodeVersion("24");
20
- process.on("SIGINT", () => {
21
+ const meterProvider = setupMetricsFromEnv(process.env);
22
+ async function shutdown() {
21
23
  console.log("\nShutting down...");
24
+ // Flush final metrics before exit. Races against a 5s deadline so an
25
+ // unresponsive OTLP endpoint cannot exhaust terminationGracePeriodSeconds.
26
+ await Promise.race([
27
+ meterProvider?.shutdown().catch(() => undefined),
28
+ new Promise((resolve) => setTimeout(resolve, 5_000)),
29
+ ]);
22
30
  process.exit(0);
23
- });
31
+ }
32
+ // SIGINT: Ctrl-C in development; SIGTERM: graceful shutdown in Docker/Kubernetes
33
+ process.on("SIGINT", shutdown);
34
+ process.on("SIGTERM", shutdown);
24
35
  if (process.env.PYROSCOPE_SERVER_ADDRESS) {
25
36
  try {
26
37
  await initProfilerFromEnv(process.env);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AAE5C,SAAS,iBAAiB,CAAC,UAAU,GAAG,IAAI;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IAED,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CACX,gBAAgB,UAAU,4CAA4C,OAAO,EAAE,CAChF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AACD,iCAAiC;AACjC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAExB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AAE5C,SAAS,iBAAiB,CAAC,UAAU,GAAG,IAAI;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IAED,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CACX,gBAAgB,UAAU,4CAA4C,OAAO,EAAE,CAChF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AACD,iCAAiC;AACjC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAExB,MAAM,aAAa,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAEvD,KAAK,UAAU,QAAQ;IACrB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,qEAAqE;IACrE,2EAA2E;IAC3E,MAAM,OAAO,CAAC,IAAI,CAAC;QACjB,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;QAChD,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;KAC3D,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,iFAAiF;AACjF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAEhC,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { MeterProvider } from "@opentelemetry/sdk-metrics";
2
+ export declare function setupMetricsFromEnv(env: typeof process.env): MeterProvider | undefined;
3
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,aAAa,EAEd,MAAM,4BAA4B,CAAC;AAKpC,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,OAAO,CAAC,GAAG,GACtB,aAAa,GAAG,SAAS,CA6B3B"}
@@ -0,0 +1,35 @@
1
+ import { metrics } from "@opentelemetry/api";
2
+ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
3
+ import { Resource } from "@opentelemetry/resources";
4
+ import { MeterProvider, PeriodicExportingMetricReader, } from "@opentelemetry/sdk-metrics";
5
+ import { childLogger } from "document-drive";
6
+ const logger = childLogger(["switchboard", "metrics"]);
7
+ export function setupMetricsFromEnv(env) {
8
+ const endpoint = env.OTEL_EXPORTER_OTLP_ENDPOINT;
9
+ if (!endpoint)
10
+ return undefined;
11
+ const parsed = parseInt(env.OTEL_METRIC_EXPORT_INTERVAL ?? "", 10);
12
+ const exportIntervalMillis = Number.isFinite(parsed) && parsed > 0 ? parsed : 5_000;
13
+ logger.info(`Initializing OpenTelemetry metrics exporter at: ${endpoint}`);
14
+ const meterProvider = new MeterProvider({
15
+ resource: new Resource({
16
+ "service.name": env.OTEL_SERVICE_NAME ?? "switchboard",
17
+ }),
18
+ readers: [
19
+ new PeriodicExportingMetricReader({
20
+ exporter: new OTLPMetricExporter({
21
+ url: `${endpoint.replace(/\/$/, "")}/v1/metrics`,
22
+ }),
23
+ exportIntervalMillis,
24
+ exportTimeoutMillis: Math.max(exportIntervalMillis - 250, 1),
25
+ }),
26
+ ],
27
+ });
28
+ // setGlobalMeterProvider is a one-way door — it cannot be unset once
29
+ // assigned. ReactorInstrumentation reads the global provider via
30
+ // metrics.getMeter(), so this must be called before instrumentation.start().
31
+ metrics.setGlobalMeterProvider(meterProvider);
32
+ logger.info(`Metrics export enabled (interval: ${exportIntervalMillis}ms)`);
33
+ return meterProvider;
34
+ }
35
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EACL,aAAa,EACb,6BAA6B,GAC9B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;AAEvD,MAAM,UAAU,mBAAmB,CACjC,GAAuB;IAEvB,MAAM,QAAQ,GAAG,GAAG,CAAC,2BAA2B,CAAC;IACjD,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEhC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,2BAA2B,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACnE,MAAM,oBAAoB,GACxB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IAEzD,MAAM,CAAC,IAAI,CAAC,mDAAmD,QAAQ,EAAE,CAAC,CAAC;IAC3E,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC;QACtC,QAAQ,EAAE,IAAI,QAAQ,CAAC;YACrB,cAAc,EAAE,GAAG,CAAC,iBAAiB,IAAI,aAAa;SACvD,CAAC;QACF,OAAO,EAAE;YACP,IAAI,6BAA6B,CAAC;gBAChC,QAAQ,EAAE,IAAI,kBAAkB,CAAC;oBAC/B,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa;iBACjD,CAAC;gBACF,oBAAoB;gBACpB,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,oBAAoB,GAAG,GAAG,EAAE,CAAC,CAAC;aAC7D,CAAC;SACH;KACF,CAAC,CAAC;IACH,qEAAqE;IACrE,iEAAiE;IACjE,6EAA6E;IAC7E,OAAO,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAC;IAC9C,MAAM,CAAC,IAAI,CAAC,qCAAqC,oBAAoB,KAAK,CAAC,CAAC;IAC5E,OAAO,aAAa,CAAC;AACvB,CAAC"}