diff --git a/packages/main/src/plugin/container-registry.spec.ts b/packages/main/src/plugin/container-registry.spec.ts index 18fc55828b7..d5b873ee0fe 100644 --- a/packages/main/src/plugin/container-registry.spec.ts +++ b/packages/main/src/plugin/container-registry.spec.ts @@ -3697,6 +3697,55 @@ test('check handleEvents is not calling the console.log for health_status event' expect(consoleLogSpy).not.toBeCalled(); }); +test('check handleEvents tracks telemetry when stream emits error', async () => { + telemetryTrackMock.mockClear(); + const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); + const getEventsMock = vi.fn(); + let eventsMockCallback: ((ignored: unknown, stream: PassThrough) => void) | undefined; + // keep the function passed in parameter of getEventsMock + getEventsMock.mockImplementation((options: (ignored: unknown, stream: PassThrough) => void) => { + eventsMockCallback = options; + }); + + const passThrough = new PassThrough(); + const fakeDockerode = { + getEvents: getEventsMock, + } as unknown as Dockerode; + + const errorCallback = vi.fn(); + + containerRegistry.handleEvents(fakeDockerode, errorCallback); + + if (eventsMockCallback) { + eventsMockCallback?.(undefined, passThrough); + } + + // emit an error on the stream + const testError = new Error('stream connection error'); + passThrough.emit('error', testError); + + // wait for error handling + await vi.waitFor(() => expect(errorCallback).toHaveBeenCalled()); + + // check that telemetry was tracked with correct event name and properties + expect(telemetry.track).toHaveBeenCalledWith( + 'container-events-failure', + expect.objectContaining({ + nbEvents: expect.any(Number), + failureAfter: expect.any(Number), + error: testError, + }), + ); + + // verify error was logged + expect(consoleErrorSpy).toHaveBeenCalledWith('/event stream received an error.', testError); + + // verify error callback was called with wrapped error + expect(errorCallback).toHaveBeenCalledWith(expect.objectContaining({ message: 'Error in handling events' })); + + consoleErrorSpy.mockRestore(); +}); + test('check volume mounted is replicated when executing replicatePodmanContainer with named volume', async () => { const dockerAPI = new Dockerode({ protocol: 'http', host: 'localhost' }); diff --git a/packages/main/src/plugin/container-registry.ts b/packages/main/src/plugin/container-registry.ts index 31bac5219f9..0ac4e6df8d1 100644 --- a/packages/main/src/plugin/container-registry.ts +++ b/packages/main/src/plugin/container-registry.ts @@ -261,7 +261,7 @@ export class ContainerProviderRegistry { stream?.on('error', error => { console.error('/event stream received an error.', error); // log why it failed and after how many ms connection dropped - this.telemetryService.track('handleContainerEventsFailure', { + this.telemetryService.track('container-events-failure', { nbEvents, failureAfter: performance.now() - startDate, error, diff --git a/telemetry.json b/telemetry.json index 9f5414012b6..535e942cfa3 100644 --- a/telemetry.json +++ b/telemetry.json @@ -3,6 +3,10 @@ { "event": "list.*", "frequency": "dailyPerInstance" + }, + { + "event": "container-events-failure", + "frequency": "dailyPerInstance" } ] }