mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-24 00:51:53 +00:00
fix(mcp): cache bound config; surface shutdown errors
initMetrics() idempotent re-entry now returns the values bound at first init rather than re-reading env (which could lie if env mutated between calls). shutdownMetrics() writes exporter/provider shutdown failures to stderr instead of swallowing — silent failure during exit hid lost final-flush data. Adds tests for idempotent re-init and forceEnabled.
This commit is contained in:
parent
8bb0508ded
commit
8e2c3dce93
2 changed files with 38 additions and 9 deletions
|
|
@ -22,6 +22,7 @@ let requestsCounter: Counter | null = null;
|
|||
let durationHistogram: Histogram | null = null;
|
||||
let resultBytesHistogram: Histogram | null = null;
|
||||
let inflightGauge: UpDownCounter | null = null;
|
||||
let boundConfig: { port: number; host: string; endpoint: string } | null = null;
|
||||
|
||||
function envFlag(value: string | undefined): boolean {
|
||||
if (typeof value !== 'string') return false;
|
||||
|
|
@ -48,13 +49,8 @@ export async function initMetrics(
|
|||
const enabled = opts.forceEnabled ?? envFlag(env['GITNEXUS_OTEL_METRICS']);
|
||||
if (!enabled) return { enabled: false };
|
||||
|
||||
if (provider !== null) {
|
||||
return {
|
||||
enabled: true,
|
||||
port: Number(env['GITNEXUS_OTEL_METRICS_PORT'] ?? 9464),
|
||||
host: env['GITNEXUS_OTEL_METRICS_HOST'] ?? '127.0.0.1',
|
||||
endpoint: env['GITNEXUS_OTEL_METRICS_ENDPOINT'] ?? '/metrics',
|
||||
};
|
||||
if (provider !== null && boundConfig !== null) {
|
||||
return { enabled: true, ...boundConfig };
|
||||
}
|
||||
|
||||
const port = Number(env['GITNEXUS_OTEL_METRICS_PORT'] ?? 9464);
|
||||
|
|
@ -115,6 +111,7 @@ export async function initMetrics(
|
|||
});
|
||||
|
||||
await exporter.startServer();
|
||||
boundConfig = { port, host, endpoint };
|
||||
|
||||
return { enabled: true, port, host, endpoint };
|
||||
}
|
||||
|
|
@ -128,8 +125,17 @@ export async function shutdownMetrics(): Promise<void> {
|
|||
durationHistogram = null;
|
||||
resultBytesHistogram = null;
|
||||
inflightGauge = null;
|
||||
if (e) await e.shutdown().catch(() => {});
|
||||
if (p) await p.shutdown().catch(() => {});
|
||||
boundConfig = null;
|
||||
if (e) {
|
||||
await e.shutdown().catch((err) => {
|
||||
process.stderr.write(`[gitnexus metrics] exporter shutdown error: ${err?.message ?? err}\n`);
|
||||
});
|
||||
}
|
||||
if (p) {
|
||||
await p.shutdown().catch((err) => {
|
||||
process.stderr.write(`[gitnexus metrics] provider shutdown error: ${err?.message ?? err}\n`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** hasError must be a boolean; never accept the error string — cypher errors echo user input. */
|
||||
|
|
|
|||
|
|
@ -69,6 +69,29 @@ describe('initMetrics gating', () => {
|
|||
expect(isMetricsEnabled()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('idempotent re-init returns the originally bound values, not current env', async () => {
|
||||
process.env['GITNEXUS_OTEL_METRICS'] = 'on';
|
||||
await withRandomPort(async () => {
|
||||
const first = await initMetrics();
|
||||
process.env['GITNEXUS_OTEL_METRICS_PORT'] = '65535';
|
||||
process.env['GITNEXUS_OTEL_METRICS_HOST'] = '0.0.0.0';
|
||||
process.env['GITNEXUS_OTEL_METRICS_ENDPOINT'] = '/changed';
|
||||
const second = await initMetrics();
|
||||
expect(second.port).toBe(first.port);
|
||||
expect(second.host).toBe(first.host);
|
||||
expect(second.endpoint).toBe(first.endpoint);
|
||||
});
|
||||
});
|
||||
|
||||
it('honors forceEnabled regardless of env', async () => {
|
||||
delete process.env['GITNEXUS_OTEL_METRICS'];
|
||||
await withRandomPort(async () => {
|
||||
const result = await initMetrics({ forceEnabled: true });
|
||||
expect(result.enabled).toBe(true);
|
||||
expect(isMetricsEnabled()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('observe() — success path', () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue