From ae3456bd5b2659899743e88d4f349f979f0a2a2f Mon Sep 17 00:00:00 2001 From: Edward Zhang Date: Wed, 14 Oct 2026 00:55:16 -0400 Subject: [PATCH 1/6] feat(service): otel setup + builtin tracing --- package.json | 3 ++- src/app.ts | 1 + src/services/observability.ts | 29 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/services/observability.ts diff --git a/package.json b/package.json index 64c5d38..f6031d1 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "main": "src/app.ts", "scripts": { - "start": "tsx src/app.ts", + "start": "tsx --env-file=.env src/app.ts", "test": "vitest run test", "stress-test": "vitest run test/search-stress.test.ts", "docs": "typedoc --entryPointStrategy expand ./src --exclude \"**/legacy/**\"" @@ -14,6 +14,7 @@ "license": "ISC", "dependencies": { "@datastructures-js/priority-queue": "^6.3.3", + "@hyperdx/node-opentelemetry": "^0.11.0", "axios": "^1.7.2", "dotenv": "^16.4.5", "express": "^4.19.2", diff --git a/src/app.ts b/src/app.ts index 7690451..fb26aed 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,5 +1,6 @@ import express from "express"; +import "@/services/observability"; import mbus from "./routes/api" const app = express(); diff --git a/src/services/observability.ts b/src/services/observability.ts new file mode 100644 index 0000000..8089d1f --- /dev/null +++ b/src/services/observability.ts @@ -0,0 +1,29 @@ +import * as HyperDX from '@hyperdx/node-opentelemetry'; +import opentelemetry, { Tracer, Meter } from '@opentelemetry/api'; +import * as z from 'zod'; + +// dotenv is NOT used because the otlp endpoint var needs to already be set to work properly +const config = z.object({ + OTEL_KEY: z.string().optional(), + OTEL_EXPORTER_OTLP_ENDPOINT: z.string().optional(), + SERVICE_NAME: z.string().default('local/mbus-backend-dev'), +}).parse(process.env); + +export let tracer: Tracer | null = null; +export let meter: Meter | null = null; + +if (config.OTEL_KEY && config.OTEL_EXPORTER_OTLP_ENDPOINT) { + // must be before any meters are created + HyperDX.init({ + apiKey: config.OTEL_KEY, + service: config.SERVICE_NAME, + }); + + tracer = opentelemetry.trace.getTracer('mbus-backend-dev', '0.1.0'); + meter = opentelemetry.metrics.getMeter('mbus-backend-dev', '0.1.0'); + + console.log('otel initialized as ' + config.SERVICE_NAME); +} else { + console.log('otel is off, make sure key and endpoint are set'); +} + From 715ac732fda83a13f7c6b058d3b8778506b08dfa Mon Sep 17 00:00:00 2001 From: Edward Zhang Date: Mon, 19 Oct 2026 15:34:10 -0400 Subject: [PATCH 2/6] chore: add pull request template --- .github/pull_request_template.md | 74 ++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..3b03a07 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,74 @@ + + +## Description +(1-2 sentences: what changed and why — e.g., "Added Firebase push notifications for real-time bus arrivals") + +## Type of Change +- [ ] New feature (`feat`) +- [ ] Bug fix (`fix`) +- [ ] Refactor / code improvement +- [ ] Dependency / build update +- [ ] Documentation +- [ ] Other (explain) + +## Changed Files +(Please list *all* files you changed, each with a description of what you changed and why.) +*Tip: see a list of everything you changed on the "Files changed" tab* + +Example: +* `map_screen.dart` + * Added "New" button to top toolbar +* `bluebus_api.dart` + * Added try/catch statements to `fetchRoutes()` for better reliability + +## Related Issues +Closes #XX, Prereq of #XX, etc. + +## Does your code rely on another PR +(attach PR number here) + +## Testing Done +**Flutter:** +- [ ] Tested on: + - [ ] iOS Simulator + - [ ] Android Emulator + - [ ] Physical device +**Vitest:** +- [ ] existing test(s) with coverage: (which tests?) +- [ ] new tests added: (describe) + +## Screenshots / Demo (if UI or notification change) + + +## Checklist +- [ ] Commit messages follow Conventional Commits +- [ ] PR title follows `(scope): short description` +- [ ] PR target branch is not `main` and is our current working update branch (e.g. `maizebus2.1`, `dev`) +- [ ] No `print()` / `debugPrint()` / `console.log()` left in production code +- [ ] Secrets / keys not committed From 95e32a1250d26c8af5d04c36bbb4b1b356a811af Mon Sep 17 00:00:00 2001 From: Edward Zhang Date: Wed, 21 Oct 2026 00:18:16 -0400 Subject: [PATCH 3/6] fix(otel): make it emit runtime and host metrics --- package.json | 3 ++- src/app.ts | 1 - src/services/observability.ts | 31 ++++++++++++++----------------- src/services/reminder.ts | 2 -- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index f6031d1..2c75559 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "main": "src/app.ts", "scripts": { - "start": "tsx --env-file=.env src/app.ts", + "start": "tsx --env-file=.env --experimental-loader=@opentelemetry/instrumentation/hook.mjs --import src/services/observability.ts src/app.ts", "test": "vitest run test", "stress-test": "vitest run test/search-stress.test.ts", "docs": "typedoc --entryPointStrategy expand ./src --exclude \"**/legacy/**\"" @@ -15,6 +15,7 @@ "dependencies": { "@datastructures-js/priority-queue": "^6.3.3", "@hyperdx/node-opentelemetry": "^0.11.0", + "@opentelemetry/host-metrics": "^0.40.0", "axios": "^1.7.2", "dotenv": "^16.4.5", "express": "^4.19.2", diff --git a/src/app.ts b/src/app.ts index fb26aed..7690451 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,6 +1,5 @@ import express from "express"; -import "@/services/observability"; import mbus from "./routes/api" const app = express(); diff --git a/src/services/observability.ts b/src/services/observability.ts index 8089d1f..32c7e17 100644 --- a/src/services/observability.ts +++ b/src/services/observability.ts @@ -1,28 +1,25 @@ import * as HyperDX from '@hyperdx/node-opentelemetry'; -import opentelemetry, { Tracer, Meter } from '@opentelemetry/api'; -import * as z from 'zod'; +import { HostMetrics } from '@opentelemetry/host-metrics'; +import { metrics } from '@opentelemetry/api' // dotenv is NOT used because the otlp endpoint var needs to already be set to work properly -const config = z.object({ - OTEL_KEY: z.string().optional(), - OTEL_EXPORTER_OTLP_ENDPOINT: z.string().optional(), - SERVICE_NAME: z.string().default('local/mbus-backend-dev'), -}).parse(process.env); +const otelKey = process.env.OTEL_KEY; +const otelExporterOtlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT; +const serviceName = process.env.SERVICE_NAME ?? 'local/mbus-backend-dev'; -export let tracer: Tracer | null = null; -export let meter: Meter | null = null; - -if (config.OTEL_KEY && config.OTEL_EXPORTER_OTLP_ENDPOINT) { +if (otelKey && otelExporterOtlpEndpoint) { // must be before any meters are created - HyperDX.init({ - apiKey: config.OTEL_KEY, - service: config.SERVICE_NAME, + HyperDX.initSDK({ + apiKey: otelKey, + service: serviceName, + experimentalExceptionCapture: true, }); - tracer = opentelemetry.trace.getTracer('mbus-backend-dev', '0.1.0'); - meter = opentelemetry.metrics.getMeter('mbus-backend-dev', '0.1.0'); + new HostMetrics({ + meterProvider: metrics.getMeterProvider(), + }).start(); - console.log('otel initialized as ' + config.SERVICE_NAME); + console.log('otel initialized as ' + serviceName); } else { console.log('otel is off, make sure key and endpoint are set'); } diff --git a/src/services/reminder.ts b/src/services/reminder.ts index a274244..581bcbb 100644 --- a/src/services/reminder.ts +++ b/src/services/reminder.ts @@ -5,8 +5,6 @@ import { applicationDefault, initializeApp } from "firebase-admin/app"; import * as state from "@/state/transitState"; import { BaseEvent, DelayEvent, eventsEqual, toKey, Key, RegistrationToken, ThresholdEvent, fromKey, delayEvent, thresholdEvent } from "./reminderTypes"; -export * from "./reminderTypes"; - dotenv.config() // Initialize Firebase From 6068225cb741e9eecc749270915984aaa1f50a3c Mon Sep 17 00:00:00 2001 From: Edward Zhang Date: Wed, 21 Oct 2026 08:45:34 -0400 Subject: [PATCH 4/6] fix(notif): make reminders work again The previous observability changes modified the exports of the reminderService, and, due to issues in the tsconfig, local compilation didn't catch this. CI compilation did though, so I've made changes in the GitHub to enforce CI more. --- src/services/reminder.ts | 2 ++ tsconfig.json | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/services/reminder.ts b/src/services/reminder.ts index 581bcbb..bd5b742 100644 --- a/src/services/reminder.ts +++ b/src/services/reminder.ts @@ -5,6 +5,8 @@ import { applicationDefault, initializeApp } from "firebase-admin/app"; import * as state from "@/state/transitState"; import { BaseEvent, DelayEvent, eventsEqual, toKey, Key, RegistrationToken, ThresholdEvent, fromKey, delayEvent, thresholdEvent } from "./reminderTypes"; +export { baseEvent, fromKey, toKey, registrationToken, sameBaseEvent } from './reminderTypes'; + dotenv.config() // Initialize Firebase diff --git a/tsconfig.json b/tsconfig.json index 144c0e8..72796ca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,13 @@ { "compilerOptions": { - "target": "es6", + "target": "es2021", "module": "esnext", - "moduleResolution": "Node", + "moduleResolution": "bundler", "esModuleInterop": true, "resolveJsonModule": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, - "baseUrl": "./", "paths": { "@/*": [ "./src/*" From f27fcd49048fc4cf0fa59ccc688382092c36d016 Mon Sep 17 00:00:00 2001 From: Edward Zhang Date: Wed, 21 Oct 2026 09:32:36 -0400 Subject: [PATCH 5/6] fix telemetry import in start script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f127f21..ea670a3 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "main": "src/app.ts", "scripts": { - "start": "tsx --env-file=.env --experimental-loader=@opentelemetry/instrumentation/hook.mjs --import src/services/observability.ts src/app.ts", + "start": "tsx --env-file=.env --experimental-loader=@opentelemetry/instrumentation/hook.mjs --import @/services/observability.ts src/app.ts", "test": "vitest run test", "stress-test": "vitest run test/search-stress.test.ts", "docs": "typedoc --entryPointStrategy expand ./src" From 5f28dabf1a84ec8947f21804e63ea40d54d2bf15 Mon Sep 17 00:00:00 2001 From: Edward Zhang Date: Wed, 21 Oct 2026 10:04:37 -0400 Subject: [PATCH 6/6] fix(ci): increase test suite startup delay --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d7f9df..a4ef521 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: do sleep 1 # waits for the walking cache to populate done - sleep 10 # waits for the graph/predictions to be built + sleep 60 # waits for the graph/predictions to be built npx vitest run test Typecheck: