Loki: Use getNormalizedLokiQuery to get queryType (#70237)

* Loki: Use getNormalizedLokiQuery to get queryType

* Simplify

* Remove unused import

* Refactor, improve and add tests

* Update
This commit is contained in:
Ivana Huckova 2023-06-20 16:27:32 +02:00 committed by GitHub
parent d8a74ab1b7
commit 60f6538bad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 29 deletions

View File

@ -8,6 +8,7 @@ import { SelectableValue } from '@grafana/data';
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
import { InlineFormLabel, RadioButtonGroup, InlineField, Input, Select } from '@grafana/ui'; import { InlineFormLabel, RadioButtonGroup, InlineField, Input, Select } from '@grafana/ui';
import { getLokiQueryType } from '../queryUtils';
import { LokiQuery, LokiQueryType } from '../types'; import { LokiQuery, LokiQueryType } from '../types';
export interface LokiOptionFieldsProps { export interface LokiOptionFieldsProps {
@ -51,7 +52,7 @@ export const RESOLUTION_OPTIONS: Array<SelectableValue<number>> = [DEFAULT_RESOL
export function LokiOptionFields(props: LokiOptionFieldsProps) { export function LokiOptionFields(props: LokiOptionFieldsProps) {
const { lineLimitValue, resolution, onRunQuery, runOnBlur, onChange } = props; const { lineLimitValue, resolution, onRunQuery, runOnBlur, onChange } = props;
const query = props.query ?? {}; const query = props.query ?? {};
let queryType = query.queryType ?? (query.instant ? LokiQueryType.Instant : LokiQueryType.Range); const queryType = getLokiQueryType(query);
function onChangeQueryLimit(value: string) { function onChangeQueryLimit(value: string) {
const nextQuery = { ...query, maxLines: preprocessMaxLines(value) }; const nextQuery = { ...query, maxLines: preprocessMaxLines(value) };

View File

@ -1,6 +1,6 @@
import { import {
getHighlighterExpressionsFromQuery, getHighlighterExpressionsFromQuery,
getNormalizedLokiQuery, getLokiQueryType,
isLogsQuery, isLogsQuery,
isQueryWithLabelFormat, isQueryWithLabelFormat,
isQueryWithParser, isQueryWithParser,
@ -11,6 +11,7 @@ import {
requestSupportsSplitting, requestSupportsSplitting,
isQueryWithDistinct, isQueryWithDistinct,
isQueryWithRangeVariable, isQueryWithRangeVariable,
getNormalizedLokiQuery,
} from './queryUtils'; } from './queryUtils';
import { LokiQuery, LokiQueryType } from './types'; import { LokiQuery, LokiQueryType } from './types';
@ -116,50 +117,69 @@ describe('getHighlighterExpressionsFromQuery', () => {
}); });
describe('getNormalizedLokiQuery', () => { describe('getNormalizedLokiQuery', () => {
function expectNormalized(inputProps: Object, outputQueryType: LokiQueryType) { it('removes deprecated instant property', () => {
const input: LokiQuery = { refId: 'A', expr: 'test1', ...inputProps }; const input: LokiQuery = { refId: 'A', expr: 'test1', instant: true };
const output = getNormalizedLokiQuery(input); const output = getNormalizedLokiQuery(input);
expect(output).toStrictEqual({ refId: 'A', expr: 'test1', queryType: outputQueryType }); expect(output).toStrictEqual({ refId: 'A', expr: 'test1', queryType: LokiQueryType.Instant });
});
it('removes deprecated range property', () => {
const input: LokiQuery = { refId: 'A', expr: 'test1', range: true };
const output = getNormalizedLokiQuery(input);
expect(output).toStrictEqual({ refId: 'A', expr: 'test1', queryType: LokiQueryType.Range });
});
it('removes deprecated range and instant properties if query with queryType', () => {
const input: LokiQuery = { refId: 'A', expr: 'test1', range: true, instant: false, queryType: LokiQueryType.Range };
const output = getNormalizedLokiQuery(input);
expect(output).toStrictEqual({ refId: 'A', expr: 'test1', queryType: LokiQueryType.Range });
});
});
describe('getLokiQueryType', () => {
function expectCorrectQueryType(inputProps: Object, outputQueryType: LokiQueryType) {
const input: LokiQuery = { refId: 'A', expr: 'test1', ...inputProps };
const output = getLokiQueryType(input);
expect(output).toStrictEqual(outputQueryType);
} }
it('handles no props case', () => { it('handles no props case', () => {
expectNormalized({}, LokiQueryType.Range); expectCorrectQueryType({}, LokiQueryType.Range);
}); });
it('handles old-style instant case', () => { it('handles old-style instant case', () => {
expectNormalized({ instant: true, range: false }, LokiQueryType.Instant); expectCorrectQueryType({ instant: true, range: false }, LokiQueryType.Instant);
}); });
it('handles old-style range case', () => { it('handles old-style range case', () => {
expectNormalized({ instant: false, range: true }, LokiQueryType.Range); expectCorrectQueryType({ instant: false, range: true }, LokiQueryType.Range);
}); });
it('handles new+old style instant', () => { it('handles new+old style instant', () => {
expectNormalized({ instant: true, range: false, queryType: LokiQueryType.Range }, LokiQueryType.Range); expectCorrectQueryType({ instant: true, range: false, queryType: LokiQueryType.Range }, LokiQueryType.Range);
}); });
it('handles new+old style range', () => { it('handles new+old style range', () => {
expectNormalized({ instant: false, range: true, queryType: LokiQueryType.Instant }, LokiQueryType.Instant); expectCorrectQueryType({ instant: false, range: true, queryType: LokiQueryType.Instant }, LokiQueryType.Instant);
}); });
it('handles new<>old conflict (new wins), range', () => { it('handles new<>old conflict (new wins), range', () => {
expectNormalized({ instant: false, range: true, queryType: LokiQueryType.Range }, LokiQueryType.Range); expectCorrectQueryType({ instant: false, range: true, queryType: LokiQueryType.Range }, LokiQueryType.Range);
}); });
it('handles new<>old conflict (new wins), instant', () => { it('handles new<>old conflict (new wins), instant', () => {
expectNormalized({ instant: true, range: false, queryType: LokiQueryType.Instant }, LokiQueryType.Instant); expectCorrectQueryType({ instant: true, range: false, queryType: LokiQueryType.Instant }, LokiQueryType.Instant);
}); });
it('handles invalid new, range', () => { it('handles invalid new, range', () => {
expectNormalized({ queryType: 'invalid' }, LokiQueryType.Range); expectCorrectQueryType({ queryType: 'invalid' }, LokiQueryType.Range);
}); });
it('handles invalid new, when old-range exists, use old', () => { it('handles invalid new, when old-range exists, use old', () => {
expectNormalized({ instant: false, range: true, queryType: 'invalid' }, LokiQueryType.Range); expectCorrectQueryType({ instant: false, range: true, queryType: 'invalid' }, LokiQueryType.Range);
}); });
it('handles invalid new, when old-instant exists, use old', () => { it('handles invalid new, when old-instant exists, use old', () => {
expectNormalized({ instant: true, range: false, queryType: 'invalid' }, LokiQueryType.Instant); expectCorrectQueryType({ instant: true, range: false, queryType: 'invalid' }, LokiQueryType.Instant);
}); });
}); });

View File

@ -84,32 +84,32 @@ export function getHighlighterExpressionsFromQuery(input: string): string[] {
return results; return results;
} }
// we are migrating from `.instant` and `.range` to `.queryType`
// this function returns a new query object that:
// - has `.queryType`
// - does not have `.instant`
// - does not have `.range`
export function getNormalizedLokiQuery(query: LokiQuery): LokiQuery { export function getNormalizedLokiQuery(query: LokiQuery): LokiQuery {
// if queryType field contains invalid data we behave as if the queryType is empty const queryType = getLokiQueryType(query);
// instant and range are deprecated, we want to remove them
const { instant, range, ...rest } = query;
return { ...rest, queryType };
}
export function getLokiQueryType(query: LokiQuery): LokiQueryType {
// we are migrating from `.instant` and `.range` to `.queryType`
// this function returns the correct query type
const { queryType } = query; const { queryType } = query;
const hasValidQueryType = const hasValidQueryType =
queryType === LokiQueryType.Range || queryType === LokiQueryType.Instant || queryType === LokiQueryType.Stream; queryType === LokiQueryType.Range || queryType === LokiQueryType.Instant || queryType === LokiQueryType.Stream;
// if queryType exists, it is respected // if queryType exists, it is respected
if (hasValidQueryType) { if (hasValidQueryType) {
const { instant, range, ...rest } = query; return queryType;
return rest;
} }
// if no queryType, and instant===true, it's instant // if no queryType, and instant===true, it's instant
if (query.instant === true) { if (query.instant === true) {
const { instant, range, ...rest } = query; return LokiQueryType.Instant;
return { ...rest, queryType: LokiQueryType.Instant };
} }
// otherwise it is range // otherwise it is range
const { instant, range, ...rest } = query; return LokiQueryType.Range;
return { ...rest, queryType: LokiQueryType.Range };
} }
const tagsToObscure = ['String', 'Identifier', 'LineComment', 'Number']; const tagsToObscure = ['String', 'Identifier', 'LineComment', 'Number'];

View File

@ -8,7 +8,7 @@ import { AutoSizeInput, RadioButtonGroup, Select } from '@grafana/ui';
import { QueryOptionGroup } from 'app/plugins/datasource/prometheus/querybuilder/shared/QueryOptionGroup'; import { QueryOptionGroup } from 'app/plugins/datasource/prometheus/querybuilder/shared/QueryOptionGroup';
import { preprocessMaxLines, queryTypeOptions, RESOLUTION_OPTIONS } from '../../components/LokiOptionFields'; import { preprocessMaxLines, queryTypeOptions, RESOLUTION_OPTIONS } from '../../components/LokiOptionFields';
import { isLogsQuery } from '../../queryUtils'; import { getLokiQueryType, isLogsQuery } from '../../queryUtils';
import { LokiQuery, LokiQueryType, QueryStats } from '../../types'; import { LokiQuery, LokiQueryType, QueryStats } from '../../types';
export interface Props { export interface Props {
@ -67,7 +67,7 @@ export const LokiQueryBuilderOptions = React.memo<Props>(
onRunQuery(); onRunQuery();
} }
const queryType = query.queryType ?? (query.instant ? LokiQueryType.Instant : LokiQueryType.Range); const queryType = getLokiQueryType(query);
const isLogQuery = isLogsQuery(query.expr); const isLogQuery = isLogsQuery(query.expr);
const isValidStep = useMemo(() => { const isValidStep = useMemo(() => {