Loki: Remove experimental lokiQuerySplittingConfig (#107298)

* Loki: Remove experimental lokiQuerySplittingConfig

* Remove unused imports
pull/107403/head
Ivana Huckova 3 weeks ago committed by GitHub
parent 12d7b804eb
commit bc425a7993
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      packages/grafana-data/src/types/featureToggles.gen.ts
  2. 7
      pkg/services/featuremgmt/registry.go
  3. 1
      pkg/services/featuremgmt/toggles_gen.csv
  4. 4
      pkg/services/featuremgmt/toggles_gen.go
  5. 3
      pkg/services/featuremgmt/toggles_gen.json
  6. 84
      public/app/plugins/datasource/loki/querySplitting.test.ts
  7. 56
      public/app/plugins/datasource/loki/querySplitting.ts
  8. 40
      public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.tsx
  9. 6
      public/app/plugins/datasource/loki/types.ts

@ -107,10 +107,6 @@ export interface FeatureToggles {
*/
lokiQuerySplitting?: boolean;
/**
* Give users the option to configure split durations for Loki queries
*/
lokiQuerySplittingConfig?: boolean;
/**
* Support overriding cookie preferences per user
*/
individualCookiePreferences?: boolean;

@ -163,13 +163,6 @@ var (
Expression: "true", // turned on by default
AllowSelfServe: true,
},
{
Name: "lokiQuerySplittingConfig",
Description: "Give users the option to configure split durations for Loki queries",
Stage: FeatureStageExperimental,
FrontendOnly: true,
Owner: grafanaObservabilityLogsSquad,
},
{
Name: "individualCookiePreferences",
Description: "Support overriding cookie preferences per user",

@ -19,7 +19,6 @@ editPanelCSVDragAndDrop,experimental,@grafana/dataviz-squad,false,false,true
logsContextDatasourceUi,GA,@grafana/observability-logs,false,false,true
lokiShardSplitting,experimental,@grafana/observability-logs,false,false,true
lokiQuerySplitting,GA,@grafana/observability-logs,false,false,true
lokiQuerySplittingConfig,experimental,@grafana/observability-logs,false,false,true
individualCookiePreferences,experimental,@grafana/grafana-backend-group,false,false,false
influxdbBackendMigration,GA,@grafana/partner-datasources,false,false,true
influxqlStreamingParser,experimental,@grafana/partner-datasources,false,false,false

1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
19 logsContextDatasourceUi GA @grafana/observability-logs false false true
20 lokiShardSplitting experimental @grafana/observability-logs false false true
21 lokiQuerySplitting GA @grafana/observability-logs false false true
lokiQuerySplittingConfig experimental @grafana/observability-logs false false true
22 individualCookiePreferences experimental @grafana/grafana-backend-group false false false
23 influxdbBackendMigration GA @grafana/partner-datasources false false true
24 influxqlStreamingParser experimental @grafana/partner-datasources false false false

@ -87,10 +87,6 @@ const (
// Split large interval queries into subqueries with smaller time intervals
FlagLokiQuerySplitting = "lokiQuerySplitting"
// FlagLokiQuerySplittingConfig
// Give users the option to configure split durations for Loki queries
FlagLokiQuerySplittingConfig = "lokiQuerySplittingConfig"
// FlagIndividualCookiePreferences
// Support overriding cookie preferences per user
FlagIndividualCookiePreferences = "individualCookiePreferences"

@ -1889,7 +1889,8 @@
"metadata": {
"name": "lokiQuerySplittingConfig",
"resourceVersion": "1750434297879",
"creationTimestamp": "2023-03-20T15:51:36Z"
"creationTimestamp": "2023-03-20T15:51:36Z",
"deletionTimestamp": "2025-06-27T09:32:43Z"
},
"spec": {
"description": "Give users the option to configure split durations for Loki queries",

@ -442,90 +442,6 @@ describe('runSplitQuery()', () => {
});
});
describe('Splitting targets based on splitDuration', () => {
const range1h = {
from: dateTime('2023-02-08T05:00:00.000Z'),
to: dateTime('2023-02-08T06:00:00.000Z'),
raw: {
from: dateTime('2023-02-08T05:00:00.000Z'),
to: dateTime('2023-02-08T06:00:00.000Z'),
},
};
beforeEach(() => {
jest.spyOn(datasource, 'runQuery').mockReturnValue(of({ data: [], refId: 'A' }));
});
test('with 30m splitDuration runs 2 queries', async () => {
const request = {
targets: [{ expr: '{a="b"}', refId: 'A', splitDuration: '30m' }],
range: range1h,
} as DataQueryRequest<LokiQuery>;
await expect(runSplitQuery(datasource, request)).toEmitValuesWith(() => {
expect(datasource.runQuery).toHaveBeenCalledTimes(2);
});
});
test('with 1h splitDuration runs 1 queries', async () => {
const request = {
targets: [{ expr: '{a="b"}', refId: 'A', splitDuration: '1h' }],
range: range1h,
} as DataQueryRequest<LokiQuery>;
await expect(runSplitQuery(datasource, request)).toEmitValuesWith(() => {
expect(datasource.runQuery).toHaveBeenCalledTimes(1);
});
});
test('with 1h splitDuration and 2 targets runs 1 queries', async () => {
const request = {
targets: [
{ expr: '{a="b"}', refId: 'A', splitDuration: '1h' },
{ expr: '{a="b"}', refId: 'B', splitDuration: '1h' },
],
range: range1h,
} as DataQueryRequest<LokiQuery>;
await expect(runSplitQuery(datasource, request)).toEmitValuesWith(() => {
expect(datasource.runQuery).toHaveBeenCalledTimes(1);
});
});
test('with 1h/30m splitDuration and 2 targets runs 3 queries', async () => {
const request = {
targets: [
{ expr: '{a="b"}', refId: 'A', splitDuration: '1h' },
{ expr: '{a="b"}', refId: 'B', splitDuration: '30m' },
],
range: range1h,
} as DataQueryRequest<LokiQuery>;
await expect(runSplitQuery(datasource, request)).toEmitValuesWith(() => {
// 2 x 30m + 1 x 1h
expect(datasource.runQuery).toHaveBeenCalledTimes(3);
});
});
test('with mixed splitDuration runs the expected amount of queries', async () => {
const request = createRequest(
[
{ expr: 'count_over_time({c="d"}[1m])', refId: 'A', splitDuration: '15m' },
{ expr: '{a="b"}', refId: 'B', splitDuration: '15m' },
{ expr: '{a="b"}', refId: 'C', splitDuration: '1h' },
],
{ range: range1h }
);
await expect(runSplitQuery(datasource, request)).toEmitValuesWith(() => {
// 4 * 15m + 4 * 15m + 1 * 1h
expect(datasource.runQuery).toHaveBeenCalledTimes(9);
});
});
test('with 1h/30m splitDuration and 1 log and 2 metric target runs 3 queries', async () => {
const request = createRequest(
[
{ expr: '{a="b"}', refId: 'A', splitDuration: '1h' },
{ expr: 'count_over_time({c="d"}[1m])', refId: 'C', splitDuration: '30m' },
],
{ range: range1h }
);
await expect(runSplitQuery(datasource, request)).toEmitValuesWith(() => {
// 2 x 30m + 1 x 1h
expect(datasource.runQuery).toHaveBeenCalledTimes(3);
});
});
});
describe('Splitting targets based on resolution', () => {
const range1d = {
from: dateTime('2023-02-08T05:00:00.000Z'),

@ -8,8 +8,6 @@ import {
DataQueryResponse,
DataTopic,
dateTime,
durationToMilliseconds,
parseDuration,
rangeUtil,
TimeRange,
LoadingState,
@ -307,45 +305,35 @@ export function runSplitQuery(
const requests: LokiGroupedRequest[] = [];
for (const direction in directionPartitionedLogQueries) {
const rangePartitionedLogQueries = groupBy(directionPartitionedLogQueries[direction], (query) =>
query.splitDuration ? durationToMilliseconds(parseDuration(query.splitDuration)) : oneDayMs
);
for (const [chunkRangeMs, queries] of Object.entries(rangePartitionedLogQueries)) {
const resolutionPartition = groupBy(queries, (query) => query.resolution || 1);
for (const resolution in resolutionPartition) {
const groupedRequest = {
request: { ...request, targets: resolutionPartition[resolution] },
partition: partitionTimeRange(true, request.range, request.intervalMs, Number(chunkRangeMs)),
};
if (direction === LokiQueryDirection.Forward) {
groupedRequest.partition.reverse();
}
const queries = directionPartitionedLogQueries[direction];
const resolutionPartition = groupBy(queries, (query) => query.resolution || 1);
for (const resolution in resolutionPartition) {
const groupedRequest = {
request: { ...request, targets: resolutionPartition[resolution] },
partition: partitionTimeRange(true, request.range, request.intervalMs, oneDayMs),
};
requests.push(groupedRequest);
if (direction === LokiQueryDirection.Forward) {
groupedRequest.partition.reverse();
}
requests.push(groupedRequest);
}
}
const rangePartitionedMetricQueries = groupBy(metricQueries, (query) =>
query.splitDuration ? durationToMilliseconds(parseDuration(query.splitDuration)) : oneDayMs
const stepMsPartition = groupBy(metricQueries, (query) =>
calculateStep(request.intervalMs, request.range, query.resolution || 1, query.step)
);
for (const [chunkRangeMs, queries] of Object.entries(rangePartitionedMetricQueries)) {
const stepMsPartition = groupBy(queries, (query) =>
calculateStep(request.intervalMs, request.range, query.resolution || 1, query.step)
);
for (const stepMs in stepMsPartition) {
const targets = stepMsPartition[stepMs].map((q) => {
const { maxLines, ...query } = q;
return query;
});
requests.push({
request: { ...request, targets },
partition: partitionTimeRange(false, request.range, Number(stepMs), Number(chunkRangeMs)),
});
}
for (const stepMs in stepMsPartition) {
const targets = stepMsPartition[stepMs].map((q) => {
const { maxLines, ...query } = q;
return query;
});
requests.push({
request: { ...request, targets },
partition: partitionTimeRange(false, request.range, Number(stepMs), oneDayMs),
});
}
if (nonSplittingQueries.length) {

@ -1,17 +1,10 @@
import { trim } from 'lodash';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo } from 'react';
import * as React from 'react';
import {
CoreApp,
isValidDuration,
isValidGrafanaDuration,
LogSortOrderChangeEvent,
LogsSortOrder,
store,
} from '@grafana/data';
import { CoreApp, isValidGrafanaDuration, LogSortOrderChangeEvent, LogsSortOrder, store } from '@grafana/data';
import { EditorField, EditorRow, QueryOptionGroup } from '@grafana/plugin-ui';
import { config, getAppEvents } from '@grafana/runtime';
import { getAppEvents } from '@grafana/runtime';
import { AutoSizeInput, RadioButtonGroup } from '@grafana/ui';
import {
@ -36,7 +29,6 @@ export interface Props {
export const LokiQueryBuilderOptions = React.memo<Props>(
({ app, query, onChange, onRunQuery, queryStats, datasource }) => {
const [splitDurationValid, setSplitDurationValid] = useState(true);
const maxLines = datasource.maxLines;
useEffect(() => {
@ -71,17 +63,6 @@ export const LokiQueryBuilderOptions = React.memo<Props>(
[onChange, onRunQuery, query]
);
const onChunkRangeChange = (evt: React.FormEvent<HTMLInputElement>) => {
const value = evt.currentTarget.value;
if (!isValidDuration(value)) {
setSplitDurationValid(false);
return;
}
setSplitDurationValid(true);
onChange({ ...query, splitDuration: value });
onRunQuery();
};
const onLegendFormatChanged = (evt: React.FormEvent<HTMLInputElement>) => {
onChange({ ...query, legendFormat: evt.currentTarget.value });
onRunQuery();
@ -214,21 +195,6 @@ export const LokiQueryBuilderOptions = React.memo<Props>(
</EditorField>
</>
)}
{config.featureToggles.lokiQuerySplittingConfig && config.featureToggles.lokiQuerySplitting && (
<EditorField
label="Split Duration"
tooltip="Defines the duration of a single query when query splitting is enabled."
>
<AutoSizeInput
minWidth={14}
type="string"
min={0}
defaultValue={query.splitDuration ?? '1d'}
onCommitChange={onChunkRangeChange}
invalid={!splitDurationValid}
/>
</EditorField>
)}
</QueryOptionGroup>
</EditorRow>
);

@ -30,12 +30,6 @@ export interface LokiQuery extends LokiQueryFromSchema {
// the temporary fix (until this gets improved in the codegen), is to
// override it here
queryType?: LokiQueryType;
/**
* This is a property for the experimental query splitting feature.
* @experimental
*/
splitDuration?: string;
}
export interface LokiOptions extends DataSourceJsonData {

Loading…
Cancel
Save