Commit 1693f083 by Dominik Prokop

Move deduplication calculation from Logs component to redux selector

parent 85780eb3
...@@ -151,6 +151,7 @@ ...@@ -151,6 +151,7 @@
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.0.0", "@babel/polyfill": "^7.0.0",
"@torkelo/react-select": "2.1.1", "@torkelo/react-select": "2.1.1",
"@types/reselect": "^2.2.0",
"angular": "1.6.6", "angular": "1.6.6",
"angular-bindonce": "0.3.1", "angular-bindonce": "0.3.1",
"angular-native-dragdrop": "1.2.2", "angular-native-dragdrop": "1.2.2",
...@@ -187,6 +188,7 @@ ...@@ -187,6 +188,7 @@
"redux-logger": "^3.0.6", "redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0", "redux-thunk": "^2.3.0",
"remarkable": "^1.7.1", "remarkable": "^1.7.1",
"reselect": "^4.0.0",
"rst2html": "github:thoward/rst2html#990cb89", "rst2html": "github:thoward/rst2html#990cb89",
"rxjs": "^6.3.3", "rxjs": "^6.3.3",
"slate": "^0.33.4", "slate": "^0.33.4",
......
import { memoize } from 'lodash';
import { createSelectorCreator } from 'reselect';
const hashFn = (...args) => args.reduce((acc, val) => acc + '-' + JSON.stringify(val), '');
export const createLodashMemoizedSelector = createSelectorCreator(memoize, hashFn);
...@@ -9,8 +9,6 @@ import { ...@@ -9,8 +9,6 @@ import {
LogsDedupDescription, LogsDedupDescription,
LogsDedupStrategy, LogsDedupStrategy,
LogsModel, LogsModel,
dedupLogRows,
filterLogLevels,
LogLevel, LogLevel,
LogsMetaKind, LogsMetaKind,
} from 'app/core/logs_model'; } from 'app/core/logs_model';
...@@ -51,6 +49,7 @@ function renderMetaItem(value: any, kind: LogsMetaKind) { ...@@ -51,6 +49,7 @@ function renderMetaItem(value: any, kind: LogsMetaKind) {
interface Props { interface Props {
data?: LogsModel; data?: LogsModel;
dedupedData?: LogsModel;
width: number; width: number;
exploreId: string; exploreId: string;
highlighterExpressions: string[]; highlighterExpressions: string[];
...@@ -59,16 +58,17 @@ interface Props { ...@@ -59,16 +58,17 @@ interface Props {
scanning?: boolean; scanning?: boolean;
scanRange?: RawTimeRange; scanRange?: RawTimeRange;
dedupStrategy: LogsDedupStrategy; dedupStrategy: LogsDedupStrategy;
hiddenLogLevels: Set<LogLevel>;
onChangeTime?: (range: RawTimeRange) => void; onChangeTime?: (range: RawTimeRange) => void;
onClickLabel?: (label: string, value: string) => void; onClickLabel?: (label: string, value: string) => void;
onStartScanning?: () => void; onStartScanning?: () => void;
onStopScanning?: () => void; onStopScanning?: () => void;
onDedupStrategyChange: (dedupStrategy: LogsDedupStrategy) => void; onDedupStrategyChange: (dedupStrategy: LogsDedupStrategy) => void;
onToggleLogLevel: (hiddenLogLevels: Set<LogLevel>) => void;
} }
interface State { interface State {
deferLogs: boolean; deferLogs: boolean;
hiddenLogLevels: Set<LogLevel>;
renderAll: boolean; renderAll: boolean;
showLabels: boolean | null; // Tristate: null means auto showLabels: boolean | null; // Tristate: null means auto
showLocalTime: boolean; showLocalTime: boolean;
...@@ -81,7 +81,6 @@ export default class Logs extends PureComponent<Props, State> { ...@@ -81,7 +81,6 @@ export default class Logs extends PureComponent<Props, State> {
state = { state = {
deferLogs: true, deferLogs: true,
hiddenLogLevels: new Set(),
renderAll: false, renderAll: false,
showLabels: null, showLabels: null,
showLocalTime: true, showLocalTime: true,
...@@ -142,7 +141,7 @@ export default class Logs extends PureComponent<Props, State> { ...@@ -142,7 +141,7 @@ export default class Logs extends PureComponent<Props, State> {
onToggleLogLevel = (rawLevel: string, hiddenRawLevels: Set<string>) => { onToggleLogLevel = (rawLevel: string, hiddenRawLevels: Set<string>) => {
const hiddenLogLevels: Set<LogLevel> = new Set(Array.from(hiddenRawLevels).map(level => LogLevel[level])); const hiddenLogLevels: Set<LogLevel> = new Set(Array.from(hiddenRawLevels).map(level => LogLevel[level]));
this.setState({ hiddenLogLevels }); this.props.onToggleLogLevel(hiddenLogLevels);
}; };
onClickScan = (event: React.SyntheticEvent) => { onClickScan = (event: React.SyntheticEvent) => {
...@@ -166,21 +165,18 @@ export default class Logs extends PureComponent<Props, State> { ...@@ -166,21 +165,18 @@ export default class Logs extends PureComponent<Props, State> {
scanning, scanning,
scanRange, scanRange,
width, width,
dedupedData,
} = this.props; } = this.props;
if (!data) { if (!data) {
return null; return null;
} }
const { deferLogs, hiddenLogLevels, renderAll, showLocalTime, showUtc, } = this.state; const { deferLogs, renderAll, showLocalTime, showUtc } = this.state;
let { showLabels } = this.state; let { showLabels } = this.state;
const { dedupStrategy } = this.props; const { dedupStrategy } = this.props;
const hasData = data && data.rows && data.rows.length > 0; const hasData = data && data.rows && data.rows.length > 0;
const showDuplicates = dedupStrategy !== LogsDedupStrategy.none; const showDuplicates = dedupStrategy !== LogsDedupStrategy.none;
// Filtering
const filteredData = filterLogLevels(data, hiddenLogLevels);
const dedupedData = dedupLogRows(filteredData, dedupStrategy);
const dedupCount = dedupedData.rows.reduce((sum, row) => sum + row.duplicates, 0); const dedupCount = dedupedData.rows.reduce((sum, row) => sum + row.duplicates, 0);
const meta = [...data.meta]; const meta = [...data.meta];
......
...@@ -4,18 +4,21 @@ import { connect } from 'react-redux'; ...@@ -4,18 +4,21 @@ import { connect } from 'react-redux';
import { RawTimeRange, TimeRange } from '@grafana/ui'; import { RawTimeRange, TimeRange } from '@grafana/ui';
import { ExploreId, ExploreItemState } from 'app/types/explore'; import { ExploreId, ExploreItemState } from 'app/types/explore';
import { LogsModel, LogsDedupStrategy } from 'app/core/logs_model'; import { LogsModel, LogsDedupStrategy, LogLevel, filterLogLevels, dedupLogRows } from 'app/core/logs_model';
import { StoreState } from 'app/types'; import { StoreState } from 'app/types';
import { toggleLogs, changeDedupStrategy } from './state/actions'; import { toggleLogs, changeDedupStrategy } from './state/actions';
import Logs from './Logs'; import Logs from './Logs';
import Panel from './Panel'; import Panel from './Panel';
import { toggleLogLevelAction } from 'app/features/explore/state/actionTypes';
import { createLodashMemoizedSelector } from 'app/core/utils/reselect';
interface LogsContainerProps { interface LogsContainerProps {
exploreId: ExploreId; exploreId: ExploreId;
loading: boolean; loading: boolean;
logsHighlighterExpressions?: string[]; logsHighlighterExpressions?: string[];
logsResult?: LogsModel; logsResult?: LogsModel;
dedupedResult?: LogsModel;
onChangeTime: (range: TimeRange) => void; onChangeTime: (range: TimeRange) => void;
onClickLabel: (key: string, value: string) => void; onClickLabel: (key: string, value: string) => void;
onStartScanning: () => void; onStartScanning: () => void;
...@@ -25,8 +28,10 @@ interface LogsContainerProps { ...@@ -25,8 +28,10 @@ interface LogsContainerProps {
scanRange?: RawTimeRange; scanRange?: RawTimeRange;
showingLogs: boolean; showingLogs: boolean;
toggleLogs: typeof toggleLogs; toggleLogs: typeof toggleLogs;
toggleLogLevelAction: typeof toggleLogLevelAction;
changeDedupStrategy: typeof changeDedupStrategy; changeDedupStrategy: typeof changeDedupStrategy;
dedupStrategy: LogsDedupStrategy; dedupStrategy: LogsDedupStrategy;
hiddenLogLevels: Set<LogLevel>;
width: number; width: number;
} }
...@@ -39,12 +44,21 @@ export class LogsContainer extends PureComponent<LogsContainerProps> { ...@@ -39,12 +44,21 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
this.props.changeDedupStrategy(this.props.exploreId, dedupStrategy); this.props.changeDedupStrategy(this.props.exploreId, dedupStrategy);
}; };
hangleToggleLogLevel = (hiddenLogLevels: Set<LogLevel>) => {
const { exploreId } = this.props;
this.props.toggleLogLevelAction({
exploreId,
hiddenLogLevels,
});
};
render() { render() {
const { const {
exploreId, exploreId,
loading, loading,
logsHighlighterExpressions, logsHighlighterExpressions,
logsResult, logsResult,
dedupedResult,
onChangeTime, onChangeTime,
onClickLabel, onClickLabel,
onStartScanning, onStartScanning,
...@@ -54,6 +68,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> { ...@@ -54,6 +68,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
scanning, scanning,
scanRange, scanRange,
width, width,
hiddenLogLevels,
} = this.props; } = this.props;
return ( return (
...@@ -61,6 +76,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> { ...@@ -61,6 +76,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
<Logs <Logs
dedupStrategy={this.props.dedupStrategy || LogsDedupStrategy.none} dedupStrategy={this.props.dedupStrategy || LogsDedupStrategy.none}
data={logsResult} data={logsResult}
dedupedData={dedupedResult}
exploreId={exploreId} exploreId={exploreId}
key={logsResult && logsResult.id} key={logsResult && logsResult.id}
highlighterExpressions={logsHighlighterExpressions} highlighterExpressions={logsHighlighterExpressions}
...@@ -70,10 +86,12 @@ export class LogsContainer extends PureComponent<LogsContainerProps> { ...@@ -70,10 +86,12 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
onStartScanning={onStartScanning} onStartScanning={onStartScanning}
onStopScanning={onStopScanning} onStopScanning={onStopScanning}
onDedupStrategyChange={this.handleDedupStrategyChange} onDedupStrategyChange={this.handleDedupStrategyChange}
onToggleLogLevel={this.hangleToggleLogLevel}
range={range} range={range}
scanning={scanning} scanning={scanning}
scanRange={scanRange} scanRange={scanRange}
width={width} width={width}
hiddenLogLevels={hiddenLogLevels}
/> />
</Panel> </Panel>
); );
...@@ -90,12 +108,29 @@ const selectItemUIState = (itemState: ExploreItemState) => { ...@@ -90,12 +108,29 @@ const selectItemUIState = (itemState: ExploreItemState) => {
dedupStrategy, dedupStrategy,
}; };
}; };
const logsSelector = (state: ExploreItemState) => state.logsResult;
const hiddenLogLevelsSelector = (state: ExploreItemState) => state.hiddenLogLevels;
const dedupStrategySelector = (state: ExploreItemState) => state.dedupStrategy;
const deduplicatedLogsSelector = createLodashMemoizedSelector(
logsSelector, hiddenLogLevelsSelector, dedupStrategySelector,
(logs, hiddenLogLevels, dedupStrategy) => {
if (!logs) {
return null;
}
const filteredData = filterLogLevels(logs, new Set(hiddenLogLevels));
return dedupLogRows(filteredData, dedupStrategy);
}
);
function mapStateToProps(state: StoreState, { exploreId }) { function mapStateToProps(state: StoreState, { exploreId }) {
const explore = state.explore; const explore = state.explore;
const item: ExploreItemState = explore[exploreId]; const item: ExploreItemState = explore[exploreId];
const { logsHighlighterExpressions, logsResult, queryTransactions, scanning, scanRange, range } = item; const { logsHighlighterExpressions, logsResult, queryTransactions, scanning, scanRange, range } = item;
const loading = queryTransactions.some(qt => qt.resultType === 'Logs' && !qt.done); const loading = queryTransactions.some(qt => qt.resultType === 'Logs' && !qt.done);
const {showingLogs, dedupStrategy} = selectItemUIState(item); const { showingLogs, dedupStrategy } = selectItemUIState(item);
const hiddenLogLevels = new Set(item.hiddenLogLevels);
const dedupedResult = deduplicatedLogsSelector(item);
return { return {
loading, loading,
...@@ -106,12 +141,15 @@ function mapStateToProps(state: StoreState, { exploreId }) { ...@@ -106,12 +141,15 @@ function mapStateToProps(state: StoreState, { exploreId }) {
showingLogs, showingLogs,
range, range,
dedupStrategy, dedupStrategy,
hiddenLogLevels,
dedupedResult,
}; };
} }
const mapDispatchToProps = { const mapDispatchToProps = {
toggleLogs, toggleLogs,
changeDedupStrategy, changeDedupStrategy,
toggleLogLevelAction,
}; };
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(LogsContainer)); export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(LogsContainer));
...@@ -18,6 +18,7 @@ import { ...@@ -18,6 +18,7 @@ import {
ExploreUIState, ExploreUIState,
} from 'app/types/explore'; } from 'app/types/explore';
import { actionCreatorFactory, noPayloadActionCreatorFactory, ActionOf } from 'app/core/redux/actionCreatorFactory'; import { actionCreatorFactory, noPayloadActionCreatorFactory, ActionOf } from 'app/core/redux/actionCreatorFactory';
import { LogLevel } from 'app/core/logs_model';
/** Higher order actions /** Higher order actions
* *
...@@ -201,6 +202,11 @@ export interface UpdateDatasourceInstancePayload { ...@@ -201,6 +202,11 @@ export interface UpdateDatasourceInstancePayload {
datasourceInstance: DataSourceApi; datasourceInstance: DataSourceApi;
} }
export interface ToggleLogLevelPayload {
exploreId: ExploreId;
hiddenLogLevels: Set<LogLevel>;
}
export interface QueriesImportedPayload { export interface QueriesImportedPayload {
exploreId: ExploreId; exploreId: ExploreId;
queries: DataQuery[]; queries: DataQuery[];
...@@ -397,6 +403,10 @@ export const updateDatasourceInstanceAction = actionCreatorFactory<UpdateDatasou ...@@ -397,6 +403,10 @@ export const updateDatasourceInstanceAction = actionCreatorFactory<UpdateDatasou
'explore/UPDATE_DATASOURCE_INSTANCE' 'explore/UPDATE_DATASOURCE_INSTANCE'
).create(); ).create();
export const toggleLogLevelAction = actionCreatorFactory<ToggleLogLevelPayload>(
'explore/TOGGLE_LOG_LEVEL'
).create();
/** /**
* Resets state for explore. * Resets state for explore.
*/ */
...@@ -436,4 +446,5 @@ export type Action = ...@@ -436,4 +446,5 @@ export type Action =
| ActionOf<ToggleGraphPayload> | ActionOf<ToggleGraphPayload>
| ActionOf<ToggleLogsPayload> | ActionOf<ToggleLogsPayload>
| ActionOf<UpdateDatasourceInstancePayload> | ActionOf<UpdateDatasourceInstancePayload>
| ActionOf<QueriesImportedPayload>; | ActionOf<QueriesImportedPayload>
| ActionOf<ToggleLogLevelPayload>;
...@@ -38,6 +38,7 @@ import { ...@@ -38,6 +38,7 @@ import {
toggleTableAction, toggleTableAction,
queriesImportedAction, queriesImportedAction,
updateUIStateAction, updateUIStateAction,
toggleLogLevelAction,
} from './actionTypes'; } from './actionTypes';
export const DEFAULT_RANGE = { export const DEFAULT_RANGE = {
...@@ -467,6 +468,16 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta ...@@ -467,6 +468,16 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
}; };
}, },
}) })
.addMapper({
filter: toggleLogLevelAction,
mapper: (state, action): ExploreItemState => {
const { hiddenLogLevels } = action.payload;
return {
...state,
hiddenLogLevels: Array.from(hiddenLogLevels)
};
},
})
.create(); .create();
/** /**
......
...@@ -11,7 +11,7 @@ import { ...@@ -11,7 +11,7 @@ import {
} from '@grafana/ui'; } from '@grafana/ui';
import { Emitter } from 'app/core/core'; import { Emitter } from 'app/core/core';
import { LogsModel, LogsDedupStrategy } from 'app/core/logs_model'; import { LogsModel, LogsDedupStrategy, LogLevel } from 'app/core/logs_model';
import TableModel from 'app/core/table_model'; import TableModel from 'app/core/table_model';
export interface CompletionItem { export interface CompletionItem {
...@@ -242,6 +242,11 @@ export interface ExploreItemState { ...@@ -242,6 +242,11 @@ export interface ExploreItemState {
* Current logs deduplication strategy * Current logs deduplication strategy
*/ */
dedupStrategy?: LogsDedupStrategy; dedupStrategy?: LogsDedupStrategy;
/**
* Currently hidden log series
*/
hiddenLogLevels?: LogLevel[];
} }
export interface ExploreUIState { export interface ExploreUIState {
......
...@@ -1819,6 +1819,13 @@ ...@@ -1819,6 +1819,13 @@
"@types/prop-types" "*" "@types/prop-types" "*"
csstype "^2.2.0" csstype "^2.2.0"
"@types/reselect@^2.2.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@types/reselect/-/reselect-2.2.0.tgz#c667206cfdc38190e1d379babe08865b2288575f"
integrity sha1-xmcgbP3DgZDh03m6vgiGWyKIV18=
dependencies:
reselect "*"
"@types/storybook__addon-actions@^3.4.1": "@types/storybook__addon-actions@^3.4.1":
version "3.4.1" version "3.4.1"
resolved "https://registry.yarnpkg.com/@types/storybook__addon-actions/-/storybook__addon-actions-3.4.1.tgz#8f90d76b023b58ee794170f2fe774a3fddda2c1d" resolved "https://registry.yarnpkg.com/@types/storybook__addon-actions/-/storybook__addon-actions-3.4.1.tgz#8f90d76b023b58ee794170f2fe774a3fddda2c1d"
...@@ -14894,6 +14901,11 @@ requires-port@^1.0.0: ...@@ -14894,6 +14901,11 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
reselect@*, reselect@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
resolve-cwd@^2.0.0: resolve-cwd@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment