feat: migrate to TypeScript, Spec Kit SDD, and lab observability stack #4

Merged
andreferraro merged 6 commits from feature/migrate-python-to-typescript into develop 2026-08-11 15:25:10 -03:00
3 changed files with 27 additions and 14 deletions
Showing only changes of commit d0d5d9a7a6 - Show all commits
+1 -2
View File
@@ -13,8 +13,7 @@ describe("greet", () => {
}); });
it("main emits telemetry and logs greeting", async () => { it("main emits telemetry and logs greeting", async () => {
process.env.OTEL_EXPORTER_OTLP_ENDPOINT = process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:9";
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://127.0.0.1:4318";
const logs: unknown[] = []; const logs: unknown[] = [];
const original = console.log; const original = console.log;
console.log = (...args: unknown[]) => { console.log = (...args: unknown[]) => {
+1 -2
View File
@@ -3,8 +3,7 @@ import test from "node:test";
import { SeverityNumber, startTelemetry } from "./telemetry.js"; import { SeverityNumber, startTelemetry } from "./telemetry.js";
test("startTelemetry emits and shuts down without throwing", async () => { test("startTelemetry emits and shuts down without throwing", async () => {
process.env.OTEL_EXPORTER_OTLP_ENDPOINT = process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:9";
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://127.0.0.1:4318";
process.env.OTEL_SERVICE_NAME = "ticketlab-test"; process.env.OTEL_SERVICE_NAME = "ticketlab-test";
const telemetry = startTelemetry("ticketlab-test"); const telemetry = startTelemetry("ticketlab-test");
+25 -10
View File
@@ -71,21 +71,36 @@ export function startTelemetry(
}); });
logs.setGlobalLoggerProvider(loggerProvider); logs.setGlobalLoggerProvider(loggerProvider);
const quiet = (p: Promise<unknown>) => p.catch(() => undefined);
// ponytail: OTLP flush can hang when the collector is down; 1.5s ceiling, upgrade to exporter timeout config
const bounded = async (work: Promise<unknown>) => {
await Promise.race([
work,
new Promise<void>((resolve) => {
setTimeout(resolve, 400);
}),
]);
};
return { return {
tracer: trace.getTracer(serviceName), tracer: trace.getTracer(serviceName),
meter: metrics.getMeter(serviceName), meter: metrics.getMeter(serviceName),
logger: logs.getLogger(serviceName), logger: logs.getLogger(serviceName),
shutdown: async () => { shutdown: async () => {
await Promise.all([ await bounded(
tracerProvider.forceFlush(), Promise.all([
meterProvider.forceFlush(), quiet(tracerProvider.forceFlush()),
loggerProvider.forceFlush(), quiet(meterProvider.forceFlush()),
]); quiet(loggerProvider.forceFlush()),
await Promise.all([ ]),
tracerProvider.shutdown(), );
meterProvider.shutdown(), await bounded(
loggerProvider.shutdown(), Promise.all([
]); quiet(tracerProvider.shutdown()),
quiet(meterProvider.shutdown()),
quiet(loggerProvider.shutdown()),
]),
);
}, },
}; };
} }