Loki: Remove `instant` query type from Log queries (#90137)

* Loki: Prevent log queries to run as `instant` query

* Loki: add tests

* Loki: only overwrite instant queries

* Loki: fix tests

* Loki: fix tests
pull/90939/head
Sven Grossmann 10 months ago committed by GitHub
parent 9bb2cf4968
commit cca9dee702
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 16
      public/app/plugins/datasource/loki/datasource.test.ts
  2. 9
      public/app/plugins/datasource/loki/module.test.ts
  3. 2
      public/app/plugins/datasource/loki/queryUtils.test.ts
  4. 12
      public/app/plugins/datasource/loki/queryUtils.ts
  5. 11
      public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx
  6. 19
      public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.tsx

@ -1362,13 +1362,14 @@ describe('LokiDatasource', () => {
expect(ds.getSupplementaryRequest(SupplementaryQueryType.LogsVolume, options)).toBeDefined();
});
it('does not create provider if there is only an instant logs query', () => {
it('does create provider if there is only an instant logs query', () => {
// we changed logic to automatically run logs queries as range queries, thus there's a provider now
const options: DataQueryRequest<LokiQuery> = {
...baseRequestOptions,
targets: [{ expr: '{label="value"', refId: 'A', queryType: LokiQueryType.Instant }],
};
expect(ds.getSupplementaryRequest(SupplementaryQueryType.LogsVolume, options)).not.toBeDefined();
expect(ds.getSupplementaryRequest(SupplementaryQueryType.LogsVolume, options)).toBeDefined();
});
});
@ -1454,7 +1455,8 @@ describe('LokiDatasource', () => {
});
});
it('does not return logs volume query for instant log query', () => {
it('does return logs volume query for instant log query', () => {
// we changed logic to automatically run logs queries as range queries, thus there's a volume query now
expect(
ds.getSupplementaryQuery(
{ type: SupplementaryQueryType.LogsVolume },
@ -1464,7 +1466,13 @@ describe('LokiDatasource', () => {
refId: 'A',
}
)
).toEqual(undefined);
).toEqual({
expr: 'sum by (level) (count_over_time({label="value"} | drop __error__[$__auto]))',
legendFormat: '{{ level }}',
queryType: 'range',
refId: 'log-volume-A',
supportingQueryType: 'logsVolume',
});
});
it('does not return logs volume query for metric query', () => {

@ -27,8 +27,7 @@ jest.mock('@grafana/runtime', () => {
{
datasource: { type: 'loki', uid: 'abc' },
editorMode: 'builder',
expr: '{place="$place"} |= `error`',
maxLines: 60,
expr: 'count_over_time({place="$place"} [5m])',
queryType: 'instant',
refId: 'A',
},
@ -77,11 +76,11 @@ describe('queriesOnInitDashboard', () => {
org_id: 1,
code_mode_queries_count: 2,
instant_queries_count: 1,
logs_queries_count: 2,
metric_queries_count: 3,
logs_queries_count: 1,
metric_queries_count: 4,
queries_count: 5,
queries_with_changed_legend_count: 3,
queries_with_changed_line_limit_count: 2,
queries_with_changed_line_limit_count: 1,
queries_with_changed_resolution_count: 0,
queries_with_template_variables_count: 2,
range_queries_count: 4,

@ -133,7 +133,7 @@ describe('getNormalizedLokiQuery', () => {
it('removes deprecated instant property', () => {
const input: LokiQuery = { refId: 'A', expr: 'test1', instant: true };
const output = getNormalizedLokiQuery(input);
expect(output).toStrictEqual({ refId: 'A', expr: 'test1', queryType: LokiQueryType.Instant });
expect(output).toStrictEqual({ refId: 'A', expr: 'test1', queryType: LokiQueryType.Range });
});
it('removes deprecated range property', () => {

@ -91,9 +91,16 @@ export function getStringsFromLineFilter(filter: SyntaxNode): SyntaxNode[] {
}
export function getNormalizedLokiQuery(query: LokiQuery): LokiQuery {
const queryType = getLokiQueryType(query);
let queryType = getLokiQueryType(query);
// instant and range are deprecated, we want to remove them
const { instant, range, ...rest } = query;
// if `query.expr` is not parsable this might throw an error
try {
if (isLogsQuery(query.expr) && queryType === LokiQueryType.Instant) {
queryType = LokiQueryType.Range;
}
} catch (e) {}
return { ...rest, queryType };
}
@ -200,7 +207,8 @@ export function isQueryWithError(query: string): boolean {
}
export function isLogsQuery(query: string): boolean {
return !isQueryWithNode(query, MetricExpr);
// As a safeguard we are checking for a length of 2, because at least the query should be `{}`
return query.trim().length > 2 && !isQueryWithNode(query, MetricExpr);
}
export function isQueryWithParser(query: string): { queryWithParser: boolean; parserCount: number } {

@ -151,6 +151,17 @@ describe('LokiQueryBuilderOptions', () => {
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.queryByText(/Invalid step/)).not.toBeInTheDocument();
});
it('does not show instant type when using a log query', async () => {
setup({ expr: '{foo="bar"}', queryType: LokiQueryType.Instant });
expect(screen.queryByText(/Instant/)).not.toBeInTheDocument();
});
it('does not show instant type in the options when using a log query', async () => {
setup({ expr: '{foo="bar"}', step: '1m' });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.queryByText(/Instant/)).not.toBeInTheDocument();
});
});
function setup(queryOverrides: Partial<LokiQuery> = {}) {

@ -67,8 +67,17 @@ export const LokiQueryBuilderOptions = React.memo<Props>(
onRunQuery();
}
const queryType = getLokiQueryType(query);
let queryType = getLokiQueryType(query);
const isLogQuery = isLogsQuery(query.expr);
const filteredQueryTypeOptions = isLogQuery
? queryTypeOptions.filter((o) => o.value !== LokiQueryType.Instant)
: queryTypeOptions;
// if the state's queryType is still Instant, trigger a change to range for log queries
if (isLogQuery && queryType === LokiQueryType.Instant) {
onChange({ ...query, queryType: LokiQueryType.Range });
queryType = LokiQueryType.Range;
}
const isValidStep = useMemo(() => {
if (!query.step || isValidGrafanaDuration(query.step) || !isNaN(Number(query.step))) {
@ -96,9 +105,11 @@ export const LokiQueryBuilderOptions = React.memo<Props>(
onCommitChange={onLegendFormatChanged}
/>
</EditorField>
<EditorField label="Type">
<RadioButtonGroup options={queryTypeOptions} value={queryType} onChange={onQueryTypeChange} />
</EditorField>
{filteredQueryTypeOptions.length > 1 && (
<EditorField label="Type">
<RadioButtonGroup options={filteredQueryTypeOptions} value={queryType} onChange={onQueryTypeChange} />
</EditorField>
)}
{isLogQuery && (
<EditorField label="Line limit" tooltip="Upper limit for number of log lines returned by query.">
<AutoSizeInput

Loading…
Cancel
Save