mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Logs: handle clicks on legend labels in histogram (#49931)
* logs: move new-histogram next to old-histogram * logs: handle legend-click in new-histogram * minor visual change
This commit is contained in:
parent
be712a5f17
commit
cbfac157fb
@ -81,8 +81,6 @@ const dummyProps: Props = {
|
|||||||
showTrace: true,
|
showTrace: true,
|
||||||
showNodeGraph: true,
|
showNodeGraph: true,
|
||||||
splitOpen: (() => {}) as any,
|
splitOpen: (() => {}) as any,
|
||||||
logsVolumeData: undefined,
|
|
||||||
loadLogsVolumeData: () => {},
|
|
||||||
changeGraphStyle: () => {},
|
changeGraphStyle: () => {},
|
||||||
graphStyle: 'lines',
|
graphStyle: 'lines',
|
||||||
};
|
};
|
||||||
|
@ -24,7 +24,6 @@ import { ExploreGraphLabel } from './ExploreGraphLabel';
|
|||||||
import ExploreQueryInspector from './ExploreQueryInspector';
|
import ExploreQueryInspector from './ExploreQueryInspector';
|
||||||
import { ExploreToolbar } from './ExploreToolbar';
|
import { ExploreToolbar } from './ExploreToolbar';
|
||||||
import LogsContainer from './LogsContainer';
|
import LogsContainer from './LogsContainer';
|
||||||
import { LogsVolumePanel } from './LogsVolumePanel';
|
|
||||||
import { NoData } from './NoData';
|
import { NoData } from './NoData';
|
||||||
import { NoDataSourceCallToAction } from './NoDataSourceCallToAction';
|
import { NoDataSourceCallToAction } from './NoDataSourceCallToAction';
|
||||||
import { NodeGraphContainer } from './NodeGraphContainer';
|
import { NodeGraphContainer } from './NodeGraphContainer';
|
||||||
@ -36,7 +35,7 @@ import TableContainer from './TableContainer';
|
|||||||
import { TraceViewContainer } from './TraceView/TraceViewContainer';
|
import { TraceViewContainer } from './TraceView/TraceViewContainer';
|
||||||
import { changeSize, changeGraphStyle } from './state/explorePane';
|
import { changeSize, changeGraphStyle } from './state/explorePane';
|
||||||
import { splitOpen } from './state/main';
|
import { splitOpen } from './state/main';
|
||||||
import { addQueryRow, loadLogsVolumeData, modifyQueries, scanStart, scanStopAction, setQueries } from './state/query';
|
import { addQueryRow, modifyQueries, scanStart, scanStopAction, setQueries } from './state/query';
|
||||||
import { makeAbsoluteTime, updateTimeRange } from './state/time';
|
import { makeAbsoluteTime, updateTimeRange } from './state/time';
|
||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
@ -250,22 +249,6 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderLogsVolume(width: number) {
|
|
||||||
const { logsVolumeData, exploreId, loadLogsVolumeData, absoluteRange, timeZone, splitOpen } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LogsVolumePanel
|
|
||||||
absoluteRange={absoluteRange}
|
|
||||||
width={width}
|
|
||||||
logsVolumeData={logsVolumeData}
|
|
||||||
onUpdateTimeRange={this.onUpdateTimeRange}
|
|
||||||
timeZone={timeZone}
|
|
||||||
splitOpen={splitOpen}
|
|
||||||
onLoadLogsVolume={() => loadLogsVolumeData(exploreId)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTablePanel(width: number) {
|
renderTablePanel(width: number) {
|
||||||
const { exploreId, datasourceInstance, timeZone } = this.props;
|
const { exploreId, datasourceInstance, timeZone } = this.props;
|
||||||
return (
|
return (
|
||||||
@ -400,7 +383,6 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
|
|||||||
{showMetrics && graphResult && (
|
{showMetrics && graphResult && (
|
||||||
<ErrorBoundaryAlert>{this.renderGraphPanel(width)}</ErrorBoundaryAlert>
|
<ErrorBoundaryAlert>{this.renderGraphPanel(width)}</ErrorBoundaryAlert>
|
||||||
)}
|
)}
|
||||||
{<ErrorBoundaryAlert>{this.renderLogsVolume(width)}</ErrorBoundaryAlert>}
|
|
||||||
{showTable && <ErrorBoundaryAlert>{this.renderTablePanel(width)}</ErrorBoundaryAlert>}
|
{showTable && <ErrorBoundaryAlert>{this.renderTablePanel(width)}</ErrorBoundaryAlert>}
|
||||||
{showLogs && <ErrorBoundaryAlert>{this.renderLogsPanel(width)}</ErrorBoundaryAlert>}
|
{showLogs && <ErrorBoundaryAlert>{this.renderLogsPanel(width)}</ErrorBoundaryAlert>}
|
||||||
{showNodeGraph && <ErrorBoundaryAlert>{this.renderNodeGraphPanel()}</ErrorBoundaryAlert>}
|
{showNodeGraph && <ErrorBoundaryAlert>{this.renderNodeGraphPanel()}</ErrorBoundaryAlert>}
|
||||||
@ -446,7 +428,6 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
|
|||||||
queryKeys,
|
queryKeys,
|
||||||
isLive,
|
isLive,
|
||||||
graphResult,
|
graphResult,
|
||||||
logsVolumeData,
|
|
||||||
logsResult,
|
logsResult,
|
||||||
showLogs,
|
showLogs,
|
||||||
showMetrics,
|
showMetrics,
|
||||||
@ -465,7 +446,6 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
|
|||||||
queryKeys,
|
queryKeys,
|
||||||
isLive,
|
isLive,
|
||||||
graphResult,
|
graphResult,
|
||||||
logsVolumeData,
|
|
||||||
logsResult: logsResult ?? undefined,
|
logsResult: logsResult ?? undefined,
|
||||||
absoluteRange,
|
absoluteRange,
|
||||||
queryResponse,
|
queryResponse,
|
||||||
@ -490,7 +470,6 @@ const mapDispatchToProps = {
|
|||||||
setQueries,
|
setQueries,
|
||||||
updateTimeRange,
|
updateTimeRange,
|
||||||
makeAbsoluteTime,
|
makeAbsoluteTime,
|
||||||
loadLogsVolumeData,
|
|
||||||
addQueryRow,
|
addQueryRow,
|
||||||
splitOpen,
|
splitOpen,
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,9 @@ describe('Logs', () => {
|
|||||||
return render(
|
return render(
|
||||||
<Logs
|
<Logs
|
||||||
exploreId={ExploreId.left}
|
exploreId={ExploreId.left}
|
||||||
|
splitOpen={() => undefined}
|
||||||
|
logsVolumeData={undefined}
|
||||||
|
loadLogsVolumeData={() => undefined}
|
||||||
logRows={rows}
|
logRows={rows}
|
||||||
timeZone={'utc'}
|
timeZone={'utc'}
|
||||||
width={50}
|
width={50}
|
||||||
|
@ -20,6 +20,8 @@ import {
|
|||||||
DataFrame,
|
DataFrame,
|
||||||
GrafanaTheme2,
|
GrafanaTheme2,
|
||||||
LoadingState,
|
LoadingState,
|
||||||
|
SplitOpen,
|
||||||
|
DataQueryResponse,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { TooltipDisplayMode } from '@grafana/schema';
|
import { TooltipDisplayMode } from '@grafana/schema';
|
||||||
import {
|
import {
|
||||||
@ -40,6 +42,7 @@ import { ExploreId } from 'app/types/explore';
|
|||||||
import { ExploreGraph } from './ExploreGraph';
|
import { ExploreGraph } from './ExploreGraph';
|
||||||
import { LogsMetaRow } from './LogsMetaRow';
|
import { LogsMetaRow } from './LogsMetaRow';
|
||||||
import LogsNavigation from './LogsNavigation';
|
import LogsNavigation from './LogsNavigation';
|
||||||
|
import { LogsVolumePanel } from './LogsVolumePanel';
|
||||||
|
|
||||||
const SETTINGS_KEYS = {
|
const SETTINGS_KEYS = {
|
||||||
showLabels: 'grafana.explore.logs.showLabels',
|
showLabels: 'grafana.explore.logs.showLabels',
|
||||||
@ -51,6 +54,7 @@ const SETTINGS_KEYS = {
|
|||||||
|
|
||||||
interface Props extends Themeable2 {
|
interface Props extends Themeable2 {
|
||||||
width: number;
|
width: number;
|
||||||
|
splitOpen: SplitOpen;
|
||||||
logRows: LogRowModel[];
|
logRows: LogRowModel[];
|
||||||
logsMeta?: LogsMetaItem[];
|
logsMeta?: LogsMetaItem[];
|
||||||
logsSeries?: DataFrame[];
|
logsSeries?: DataFrame[];
|
||||||
@ -64,6 +68,8 @@ interface Props extends Themeable2 {
|
|||||||
scanning?: boolean;
|
scanning?: boolean;
|
||||||
scanRange?: RawTimeRange;
|
scanRange?: RawTimeRange;
|
||||||
exploreId: ExploreId;
|
exploreId: ExploreId;
|
||||||
|
logsVolumeData: DataQueryResponse | undefined;
|
||||||
|
loadLogsVolumeData: (exploreId: ExploreId) => void;
|
||||||
showContextToggle?: (row?: LogRowModel) => boolean;
|
showContextToggle?: (row?: LogRowModel) => boolean;
|
||||||
onChangeTime: (range: AbsoluteTimeRange) => void;
|
onChangeTime: (range: AbsoluteTimeRange) => void;
|
||||||
onClickFilterLabel?: (key: string, value: string) => void;
|
onClickFilterLabel?: (key: string, value: string) => void;
|
||||||
@ -268,10 +274,13 @@ class UnthemedLogs extends PureComponent<Props, State> {
|
|||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
width,
|
width,
|
||||||
|
splitOpen,
|
||||||
logRows,
|
logRows,
|
||||||
logsMeta,
|
logsMeta,
|
||||||
logsSeries,
|
logsSeries,
|
||||||
visibleRange,
|
visibleRange,
|
||||||
|
logsVolumeData,
|
||||||
|
loadLogsVolumeData,
|
||||||
loading = false,
|
loading = false,
|
||||||
loadingState,
|
loadingState,
|
||||||
onClickFilterLabel,
|
onClickFilterLabel,
|
||||||
@ -335,6 +344,16 @@ class UnthemedLogs extends PureComponent<Props, State> {
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
|
<LogsVolumePanel
|
||||||
|
absoluteRange={absoluteRange}
|
||||||
|
width={width}
|
||||||
|
logsVolumeData={logsVolumeData}
|
||||||
|
onUpdateTimeRange={onChangeTime}
|
||||||
|
timeZone={timeZone}
|
||||||
|
splitOpen={splitOpen}
|
||||||
|
onLoadLogsVolume={() => loadLogsVolumeData(exploreId)}
|
||||||
|
onHiddenSeriesChanged={this.onToggleLogLevel}
|
||||||
|
/>
|
||||||
<div className={styles.logOptions} ref={this.topLogsRef}>
|
<div className={styles.logOptions} ref={this.topLogsRef}>
|
||||||
<InlineFieldRow>
|
<InlineFieldRow>
|
||||||
<InlineField label="Time" className={styles.horizontalInlineLabel} transparent>
|
<InlineField label="Time" className={styles.horizontalInlineLabel} transparent>
|
||||||
@ -465,7 +484,6 @@ class UnthemedLogs extends PureComponent<Props, State> {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{scanning && (
|
{scanning && (
|
||||||
<div className={styles.noData}>
|
<div className={styles.noData}>
|
||||||
<span>{scanText}</span>
|
<span>{scanText}</span>
|
||||||
|
@ -19,7 +19,7 @@ import { getTimeZone } from '../profile/state/selectors';
|
|||||||
import { LiveLogsWithTheme } from './LiveLogs';
|
import { LiveLogsWithTheme } from './LiveLogs';
|
||||||
import { Logs } from './Logs';
|
import { Logs } from './Logs';
|
||||||
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 { LiveTailControls } from './useLiveTailControls';
|
import { LiveTailControls } from './useLiveTailControls';
|
||||||
import { LogsCrossFadeTransition } from './utils/LogsCrossFadeTransition';
|
import { LogsCrossFadeTransition } from './utils/LogsCrossFadeTransition';
|
||||||
@ -76,6 +76,8 @@ class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
logsMeta,
|
logsMeta,
|
||||||
logsSeries,
|
logsSeries,
|
||||||
logsQueries,
|
logsQueries,
|
||||||
|
logsVolumeData,
|
||||||
|
loadLogsVolumeData,
|
||||||
onClickFilterLabel,
|
onClickFilterLabel,
|
||||||
onClickFilterOutLabel,
|
onClickFilterOutLabel,
|
||||||
onStartScanning,
|
onStartScanning,
|
||||||
@ -86,6 +88,7 @@ class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
scanning,
|
scanning,
|
||||||
range,
|
range,
|
||||||
width,
|
width,
|
||||||
|
splitOpen,
|
||||||
isLive,
|
isLive,
|
||||||
exploreId,
|
exploreId,
|
||||||
addResultsToCache,
|
addResultsToCache,
|
||||||
@ -131,10 +134,13 @@ class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
logRows={logRows}
|
logRows={logRows}
|
||||||
logsMeta={logsMeta}
|
logsMeta={logsMeta}
|
||||||
logsSeries={logsSeries}
|
logsSeries={logsSeries}
|
||||||
|
logsVolumeData={logsVolumeData}
|
||||||
logsQueries={logsQueries}
|
logsQueries={logsQueries}
|
||||||
width={width}
|
width={width}
|
||||||
|
splitOpen={splitOpen}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
loadingState={loadingState}
|
loadingState={loadingState}
|
||||||
|
loadLogsVolumeData={loadLogsVolumeData}
|
||||||
onChangeTime={this.onChangeTime}
|
onChangeTime={this.onChangeTime}
|
||||||
onClickFilterLabel={onClickFilterLabel}
|
onClickFilterLabel={onClickFilterLabel}
|
||||||
onClickFilterOutLabel={onClickFilterOutLabel}
|
onClickFilterOutLabel={onClickFilterOutLabel}
|
||||||
@ -200,6 +206,7 @@ const mapDispatchToProps = {
|
|||||||
splitOpen,
|
splitOpen,
|
||||||
addResultsToCache,
|
addResultsToCache,
|
||||||
clearCache,
|
clearCache,
|
||||||
|
loadLogsVolumeData,
|
||||||
};
|
};
|
||||||
|
|
||||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
@ -22,6 +22,7 @@ function renderPanel(logsVolumeData?: DataQueryResponse) {
|
|||||||
onUpdateTimeRange={() => {}}
|
onUpdateTimeRange={() => {}}
|
||||||
logsVolumeData={logsVolumeData}
|
logsVolumeData={logsVolumeData}
|
||||||
onLoadLogsVolume={() => {}}
|
onLoadLogsVolume={() => {}}
|
||||||
|
onHiddenSeriesChanged={() => null}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ type Props = {
|
|||||||
width: number;
|
width: number;
|
||||||
onUpdateTimeRange: (timeRange: AbsoluteTimeRange) => void;
|
onUpdateTimeRange: (timeRange: AbsoluteTimeRange) => void;
|
||||||
onLoadLogsVolume: () => void;
|
onLoadLogsVolume: () => void;
|
||||||
|
onHiddenSeriesChanged: (hiddenSeries: string[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SHORT_ERROR_MESSAGE_LIMIT = 100;
|
const SHORT_ERROR_MESSAGE_LIMIT = 100;
|
||||||
@ -46,7 +47,16 @@ function ErrorAlert(props: { error: DataQueryError }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function LogsVolumePanel(props: Props) {
|
export function LogsVolumePanel(props: Props) {
|
||||||
const { width, logsVolumeData, absoluteRange, timeZone, splitOpen, onUpdateTimeRange, onLoadLogsVolume } = props;
|
const {
|
||||||
|
width,
|
||||||
|
logsVolumeData,
|
||||||
|
absoluteRange,
|
||||||
|
timeZone,
|
||||||
|
splitOpen,
|
||||||
|
onUpdateTimeRange,
|
||||||
|
onLoadLogsVolume,
|
||||||
|
onHiddenSeriesChanged,
|
||||||
|
} = props;
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const spacing = parseInt(theme.spacing(2).slice(0, -2), 10);
|
const spacing = parseInt(theme.spacing(2).slice(0, -2), 10);
|
||||||
@ -74,6 +84,7 @@ export function LogsVolumePanel(props: Props) {
|
|||||||
timeZone={timeZone}
|
timeZone={timeZone}
|
||||||
splitOpenFn={splitOpen}
|
splitOpenFn={splitOpen}
|
||||||
tooltipDisplayMode={TooltipDisplayMode.Multi}
|
tooltipDisplayMode={TooltipDisplayMode.Multi}
|
||||||
|
onHiddenSeriesChanged={onHiddenSeriesChanged}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -93,7 +104,7 @@ export function LogsVolumePanel(props: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Collapse label="Log volume" isOpen={true} loading={logsVolumeData?.state === LoadingState.Loading}>
|
<Collapse label="" isOpen={true} loading={logsVolumeData?.state === LoadingState.Loading}>
|
||||||
<div style={{ height }} className={styles.contentContainer}>
|
<div style={{ height }} className={styles.contentContainer}>
|
||||||
{LogsVolumePanelContent}
|
{LogsVolumePanelContent}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user