mirror of
https://github.com/grafana/grafana.git
synced 2025-09-24 19:13:46 +08:00
Prometheus: Use fetch instead of deprecated datasourceRequest (#27090)
* Prometheus: replaces dataSourcRequest with fetch * Tests: fixes typings * Refactor: removes unnecessary from operator * Refactor: removes weird json() function calls * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/metric_find_query.test.ts Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
This commit is contained in:
@ -22,13 +22,14 @@ import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { VariableHide } from '../../../features/variables/types';
|
||||
import { describe } from '../../../../test/lib/common';
|
||||
import { QueryOptions } from 'app/types';
|
||||
import { of, throwError } from 'rxjs';
|
||||
|
||||
const datasourceRequestMock = jest.fn().mockResolvedValue(createDefaultPromResponse());
|
||||
const fetchMock = jest.fn().mockReturnValue(of(createDefaultPromResponse()));
|
||||
|
||||
jest.mock('./metric_find_query');
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
getBackendSrv: () => ({
|
||||
datasourceRequest: datasourceRequestMock,
|
||||
fetch: fetchMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -56,7 +57,7 @@ const replaceMock = (templateSrv.replace as any) as jest.Mock<any>;
|
||||
const getTimeSrvMock = (getTimeSrv as any) as jest.Mock<TimeSrv>;
|
||||
|
||||
beforeEach(() => {
|
||||
datasourceRequestMock.mockClear();
|
||||
fetchMock.mockClear();
|
||||
getAdhocFiltersMock.mockClear();
|
||||
replaceMock.mockClear();
|
||||
getTimeSrvMock.mockClear();
|
||||
@ -137,8 +138,8 @@ describe('PrometheusDatasource', () => {
|
||||
describe('Datasource metadata requests', () => {
|
||||
it('should perform a GET request with the default config', () => {
|
||||
ds.metadataRequest('/foo');
|
||||
expect(datasourceRequestMock.mock.calls.length).toBe(1);
|
||||
expect(datasourceRequestMock.mock.calls[0][0].method).toBe('GET');
|
||||
expect(fetchMock.mock.calls.length).toBe(1);
|
||||
expect(fetchMock.mock.calls[0][0].method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should still perform a GET request with the DS HTTP method set to POST', () => {
|
||||
@ -146,8 +147,8 @@ describe('PrometheusDatasource', () => {
|
||||
postSettings.jsonData.httpMethod = 'POST';
|
||||
const promDs = new PrometheusDatasource(postSettings);
|
||||
promDs.metadataRequest('/foo');
|
||||
expect(datasourceRequestMock.mock.calls.length).toBe(1);
|
||||
expect(datasourceRequestMock.mock.calls[0][0].method).toBe('GET');
|
||||
expect(fetchMock.mock.calls.length).toBe(1);
|
||||
expect(fetchMock.mock.calls[0][0].method).toBe('GET');
|
||||
});
|
||||
});
|
||||
|
||||
@ -204,8 +205,8 @@ describe('PrometheusDatasource', () => {
|
||||
|
||||
describe('When performing performSuggestQuery', () => {
|
||||
it('should cache response', async () => {
|
||||
datasourceRequestMock.mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
fetchMock.mockImplementation(() =>
|
||||
of({
|
||||
status: 'success',
|
||||
data: { data: ['value1', 'value2', 'value3'] },
|
||||
})
|
||||
@ -215,7 +216,7 @@ describe('PrometheusDatasource', () => {
|
||||
|
||||
expect(results).toHaveLength(3);
|
||||
|
||||
datasourceRequestMock.mockImplementation(jest.fn());
|
||||
fetchMock.mockImplementation(jest.fn());
|
||||
results = await ds.performSuggestQuery('value', true);
|
||||
|
||||
expect(results).toHaveLength(3);
|
||||
@ -282,7 +283,7 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
];
|
||||
|
||||
ds.performTimeSeriesQuery = jest.fn().mockReturnValue([responseMock]);
|
||||
ds.performTimeSeriesQuery = jest.fn().mockReturnValue(of([responseMock]));
|
||||
ds.query(query).subscribe((result: any) => {
|
||||
const results = result.data;
|
||||
return expect(results).toMatchObject(expected);
|
||||
@ -324,7 +325,7 @@ describe('PrometheusDatasource', () => {
|
||||
|
||||
const expected = ['1', '2', '4', '+Inf'];
|
||||
|
||||
ds.performTimeSeriesQuery = jest.fn().mockReturnValue([responseMock]);
|
||||
ds.performTimeSeriesQuery = jest.fn().mockReturnValue(of([responseMock]));
|
||||
ds.query(query).subscribe((result: any) => {
|
||||
const seriesLabels = _.map(result.data, 'target');
|
||||
return expect(seriesLabels).toEqual(expected);
|
||||
@ -609,14 +610,14 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
},
|
||||
};
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any).subscribe((data: any) => {
|
||||
results = data;
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate the correct query', () => {
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -646,7 +647,7 @@ describe('PrometheusDatasource', () => {
|
||||
};
|
||||
|
||||
it('should generate an error', () => {
|
||||
datasourceRequestMock.mockImplementation(() => Promise.reject(response));
|
||||
fetchMock.mockImplementation(() => throwError(response));
|
||||
ds.query(query as any).subscribe((e: any) => {
|
||||
results = e.message;
|
||||
expect(results).toBe(`"${errMessage}"`);
|
||||
@ -691,7 +692,7 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
};
|
||||
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
|
||||
ds.query(query as any).subscribe((data: any) => {
|
||||
results = data;
|
||||
@ -754,14 +755,14 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
};
|
||||
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any).subscribe((data: any) => {
|
||||
results = data;
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate the correct query', () => {
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -812,7 +813,7 @@ describe('PrometheusDatasource', () => {
|
||||
|
||||
describe('when time series query is cancelled', () => {
|
||||
it('should return empty results', async () => {
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve({ cancelled: true }));
|
||||
fetchMock.mockImplementation(() => of({ cancelled: true }));
|
||||
|
||||
await ds.annotationQuery(options).then((data: any) => {
|
||||
results = data;
|
||||
@ -825,7 +826,7 @@ describe('PrometheusDatasource', () => {
|
||||
describe('not use useValueForTime', () => {
|
||||
beforeEach(async () => {
|
||||
options.annotation.useValueForTime = false;
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
|
||||
await ds.annotationQuery(options).then((data: any) => {
|
||||
results = data;
|
||||
@ -844,7 +845,7 @@ describe('PrometheusDatasource', () => {
|
||||
describe('use useValueForTime', () => {
|
||||
beforeEach(async () => {
|
||||
options.annotation.useValueForTime = true;
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
|
||||
await ds.annotationQuery(options).then((data: any) => {
|
||||
results = data;
|
||||
@ -858,7 +859,7 @@ describe('PrometheusDatasource', () => {
|
||||
|
||||
describe('step parameter', () => {
|
||||
beforeEach(() => {
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
});
|
||||
|
||||
it('should use default step for short range if no interval is given', () => {
|
||||
@ -870,7 +871,7 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
};
|
||||
ds.annotationQuery(query);
|
||||
const req = datasourceRequestMock.mock.calls[0][0];
|
||||
const req = fetchMock.mock.calls[0][0];
|
||||
expect(req.url).toContain('step=60');
|
||||
});
|
||||
|
||||
@ -887,7 +888,7 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
};
|
||||
ds.annotationQuery(query);
|
||||
const req = datasourceRequestMock.mock.calls[0][0];
|
||||
const req = fetchMock.mock.calls[0][0];
|
||||
expect(req.url).toContain('step=60');
|
||||
});
|
||||
|
||||
@ -905,7 +906,7 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
};
|
||||
ds.annotationQuery(query);
|
||||
const req = datasourceRequestMock.mock.calls[0][0];
|
||||
const req = fetchMock.mock.calls[0][0];
|
||||
expect(req.url).toContain('step=10');
|
||||
});
|
||||
|
||||
@ -923,7 +924,7 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
};
|
||||
ds.annotationQuery(query);
|
||||
const req = datasourceRequestMock.mock.calls[0][0];
|
||||
const req = fetchMock.mock.calls[0][0];
|
||||
expect(req.url).toContain('step=10');
|
||||
});
|
||||
|
||||
@ -936,7 +937,7 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
};
|
||||
ds.annotationQuery(query);
|
||||
const req = datasourceRequestMock.mock.calls[0][0];
|
||||
const req = fetchMock.mock.calls[0][0];
|
||||
// Range in seconds: (to - from) / 1000
|
||||
// Max_datapoints: 11000
|
||||
// Step: range / max_datapoints
|
||||
@ -976,7 +977,7 @@ describe('PrometheusDatasource', () => {
|
||||
};
|
||||
|
||||
options.annotation.useValueForTime = false;
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
|
||||
return ds.annotationQuery(options);
|
||||
}
|
||||
@ -1063,7 +1064,7 @@ describe('PrometheusDatasource', () => {
|
||||
},
|
||||
};
|
||||
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any).subscribe((data: any) => {
|
||||
results = data;
|
||||
});
|
||||
@ -1099,9 +1100,9 @@ describe('PrometheusDatasource', () => {
|
||||
};
|
||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=10';
|
||||
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1114,9 +1115,9 @@ describe('PrometheusDatasource', () => {
|
||||
interval: '100ms',
|
||||
};
|
||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=0.1';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1134,9 +1135,9 @@ describe('PrometheusDatasource', () => {
|
||||
interval: '10s',
|
||||
};
|
||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=10';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1151,9 +1152,9 @@ describe('PrometheusDatasource', () => {
|
||||
const end = 7 * 60 * 60;
|
||||
const start = 60 * 60;
|
||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=' + start + '&end=' + end + '&step=2';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1173,9 +1174,9 @@ describe('PrometheusDatasource', () => {
|
||||
};
|
||||
// times get rounded up to interval
|
||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=50&end=400&step=50';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1194,9 +1195,9 @@ describe('PrometheusDatasource', () => {
|
||||
interval: '5s',
|
||||
};
|
||||
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=60&end=420&step=15';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1216,9 +1217,9 @@ describe('PrometheusDatasource', () => {
|
||||
};
|
||||
// times get aligned to interval
|
||||
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=0&end=400&step=100';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1238,9 +1239,9 @@ describe('PrometheusDatasource', () => {
|
||||
const end = 7 * 24 * 60 * 60;
|
||||
const start = 0;
|
||||
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=' + start + '&end=' + end + '&step=100';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1271,9 +1272,9 @@ describe('PrometheusDatasource', () => {
|
||||
);
|
||||
const urlExpected =
|
||||
'proxied/api/v1/query_range?query=test' + '&start=' + adjusted.start + '&end=' + adjusted.end + '&step=' + step;
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
});
|
||||
@ -1313,9 +1314,9 @@ describe('PrometheusDatasource', () => {
|
||||
'&start=60&end=420&step=10';
|
||||
|
||||
templateSrv.replace = jest.fn(str => str) as any;
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
|
||||
@ -1352,10 +1353,10 @@ describe('PrometheusDatasource', () => {
|
||||
'proxied/api/v1/query_range?query=' +
|
||||
encodeURIComponent('rate(test[$__interval])') +
|
||||
'&start=60&end=420&step=10';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
templateSrv.replace = jest.fn(str => str) as any;
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
|
||||
@ -1393,10 +1394,10 @@ describe('PrometheusDatasource', () => {
|
||||
'proxied/api/v1/query_range?query=' +
|
||||
encodeURIComponent('rate(test[$__interval])') +
|
||||
'&start=0&end=400&step=100';
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
templateSrv.replace = jest.fn(str => str) as any;
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
|
||||
@ -1441,9 +1442,9 @@ describe('PrometheusDatasource', () => {
|
||||
'&start=50&end=400&step=50';
|
||||
|
||||
templateSrv.replace = jest.fn(str => str) as any;
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
|
||||
@ -1482,9 +1483,9 @@ describe('PrometheusDatasource', () => {
|
||||
encodeURIComponent('rate(test[$__interval])') +
|
||||
'&start=60&end=420&step=15';
|
||||
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
|
||||
@ -1538,10 +1539,10 @@ describe('PrometheusDatasource', () => {
|
||||
adjusted.end +
|
||||
'&step=' +
|
||||
step;
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
templateSrv.replace = jest.fn(str => str) as any;
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('GET');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
|
||||
@ -1590,9 +1591,9 @@ describe('PrometheusDatasource', () => {
|
||||
)}&start=0&end=3600&step=60`;
|
||||
|
||||
templateSrv.replace = jest.fn(str => str) as any;
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any);
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.url).toBe(urlExpected);
|
||||
|
||||
// @ts-ignore
|
||||
@ -1678,14 +1679,14 @@ describe('PrometheusDatasource for POST', () => {
|
||||
},
|
||||
},
|
||||
};
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||
fetchMock.mockImplementation(() => of(response));
|
||||
ds.query(query as any).subscribe((data: any) => {
|
||||
results = data;
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate the correct query', () => {
|
||||
const res = datasourceRequestMock.mock.calls[0][0];
|
||||
const res = fetchMock.mock.calls[0][0];
|
||||
expect(res.method).toBe('POST');
|
||||
expect(res.url).toBe(urlExpected);
|
||||
expect(res.data).toEqual(dataExpected);
|
||||
|
@ -18,13 +18,13 @@ import {
|
||||
TimeRange,
|
||||
TimeSeries,
|
||||
} from '@grafana/data';
|
||||
import { forkJoin, from, merge, Observable, of } from 'rxjs';
|
||||
import { filter, map, tap } from 'rxjs/operators';
|
||||
import { forkJoin, merge, Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, filter, map, tap } from 'rxjs/operators';
|
||||
|
||||
import PrometheusMetricFindQuery from './metric_find_query';
|
||||
import { ResultTransformer } from './result_transformer';
|
||||
import PrometheusLanguageProvider from './language_provider';
|
||||
import { getBackendSrv, BackendSrvRequest } from '@grafana/runtime';
|
||||
import { BackendSrvRequest, getBackendSrv } from '@grafana/runtime';
|
||||
import addLabelToQuery from './add_label_to_query';
|
||||
import { getQueryHints } from './query_hints';
|
||||
import { expandRecordingRules } from './language_utils';
|
||||
@ -111,7 +111,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
}
|
||||
}
|
||||
|
||||
_request(url: string, data: Record<string, string> | null, overrides: Partial<BackendSrvRequest> = {}) {
|
||||
_request<T = any>(url: string, data: Record<string, string> | null, overrides: Partial<BackendSrvRequest> = {}) {
|
||||
const options: BackendSrvRequest = defaults(overrides, {
|
||||
url: this.url + url,
|
||||
method: this.httpMethod,
|
||||
@ -140,12 +140,12 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
options.headers!.Authorization = this.basicAuth;
|
||||
}
|
||||
|
||||
return getBackendSrv().datasourceRequest(options);
|
||||
return getBackendSrv().fetch<T>(options);
|
||||
}
|
||||
|
||||
// Use this for tab completion features, wont publish response to other components
|
||||
metadataRequest(url: string) {
|
||||
return this._request(url, null, { method: 'GET', hideFromInspector: true });
|
||||
metadataRequest<T = any>(url: string) {
|
||||
return this._request<T>(url, null, { method: 'GET', hideFromInspector: true }).toPromise(); // toPromise until we change getTagValues, getTagKeys to Observable
|
||||
}
|
||||
|
||||
interpolateQueryExpr(value: string | string[] = [], variable: any) {
|
||||
@ -272,8 +272,8 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
const target = activeTargets[index];
|
||||
|
||||
let observable = query.instant
|
||||
? from(this.performInstantQuery(query, end))
|
||||
: from(this.performTimeSeriesQuery(query, query.start, query.end));
|
||||
? this.performInstantQuery(query, end)
|
||||
: this.performTimeSeriesQuery(query, query.start, query.end);
|
||||
|
||||
return observable.pipe(
|
||||
// Decrease the counter here. We assume that each request returns only single value and then completes
|
||||
@ -305,8 +305,8 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
const target = activeTargets[index];
|
||||
|
||||
let observable = query.instant
|
||||
? from(this.performInstantQuery(query, end))
|
||||
: from(this.performTimeSeriesQuery(query, query.start, query.end));
|
||||
? this.performInstantQuery(query, end)
|
||||
: this.performTimeSeriesQuery(query, query.start, query.end);
|
||||
|
||||
return observable.pipe(
|
||||
filter((response: any) => (response.cancelled ? false : true)),
|
||||
@ -448,13 +448,15 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
}
|
||||
}
|
||||
|
||||
return this._request(url, data, { requestId: query.requestId, headers: query.headers }).catch((err: any) => {
|
||||
if (err.cancelled) {
|
||||
return err;
|
||||
}
|
||||
return this._request(url, data, { requestId: query.requestId, headers: query.headers }).pipe(
|
||||
catchError(err => {
|
||||
if (err.cancelled) {
|
||||
return of(err);
|
||||
}
|
||||
|
||||
throw this.handleErrors(err, query);
|
||||
});
|
||||
return throwError(this.handleErrors(err, query));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
performInstantQuery(query: PromQueryRequest, time: number) {
|
||||
@ -474,13 +476,15 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
}
|
||||
}
|
||||
|
||||
return this._request(url, data, { requestId: query.requestId, headers: query.headers }).catch((err: any) => {
|
||||
if (err.cancelled) {
|
||||
return err;
|
||||
}
|
||||
return this._request(url, data, { requestId: query.requestId, headers: query.headers }).pipe(
|
||||
catchError(err => {
|
||||
if (err.cancelled) {
|
||||
return of(err);
|
||||
}
|
||||
|
||||
throw this.handleErrors(err, query);
|
||||
});
|
||||
return throwError(this.handleErrors(err, query));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
handleErrors = (err: any, target: PromQuery) => {
|
||||
@ -582,7 +586,11 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
const query = this.createQuery(queryModel, queryOptions, start, end);
|
||||
|
||||
const self = this;
|
||||
const response: PromDataQueryResponse = await this.performTimeSeriesQuery(query, query.start, query.end);
|
||||
const response: PromDataQueryResponse = await this.performTimeSeriesQuery(
|
||||
query,
|
||||
query.start,
|
||||
query.end
|
||||
).toPromise();
|
||||
const eventList: AnnotationEvent[] = [];
|
||||
const splitKeys = tagKeys.split(',');
|
||||
|
||||
@ -662,7 +670,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
async testDatasource() {
|
||||
const now = new Date().getTime();
|
||||
const query = { expr: '1+1' } as PromQueryRequest;
|
||||
const response = await this.performInstantQuery(query, now / 1000);
|
||||
const response = await this.performInstantQuery(query, now / 1000).toPromise();
|
||||
return response.data.status === 'success'
|
||||
? { status: 'success', message: 'Data source is working' }
|
||||
: { status: 'error', message: response.error };
|
||||
@ -690,9 +698,8 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
async loadRules() {
|
||||
try {
|
||||
const res = await this.metadataRequest('/api/v1/rules');
|
||||
const body = res.data || res.json();
|
||||
const groups = res.data?.data?.groups;
|
||||
|
||||
const groups = body?.data?.groups;
|
||||
if (groups) {
|
||||
this.ruleMappings = extractRuleMappingFromGroups(groups);
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ import _ from 'lodash';
|
||||
import LRU from 'lru-cache';
|
||||
import { Value } from 'slate';
|
||||
|
||||
import { dateTime, LanguageProvider, HistoryItem } from '@grafana/data';
|
||||
import { CompletionItem, TypeaheadInput, TypeaheadOutput, CompletionItemGroup } from '@grafana/ui';
|
||||
import { dateTime, HistoryItem, LanguageProvider } from '@grafana/data';
|
||||
import { CompletionItem, CompletionItemGroup, TypeaheadInput, TypeaheadOutput } from '@grafana/ui';
|
||||
|
||||
import { parseSelector, processLabels, processHistogramLabels, fixSummariesMetadata } from './language_utils';
|
||||
import { fixSummariesMetadata, parseSelector, processHistogramLabels, processLabels } from './language_utils';
|
||||
import PromqlSyntax, { FUNCTIONS, RATE_RANGES } from './promql';
|
||||
|
||||
import { PrometheusDatasource } from './datasource';
|
||||
import { PromQuery, PromMetricsMetadata } from './types';
|
||||
import { PromMetricsMetadata, PromQuery } from './types';
|
||||
|
||||
const DEFAULT_KEYS = ['job', 'instance'];
|
||||
const EMPTY_SELECTOR = '{}';
|
||||
@ -101,9 +101,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
||||
request = async (url: string, defaultValue: any): Promise<any> => {
|
||||
try {
|
||||
const res = await this.datasource.metadataRequest(url);
|
||||
const body = await (res.data || res.json());
|
||||
|
||||
return body.data;
|
||||
return res.data.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
import 'whatwg-fetch'; // fetch polyfill needed backendSrv
|
||||
import { of } from 'rxjs';
|
||||
import { DataSourceInstanceSettings, toUtc } from '@grafana/data';
|
||||
|
||||
import { PrometheusDatasource } from './datasource';
|
||||
import PrometheusMetricFindQuery from './metric_find_query';
|
||||
import { DataSourceInstanceSettings, toUtc } from '@grafana/data';
|
||||
import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__
|
||||
import { PromOptions } from './types';
|
||||
import { FetchResponse } from '@grafana/runtime';
|
||||
|
||||
jest.mock('app/features/templating/template_srv', () => {
|
||||
return {
|
||||
@ -16,7 +20,7 @@ jest.mock('@grafana/runtime', () => ({
|
||||
getBackendSrv: () => backendSrv,
|
||||
}));
|
||||
|
||||
const datasourceRequestMock = jest.spyOn(backendSrv, 'datasourceRequest');
|
||||
const fetchMock = jest.spyOn(backendSrv, 'fetch');
|
||||
|
||||
const instanceSettings = ({
|
||||
url: 'proxied',
|
||||
@ -54,7 +58,7 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
});
|
||||
|
||||
const setupMetricFindQuery = (data: any) => {
|
||||
datasourceRequestMock.mockImplementation(() => Promise.resolve({ status: 'success', data: data.response }));
|
||||
fetchMock.mockImplementation(() => of(({ status: 'success', data: data.response } as unknown) as FetchResponse));
|
||||
return new PrometheusMetricFindQuery(ds, data.query);
|
||||
};
|
||||
|
||||
@ -69,8 +73,8 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
const results = await query.process();
|
||||
|
||||
expect(results).toHaveLength(3);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledTimes(1);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledWith({
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock).toHaveBeenCalledWith({
|
||||
method: 'GET',
|
||||
url: 'proxied/api/v1/labels',
|
||||
hideFromInspector: true,
|
||||
@ -88,8 +92,8 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
const results = await query.process();
|
||||
|
||||
expect(results).toHaveLength(3);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledTimes(1);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledWith({
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock).toHaveBeenCalledWith({
|
||||
method: 'GET',
|
||||
url: 'proxied/api/v1/label/resource/values',
|
||||
hideFromInspector: true,
|
||||
@ -111,8 +115,8 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
const results = await query.process();
|
||||
|
||||
expect(results).toHaveLength(3);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledTimes(1);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledWith({
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock).toHaveBeenCalledWith({
|
||||
method: 'GET',
|
||||
url: `proxied/api/v1/series?match${encodeURIComponent(
|
||||
'[]'
|
||||
@ -136,8 +140,8 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
const results = await query.process();
|
||||
|
||||
expect(results).toHaveLength(3);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledTimes(1);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledWith({
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock).toHaveBeenCalledWith({
|
||||
method: 'GET',
|
||||
url:
|
||||
'proxied/api/v1/series?match%5B%5D=metric%7Blabel1%3D%22foo%22%2C+label2%3D%22bar%22%2C+label3%3D%22baz%22%7D&start=1524650400&end=1524654000',
|
||||
@ -162,8 +166,8 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
expect(results).toHaveLength(2);
|
||||
expect(results[0].text).toBe('value1');
|
||||
expect(results[1].text).toBe('value2');
|
||||
expect(datasourceRequestMock).toHaveBeenCalledTimes(1);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledWith({
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock).toHaveBeenCalledWith({
|
||||
method: 'GET',
|
||||
url: `proxied/api/v1/series?match${encodeURIComponent(
|
||||
'[]'
|
||||
@ -183,8 +187,8 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
const results = await query.process();
|
||||
|
||||
expect(results).toHaveLength(3);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledTimes(1);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledWith({
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock).toHaveBeenCalledWith({
|
||||
method: 'GET',
|
||||
url: 'proxied/api/v1/label/__name__/values',
|
||||
hideFromInspector: true,
|
||||
@ -211,8 +215,8 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
|
||||
expect(results).toHaveLength(1);
|
||||
expect(results[0].text).toBe('metric{job="testjob"} 3846 1443454528000');
|
||||
expect(datasourceRequestMock).toHaveBeenCalledTimes(1);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledWith({
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock).toHaveBeenCalledWith({
|
||||
method: 'GET',
|
||||
url: `proxied/api/v1/query?query=metric&time=${raw.to.unix()}`,
|
||||
requestId: undefined,
|
||||
@ -237,8 +241,8 @@ describe('PrometheusMetricFindQuery', () => {
|
||||
expect(results[0].text).toBe('up{instance="127.0.0.1:1234",job="job1"}');
|
||||
expect(results[1].text).toBe('up{instance="127.0.0.1:5678",job="job1"}');
|
||||
expect(results[2].text).toBe('up{instance="127.0.0.1:9102",job="job1"}');
|
||||
expect(datasourceRequestMock).toHaveBeenCalledTimes(1);
|
||||
expect(datasourceRequestMock).toHaveBeenCalledWith({
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock).toHaveBeenCalledWith({
|
||||
method: 'GET',
|
||||
url: `proxied/api/v1/series?match${encodeURIComponent('[]')}=${encodeURIComponent(
|
||||
'up{job="job1"}'
|
||||
|
@ -1,6 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import { TimeRange, MetricFindValue } from '@grafana/data';
|
||||
import { PrometheusDatasource, PromDataQueryResponse } from './datasource';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { MetricFindValue, TimeRange } from '@grafana/data';
|
||||
import { PromDataQueryResponse, PrometheusDatasource } from './datasource';
|
||||
import { PromQueryRequest } from './types';
|
||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
|
||||
@ -39,7 +40,7 @@ export default class PrometheusMetricFindQuery {
|
||||
|
||||
const queryResultQuery = this.query.match(queryResultRegex);
|
||||
if (queryResultQuery) {
|
||||
return this.queryResultQuery(queryResultQuery[1]);
|
||||
return this.queryResultQuery(queryResultQuery[1]).toPromise();
|
||||
}
|
||||
|
||||
// if query contains full metric name, return metric name and label list
|
||||
@ -116,24 +117,26 @@ export default class PrometheusMetricFindQuery {
|
||||
queryResultQuery(query: string) {
|
||||
const end = this.datasource.getPrometheusTime(this.range.to, true);
|
||||
const instantQuery: PromQueryRequest = { expr: query } as PromQueryRequest;
|
||||
return this.datasource.performInstantQuery(instantQuery, end).then((result: PromDataQueryResponse) => {
|
||||
return _.map(result.data.data.result, metricData => {
|
||||
let text = metricData.metric.__name__ || '';
|
||||
delete metricData.metric.__name__;
|
||||
text +=
|
||||
'{' +
|
||||
_.map(metricData.metric, (v, k) => {
|
||||
return k + '="' + v + '"';
|
||||
}).join(',') +
|
||||
'}';
|
||||
text += ' ' + metricData.value[1] + ' ' + metricData.value[0] * 1000;
|
||||
return this.datasource.performInstantQuery(instantQuery, end).pipe(
|
||||
map((result: PromDataQueryResponse) => {
|
||||
return _.map(result.data.data.result, metricData => {
|
||||
let text = metricData.metric.__name__ || '';
|
||||
delete metricData.metric.__name__;
|
||||
text +=
|
||||
'{' +
|
||||
_.map(metricData.metric, (v, k) => {
|
||||
return k + '="' + v + '"';
|
||||
}).join(',') +
|
||||
'}';
|
||||
text += ' ' + metricData.value[1] + ' ' + metricData.value[0] * 1000;
|
||||
|
||||
return {
|
||||
text: text,
|
||||
expandable: true,
|
||||
};
|
||||
});
|
||||
});
|
||||
return {
|
||||
text: text,
|
||||
expandable: true,
|
||||
};
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
metricNameAndLabelsQuery(query: string): Promise<MetricFindValue[]> {
|
||||
|
Reference in New Issue
Block a user