loki: use metadataRequest in testDatasource (#48431)

This commit is contained in:
Gábor Farkas 2022-05-05 09:43:36 +02:00 committed by GitHub
parent 46b40b6e82
commit 60cabaea0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 87 deletions

View File

@ -534,74 +534,56 @@ describe('LokiDatasource', () => {
}); });
describe('when performing testDataSource', () => { describe('when performing testDataSource', () => {
describe('and call succeeds', () => { it('should return successfully when call succeeds with labels', async () => {
it('should return successfully', async () => {
fetchMock.mockImplementation(() => of(createFetchResponse({ values: ['avalue'] })));
const ds = createLokiDSForTests({} as TemplateSrv); 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 when call succeeds without labels', async () => {
it('should return error status and a detailed error message', async () => { const ds = createLokiDSForTests({} as TemplateSrv);
fetchMock.mockImplementation(() => ds.metadataRequest = () => Promise.resolve([]);
throwError({
statusText: 'Unauthorized', const result = await ds.testDatasource();
status: 401,
expect(result).toStrictEqual({
status: 'error',
message: 'Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.',
});
});
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 result = await ds.testDatasource();
expect(result).toStrictEqual({
status: 'error',
message: 'Unable to fetch labels from Loki, please check the server logs for more details',
});
});
it('should return error status with details when call fails with details', async () => {
const ds = createLokiDSForTests({} as TemplateSrv);
ds.metadataRequest = () =>
Promise.reject({
data: { data: {
message: 'Unauthorized', message: 'error42',
}, },
}) });
);
const ds = createLokiDSForTests({} as TemplateSrv);
const result = await ds.testDatasource(); const result = await ds.testDatasource();
expect(result.status).toEqual('error'); expect(result).toStrictEqual({
expect(result.message).toBe('Loki: Unauthorized. 401. Unauthorized'); status: 'error',
}); message: 'Unable to fetch labels from Loki (error42), please check the server logs for more details',
});
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',
},
})
);
const ds = createLokiDSForTests({} as TemplateSrv);
const result = await ds.testDatasource();
expect(result.status).toEqual('error');
expect(result.message).toBe('Loki: Not found. 404. 404 page not found');
});
});
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: '',
})
);
const ds = createLokiDSForTests({} as TemplateSrv);
const result = await ds.testDatasource();
expect(result.status).toEqual('error');
expect(result.message).toBe('Loki: Bad Gateway. 502');
}); });
}); });
}); });

View File

@ -689,44 +689,35 @@ export class LokiDatasource
}; };
}; };
testDatasource() { testDatasource(): Promise<{ status: string; message: string }> {
// Consider only last 10 minutes otherwise request takes too long // Consider only last 10 minutes otherwise request takes too long
const startMs = Date.now() - 10 * 60 * 1000; const nowMs = Date.now();
const start = `${startMs}000000`; // API expects nanoseconds const params = {
return lastValueFrom( start: (nowMs - 10 * 60 * 1000) * NS_IN_MS,
this._request(`${LOKI_ENDPOINT}/label`, { start }).pipe( end: nowMs * NS_IN_MS,
map((res) => { };
const values: any[] = res?.data?.data || res?.data?.values || [];
const testResult = return this.metadataRequest('labels', params).then(
values.length > 0 (values) => {
return values.length > 0
? { status: 'success', message: 'Data source connected and labels found.' } ? { status: 'success', message: 'Data source connected and labels found.' }
: { : {
status: 'error', status: 'error',
message: message:
'Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.', 'Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.',
}; };
return testResult; },
}), (err) => {
catchError((err: any) => { // we did a resource-call that failed.
let message = 'Loki: '; // the only info we have, if exists, is err.data.message
if (err.statusText) { // (when in development-mode, err.data.error exists too, but not in production-mode)
message += err.statusText; // things like err.status & err.statusText does not help,
} else { // because those will only describe how the request between browser<>server failed
message += 'Cannot connect to Loki'; 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 };
} }
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 });
})
)
); );
} }