Loki: Remove experimental predefined operations (#107289)

* Loki: Remove experimental predefined operations

* Fix lint
This commit is contained in:
Ivana Huckova 2025-06-30 16:08:36 +02:00 committed by GitHub
parent 7f2aed42a0
commit cc542f2b91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 12 additions and 133 deletions

View File

@ -166,10 +166,6 @@ export interface FeatureToggles {
*/
extraThemes?: boolean;
/**
* Adds predefined query operations to Loki query editor
*/
lokiPredefinedOperations?: boolean;
/**
* Enables the plugins frontend sandbox
*/
pluginsFrontendSandbox?: boolean;

View File

@ -262,13 +262,6 @@ var (
Stage: FeatureStageExperimental,
Owner: grafanaFrontendPlatformSquad,
},
{
Name: "lokiPredefinedOperations",
Description: "Adds predefined query operations to Loki query editor",
FrontendOnly: true,
Stage: FeatureStageExperimental,
Owner: grafanaObservabilityLogsSquad,
},
{
Name: "pluginsFrontendSandbox",
Description: "Enables the plugins frontend sandbox",

View File

@ -33,7 +33,6 @@ refactorVariablesTimeRange,preview,@grafana/dashboards-squad,false,false,false
faroDatasourceSelector,preview,@grafana/app-o11y,false,false,true
enableDatagridEditing,preview,@grafana/dataviz-squad,false,false,true
extraThemes,experimental,@grafana/grafana-frontend-platform,false,false,true
lokiPredefinedOperations,experimental,@grafana/observability-logs,false,false,true
pluginsFrontendSandbox,privatePreview,@grafana/plugins-platform-backend,false,false,false
pluginsDetailsRightPanel,GA,@grafana/plugins-platform-backend,false,false,true
sqlDatasourceDatabaseSelection,preview,@grafana/oss-big-tent,false,false,true

1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
33 faroDatasourceSelector preview @grafana/app-o11y false false true
34 enableDatagridEditing preview @grafana/dataviz-squad false false true
35 extraThemes experimental @grafana/grafana-frontend-platform false false true
lokiPredefinedOperations experimental @grafana/observability-logs false false true
36 pluginsFrontendSandbox privatePreview @grafana/plugins-platform-backend false false false
37 pluginsDetailsRightPanel GA @grafana/plugins-platform-backend false false true
38 sqlDatasourceDatabaseSelection preview @grafana/oss-big-tent false false true

View File

@ -143,10 +143,6 @@ const (
// Enables extra themes
FlagExtraThemes = "extraThemes"
// FlagLokiPredefinedOperations
// Adds predefined query operations to Loki query editor
FlagLokiPredefinedOperations = "lokiPredefinedOperations"
// FlagPluginsFrontendSandbox
// Enables the plugins frontend sandbox
FlagPluginsFrontendSandbox = "pluginsFrontendSandbox"

View File

@ -1846,7 +1846,8 @@
"metadata": {
"name": "lokiPredefinedOperations",
"resourceVersion": "1750434297879",
"creationTimestamp": "2023-06-02T10:52:36Z"
"creationTimestamp": "2023-06-02T10:52:36Z",
"deletionTimestamp": "2025-06-27T08:08:44Z"
},
"spec": {
"description": "Adds predefined query operations to Loki query editor",

View File

@ -12,7 +12,7 @@ import {
QueryHeaderSwitch,
QueryEditorMode,
} from '@grafana/plugin-ui';
import { config, reportInteraction } from '@grafana/runtime';
import { reportInteraction } from '@grafana/runtime';
import { Button, ConfirmModal, Space, Stack } from '@grafana/ui';
import { LabelBrowserModal } from '../querybuilder/components/LabelBrowserModal';
@ -43,13 +43,9 @@ export const LokiQueryEditor = memo<LokiQueryEditorProps>((props) => {
const [queryStats, setQueryStats] = useState<QueryStats | null>(null);
const [explain, setExplain] = useState(window.localStorage.getItem(lokiQueryEditorExplainKey) === 'true');
const predefinedOperations = datasource.predefinedOperations;
const previousTimeRange = usePrevious(timeRange);
const query = getQueryWithDefaults(props.query);
if (config.featureToggles.lokiPredefinedOperations && !query.expr && predefinedOperations) {
query.expr = `{} ${predefinedOperations}`;
}
const previousQueryExpr = usePrevious(query.expr);
const previousQueryType = usePrevious(query.queryType);

View File

@ -1,5 +1,3 @@
import { useCallback } from 'react';
import { DataSourcePluginOptionsEditorProps, DataSourceSettings } from '@grafana/data';
import {
ConfigSection,
@ -9,7 +7,7 @@ import {
convertLegacyAuthProps,
AdvancedHttpSettings,
} from '@grafana/plugin-ui';
import { config, reportInteraction } from '@grafana/runtime';
import { config } from '@grafana/runtime';
import { Divider, SecureSocksProxySettings, Stack } from '@grafana/ui';
import { LokiOptions } from '../types';
@ -33,20 +31,10 @@ const makeJsonUpdater =
};
const setMaxLines = makeJsonUpdater('maxLines');
const setPredefinedOperations = makeJsonUpdater('predefinedOperations');
const setDerivedFields = makeJsonUpdater('derivedFields');
export const ConfigEditor = (props: Props) => {
const { options, onOptionsChange } = props;
const updatePredefinedOperations = useCallback(
(value: string) => {
reportInteraction('grafana_loki_predefined_operations_changed', { value });
onOptionsChange(setPredefinedOperations(options, value));
},
[options, onOptionsChange]
);
return (
<>
<DataSourceDescription
@ -79,8 +67,6 @@ export const ConfigEditor = (props: Props) => {
<QuerySettings
maxLines={options.jsonData.maxLines || ''}
onMaxLinedChange={(value) => onOptionsChange(setMaxLines(options, value))}
predefinedOperations={options.jsonData.predefinedOperations || ''}
onPredefinedOperationsChange={updatePredefinedOperations}
/>
<DerivedFields
fields={options.jsonData.derivedFields}

View File

@ -1,18 +1,15 @@
import * as React from 'react';
import { ConfigDescriptionLink, ConfigSubSection } from '@grafana/plugin-ui';
import { config } from '@grafana/runtime';
import { Badge, InlineField, InlineFieldRow, Input } from '@grafana/ui';
import { InlineField, Input } from '@grafana/ui';
type Props = {
maxLines: string;
onMaxLinedChange: (value: string) => void;
predefinedOperations: string;
onPredefinedOperationsChange: (value: string) => void;
};
export const QuerySettings = (props: Props) => {
const { maxLines, onMaxLinedChange, predefinedOperations, onPredefinedOperationsChange } = props;
const { maxLines, onMaxLinedChange } = props;
return (
<ConfigSubSection
title="Queries"
@ -46,43 +43,6 @@ export const QuerySettings = (props: Props) => {
spellCheck={false}
/>
</InlineField>
{config.featureToggles.lokiPredefinedOperations && (
<InlineFieldRow>
<InlineField
label="Predefined operations"
htmlFor="loki_config_predefinedOperations"
labelWidth={22}
tooltip={
<>
{
'Predefined operations are used as an initial state for your queries. They are useful, if you want to unpack, parse or format all log lines. Currently we support only log operations starting with |. For example: | unpack | line_format "{{.message}}".'
}
</>
}
>
<Input
type="string"
id="loki_config_predefinedOperations"
value={predefinedOperations}
onChange={(event: React.FormEvent<HTMLInputElement>) =>
onPredefinedOperationsChange(event.currentTarget.value)
}
width={40}
placeholder="| unpack | line_format"
spellCheck={false}
/>
</InlineField>
<InlineField>
<Badge
text="Experimental"
color="orange"
icon="exclamation-triangle"
tooltip="Predefined operations is an experimental feature that may change in the future."
/>
</InlineField>
</InlineFieldRow>
)}
</ConfigSubSection>
);
};

View File

@ -147,7 +147,6 @@ export class LokiDatasource
private logContextProvider: LogContextProvider;
languageProvider: LanguageProvider;
maxLines: number;
predefinedOperations: string;
constructor(
private instanceSettings: DataSourceInstanceSettings<LokiOptions>,
@ -158,7 +157,6 @@ export class LokiDatasource
this.languageProvider = new LanguageProvider(this);
const settingsData = instanceSettings.jsonData || {};
this.maxLines = parseInt(settingsData.maxLines ?? '0', 10) || DEFAULT_MAX_LINES;
this.predefinedOperations = settingsData.predefinedOperations ?? '';
this.annotations = {
QueryEditor: LokiAnnotationsQueryEditor,
};
@ -342,11 +340,7 @@ export class LokiDatasource
}
const startTime = new Date();
return this.runQuery(fixedRequest).pipe(
tap((response) =>
trackQuery(response, fixedRequest, startTime, { predefinedOperations: this.predefinedOperations })
)
);
return this.runQuery(fixedRequest).pipe(tap((response) => trackQuery(response, fixedRequest, startTime)));
}
/**

View File

@ -306,8 +306,7 @@ describe('runSplitQuery()', () => {
},
],
request,
new Date(),
{ predefinedOperations: '' }
new Date()
);
});
});
@ -336,8 +335,7 @@ describe('runSplitQuery()', () => {
},
],
request,
new Date(),
{ predefinedOperations: '' }
new Date()
);
});
});

View File

@ -359,9 +359,7 @@ export function runSplitQuery(
return runSplitGroupedQueries(datasource, requests, options).pipe(
tap((response) => {
if (response.state === LoadingState.Done) {
trackGroupedQueries(response, requests, request, startTime, {
predefinedOperations: datasource.predefinedOperations,
});
trackGroupedQueries(response, requests, request, startTime);
}
})
);

View File

@ -85,7 +85,6 @@ describe('Tracks queries', () => {
time_range_from: '2023-02-08T05:00:00.000Z',
time_range_to: '2023-02-10T06:00:00.000Z',
time_taken: 0,
predefined_operations_applied: 'n/a',
});
});
@ -100,31 +99,6 @@ describe('Tracks queries', () => {
});
});
test('Tracks predefined operations', () => {
trackQuery({ data: [] }, originalRequest, new Date(), { predefinedOperations: 'count_over_time' });
expect(reportInteraction).toHaveBeenCalledWith('grafana_explore_loki_query_executed', {
bytes_processed: 0,
editor_mode: 'builder',
grafana_version: '1.0',
has_data: false,
has_error: false,
is_split: false,
legend: undefined,
line_limit: undefined,
obfuscated_query: 'count_over_time({Identifier=String}[1m])',
query_type: 'metric',
query_vector_type: undefined,
resolution: 1,
simultaneously_executed_query_count: 2,
simultaneously_hidden_query_count: 1,
time_range_from: '2023-02-08T05:00:00.000Z',
time_range_to: '2023-02-10T06:00:00.000Z',
time_taken: 0,
predefined_operations_applied: true,
});
});
test('Tracks grouped queries', () => {
trackGroupedQueries({ data: [] }, requests, originalRequest, new Date());
@ -150,7 +124,6 @@ test('Tracks grouped queries', () => {
time_range_from: '2023-02-08T05:00:00.000Z',
time_range_to: '2023-02-10T06:00:00.000Z',
time_taken: 0,
predefined_operations_applied: 'n/a',
});
expect(reportInteraction).toHaveBeenCalledWith('grafana_explore_loki_query_executed', {
@ -175,7 +148,6 @@ test('Tracks grouped queries', () => {
time_range_from: '2023-02-08T05:00:00.000Z',
time_range_to: '2023-02-10T06:00:00.000Z',
time_taken: 0,
predefined_operations_applied: 'n/a',
});
});

View File

@ -53,10 +53,6 @@ type LokiOnDashboardLoadedTrackingEvent = {
queries_with_changed_legend_count: number;
};
export type LokiTrackingSettings = {
predefinedOperations?: string;
};
export const onDashboardLoadedHandler = ({
payload: { dashboardId, orgId, grafanaVersion, queries },
}: DashboardLoadedEvent<LokiQuery>) => {
@ -158,7 +154,6 @@ export function trackQuery(
response: DataQueryResponse,
request: DataQueryRequest<LokiQuery>,
startTime: Date,
trackingSettings: LokiTrackingSettings = {},
extraPayload: Record<string, unknown> = {}
): void {
// We only want to track usage for these specific apps
@ -193,9 +188,6 @@ export function trackQuery(
time_taken: Date.now() - startTime.getTime(),
bytes_processed: totalBytes,
is_split: false,
predefined_operations_applied: trackingSettings.predefinedOperations
? query.expr.includes(trackingSettings.predefinedOperations)
: 'n/a',
...extraPayload,
});
}
@ -205,8 +197,7 @@ export function trackGroupedQueries(
response: DataQueryResponse,
groupedRequests: LokiGroupedRequest[],
originalRequest: DataQueryRequest<LokiQuery>,
startTime: Date,
trackingSettings: LokiTrackingSettings = {}
startTime: Date
): void {
const splittingPayload = {
split_query_group_count: groupedRequests.length,
@ -219,7 +210,7 @@ export function trackGroupedQueries(
for (const group of groupedRequests) {
const split_query_partition_size = group.partition.length;
trackQuery(response, group.request, startTime, trackingSettings, {
trackQuery(response, group.request, startTime, {
...splittingPayload,
split_query_partition_size,
});

View File

@ -43,7 +43,6 @@ export interface LokiOptions extends DataSourceJsonData {
derivedFields?: DerivedFieldConfig[];
alertmanager?: string;
keepCookies?: string[];
predefinedOperations?: string;
}
export interface LokiStreamResult {