diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index b790bd86f42..c71756edd43 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -534,74 +534,56 @@ describe('LokiDatasource', () => { }); describe('when performing testDataSource', () => { - describe('and call succeeds', () => { - it('should return successfully', async () => { - fetchMock.mockImplementation(() => of(createFetchResponse({ values: ['avalue'] }))); - const ds = createLokiDSForTests({} as TemplateSrv); + it('should return successfully when call succeeds with labels', async () => { + const ds = createLokiDSForTests({} as TemplateSrv); + ds.metadataRequest = () => Promise.resolve(['avalue']); - const result = await ds.testDatasource(); + const result = await ds.testDatasource(); - expect(result.status).toBe('success'); + expect(result).toStrictEqual({ + status: 'success', + message: 'Data source connected and labels found.', }); }); - describe('and call fails with 401 error', () => { - it('should return error status and a detailed error message', async () => { - fetchMock.mockImplementation(() => - throwError({ - statusText: 'Unauthorized', - status: 401, - data: { - message: 'Unauthorized', - }, - }) - ); - const ds = createLokiDSForTests({} as TemplateSrv); + it('should return error when call succeeds without labels', async () => { + const ds = createLokiDSForTests({} as TemplateSrv); + ds.metadataRequest = () => Promise.resolve([]); - const result = await ds.testDatasource(); + const result = await ds.testDatasource(); - expect(result.status).toEqual('error'); - expect(result.message).toBe('Loki: Unauthorized. 401. Unauthorized'); + expect(result).toStrictEqual({ + status: 'error', + message: 'Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.', }); }); - describe('and call fails with 404 error', () => { - it('should return error status and a detailed error message', async () => { - fetchMock.mockImplementation(() => - throwError({ - statusText: 'Not found', - status: 404, - data: { - message: '404 page not found', - }, - }) - ); + it('should return error status with no details when call fails with no details', async () => { + const ds = createLokiDSForTests({} as TemplateSrv); + ds.metadataRequest = () => Promise.reject({}); - const ds = createLokiDSForTests({} as TemplateSrv); + const result = await ds.testDatasource(); - const result = await ds.testDatasource(); - - expect(result.status).toEqual('error'); - expect(result.message).toBe('Loki: Not found. 404. 404 page not found'); + expect(result).toStrictEqual({ + status: 'error', + message: 'Unable to fetch labels from Loki, please check the server logs for more details', }); }); - describe('and call fails with 502 error', () => { - it('should return error status and a detailed error message', async () => { - fetchMock.mockImplementation(() => - throwError({ - statusText: 'Bad Gateway', - status: 502, - data: '', - }) - ); + it('should return error status with details when call fails with details', async () => { + const ds = createLokiDSForTests({} as TemplateSrv); + ds.metadataRequest = () => + Promise.reject({ + data: { + message: 'error42', + }, + }); - const ds = createLokiDSForTests({} as TemplateSrv); + const result = await ds.testDatasource(); - const result = await ds.testDatasource(); - - expect(result.status).toEqual('error'); - expect(result.message).toBe('Loki: Bad Gateway. 502'); + expect(result).toStrictEqual({ + status: 'error', + message: 'Unable to fetch labels from Loki (error42), please check the server logs for more details', }); }); }); diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index 70f2b40d074..a1d220b9394 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -689,44 +689,35 @@ export class LokiDatasource }; }; - testDatasource() { + testDatasource(): Promise<{ status: string; message: string }> { // Consider only last 10 minutes otherwise request takes too long - const startMs = Date.now() - 10 * 60 * 1000; - const start = `${startMs}000000`; // API expects nanoseconds - return lastValueFrom( - this._request(`${LOKI_ENDPOINT}/label`, { start }).pipe( - map((res) => { - const values: any[] = res?.data?.data || res?.data?.values || []; - const testResult = - values.length > 0 - ? { status: 'success', message: 'Data source connected and labels found.' } - : { - status: 'error', - message: - 'Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.', - }; - return testResult; - }), - catchError((err: any) => { - let message = 'Loki: '; - if (err.statusText) { - message += err.statusText; - } else { - message += 'Cannot connect to Loki'; - } + const nowMs = Date.now(); + const params = { + start: (nowMs - 10 * 60 * 1000) * NS_IN_MS, + end: nowMs * NS_IN_MS, + }; - if (err.status) { - message += `. ${err.status}`; - } - - if (err.data && err.data.message) { - message += `. ${err.data.message}`; - } else if (err.data) { - message += `. ${err.data}`; - } - return of({ status: 'error', message: message }); - }) - ) + return this.metadataRequest('labels', params).then( + (values) => { + return values.length > 0 + ? { status: 'success', message: 'Data source connected and labels found.' } + : { + status: 'error', + message: + 'Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.', + }; + }, + (err) => { + // we did a resource-call that failed. + // the only info we have, if exists, is err.data.message + // (when in development-mode, err.data.error exists too, but not in production-mode) + // things like err.status & err.statusText does not help, + // because those will only describe how the request between browser<>server failed + const info: string = err?.data?.message ?? ''; + const infoInParentheses = info !== '' ? ` (${info})` : ''; + const message = `Unable to fetch labels from Loki${infoInParentheses}, please check the server logs for more details`; + return { status: 'error', message: message }; + } ); }