Logs: remove toggleLabelsInLogsUI (#77264)

* toggleLabelsInLogsUI: remove flag

* Remove unused imports

* isFilterLabelActive: refId is not optional

* Revert "isFilterLabelActive: refId is not optional"

This reverts commit 008931b7e9.

* Revert method signature change

* Update tests

* Update tests
This commit is contained in:
Matias Chomicki 2023-10-27 13:00:49 +02:00 committed by GitHub
parent 8e8731edc5
commit 46f331e284
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 22 additions and 69 deletions

View File

@ -48,7 +48,6 @@ Some features are enabled by default. You can disable these feature by setting t
| `cloudWatchLogsMonacoEditor` | Enables the Monaco editor for CloudWatch Logs queries | Yes |
| `recordedQueriesMulti` | Enables writing multiple items from a single query within Recorded Queries | Yes |
| `transformationsRedesign` | Enables the transformations redesign | Yes |
| `toggleLabelsInLogsUI` | Enable toggleable filters in log details view | Yes |
| `azureMonitorDataplane` | Adds dataplane compliant frame metadata in the Azure Monitor datasource | Yes |
| `prometheusConfigOverhaulAuth` | Update the Prometheus configuration page with the new auth component | Yes |
| `dashgpt` | Enable AI powered features in dashboards | Yes |

View File

@ -103,7 +103,6 @@ export interface FeatureToggles {
logsExploreTableVisualisation?: boolean;
awsDatasourcesTempCredentials?: boolean;
transformationsRedesign?: boolean;
toggleLabelsInLogsUI?: boolean;
mlExpressions?: boolean;
traceQLStreaming?: boolean;
metricsSummary?: boolean;

View File

@ -589,14 +589,6 @@ var (
Expression: "true", // enabled by default
Owner: grafanaObservabilityMetricsSquad,
},
{
Name: "toggleLabelsInLogsUI",
Description: "Enable toggleable filters in log details view",
Stage: FeatureStageGeneralAvailability,
FrontendOnly: true,
Expression: "true", // enabled by default
Owner: grafanaObservabilityLogsSquad,
},
{
Name: "mlExpressions",
Description: "Enable support for Machine Learning in server-side expressions",

View File

@ -84,7 +84,6 @@ prometheusIncrementalQueryInstrumentation,experimental,@grafana/observability-me
logsExploreTableVisualisation,experimental,@grafana/observability-logs,false,false,false,true
awsDatasourcesTempCredentials,experimental,@grafana/aws-datasources,false,false,false,false
transformationsRedesign,GA,@grafana/observability-metrics,false,false,false,true
toggleLabelsInLogsUI,GA,@grafana/observability-logs,false,false,false,true
mlExpressions,experimental,@grafana/alerting-squad,false,false,false,false
traceQLStreaming,experimental,@grafana/observability-traces-and-profiling,false,false,false,true
metricsSummary,experimental,@grafana/observability-traces-and-profiling,false,false,false,true

1 Name Stage Owner requiresDevMode RequiresLicense RequiresRestart FrontendOnly
84 logsExploreTableVisualisation experimental @grafana/observability-logs false false false true
85 awsDatasourcesTempCredentials experimental @grafana/aws-datasources false false false false
86 transformationsRedesign GA @grafana/observability-metrics false false false true
toggleLabelsInLogsUI GA @grafana/observability-logs false false false true
87 mlExpressions experimental @grafana/alerting-squad false false false false
88 traceQLStreaming experimental @grafana/observability-traces-and-profiling false false false true
89 metricsSummary experimental @grafana/observability-traces-and-profiling false false false true

View File

@ -347,10 +347,6 @@ const (
// Enables the transformations redesign
FlagTransformationsRedesign = "transformationsRedesign"
// FlagToggleLabelsInLogsUI
// Enable toggleable filters in log details view
FlagToggleLabelsInLogsUI = "toggleLabelsInLogsUI"
// FlagMlExpressions
// Enable support for Machine Learning in server-side expressions
FlagMlExpressions = "mlExpressions"

View File

@ -17,7 +17,7 @@ import {
SupplementaryQueryType,
} from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { config, getDataSourceSrv, reportInteraction } from '@grafana/runtime';
import { getDataSourceSrv, reportInteraction } from '@grafana/runtime';
import { DataQuery } from '@grafana/schema';
import {
AdHocFilterItem,
@ -206,9 +206,6 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
* @alpha
*/
isFilterLabelActive = async (key: string, value: string, refId?: string) => {
if (!config.featureToggles.toggleLabelsInLogsUI) {
return false;
}
const query = this.props.queries.find((q) => q.refId === refId);
if (!query) {
return false;
@ -254,7 +251,7 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
return query;
}
const ds = await getDataSourceSrv().get(datasource);
if (hasToggleableQueryFiltersSupport(ds) && config.featureToggles.toggleLabelsInLogsUI) {
if (hasToggleableQueryFiltersSupport(ds)) {
return ds.toggleQueryFilter(query, {
type: modification.type === 'ADD_FILTER' ? 'FILTER_FOR' : 'FILTER_OUT',
options: modification.options ?? {},

View File

@ -3,7 +3,6 @@ import userEvent from '@testing-library/user-event';
import React from 'react';
import { Field, LogLevel, LogRowModel, MutableDataFrame, createTheme, FieldType } from '@grafana/data';
import { config } from '@grafana/runtime';
import { LogDetails, Props } from './LogDetails';
import { createLogRow } from './__mocks__/logRow';
@ -57,16 +56,10 @@ describe('LogDetails', () => {
},
{ labels: { key1: 'label1' } }
);
expect(screen.getByLabelText('Filter for value')).toBeInTheDocument();
expect(screen.getByLabelText('Filter out value')).toBeInTheDocument();
expect(screen.getByLabelText('Filter for value in query A')).toBeInTheDocument();
expect(screen.getByLabelText('Filter out value in query A')).toBeInTheDocument();
});
describe('With toggleLabelsInLogsUI=true', () => {
beforeAll(() => {
config.featureToggles.toggleLabelsInLogsUI = true;
});
afterAll(() => {
config.featureToggles.toggleLabelsInLogsUI = false;
});
describe('Toggleable filters', () => {
it('should provide the log row to Explore filter functions', async () => {
const onClickFilterLabelMock = jest.fn();
const onClickFilterOutLabelMock = jest.fn();

View File

@ -1,10 +1,8 @@
import { fireEvent, render, screen } from '@testing-library/react';
import React, { ComponentProps } from 'react';
import { LogRowModel } from '@grafana/data';
import config from 'app/core/config';
import { LogDetailsRow } from './LogDetailsRow';
import { createLogRow } from './__mocks__/logRow';
type Props = ComponentProps<typeof LogDetailsRow>;
@ -20,7 +18,7 @@ const setup = (propOverrides?: Partial<Props>) => {
onClickShowField: () => {},
onClickHideField: () => {},
displayedFields: [],
row: {} as LogRowModel,
row: createLogRow(),
disableActions: false,
};
@ -55,32 +53,18 @@ describe('LogDetailsRow', () => {
expect(screen.getAllByRole('button', { name: 'Ad-hoc statistics' })).toHaveLength(1);
});
describe('if props is a label', () => {
it('should render filter label button', () => {
describe('toggleable filters', () => {
it('should render filter buttons', () => {
setup();
expect(screen.getAllByRole('button', { name: 'Filter for value' })).toHaveLength(1);
expect(screen.queryByRole('button', { name: 'Remove filter' })).not.toBeInTheDocument();
expect(screen.getAllByRole('button', { name: 'Filter for value in query A' })).toHaveLength(1);
expect(screen.getAllByRole('button', { name: 'Filter out value in query A' })).toHaveLength(1);
expect(screen.queryByRole('button', { name: 'Remove filter in query A' })).not.toBeInTheDocument();
});
it('should render filter out label button', () => {
setup();
expect(screen.getAllByRole('button', { name: 'Filter out value' })).toHaveLength(1);
});
it('should render filter buttons when toggleLabelsInLogsUI false', async () => {
it('should render remove filter button when the filter is active', async () => {
setup({
isFilterLabelActive: jest.fn().mockResolvedValue(true),
});
expect(screen.getByRole('button', { name: 'Filter for value' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Filter out value' })).toBeInTheDocument();
});
it('should render remove filter button when toggleLabelsInLogsUI true', async () => {
const defaultValue = config.featureToggles.toggleLabelsInLogsUI;
config.featureToggles.toggleLabelsInLogsUI = true;
setup({
isFilterLabelActive: jest.fn().mockResolvedValue(true),
});
expect(await screen.findByRole('button', { name: 'Remove filter' })).toBeInTheDocument();
config.featureToggles.toggleLabelsInLogsUI = defaultValue;
expect(await screen.findByRole('button', { name: 'Remove filter in query A' })).toBeInTheDocument();
});
});

View File

@ -4,7 +4,7 @@ import memoizeOne from 'memoize-one';
import React, { PureComponent, useState } from 'react';
import { CoreApp, Field, GrafanaTheme2, IconName, LinkModel, LogLabelStatsModel, LogRowModel } from '@grafana/data';
import { config, reportInteraction } from '@grafana/runtime';
import { reportInteraction } from '@grafana/runtime';
import { ClipboardButton, DataLinkButton, IconButton, Themeable2, withTheme2 } from '@grafana/ui';
import { LogLabelStats } from './LogLabelStats';
@ -257,8 +257,7 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
const singleKey = parsedKeys == null ? false : parsedKeys.length === 1;
const singleVal = parsedValues == null ? false : parsedValues.length === 1;
const hasFilteringFunctionality = !disableActions && onClickFilterLabel && onClickFilterOutLabel;
const refIdTooltip =
config.featureToggles.toggleLabelsInLogsUI && row.dataFrame?.refId ? ` in query ${row.dataFrame?.refId}` : '';
const refIdTooltip = row.dataFrame?.refId ? ` in query ${row.dataFrame?.refId}` : '';
const isMultiParsedValueWithNoContent =
!singleVal && parsedValues != null && !parsedValues.every((val) => val === '');
@ -277,17 +276,12 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
<div className={styles.buttonRow}>
{hasFilteringFunctionality && (
<>
{config.featureToggles.toggleLabelsInLogsUI ? (
// If we are using the new label toggling, we want to use the async icon button
<AsyncIconButton
name="search-plus"
onClick={this.filterLabel}
isActive={this.isFilterLabelActive}
tooltipSuffix={refIdTooltip}
/>
) : (
<IconButton name="search-plus" onClick={this.filterLabel} tooltip="Filter for value" />
)}
<AsyncIconButton
name="search-plus"
onClick={this.filterLabel}
isActive={this.isFilterLabelActive}
tooltipSuffix={refIdTooltip}
/>
<IconButton
name="search-minus"
tooltip={`Filter out value${refIdTooltip}`}