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>
pull/27124/head
Hugo Häggmark 5 years ago committed by GitHub
parent 0fb7ee05d1
commit a73e6f728d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 127
      public/app/plugins/datasource/prometheus/datasource.test.ts
  2. 61
      public/app/plugins/datasource/prometheus/datasource.ts
  3. 12
      public/app/plugins/datasource/prometheus/language_provider.ts
  4. 42
      public/app/plugins/datasource/prometheus/metric_find_query.test.ts
  5. 43
      public/app/plugins/datasource/prometheus/metric_find_query.ts

@ -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[]> {

Loading…
Cancel
Save