Logs: Move button to load logs volume to logs options header (#40578)

* Move button to load logs volume to logs options header

* Update snapshot

* Do not show load logs volume button when data source does not support it
This commit is contained in:
Piotr Jamróz 2021-10-20 13:58:04 +02:00 committed by GitHub
parent 1e471a6f76
commit bd97c79454
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 52 additions and 53 deletions

View File

@ -84,7 +84,6 @@ const dummyProps: Props = {
showNodeGraph: true, showNodeGraph: true,
splitOpen: (() => {}) as any, splitOpen: (() => {}) as any,
logsVolumeData: undefined, logsVolumeData: undefined,
logsVolumeDataProvider: undefined,
loadLogsVolumeData: () => {}, loadLogsVolumeData: () => {},
}; };

View File

@ -6,15 +6,7 @@ import AutoSizer from 'react-virtualized-auto-sizer';
import memoizeOne from 'memoize-one'; import memoizeOne from 'memoize-one';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { Collapse, CustomScrollbar, ErrorBoundaryAlert, Themeable2, withTheme2 } from '@grafana/ui'; import { Collapse, CustomScrollbar, ErrorBoundaryAlert, Themeable2, withTheme2 } from '@grafana/ui';
import { import { AbsoluteTimeRange, DataFrame, DataQuery, GrafanaTheme2, LoadingState, RawTimeRange } from '@grafana/data';
AbsoluteTimeRange,
DataFrame,
DataQuery,
GrafanaTheme2,
hasLogsVolumeSupport,
LoadingState,
RawTimeRange,
} from '@grafana/data';
import LogsContainer from './LogsContainer'; import LogsContainer from './LogsContainer';
import { QueryRows } from './QueryRows'; import { QueryRows } from './QueryRows';
@ -302,8 +294,6 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
showLogs, showLogs,
showTrace, showTrace,
showNodeGraph, showNodeGraph,
logsVolumeDataProvider,
loadLogsVolumeData,
} = this.props; } = this.props;
const { openDrawer } = this.state; const { openDrawer } = this.state;
const styles = getStyles(theme); const styles = getStyles(theme);
@ -326,11 +316,9 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
addQueryRowButtonHidden={false} addQueryRowButtonHidden={false}
richHistoryButtonActive={showRichHistory} richHistoryButtonActive={showRichHistory}
queryInspectorButtonActive={showQueryInspector} queryInspectorButtonActive={showQueryInspector}
loadingLogsVolumeAvailable={hasLogsVolumeSupport(datasourceInstance) && !!logsVolumeDataProvider}
onClickAddQueryRowButton={this.onClickAddQueryRowButton} onClickAddQueryRowButton={this.onClickAddQueryRowButton}
onClickRichHistoryButton={this.toggleShowRichHistory} onClickRichHistoryButton={this.toggleShowRichHistory}
onClickQueryInspectorButton={this.toggleShowQueryInspector} onClickQueryInspectorButton={this.toggleShowQueryInspector}
onClickLoadLogsVolume={() => loadLogsVolumeData(exploreId)}
/> />
<ResponseErrorContainer exploreId={exploreId} /> <ResponseErrorContainer exploreId={exploreId} />
</div> </div>
@ -392,7 +380,6 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
queryKeys, queryKeys,
isLive, isLive,
graphResult, graphResult,
logsVolumeDataProvider,
logsVolumeData, logsVolumeData,
logsResult, logsResult,
showLogs, showLogs,
@ -411,7 +398,6 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
queryKeys, queryKeys,
isLive, isLive,
graphResult, graphResult,
logsVolumeDataProvider,
logsVolumeData, logsVolumeData,
logsResult: logsResult ?? undefined, logsResult: logsResult ?? undefined,
absoluteRange, absoluteRange,

View File

@ -69,6 +69,8 @@ interface Props extends Themeable2 {
getFieldLinks: (field: Field, rowIndex: number) => Array<LinkModel<Field>>; getFieldLinks: (field: Field, rowIndex: number) => Array<LinkModel<Field>>;
addResultsToCache: () => void; addResultsToCache: () => void;
clearCache: () => void; clearCache: () => void;
loadingLogsVolumeAvailable: boolean;
onClickLoadLogsVolume: () => void;
} }
interface State { interface State {
@ -268,6 +270,8 @@ export class UnthemedLogs extends PureComponent<Props, State> {
logsQueries, logsQueries,
clearCache, clearCache,
addResultsToCache, addResultsToCache,
onClickLoadLogsVolume,
loadingLogsVolumeAvailable,
} = this.props; } = this.props;
const { const {
@ -340,17 +344,31 @@ export class UnthemedLogs extends PureComponent<Props, State> {
/> />
</InlineField> </InlineField>
</InlineFieldRow> </InlineFieldRow>
<div>
{loadingLogsVolumeAvailable && (
<Button
variant="secondary"
aria-label="Load volume button"
title="Execute a query to show full range logs volume"
onClick={onClickLoadLogsVolume}
icon="graph-bar"
className={styles.headerButton}
>
Load volume
</Button>
)}
<Button <Button
variant="secondary" variant="secondary"
disabled={isFlipping} disabled={isFlipping}
title={logsSortOrder === LogsSortOrder.Ascending ? 'Change to newest first' : 'Change to oldest first'} title={logsSortOrder === LogsSortOrder.Ascending ? 'Change to newest first' : 'Change to oldest first'}
aria-label="Flip results order" aria-label="Flip results order"
className={styles.flipButton} className={styles.headerButton}
onClick={this.onChangeLogsSortOrder} onClick={this.onChangeLogsSortOrder}
> >
{isFlipping ? 'Flipping...' : 'Flip results order'} {isFlipping ? 'Flipping...' : 'Flip results order'}
</Button> </Button>
</div> </div>
</div>
<LogsMetaRow <LogsMetaRow
logRows={logRows} logRows={logRows}
meta={logsMeta || []} meta={logsMeta || []}
@ -441,7 +459,7 @@ const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean) => {
margin: ${theme.spacing(2, 0, 1)}; margin: ${theme.spacing(2, 0, 1)};
border: 1px solid ${theme.colors.border.medium}; border: 1px solid ${theme.colors.border.medium};
`, `,
flipButton: css` headerButton: css`
margin: ${theme.spacing(0.5, 0, 0, 1)}; margin: ${theme.spacing(0.5, 0, 0, 1)};
`, `,
radioButtons: css` radioButtons: css`

View File

@ -6,6 +6,7 @@ import {
AbsoluteTimeRange, AbsoluteTimeRange,
Field, Field,
hasLogsContextSupport, hasLogsContextSupport,
hasLogsVolumeSupport,
LoadingState, LoadingState,
LogRowModel, LogRowModel,
RawTimeRange, RawTimeRange,
@ -13,7 +14,7 @@ import {
import { ExploreId, ExploreItemState } from 'app/types/explore'; import { ExploreId, ExploreItemState } from 'app/types/explore';
import { StoreState } from 'app/types'; import { StoreState } from 'app/types';
import { splitOpen } from './state/main'; import { splitOpen } from './state/main';
import { addResultsToCache, clearCache } from './state/query'; import { addResultsToCache, clearCache, loadLogsVolumeData } from './state/query';
import { updateTimeRange } from './state/time'; import { updateTimeRange } from './state/time';
import { getTimeZone } from '../profile/state/selectors'; import { getTimeZone } from '../profile/state/selectors';
import { LiveLogsWithTheme } from './LiveLogs'; import { LiveLogsWithTheme } from './LiveLogs';
@ -67,6 +68,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
render() { render() {
const { const {
datasourceInstance,
loading, loading,
loadingState, loadingState,
logRows, logRows,
@ -87,6 +89,8 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
exploreId, exploreId,
addResultsToCache, addResultsToCache,
clearCache, clearCache,
logsVolumeDataProvider,
loadLogsVolumeData,
} = this.props; } = this.props;
if (!logRows) { if (!logRows) {
@ -146,6 +150,8 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
getFieldLinks={this.getFieldLinks} getFieldLinks={this.getFieldLinks}
addResultsToCache={() => addResultsToCache(exploreId)} addResultsToCache={() => addResultsToCache(exploreId)}
clearCache={() => clearCache(exploreId)} clearCache={() => clearCache(exploreId)}
loadingLogsVolumeAvailable={hasLogsVolumeSupport(datasourceInstance) && !!logsVolumeDataProvider}
onClickLoadLogsVolume={() => loadLogsVolumeData(exploreId)}
/> />
</Collapse> </Collapse>
</LogsCrossFadeTransition> </LogsCrossFadeTransition>
@ -158,7 +164,18 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }
const explore = state.explore; const explore = state.explore;
// @ts-ignore // @ts-ignore
const item: ExploreItemState = explore[exploreId]; const item: ExploreItemState = explore[exploreId];
const { logsResult, loading, scanning, datasourceInstance, isLive, isPaused, range, absoluteRange } = item; const {
logsResult,
loading,
scanning,
datasourceInstance,
isLive,
isPaused,
range,
absoluteRange,
logsVolumeDataProvider,
logsVolumeData,
} = item;
const timeZone = getTimeZone(state.user); const timeZone = getTimeZone(state.user);
return { return {
@ -175,6 +192,8 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }
isPaused, isPaused,
range, range,
absoluteRange, absoluteRange,
logsVolumeDataProvider,
logsVolumeData,
}; };
} }
@ -183,6 +202,7 @@ const mapDispatchToProps = {
splitOpen, splitOpen,
addResultsToCache, addResultsToCache,
clearCache, clearCache,
loadLogsVolumeData,
}; };
const connector = connect(mapStateToProps, mapDispatchToProps); const connector = connect(mapStateToProps, mapDispatchToProps);

View File

@ -6,7 +6,6 @@ import { SecondaryActions } from './SecondaryActions';
const addQueryRowButtonSelector = '[aria-label="Add row button"]'; const addQueryRowButtonSelector = '[aria-label="Add row button"]';
const richHistoryButtonSelector = '[aria-label="Rich history button"]'; const richHistoryButtonSelector = '[aria-label="Rich history button"]';
const queryInspectorButtonSelector = '[aria-label="Query inspector button"]'; const queryInspectorButtonSelector = '[aria-label="Query inspector button"]';
const onClickLoadLogsVolumeSelector = '[aria-label="Load logs volume button"]';
describe('SecondaryActions', () => { describe('SecondaryActions', () => {
it('should render component two buttons', () => { it('should render component two buttons', () => {
@ -15,7 +14,6 @@ describe('SecondaryActions', () => {
onClickAddQueryRowButton={noop} onClickAddQueryRowButton={noop}
onClickRichHistoryButton={noop} onClickRichHistoryButton={noop}
onClickQueryInspectorButton={noop} onClickQueryInspectorButton={noop}
onClickLoadLogsVolume={noop}
/> />
); );
expect(wrapper.find(addQueryRowButtonSelector)).toHaveLength(1); expect(wrapper.find(addQueryRowButtonSelector)).toHaveLength(1);
@ -29,7 +27,6 @@ describe('SecondaryActions', () => {
onClickAddQueryRowButton={noop} onClickAddQueryRowButton={noop}
onClickRichHistoryButton={noop} onClickRichHistoryButton={noop}
onClickQueryInspectorButton={noop} onClickQueryInspectorButton={noop}
onClickLoadLogsVolume={noop}
/> />
); );
expect(wrapper.find(addQueryRowButtonSelector)).toHaveLength(0); expect(wrapper.find(addQueryRowButtonSelector)).toHaveLength(0);
@ -43,7 +40,6 @@ describe('SecondaryActions', () => {
onClickAddQueryRowButton={noop} onClickAddQueryRowButton={noop}
onClickRichHistoryButton={noop} onClickRichHistoryButton={noop}
onClickQueryInspectorButton={noop} onClickQueryInspectorButton={noop}
onClickLoadLogsVolume={noop}
/> />
); );
expect(wrapper.find(addQueryRowButtonSelector).props().disabled).toBe(true); expect(wrapper.find(addQueryRowButtonSelector).props().disabled).toBe(true);
@ -53,14 +49,11 @@ describe('SecondaryActions', () => {
const onClickAddRow = jest.fn(); const onClickAddRow = jest.fn();
const onClickHistory = jest.fn(); const onClickHistory = jest.fn();
const onClickQueryInspector = jest.fn(); const onClickQueryInspector = jest.fn();
const onClickLoadLogsVolumeInspector = jest.fn();
const wrapper = shallow( const wrapper = shallow(
<SecondaryActions <SecondaryActions
onClickAddQueryRowButton={onClickAddRow} onClickAddQueryRowButton={onClickAddRow}
onClickRichHistoryButton={onClickHistory} onClickRichHistoryButton={onClickHistory}
onClickQueryInspectorButton={onClickQueryInspector} onClickQueryInspectorButton={onClickQueryInspector}
loadingLogsVolumeAvailable={true}
onClickLoadLogsVolume={onClickLoadLogsVolumeInspector}
/> />
); );
@ -72,8 +65,5 @@ describe('SecondaryActions', () => {
wrapper.find(queryInspectorButtonSelector).simulate('click'); wrapper.find(queryInspectorButtonSelector).simulate('click');
expect(onClickQueryInspector).toBeCalled(); expect(onClickQueryInspector).toBeCalled();
wrapper.find(onClickLoadLogsVolumeSelector).simulate('click');
expect(onClickQueryInspector).toBeCalled();
}); });
}); });

View File

@ -8,12 +8,10 @@ type Props = {
addQueryRowButtonHidden?: boolean; addQueryRowButtonHidden?: boolean;
richHistoryButtonActive?: boolean; richHistoryButtonActive?: boolean;
queryInspectorButtonActive?: boolean; queryInspectorButtonActive?: boolean;
loadingLogsVolumeAvailable?: boolean;
onClickAddQueryRowButton: () => void; onClickAddQueryRowButton: () => void;
onClickRichHistoryButton: () => void; onClickRichHistoryButton: () => void;
onClickQueryInspectorButton: () => void; onClickQueryInspectorButton: () => void;
onClickLoadLogsVolume: () => void;
}; };
const getStyles = (theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => {
@ -58,16 +56,6 @@ export function SecondaryActions(props: Props) {
> >
Inspector Inspector
</Button> </Button>
{props.loadingLogsVolumeAvailable && (
<Button
variant="secondary"
aria-label="Load logs volume button"
onClick={props.onClickLoadLogsVolume}
icon="graph-bar"
>
Load logs volume
</Button>
)}
</HorizontalGroup> </HorizontalGroup>
</div> </div>
); );

View File

@ -20,9 +20,7 @@ exports[`Explore should render component 1`] = `
<SecondaryActions <SecondaryActions
addQueryRowButtonDisabled={false} addQueryRowButtonDisabled={false}
addQueryRowButtonHidden={false} addQueryRowButtonHidden={false}
loadingLogsVolumeAvailable={false}
onClickAddQueryRowButton={[Function]} onClickAddQueryRowButton={[Function]}
onClickLoadLogsVolume={[Function]}
onClickQueryInspectorButton={[Function]} onClickQueryInspectorButton={[Function]}
onClickRichHistoryButton={[Function]} onClickRichHistoryButton={[Function]}
queryInspectorButtonActive={false} queryInspectorButtonActive={false}