grafana/public/app/features/explore/LogsContainer.tsx
Ivana Huckova a5e8e0e291 Explore: UI change for log row details (#20034)
Add LogDetail section that is shown when log line is clicked and expanded. Contains labels/fields and actions to show stats and add/remove label filter.
2019-11-01 10:01:00 +01:00

198 lines
5.5 KiB
TypeScript

import React, { PureComponent } from 'react';
import { hot } from 'react-hot-loader';
import { connect } from 'react-redux';
import { Collapse } from '@grafana/ui';
import {
DataSourceApi,
RawTimeRange,
LogLevel,
TimeZone,
AbsoluteTimeRange,
LogsModel,
LogRowModel,
LogsDedupStrategy,
TimeRange,
} from '@grafana/data';
import { ExploreId, ExploreItemState } from 'app/types/explore';
import { StoreState } from 'app/types';
import { changeDedupStrategy, updateTimeRange } from './state/actions';
import { toggleLogLevelAction } from 'app/features/explore/state/actionTypes';
import { deduplicatedLogsSelector, exploreItemUIStateSelector } from 'app/features/explore/state/selectors';
import { getTimeZone } from '../profile/state/selectors';
import { LiveLogsWithTheme } from './LiveLogs';
import { Logs } from './Logs';
import { LogsCrossFadeTransition } from './utils/LogsCrossFadeTransition';
import { LiveTailControls } from './useLiveTailControls';
interface LogsContainerProps {
datasourceInstance: DataSourceApi | null;
exploreId: ExploreId;
loading: boolean;
logsHighlighterExpressions?: string[];
logsResult?: LogsModel;
dedupedResult?: LogsModel;
onClickFilterLabel?: (key: string, value: string) => void;
onClickFilterOutLabel?: (key: string, value: string) => void;
onStartScanning: () => void;
onStopScanning: () => void;
timeZone: TimeZone;
scanning?: boolean;
scanRange?: RawTimeRange;
toggleLogLevelAction: typeof toggleLogLevelAction;
changeDedupStrategy: typeof changeDedupStrategy;
dedupStrategy: LogsDedupStrategy;
width: number;
isLive: boolean;
updateTimeRange: typeof updateTimeRange;
range: TimeRange;
syncedTimes: boolean;
absoluteRange: AbsoluteTimeRange;
isPaused: boolean;
}
export class LogsContainer extends PureComponent<LogsContainerProps> {
onChangeTime = (absoluteRange: AbsoluteTimeRange) => {
const { exploreId, updateTimeRange } = this.props;
updateTimeRange({ exploreId, absoluteRange });
};
handleDedupStrategyChange = (dedupStrategy: LogsDedupStrategy) => {
this.props.changeDedupStrategy(this.props.exploreId, dedupStrategy);
};
handleToggleLogLevel = (hiddenLogLevels: LogLevel[]) => {
const { exploreId } = this.props;
this.props.toggleLogLevelAction({
exploreId,
hiddenLogLevels,
});
};
getLogRowContext = async (row: LogRowModel, options?: any): Promise<any> => {
const { datasourceInstance } = this.props;
if (datasourceInstance) {
return datasourceInstance.getLogRowContext(row, options);
}
return [];
};
render() {
const {
loading,
logsHighlighterExpressions,
logsResult,
dedupedResult,
onClickFilterLabel,
onClickFilterOutLabel,
onStartScanning,
onStopScanning,
absoluteRange,
timeZone,
scanning,
range,
width,
isLive,
exploreId,
} = this.props;
return (
<>
<LogsCrossFadeTransition visible={isLive}>
<Collapse label="Logs" loading={false} isOpen>
<LiveTailControls exploreId={exploreId}>
{controls => (
<LiveLogsWithTheme
logsResult={logsResult}
timeZone={timeZone}
stopLive={controls.stop}
isPaused={this.props.isPaused}
onPause={controls.pause}
onResume={controls.resume}
/>
)}
</LiveTailControls>
</Collapse>
</LogsCrossFadeTransition>
<LogsCrossFadeTransition visible={!isLive}>
<Collapse label="Logs" loading={loading} isOpen>
<Logs
dedupStrategy={this.props.dedupStrategy || LogsDedupStrategy.none}
data={logsResult}
dedupedData={dedupedResult}
highlighterExpressions={logsHighlighterExpressions}
loading={loading}
onChangeTime={this.onChangeTime}
onClickFilterLabel={onClickFilterLabel}
onClickFilterOutLabel={onClickFilterOutLabel}
onStartScanning={onStartScanning}
onStopScanning={onStopScanning}
onDedupStrategyChange={this.handleDedupStrategyChange}
onToggleLogLevel={this.handleToggleLogLevel}
absoluteRange={absoluteRange}
timeZone={timeZone}
scanning={scanning}
scanRange={range.raw}
width={width}
getRowContext={this.getLogRowContext}
/>
</Collapse>
</LogsCrossFadeTransition>
</>
);
}
}
function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }) {
const explore = state.explore;
// @ts-ignore
const item: ExploreItemState = explore[exploreId];
const {
logsHighlighterExpressions,
logsResult,
loading,
scanning,
datasourceInstance,
isLive,
isPaused,
range,
absoluteRange,
} = item;
const { dedupStrategy } = exploreItemUIStateSelector(item);
const dedupedResult = deduplicatedLogsSelector(item);
const timeZone = getTimeZone(state.user);
return {
loading,
logsHighlighterExpressions,
logsResult,
scanning,
timeZone,
dedupStrategy,
dedupedResult,
datasourceInstance,
isLive,
isPaused,
range,
absoluteRange,
};
}
const mapDispatchToProps = {
changeDedupStrategy,
toggleLogLevelAction,
updateTimeRange,
};
export default hot(module)(
connect(
mapStateToProps,
mapDispatchToProps
)(LogsContainer)
);