React ui add query stats (#6190)

* Adds the query stats to UI

Adds the query load time, resolution and total number of time series,
as the current UI has

Signed-off-by: cstdev <pietomb00@hotmail.com>

* Implement unit test for QueryStats

Signed-off-by: cstdev <pietomb00@hotmail.com>

* Tidy Query Stats component

Rename it and expose a interface for the values it displays
Make it a functional component as it has no state or lifecycle
Better null/undefined checks
Only render if needed, decided by the panel
Remove old stats if the next errors

Signed-off-by: cstdev <pietomb00@hotmail.com>
This commit is contained in:
CSTDev 2019-10-23 11:47:37 +01:00 committed by Julius Volz
parent 5f1be2cf45
commit 4262ad92ce
3 changed files with 50 additions and 5 deletions

View file

@ -19,6 +19,7 @@ import GraphControls from './GraphControls';
import Graph from './Graph'; import Graph from './Graph';
import DataTable from './DataTable'; import DataTable from './DataTable';
import TimeInput from './TimeInput'; import TimeInput from './TimeInput';
import QueryStatsView, { QueryStats } from './QueryStatsView';
interface PanelProps { interface PanelProps {
options: PanelOptions; options: PanelOptions;
@ -36,7 +37,7 @@ interface PanelState {
} | null; } | null;
loading: boolean; loading: boolean;
error: string | null; error: string | null;
stats: null; // TODO: Stats. stats: QueryStats | null,
} }
export interface PanelOptions { export interface PanelOptions {
@ -100,6 +101,7 @@ class Panel extends Component<PanelProps, PanelState> {
} }
executeQuery = (expr: string): void => { executeQuery = (expr: string): void => {
const queryStart = Date.now();
if (this.props.options.expr !== expr) { if (this.props.options.expr !== expr) {
this.setOptions({expr: expr}); this.setOptions({expr: expr});
} }
@ -119,7 +121,6 @@ class Panel extends Component<PanelProps, PanelState> {
const endTime = this.getEndTime().valueOf() / 1000; // TODO: shouldn't valueof only work when it's a moment? const endTime = this.getEndTime().valueOf() / 1000; // TODO: shouldn't valueof only work when it's a moment?
const startTime = endTime - this.props.options.range; const startTime = endTime - this.props.options.range;
const resolution = this.props.options.resolution || Math.max(Math.floor(this.props.options.range / 250), 1); const resolution = this.props.options.resolution || Math.max(Math.floor(this.props.options.range / 250), 1);
const url = new URL(window.location.href); const url = new URL(window.location.href);
const params: {[key: string]: string} = { const params: {[key: string]: string} = {
'query': expr, 'query': expr,
@ -153,13 +154,28 @@ class Panel extends Component<PanelProps, PanelState> {
throw new Error(json.error || 'invalid response JSON'); throw new Error(json.error || 'invalid response JSON');
} }
let resultSeries = 0;
if (json.data) {
const { resultType, result } = json.data;
if (resultType === "scalar") {
resultSeries = 1;
} else if (result && result.length > 0) {
resultSeries = result.length;
}
}
this.setState({ this.setState({
error: null, error: null,
data: json.data, data: json.data,
lastQueryParams: { lastQueryParams: {
startTime: startTime, startTime,
endTime: endTime, endTime,
resolution: resolution, resolution,
},
stats: {
loadTime: Date.now() - queryStart,
resolution,
resultSeries
}, },
loading: false, loading: false,
}); });
@ -246,6 +262,10 @@ class Panel extends Component<PanelProps, PanelState> {
Graph Graph
</NavLink> </NavLink>
</NavItem> </NavItem>
{
(!this.state.loading && !this.state.error && this.state.stats) &&
<QueryStatsView {...this.state.stats} />
}
</Nav> </Nav>
<TabContent activeTab={this.props.options.type}> <TabContent activeTab={this.props.options.type}>
<TabPane tabId="table"> <TabPane tabId="table">

View file

@ -0,0 +1,5 @@
.query-stats{
flex-grow: 1;
font-size: 9px;
color: #999;
}

View file

@ -0,0 +1,20 @@
import React, { FC } from 'react';
import './QueryStatsView.css';
export interface QueryStats {
loadTime: number;
resolution: number;
resultSeries: number;
}
const QueryStatsView: FC<QueryStats> = props => {
const {loadTime, resolution, resultSeries} = props;
return (
<div className="query-stats">
<span className="float-right">Load time: {loadTime}ms &ensp; Resolution: {resolution}s &ensp; Result series: {resultSeries}</span>
</div>
);
}
export default QueryStatsView;