Logs: Hide filters in log details if the data source doesn't support them (#73230)

* Logs: Hide filters in log details if the data source doesn't support them

* Logs Container: use logsQueries prop

* Log details: add filters visibility test
This commit is contained in:
Matias Chomicki 2023-08-17 17:53:11 +02:00 committed by GitHub
parent 5988da1aa8
commit 48c3dc7203
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 7 deletions

View File

@ -82,8 +82,8 @@ interface Props extends Themeable2 {
loadLogsVolumeData: () => void;
showContextToggle?: (row?: LogRowModel) => boolean;
onChangeTime: (range: AbsoluteTimeRange) => void;
onClickFilterLabel: (key: string, value: string) => void;
onClickFilterOutLabel: (key: string, value: string) => void;
onClickFilterLabel?: (key: string, value: string) => void;
onClickFilterOutLabel?: (key: string, value: string) => void;
onStartScanning?: () => void;
onStopScanning?: () => void;
getRowContext?: (row: LogRowModel, origRow: LogRowModel, options: LogRowContextOptions) => Promise<any>;
@ -95,7 +95,7 @@ interface Props extends Themeable2 {
eventBus: EventBus;
panelState?: ExplorePanelsState;
scrollElement?: HTMLDivElement;
isFilterLabelActive: (key: string, value: string) => Promise<boolean>;
isFilterLabelActive?: (key: string, value: string) => Promise<boolean>;
logsFrames?: DataFrame[];
range: TimeRange;
}

View File

@ -17,7 +17,9 @@ import {
LogRowContextOptions,
DataSourceWithLogsContextSupport,
DataSourceApi,
hasToggleableQueryFiltersSupport,
} from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
import { DataQuery } from '@grafana/schema';
import { Collapse } from '@grafana/ui';
import { StoreState } from 'app/types';
@ -55,7 +57,50 @@ interface LogsContainerProps extends PropsFromRedux {
isFilterLabelActive: (key: string, value: string) => Promise<boolean>;
}
class LogsContainer extends PureComponent<LogsContainerProps> {
interface LogsContainerState {
logDetailsFilterAvailable: boolean;
}
class LogsContainer extends PureComponent<LogsContainerProps, LogsContainerState> {
state: LogsContainerState = {
logDetailsFilterAvailable: false,
};
componentDidMount() {
this.checkFiltersAvailability();
}
componentDidUpdate(prevProps: LogsContainerProps) {
this.checkFiltersAvailability();
}
private checkFiltersAvailability() {
const { logsQueries, datasourceInstance } = this.props;
if (!logsQueries) {
return;
}
if (datasourceInstance?.modifyQuery || hasToggleableQueryFiltersSupport(datasourceInstance)) {
this.setState({ logDetailsFilterAvailable: true });
return;
}
const promises = [];
for (const query of logsQueries) {
if (query.datasource) {
promises.push(getDataSourceSrv().get(query.datasource));
}
}
Promise.all(promises).then((dataSources) => {
const logDetailsFilterAvailable = dataSources.some(
(ds) => ds.modifyQuery || hasToggleableQueryFiltersSupport(ds)
);
this.setState({ logDetailsFilterAvailable });
});
}
onChangeTime = (absoluteRange: AbsoluteTimeRange) => {
const { exploreId, updateTimeRange } = this.props;
updateTimeRange({ exploreId, absoluteRange });
@ -153,6 +198,7 @@ class LogsContainer extends PureComponent<LogsContainerProps> {
logsVolume,
scrollElement,
} = this.props;
const { logDetailsFilterAvailable } = this.state;
if (!logRows) {
return null;
@ -197,8 +243,8 @@ class LogsContainer extends PureComponent<LogsContainerProps> {
loadingState={loadingState}
loadLogsVolumeData={() => loadSupplementaryQueryData(exploreId, SupplementaryQueryType.LogsVolume)}
onChangeTime={this.onChangeTime}
onClickFilterLabel={onClickFilterLabel}
onClickFilterOutLabel={onClickFilterOutLabel}
onClickFilterLabel={logDetailsFilterAvailable ? onClickFilterLabel : undefined}
onClickFilterOutLabel={logDetailsFilterAvailable ? onClickFilterOutLabel : undefined}
onStartScanning={onStartScanning}
onStopScanning={onStopScanning}
absoluteRange={absoluteRange}
@ -217,7 +263,7 @@ class LogsContainer extends PureComponent<LogsContainerProps> {
panelState={this.props.panelState}
logsFrames={this.props.logsFrames}
scrollElement={scrollElement}
isFilterLabelActive={this.props.isFilterLabelActive}
isFilterLabelActive={logDetailsFilterAvailable ? this.props.isFilterLabelActive : undefined}
range={range}
/>
</LogsCrossFadeTransition>

View File

@ -47,6 +47,28 @@ describe('LogDetails', () => {
expect(screen.getByRole('cell', { name: 'key2' })).toBeInTheDocument();
expect(screen.getByRole('cell', { name: 'label2' })).toBeInTheDocument();
});
it('should render filter controls when the callbacks are provided', () => {
setup(
{
onClickFilterLabel: () => {},
onClickFilterOutLabel: () => {},
},
{ labels: { key1: 'label1' } }
);
expect(screen.getByLabelText('Filter for value')).toBeInTheDocument();
expect(screen.getByLabelText('Filter out value')).toBeInTheDocument();
});
it('should not render filter controls when the callbacks are not provided', () => {
setup(
{
onClickFilterLabel: undefined,
onClickFilterOutLabel: undefined,
},
{ labels: { key1: 'label1' } }
);
expect(screen.queryByLabelText('Filter for value')).not.toBeInTheDocument();
expect(screen.queryByLabelText('Filter out value')).not.toBeInTheDocument();
});
});
describe('when log row has error', () => {
it('should not render log level border', () => {