loki: better resource-call urls (#48250)

This commit is contained in:
Gábor Farkas 2022-04-28 14:28:57 +02:00 committed by GitHub
parent 9688d7d7aa
commit ae926c2144
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 29 additions and 26 deletions

View File

@ -98,11 +98,12 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq
if req.Method != "GET" {
return fmt.Errorf("invalid resource method: %s", req.Method)
}
if (!strings.HasPrefix(url, "/loki/api/v1/labels?")) &&
(!strings.HasPrefix(url, "/loki/api/v1/label/")) && // the `/label/$label_name/values` form
(!strings.HasPrefix(url, "/loki/api/v1/series?")) {
if (!strings.HasPrefix(url, "labels?")) &&
(!strings.HasPrefix(url, "label/")) && // the `/label/$label_name/values` form
(!strings.HasPrefix(url, "series?")) {
return fmt.Errorf("invalid resource URL: %s", url)
}
lokiURL := fmt.Sprintf("/loki/api/v1/%s", url)
dsInfo, err := s.getDSInfo(req.PluginContext)
if err != nil {
@ -110,7 +111,7 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq
}
api := newLokiAPI(dsInfo.HTTPClient, dsInfo.URL, s.plog)
bytes, err := api.RawQuery(ctx, url)
bytes, err := api.RawQuery(ctx, lokiURL)
if err != nil {
return err

View File

@ -1000,7 +1000,7 @@ describe('LokiDatasource', () => {
describe('importing queries', () => {
it('keeps all labels when no labels are loaded', async () => {
const ds = createLokiDSForTests();
fetchMock.mockImplementation(() => of(createFetchResponse({ data: [] })));
ds.getResource = () => Promise.resolve({ data: [] });
const queries = await ds.importFromAbstractQueries([
{
refId: 'A',
@ -1015,7 +1015,9 @@ describe('LokiDatasource', () => {
it('filters out non existing labels', async () => {
const ds = createLokiDSForTests();
fetchMock.mockImplementation(() => of(createFetchResponse({ data: ['foo'] })));
ds.getResource = () => {
return Promise.resolve({ data: ['foo'] });
};
const queries = await ds.importFromAbstractQueries([
{
refId: 'A',

View File

@ -439,13 +439,13 @@ export class LokiDatasource
}
async metadataRequest(url: string, params?: Record<string, string | number>) {
if (config.featureToggles.lokiBackendMode) {
const res = await this.getResource(url, params);
return res.data || [];
} else {
const res = await lastValueFrom(this._request(url, params, { hideFromInspector: true }));
return res.data.data || [];
// url must not start with a `/`, otherwise the AJAX-request
// going from the browser will contain `//`, which can cause problems.
if (url.startsWith('/')) {
throw new Error(`invalid metadata request url: ${url}`);
}
const res = await this.getResource(url, params);
return res.data || [];
}
async metricFindQuery(query: string) {
@ -479,7 +479,7 @@ export class LokiDatasource
}
async labelNamesQuery() {
const url = `${LOKI_ENDPOINT}/labels`;
const url = 'labels';
const params = this.getTimeRangeParams();
const result = await this.metadataRequest(url, params);
return result.map((value: string) => ({ text: value }));
@ -487,7 +487,7 @@ export class LokiDatasource
async labelValuesQuery(label: string) {
const params = this.getTimeRangeParams();
const url = `${LOKI_ENDPOINT}/label/${label}/values`;
const url = `label/${label}/values`;
const result = await this.metadataRequest(url, params);
return result.map((value: string) => ({ text: value }));
}
@ -498,7 +498,7 @@ export class LokiDatasource
...timeParams,
'match[]': expr,
};
const url = `${LOKI_ENDPOINT}/series`;
const url = 'series';
const streams = new Set();
const result = await this.metadataRequest(url, params);
result.forEach((stream: { [key: string]: string }) => {

View File

@ -95,7 +95,7 @@ describe('Language completion provider', () => {
const fetchSeries = languageProvider.fetchSeries;
const requestSpy = jest.spyOn(languageProvider, 'request');
fetchSeries('{job="grafana"}');
expect(requestSpy).toHaveBeenCalledWith('/loki/api/v1/series', {
expect(requestSpy).toHaveBeenCalledWith('series', {
end: 1560163909000,
'match[]': '{job="grafana"}',
start: 1560153109000,
@ -116,7 +116,7 @@ describe('Language completion provider', () => {
const requestSpy = jest.spyOn(languageProvider, 'request').mockResolvedValue([]);
fetchSeriesLabels('$stream');
expect(requestSpy).toHaveBeenCalled();
expect(requestSpy).toHaveBeenCalledWith('/loki/api/v1/series', {
expect(requestSpy).toHaveBeenCalledWith('series', {
end: 1,
'match[]': 'interpolated-stream',
start: 0,
@ -259,7 +259,7 @@ describe('Request URL', () => {
const instance = new LanguageProvider(datasourceWithLabels);
instance.fetchLabels();
const expectedUrl = '/loki/api/v1/labels';
const expectedUrl = 'labels';
expect(datasourceSpy).toHaveBeenCalledWith(expectedUrl, rangeParams);
});
});

View File

@ -364,7 +364,7 @@ export default class LokiLanguageProvider extends LanguageProvider {
* Fetches all label keys
*/
async fetchLabels(): Promise<string[]> {
const url = '/loki/api/v1/labels';
const url = 'labels';
const timeRange = this.datasource.getTimeRangeParams();
this.labelFetchTs = Date.now().valueOf();
@ -393,7 +393,7 @@ export default class LokiLanguageProvider extends LanguageProvider {
*/
fetchSeriesLabels = async (match: string): Promise<Record<string, string[]>> => {
const interpolatedMatch = this.datasource.interpolateString(match);
const url = '/loki/api/v1/series';
const url = 'series';
const { start, end } = this.datasource.getTimeRangeParams();
const cacheKey = this.generateCacheKey(url, start, end, interpolatedMatch);
@ -415,7 +415,7 @@ export default class LokiLanguageProvider extends LanguageProvider {
* @param match
*/
fetchSeries = async (match: string): Promise<Array<Record<string, string>>> => {
const url = '/loki/api/v1/series';
const url = 'series';
const { start, end } = this.datasource.getTimeRangeParams();
const params = { 'match[]': match, start, end };
return await this.request(url, params);
@ -440,7 +440,7 @@ export default class LokiLanguageProvider extends LanguageProvider {
async fetchLabelValues(key: string): Promise<string[]> {
const interpolatedKey = this.datasource.interpolateString(key);
const url = `/loki/api/v1/label/${interpolatedKey}/values`;
const url = `label/${interpolatedKey}/values`;
const rangeParams = this.datasource.getTimeRangeParams();
const { start, end } = rangeParams;

View File

@ -2,7 +2,7 @@ import { DataSourceSettings } from '@grafana/data';
import { createDatasourceSettings } from '../../../features/datasources/mocks';
import { LokiDatasource, LOKI_ENDPOINT } from './datasource';
import { LokiDatasource } from './datasource';
import { LokiOptions } from './types';
interface Labels {
@ -18,10 +18,10 @@ interface SeriesForSelector {
}
export function makeMockLokiDatasource(labelsAndValues: Labels, series?: SeriesForSelector): LokiDatasource {
const lokiLabelsAndValuesEndpointRegex = /^\/loki\/api\/v1\/label\/(\w*)\/values/;
const lokiSeriesEndpointRegex = /^\/loki\/api\/v1\/series/;
const lokiLabelsAndValuesEndpointRegex = /^label\/(\w*)\/values/;
const lokiSeriesEndpointRegex = /^series/;
const lokiLabelsEndpoint = `${LOKI_ENDPOINT}/labels`;
const lokiLabelsEndpoint = 'labels';
const rangeMock = {
start: 1560153109000,
end: 1560163909000,