mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Datasource/Loki: Remove code dealing with legacy Loki endpoints (#23437)
This commit is contained in:
@@ -1,22 +1,16 @@
|
||||
// Libraries
|
||||
import { isEmpty, map as lodashMap } from 'lodash';
|
||||
import { Observable, from, merge, of, iif, defer } from 'rxjs';
|
||||
import { map, filter, catchError, switchMap, mergeMap } from 'rxjs/operators';
|
||||
import { Observable, from, merge, of } from 'rxjs';
|
||||
import { map, filter, catchError, switchMap } from 'rxjs/operators';
|
||||
|
||||
// Services & Utils
|
||||
import { DataFrame, dateMath, FieldCache } from '@grafana/data';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { addLabelToSelector, keepSelectorFilters } from 'app/plugins/datasource/prometheus/add_label_to_query';
|
||||
import { DatasourceRequestOptions } from 'app/core/services/backend_srv';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { safeStringifyValue, convertToWebSocketUrl } from 'app/core/utils/explore';
|
||||
import {
|
||||
lokiResultsToTableModel,
|
||||
processRangeQueryResponse,
|
||||
legacyLogStreamToDataFrame,
|
||||
lokiStreamResultToDataFrame,
|
||||
lokiLegacyStreamsToDataframes,
|
||||
} from './result_transformer';
|
||||
import { lokiResultsToTableModel, processRangeQueryResponse, lokiStreamResultToDataFrame } from './result_transformer';
|
||||
import { formatQuery, parseQuery, getHighlighterExpressionsFromQuery } from './query_utils';
|
||||
|
||||
// Types
|
||||
@@ -26,7 +20,6 @@ import {
|
||||
LoadingState,
|
||||
AnnotationEvent,
|
||||
DataFrameView,
|
||||
TimeRange,
|
||||
TimeSeries,
|
||||
PluginMeta,
|
||||
DataSourceApi,
|
||||
@@ -42,30 +35,25 @@ import {
|
||||
import {
|
||||
LokiQuery,
|
||||
LokiOptions,
|
||||
LokiLegacyQueryRequest,
|
||||
LokiLegacyStreamResponse,
|
||||
LokiResponse,
|
||||
LokiResultType,
|
||||
LokiRangeQueryRequest,
|
||||
LokiStreamResponse,
|
||||
} from './types';
|
||||
import { LegacyTarget, LiveStreams } from './live_streams';
|
||||
import { LiveStreams, LokiLiveTarget } from './live_streams';
|
||||
import LanguageProvider from './language_provider';
|
||||
import { serializeParams } from '../../../core/utils/fetch';
|
||||
|
||||
export type RangeQueryOptions = Pick<DataQueryRequest<LokiQuery>, 'range' | 'intervalMs' | 'maxDataPoints' | 'reverse'>;
|
||||
export const DEFAULT_MAX_LINES = 1000;
|
||||
export const LEGACY_LOKI_ENDPOINT = '/api/prom';
|
||||
export const LOKI_ENDPOINT = '/loki/api/v1';
|
||||
|
||||
const LEGACY_QUERY_ENDPOINT = `${LEGACY_LOKI_ENDPOINT}/query`;
|
||||
const RANGE_QUERY_ENDPOINT = `${LOKI_ENDPOINT}/query_range`;
|
||||
const INSTANT_QUERY_ENDPOINT = `${LOKI_ENDPOINT}/query`;
|
||||
|
||||
const DEFAULT_QUERY_PARAMS: Partial<LokiLegacyQueryRequest> = {
|
||||
const DEFAULT_QUERY_PARAMS: Partial<LokiRangeQueryRequest> = {
|
||||
direction: 'BACKWARD',
|
||||
limit: DEFAULT_MAX_LINES,
|
||||
regexp: '',
|
||||
query: '',
|
||||
};
|
||||
|
||||
@@ -76,7 +64,6 @@ interface LokiContextQueryOptions {
|
||||
|
||||
export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
private streams = new LiveStreams();
|
||||
private version: string;
|
||||
languageProvider: LanguageProvider;
|
||||
maxLines: number;
|
||||
|
||||
@@ -89,23 +76,6 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
this.maxLines = parseInt(settingsData.maxLines, 10) || DEFAULT_MAX_LINES;
|
||||
}
|
||||
|
||||
getVersion() {
|
||||
if (this.version) {
|
||||
return Promise.resolve(this.version);
|
||||
}
|
||||
|
||||
return this._request(RANGE_QUERY_ENDPOINT)
|
||||
.toPromise()
|
||||
.then(() => {
|
||||
this.version = 'v1';
|
||||
return this.version;
|
||||
})
|
||||
.catch((err: any) => {
|
||||
this.version = err.status !== 404 ? 'v1' : 'v0';
|
||||
return this.version;
|
||||
});
|
||||
}
|
||||
|
||||
_request(apiUrl: string, data?: any, options?: DatasourceRequestOptions): Observable<Record<string, any>> {
|
||||
const baseUrl = this.instanceSettings.url;
|
||||
const params = data ? serializeParams(data) : '';
|
||||
@@ -131,13 +101,13 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
filteredTargets.forEach(target =>
|
||||
subQueries.push(
|
||||
this.runInstantQuery(target, options, filteredTargets.length),
|
||||
this.runRangeQueryWithFallback(target, options, filteredTargets.length)
|
||||
this.runRangeQuery(target, options, filteredTargets.length)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
filteredTargets.forEach(target =>
|
||||
subQueries.push(
|
||||
this.runRangeQueryWithFallback(target, options, filteredTargets.length).pipe(
|
||||
this.runRangeQuery(target, options, filteredTargets.length).pipe(
|
||||
map(dataQueryResponse => {
|
||||
if (options.exploreMode === ExploreMode.Logs && dataQueryResponse.data.find(d => isTimeSeries(d))) {
|
||||
throw new Error(
|
||||
@@ -163,41 +133,6 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
return merge(...subQueries);
|
||||
}
|
||||
|
||||
runLegacyQuery = (
|
||||
target: LokiQuery,
|
||||
options: { range?: TimeRange; maxDataPoints?: number; reverse?: boolean }
|
||||
): Observable<DataQueryResponse> => {
|
||||
if (target.liveStreaming) {
|
||||
return this.runLiveQuery(target, options);
|
||||
}
|
||||
|
||||
const range = options.range
|
||||
? { start: this.getTime(options.range.from, false), end: this.getTime(options.range.to, true) }
|
||||
: {};
|
||||
const query: LokiLegacyQueryRequest = {
|
||||
...DEFAULT_QUERY_PARAMS,
|
||||
...parseQuery(target.expr),
|
||||
...range,
|
||||
limit: Math.min(options.maxDataPoints || Infinity, this.maxLines),
|
||||
refId: target.refId,
|
||||
};
|
||||
|
||||
return this._request(LEGACY_QUERY_ENDPOINT, query).pipe(
|
||||
catchError((err: any) => this.throwUnless(err, err.cancelled, target)),
|
||||
filter((response: any) => !response.cancelled),
|
||||
map((response: { data: LokiLegacyStreamResponse }) => ({
|
||||
data: lokiLegacyStreamsToDataframes(
|
||||
response.data,
|
||||
query,
|
||||
this.maxLines,
|
||||
this.instanceSettings.jsonData,
|
||||
options.reverse
|
||||
),
|
||||
key: `${target.refId}_log`,
|
||||
}))
|
||||
);
|
||||
};
|
||||
|
||||
runInstantQuery = (
|
||||
target: LokiQuery,
|
||||
options: DataQueryRequest<LokiQuery>,
|
||||
@@ -255,9 +190,9 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to send a query to /loki/api/v1/query_range but falls back to the legacy endpoint if necessary.
|
||||
* Attempts to send a query to /loki/api/v1/query_range
|
||||
*/
|
||||
runRangeQueryWithFallback = (
|
||||
runRangeQuery = (
|
||||
target: LokiQuery,
|
||||
options: RangeQueryOptions,
|
||||
responseListLength = 1
|
||||
@@ -291,47 +226,26 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
catchError((err: any) => this.throwUnless(err, err.cancelled || err.status === 404, target)),
|
||||
filter((response: any) => (response.cancelled ? false : true)),
|
||||
switchMap((response: { data: LokiResponse; status: number }) =>
|
||||
iif<DataQueryResponse, DataQueryResponse>(
|
||||
() => response.status === 404,
|
||||
defer(() => this.runLegacyQuery(target, queryOptions)),
|
||||
defer(() =>
|
||||
processRangeQueryResponse(
|
||||
response.data,
|
||||
target,
|
||||
query,
|
||||
responseListLength,
|
||||
linesLimit,
|
||||
this.instanceSettings.jsonData,
|
||||
options.reverse
|
||||
)
|
||||
)
|
||||
processRangeQueryResponse(
|
||||
response.data,
|
||||
target,
|
||||
query,
|
||||
responseListLength,
|
||||
linesLimit,
|
||||
this.instanceSettings.jsonData,
|
||||
options.reverse
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
createLegacyLiveTarget(target: LokiQuery, options: { maxDataPoints?: number }): LegacyTarget {
|
||||
const { query, regexp } = parseQuery(target.expr);
|
||||
createLiveTarget(target: LokiQuery, options: { maxDataPoints?: number }): LokiLiveTarget {
|
||||
const { query } = parseQuery(target.expr);
|
||||
const baseUrl = this.instanceSettings.url;
|
||||
const params = serializeParams({ query });
|
||||
|
||||
return {
|
||||
query,
|
||||
regexp,
|
||||
url: convertToWebSocketUrl(`${baseUrl}/api/prom/tail?${params}`),
|
||||
refId: target.refId,
|
||||
size: Math.min(options.maxDataPoints || Infinity, this.maxLines),
|
||||
};
|
||||
}
|
||||
|
||||
createLiveTarget(target: LokiQuery, options: { maxDataPoints?: number }): LegacyTarget {
|
||||
const { query, regexp } = parseQuery(target.expr);
|
||||
const baseUrl = this.instanceSettings.url;
|
||||
const params = serializeParams({ query });
|
||||
|
||||
return {
|
||||
query,
|
||||
regexp,
|
||||
url: convertToWebSocketUrl(`${baseUrl}/loki/api/v1/tail?${params}`),
|
||||
refId: target.refId,
|
||||
size: Math.min(options.maxDataPoints || Infinity, this.maxLines),
|
||||
@@ -347,17 +261,7 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
runLiveQuery = (target: LokiQuery, options: { maxDataPoints?: number }): Observable<DataQueryResponse> => {
|
||||
const liveTarget = this.createLiveTarget(target, options);
|
||||
|
||||
return from(this.getVersion()).pipe(
|
||||
mergeMap(version =>
|
||||
iif(
|
||||
() => version === 'v1',
|
||||
defer(() => this.streams.getStream(liveTarget)),
|
||||
defer(() => {
|
||||
const legacyTarget = this.createLegacyLiveTarget(target, options);
|
||||
return this.streams.getLegacyStream(legacyTarget);
|
||||
})
|
||||
)
|
||||
),
|
||||
return this.streams.getStream(liveTarget).pipe(
|
||||
map(data => ({
|
||||
data,
|
||||
key: `loki-${liveTarget.refId}`,
|
||||
@@ -418,16 +322,13 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
}
|
||||
|
||||
async labelNamesQuery() {
|
||||
const url = (await this.getVersion()) === 'v0' ? `${LEGACY_LOKI_ENDPOINT}/label` : `${LOKI_ENDPOINT}/label`;
|
||||
const url = `${LOKI_ENDPOINT}/label`;
|
||||
const result = await this.metadataRequest(url);
|
||||
return result.map((value: string) => ({ text: value }));
|
||||
}
|
||||
|
||||
async labelValuesQuery(label: string) {
|
||||
const url =
|
||||
(await this.getVersion()) === 'v0'
|
||||
? `${LEGACY_LOKI_ENDPOINT}/label/${label}/values`
|
||||
: `${LOKI_ENDPOINT}/label/${label}/values`;
|
||||
const url = `${LOKI_ENDPOINT}/label/${label}/values`;
|
||||
const result = await this.metadataRequest(url);
|
||||
return result.map((value: string) => ({ text: value }));
|
||||
}
|
||||
@@ -506,29 +407,9 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
throw error;
|
||||
}),
|
||||
switchMap((res: { data: LokiStreamResponse; status: number }) =>
|
||||
iif(
|
||||
() => res.status === 404,
|
||||
defer(() =>
|
||||
this._request(LEGACY_QUERY_ENDPOINT, target).pipe(
|
||||
catchError((err: any) => {
|
||||
const error: DataQueryError = {
|
||||
message: 'Error during context query. Please check JS console logs.',
|
||||
status: err.status,
|
||||
statusText: err.statusText,
|
||||
};
|
||||
throw error;
|
||||
}),
|
||||
map((res: { data: LokiLegacyStreamResponse }) => ({
|
||||
data: res.data ? res.data.streams.map(stream => legacyLogStreamToDataFrame(stream, reverse)) : [],
|
||||
}))
|
||||
)
|
||||
),
|
||||
defer(() =>
|
||||
of({
|
||||
data: res.data ? res.data.data.result.map(stream => lokiStreamResultToDataFrame(stream, reverse)) : [],
|
||||
})
|
||||
)
|
||||
)
|
||||
of({
|
||||
data: res.data ? res.data.data.result.map(stream => lokiStreamResultToDataFrame(stream, reverse)) : [],
|
||||
})
|
||||
)
|
||||
)
|
||||
.toPromise();
|
||||
@@ -576,22 +457,8 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
// 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 this._request('/loki/api/v1/label', { start })
|
||||
return this._request(`${LOKI_ENDPOINT}/label`, { start })
|
||||
.pipe(
|
||||
catchError((err: any) => {
|
||||
if (err.status === 404) {
|
||||
return of(err);
|
||||
}
|
||||
|
||||
throw err;
|
||||
}),
|
||||
switchMap((response: { data: { values: string[] }; status: number }) =>
|
||||
iif<DataQueryResponse, any>(
|
||||
() => response.status === 404,
|
||||
defer(() => this._request('/api/prom/label', { start })),
|
||||
defer(() => of(response))
|
||||
)
|
||||
),
|
||||
map(res => {
|
||||
const values: any[] = res?.data?.data || res?.data?.values || [];
|
||||
const testResult =
|
||||
@@ -634,7 +501,7 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
|
||||
const interpolatedExpr = this.templateSrv.replace(options.annotation.expr, {}, this.interpolateQueryExpr);
|
||||
const query = { refId: `annotation-${options.annotation.name}`, expr: interpolatedExpr };
|
||||
const { data } = await this.runRangeQueryWithFallback(query, options).toPromise();
|
||||
const { data } = await this.runRangeQuery(query, options).toPromise();
|
||||
const annotations: AnnotationEvent[] = [];
|
||||
|
||||
for (const frame of data) {
|
||||
|
||||
Reference in New Issue
Block a user