mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Grpahing, try out echarts
Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
parent
a125b6756a
commit
8ce943cdfc
126
package-lock.json
generated
126
package-lock.json
generated
|
@ -2403,6 +2403,11 @@
|
|||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.2.1.tgz",
|
||||
"integrity": "sha512-tt/7vIv3Gm2mnd/WeDx36nfGGHleil0Wg8IeB7eMrVkY0fZ5iTaBisSh8oNANc2IBsCc6vCgCNTIM/IEN0+50Q=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
@ -2872,6 +2877,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"classnames": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
|
||||
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
|
||||
|
@ -3973,6 +3983,14 @@
|
|||
"utila": "~0.4"
|
||||
}
|
||||
},
|
||||
"dom-helpers": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
|
||||
"integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
|
||||
|
@ -4067,6 +4085,23 @@
|
|||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"echarts": {
|
||||
"version": "4.2.0-rc.2",
|
||||
"resolved": "https://registry.npmjs.org/echarts/-/echarts-4.2.0-rc.2.tgz",
|
||||
"integrity": "sha512-5Y4Kyi4eNsRM9Cnl7Q8C6PFVjznBJv1VIiMm/VSQ9zyqeo+ce1695GqUd9v4zfVx+Ow1gnwMJX67h0FNvarScw==",
|
||||
"requires": {
|
||||
"zrender": "4.0.5"
|
||||
}
|
||||
},
|
||||
"echarts-for-react": {
|
||||
"version": "2.0.15-beta.0",
|
||||
"resolved": "https://registry.npmjs.org/echarts-for-react/-/echarts-for-react-2.0.15-beta.0.tgz",
|
||||
"integrity": "sha512-brgogznteCirkvOvl/ZOozkpvBt612LBtDiSGE/pANTIO2+YyGpNfFXAIjEIDAY6yTvgdj+Ei7JISAfflXEn5Q==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"size-sensor": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
|
@ -8329,6 +8364,11 @@
|
|||
"topo": "2.x.x"
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
|
||||
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
|
||||
},
|
||||
"js-levenshtein": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
|
||||
|
@ -8650,6 +8690,16 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
|
||||
},
|
||||
"lodash.isfunction": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
|
||||
"integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw=="
|
||||
},
|
||||
"lodash.isobject": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
|
||||
"integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0="
|
||||
},
|
||||
"lodash.memoize": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
|
@ -8682,6 +8732,11 @@
|
|||
"lodash._reinterpolate": "~3.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.tonumber": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.tonumber/-/lodash.tonumber-4.0.3.tgz",
|
||||
"integrity": "sha1-C5azGzVnJ5Prf1pj7nkfG56QJdk="
|
||||
},
|
||||
"lodash.uniq": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||
|
@ -9756,6 +9811,11 @@
|
|||
"resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.1.0.tgz",
|
||||
"integrity": "sha512-CPCdcFxx7fEcDMWTDjXe2Wypt4JuMt4q5Q2UrpTcyBBkLiCIyPEh/mCGmUWIcNkKGyXwQ9Y2wVhlKm6ketiBNQ=="
|
||||
},
|
||||
"popper.js": {
|
||||
"version": "1.14.7",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.7.tgz",
|
||||
"integrity": "sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ=="
|
||||
},
|
||||
"portfinder": {
|
||||
"version": "1.0.20",
|
||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz",
|
||||
|
@ -13601,6 +13661,20 @@
|
|||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-5.1.2.tgz",
|
||||
"integrity": "sha512-7kEBKwU9R8fKnZJBRa5RSIfay4KJwnYvKB6gODGicUmDSAhQJ7Tdnll5S0RLtYrzRfMVXlqYw61rzrSpP4ThLQ=="
|
||||
},
|
||||
"react-lifecycles-compat": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-popper": {
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.10.4.tgz",
|
||||
"integrity": "sha1-rypBXqIike3VBGeNev2opu4ylao=",
|
||||
"requires": {
|
||||
"popper.js": "^1.14.1",
|
||||
"prop-types": "^15.6.1"
|
||||
}
|
||||
},
|
||||
"react-scripts": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-2.1.3.tgz",
|
||||
|
@ -13656,6 +13730,48 @@
|
|||
"workbox-webpack-plugin": "3.6.3"
|
||||
}
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.5.3.tgz",
|
||||
"integrity": "sha512-2DGFck6h99kLNr8pOFk+z4Soq3iISydwOFeeEVPjTN6+Y01CmvbWmnN02VuTWyFdnRtIDPe+wy2q6Ui8snBPZg==",
|
||||
"requires": {
|
||||
"dom-helpers": "^3.3.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-lifecycles-compat": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"reactstrap": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-7.1.0.tgz",
|
||||
"integrity": "sha512-wtc4RkgnGn1TsZ0AxOZ2OqT+b8YmCWZj/tErPujWLepxzlEEhveZGC+uDerdaHVSAzJUP2DTk605iper7hutQQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"classnames": "^2.2.3",
|
||||
"lodash.isfunction": "^3.0.9",
|
||||
"lodash.isobject": "^3.0.2",
|
||||
"lodash.tonumber": "^4.0.3",
|
||||
"prop-types": "^15.5.8",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
"react-popper": "^0.10.4",
|
||||
"react-transition-group": "^2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz",
|
||||
"integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.12.0"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
|
||||
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
|
||||
|
@ -14986,6 +15102,11 @@
|
|||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz",
|
||||
"integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g=="
|
||||
},
|
||||
"size-sensor": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/size-sensor/-/size-sensor-0.2.2.tgz",
|
||||
"integrity": "sha512-dL/IdBhGDvCHlxQgxryqJNEnSWQz4xvKntsW028CgaJLBLSw8rpi7oUVSM4+xnaHbH+BFkXz6H5aMStfH8v2Pg=="
|
||||
},
|
||||
"slash": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
|
||||
|
@ -17137,6 +17258,11 @@
|
|||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"zrender": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/zrender/-/zrender-4.0.5.tgz",
|
||||
"integrity": "sha512-SintgipGEJPT9Sz2ABRoE4ZD7Yzy7oR7j7KP6H+C9FlbHWnLUfGVK7E8UV27pGwlxAMB0EsnrqhXx5XjAfv/KA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,14 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"bootstrap": "^4.2.1",
|
||||
"echarts": "^4.2.0-rc.2",
|
||||
"echarts-for-react": "^2.0.15-beta.0",
|
||||
"jquery": "^3.3.1",
|
||||
"react": "^16.7.0",
|
||||
"react-dom": "^16.7.0",
|
||||
"react-scripts": "2.1.3"
|
||||
"react-scripts": "2.1.3",
|
||||
"reactstrap": "^7.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
|
30
src/App.css
Normal file
30
src/App.css
Normal file
|
@ -0,0 +1,30 @@
|
|||
body {
|
||||
padding-top: 10px; /* TODO remove */
|
||||
}
|
||||
|
||||
.expression-input {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.alert.alert-danger {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
border-left: 1px solid #dee2e6;
|
||||
border-right: 1px solid #dee2e6;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.data-table.table {
|
||||
white-space: pre;
|
||||
margin: 2px 0 2px 0;
|
||||
}
|
||||
|
||||
.data-table > tbody > tr > td {
|
||||
padding: 6px 16px 6px 16px;
|
||||
}
|
249
src/App.js
249
src/App.js
|
@ -1,9 +1,14 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Alert, Button, Col, Container, InputGroup, InputGroupAddon, Input, Nav, NavItem, NavLink, Row, TabContent, TabPane, Table } from 'reactstrap';
|
||||
import ReactEcharts from 'echarts-for-react';
|
||||
import './App.css'
|
||||
|
||||
class App extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Container fluid={true}>
|
||||
<PanelList />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +51,7 @@ class PanelList extends Component {
|
|||
return (
|
||||
<>
|
||||
{this.state.panels}
|
||||
<button onClick={this.addPanel}>+</button>
|
||||
<Button color="primary" onClick={this.addPanel}>Add Panel</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -58,7 +63,7 @@ class Panel extends Component {
|
|||
|
||||
this.state = {
|
||||
expr: '',
|
||||
type: 'graph', // TODO enum?
|
||||
type: 'table', // TODO enum?
|
||||
range: '1h',
|
||||
endTime: null,
|
||||
data: null,
|
||||
|
@ -72,9 +77,38 @@ class Panel extends Component {
|
|||
}
|
||||
|
||||
execute() {
|
||||
if (this.state.expr === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({loading: true});
|
||||
|
||||
fetch('http://demo.robustperception.io:9090/api/v1/query?query=' + encodeURIComponent(this.state.expr))
|
||||
let url = new URL('http://demo.robustperception.io:9090/');//window.location.href);
|
||||
let params = {
|
||||
'query': this.state.expr,
|
||||
};
|
||||
switch (this.state.type) {
|
||||
case 'graph':
|
||||
url.pathname = '/api/v1/query_range'
|
||||
Object.assign(params, {
|
||||
start: '1549118381',
|
||||
end: '1549119381',
|
||||
step: 10,
|
||||
})
|
||||
// TODO path prefix here and elsewhere.
|
||||
break;
|
||||
case 'table':
|
||||
url.pathname = '/api/v1/query'
|
||||
Object.assign(params, {
|
||||
time: '1549119381',
|
||||
})
|
||||
break;
|
||||
default:
|
||||
// TODO
|
||||
}
|
||||
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
|
||||
|
||||
fetch(url)
|
||||
.then(resp => {
|
||||
if (resp.ok) {
|
||||
return resp.json();
|
||||
|
@ -85,6 +119,7 @@ class Panel extends Component {
|
|||
})
|
||||
.then(json =>
|
||||
this.setState({
|
||||
error: null,
|
||||
data: json.data,
|
||||
loading: false,
|
||||
})
|
||||
|
@ -103,13 +138,58 @@ class Panel extends Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Row>
|
||||
<Col>
|
||||
<ExpressionInput value={this.state.expr} onChange={this.handleExpressionChange} execute={this.execute}/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
{this.state.loading && "Loading..."}
|
||||
{this.state.error}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
{this.state.error && <Alert color="danger">{this.state.error.toString()}</Alert>}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<Nav tabs>
|
||||
<NavItem>
|
||||
<NavLink
|
||||
className={this.state.type === 'graph' ? 'active' : ''}
|
||||
onClick={() => { this.setState({type: 'graph'}); }}
|
||||
>
|
||||
Graph
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
<NavItem>
|
||||
<NavLink
|
||||
className={this.state.type === 'table' ? 'active' : ''}
|
||||
onClick={() => { this.setState({type: 'table'}); }}
|
||||
>
|
||||
Table
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
</Nav>
|
||||
<TabContent activeTab={this.state.type}>
|
||||
<TabPane tabId="graph">
|
||||
<Graph data={this.state.data} />
|
||||
</TabPane>
|
||||
<TabPane tabId="table">
|
||||
<DataTable data={this.state.data} />
|
||||
<button onClick={this.props.removePanel}>-</button>
|
||||
</div>
|
||||
</TabPane>
|
||||
</TabContent>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<Button className="float-right" color="link" onClick={this.props.removePanel}>Remove Panel</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -128,34 +208,167 @@ class ExpressionInput extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
numRows() {
|
||||
// TODO: Not ideal. This doesn't handle long lines.
|
||||
return this.props.value.split(/\r\n|\r|\n/).length;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<textarea
|
||||
<InputGroup className="expression-input">
|
||||
<Input
|
||||
autoFocus
|
||||
type="textarea"
|
||||
rows={this.numRows()}
|
||||
value={this.props.value}
|
||||
onChange={this.props.onChange}
|
||||
onKeyPress={this.handleKeyPress}
|
||||
placeholder="Expression (press Shift+Enter for newlines)" />
|
||||
<button onClick={this.props.execute}>Execute</button>
|
||||
</div>
|
||||
<InputGroupAddon addonType="append">
|
||||
<Button color="primary" onClick={this.props.execute}>Execute</Button>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function DataTable(props) {
|
||||
if (!props.data) {
|
||||
return <div>no data</div>;
|
||||
const data = props.data;
|
||||
var rows = <tr><td colSpan="2"><i>no data</i></td></tr>
|
||||
|
||||
if (props.data) {
|
||||
switch(data.resultType) {
|
||||
case 'vector':
|
||||
if (data.result === null || data.result.length === 0) {
|
||||
break;
|
||||
}
|
||||
const rows = props.data.result.map((s, index) => {
|
||||
return <tr key={index}><th>{metricToSeriesName(s.metric)}</th><td>{s.value[1]} @ {s.value[0]}</td></tr>
|
||||
rows = props.data.result.map((s, index) => {
|
||||
return <tr key={index}><td>{metricToSeriesName(s.metric)}</td><td>{s.value[1]}</td></tr>
|
||||
});
|
||||
break;
|
||||
case 'matrix':
|
||||
if (data.result === null || data.result.length === 0) {
|
||||
break;
|
||||
}
|
||||
rows = props.data.result.map((s, index) => {
|
||||
const valueText = s.values.map((v) => {
|
||||
return [1] + ' @' + v[0];
|
||||
}).join('\n');
|
||||
return <tr key={index}><td>{metricToSeriesName(s.metric)}</td><td>{valueText}</td></tr>
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<table>
|
||||
<tbody>{rows}</tbody>
|
||||
</table>
|
||||
<Table hover size="sm" className="data-table">
|
||||
<tbody>
|
||||
{rows}
|
||||
</tbody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
class Graph extends Component {
|
||||
componentDidMount() {
|
||||
this.chart = null;
|
||||
}
|
||||
|
||||
getOption() {
|
||||
const data = this.transformData(this.props.data);
|
||||
console.log(data);
|
||||
|
||||
return {
|
||||
legend: {
|
||||
show: true,
|
||||
orient: 'vertical',
|
||||
},
|
||||
addDataAnimation: false,
|
||||
xAxis : [
|
||||
{
|
||||
type : 'category',
|
||||
boundaryGap : false,
|
||||
//data : ['周一','周二','周三','周四','周五','周六','周日']
|
||||
}
|
||||
],
|
||||
yAxis : [
|
||||
{
|
||||
type : 'value'
|
||||
}
|
||||
],
|
||||
series: data//[
|
||||
// {
|
||||
// 'name': "up{}",
|
||||
// 'type': "line",
|
||||
// 'data': [
|
||||
// [1,1], [2,4], [3,3], [4, -2],
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// 'connectNulls': false,
|
||||
// 'name': "foo{}",
|
||||
// 'type': "line",
|
||||
// 'data': [
|
||||
// [1,5], [2,5], [3, NaN], [4, -3], [5, 6], [6, 1]
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// 'name': "bar{}",
|
||||
// 'type': "line",
|
||||
// 'data': [
|
||||
// [1,1], [2,3], [3,8], [4, -1],
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// 'name': "down{}",
|
||||
// 'type': "line",
|
||||
// 'data': [
|
||||
// [1,2], [2,0], [3,0], [4, 2]
|
||||
// ],
|
||||
// }
|
||||
//],
|
||||
};
|
||||
}
|
||||
|
||||
transformData(data) {
|
||||
if (data.resultType !== 'matrix') {
|
||||
// TODO self.showError("Result is not of matrix type! Please enter a correct expression.");
|
||||
return [];
|
||||
}
|
||||
|
||||
return data.result.map(ts => {
|
||||
return {
|
||||
name: metricToSeriesName(ts.metric),
|
||||
data: ts.values.map(v => [v[0], this.parseValue(v[1])]),
|
||||
type: 'line',
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
parseValue(value) {
|
||||
var val = parseFloat(value);
|
||||
if (isNaN(val)) {
|
||||
// "+Inf", "-Inf", "+Inf" will be parsed into NaN by parseFloat(). The
|
||||
// can't be graphed, so show them as gaps (null).
|
||||
return null;
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.props.data === null) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<ReactEcharts option={this.getOption()} ref={(ref) => { this.echarts = ref }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function metricToSeriesName(labels) {
|
||||
var tsName = (labels.__name__ || '') + "{";
|
||||
var labelStrings = [];
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
|
|
Loading…
Reference in a new issue