UNPKG

@accounter/server

Version:
127 lines 6.26 kB
import { beforeEach, describe, expect, it, vi } from 'vitest'; vi.mock('dotenv', () => ({ config: vi.fn() })); const mockOtelConfig = vi.hoisted(() => ({ startupStrict: false, })); const mockBuildOtelSdk = vi.hoisted(() => vi.fn()); vi.mock('../../environment.js', () => ({ env: { otel: mockOtelConfig }, })); vi.mock('../builder.js', () => ({ buildOtelSdk: mockBuildOtelSdk, })); function createMockSdk() { return { start: vi.fn().mockResolvedValue(undefined), shutdown: vi.fn().mockResolvedValue(undefined), }; } function createDeferred() { let resolve; let reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve, reject }; } describe('telemetry lifecycle', () => { beforeEach(() => { vi.resetModules(); vi.clearAllMocks(); mockOtelConfig.startupStrict = false; }); describe('startTelemetry', () => { it('throws startup errors in strict mode', async () => { mockOtelConfig.startupStrict = true; const sdk = createMockSdk(); const startupError = new Error('startup failed'); sdk.start.mockRejectedValueOnce(startupError); mockBuildOtelSdk.mockReturnValueOnce(sdk); const { startTelemetry } = await import('../index.js'); await expect(startTelemetry()).rejects.toThrow('startup failed'); }); it('logs startup errors and continues in non-strict mode', async () => { const sdk = createMockSdk(); const startupError = new Error('startup failed'); sdk.start.mockRejectedValueOnce(startupError); mockBuildOtelSdk.mockReturnValueOnce(sdk); const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined); const { startTelemetry } = await import('../index.js'); await expect(startTelemetry()).resolves.toBeUndefined(); expect(consoleErrorSpy).toHaveBeenCalledWith('OpenTelemetry startup failed, continuing without tracing.', startupError); consoleErrorSpy.mockRestore(); }); it('reuses the same in-flight startup for concurrent startTelemetry calls', async () => { const startDeferred = createDeferred(); const sdk = createMockSdk(); sdk.start.mockImplementationOnce(() => startDeferred.promise); mockBuildOtelSdk.mockReturnValue(sdk); const { startTelemetry } = await import('../index.js'); const firstStart = startTelemetry(); const secondStart = startTelemetry(); expect(mockBuildOtelSdk).toHaveBeenCalledOnce(); expect(sdk.start).toHaveBeenCalledOnce(); startDeferred.resolve(); await Promise.all([firstStart, secondStart]); await startTelemetry(); expect(mockBuildOtelSdk).toHaveBeenCalledOnce(); }); it('clears the in-flight startup lock after a strict startup failure so later calls can retry', async () => { mockOtelConfig.startupStrict = true; const startupError = new Error('startup failed'); const failingSdk = createMockSdk(); failingSdk.start.mockRejectedValueOnce(startupError); const succeedingSdk = createMockSdk(); mockBuildOtelSdk.mockReturnValueOnce(failingSdk).mockReturnValueOnce(succeedingSdk); const { startTelemetry } = await import('../index.js'); await expect(Promise.all([startTelemetry(), startTelemetry()])).rejects.toThrow(startupError); expect(mockBuildOtelSdk).toHaveBeenCalledOnce(); await expect(startTelemetry()).resolves.toBeUndefined(); expect(mockBuildOtelSdk).toHaveBeenCalledTimes(2); expect(succeedingSdk.start).toHaveBeenCalledOnce(); }); }); describe('shutdownTelemetry', () => { it('waits for an in-flight startup before shutting down the SDK', async () => { const startDeferred = createDeferred(); const sdk = createMockSdk(); sdk.start.mockImplementationOnce(() => startDeferred.promise); mockBuildOtelSdk.mockReturnValueOnce(sdk); const consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(() => undefined); const { shutdownTelemetry, startTelemetry } = await import('../index.js'); const start = startTelemetry(); const shutdown = shutdownTelemetry(); expect(sdk.shutdown).not.toHaveBeenCalled(); startDeferred.resolve(); await start; await shutdown; expect(sdk.shutdown).toHaveBeenCalledOnce(); consoleInfoSpy.mockRestore(); }); it('logs shutdown success when sdk shutdown resolves', async () => { const sdk = createMockSdk(); mockBuildOtelSdk.mockReturnValueOnce(sdk); const consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(() => undefined); const { startTelemetry, shutdownTelemetry } = await import('../index.js'); await startTelemetry(); await shutdownTelemetry(); expect(sdk.shutdown).toHaveBeenCalledOnce(); expect(consoleInfoSpy).toHaveBeenCalledWith('OpenTelemetry shutdown completed.'); consoleInfoSpy.mockRestore(); }); it('logs shutdown failure when sdk shutdown rejects', async () => { const sdk = createMockSdk(); const shutdownError = new Error('shutdown failed'); sdk.shutdown.mockRejectedValueOnce(shutdownError); mockBuildOtelSdk.mockReturnValueOnce(sdk); const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined); const { startTelemetry, shutdownTelemetry } = await import('../index.js'); await startTelemetry(); await expect(shutdownTelemetry()).resolves.toBeUndefined(); expect(consoleErrorSpy).toHaveBeenCalledWith('OpenTelemetry shutdown failed.', shutdownError); consoleErrorSpy.mockRestore(); }); }); }); //# sourceMappingURL=index.test.js.map