Files
TicketLab_MCP/src/telemetry.ts
T
andreferraroandCursor 3b5c3fb86f
sonar / sonar (push) Skipped
sonar / sonar (pull_request) Failing after 40s
feat: add lab SQLite migrate, LiteLLM env, and OTEL/Grafana stack
Enable local workshop readiness with executable SQLite migrations, OpenTelemetry hello signals, and a provisioned Grafana demo dashboard over Tempo/Loki/Prometheus.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 14:58:33 -03:00

94 lines
2.6 KiB
TypeScript

import { metrics, trace } from "@opentelemetry/api";
import { logs } from "@opentelemetry/api-logs";
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { resourceFromAttributes } from "@opentelemetry/resources";
import {
LoggerProvider,
SimpleLogRecordProcessor,
} from "@opentelemetry/sdk-logs";
import {
MeterProvider,
PeriodicExportingMetricReader,
} from "@opentelemetry/sdk-metrics";
import {
NodeTracerProvider,
SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-node";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
export type Telemetry = {
tracer: ReturnType<typeof trace.getTracer>;
meter: ReturnType<typeof metrics.getMeter>;
logger: ReturnType<typeof logs.getLogger>;
shutdown: () => Promise<void>;
};
function otlpBaseUrl(): string {
return (
process.env.OTEL_EXPORTER_OTLP_ENDPOINT?.replace(/\/$/, "") ??
"http://localhost:4318"
);
}
export function startTelemetry(
serviceName = process.env.OTEL_SERVICE_NAME ?? "ticketlab",
): Telemetry {
const resource = resourceFromAttributes({
[ATTR_SERVICE_NAME]: serviceName,
});
const base = otlpBaseUrl();
const tracerProvider = new NodeTracerProvider({
resource,
spanProcessors: [
new SimpleSpanProcessor(
new OTLPTraceExporter({ url: `${base}/v1/traces` }),
),
],
});
tracerProvider.register();
const meterProvider = new MeterProvider({
resource,
readers: [
new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({ url: `${base}/v1/metrics` }),
exportIntervalMillis: 500,
}),
],
});
metrics.setGlobalMeterProvider(meterProvider);
const loggerProvider = new LoggerProvider({
resource,
processors: [
new SimpleLogRecordProcessor({
exporter: new OTLPLogExporter({ url: `${base}/v1/logs` }),
}),
],
});
logs.setGlobalLoggerProvider(loggerProvider);
return {
tracer: trace.getTracer(serviceName),
meter: metrics.getMeter(serviceName),
logger: logs.getLogger(serviceName),
shutdown: async () => {
await Promise.all([
tracerProvider.forceFlush(),
meterProvider.forceFlush(),
loggerProvider.forceFlush(),
]);
await Promise.all([
tracerProvider.shutdown(),
meterProvider.shutdown(),
loggerProvider.shutdown(),
]);
},
};
}
export { SeverityNumber } from "@opentelemetry/api-logs";