mirror of
https://github.com/openziti/zrok.git
synced 2024-12-22 14:50:55 +01:00
parent
7d611fda30
commit
b5b3385b46
@ -34,12 +34,12 @@ func (h *getAccountMetricsHandler) Handle(params metadata.GetAccountMetricsParam
|
||||
if params.Duration != nil {
|
||||
v, err := time.ParseDuration(*params.Duration)
|
||||
if err != nil {
|
||||
logrus.Errorf("bad duration '%v' for '%v': %v", params.Duration, principal.Email, err)
|
||||
logrus.Errorf("bad duration '%v' for '%v': %v", *params.Duration, principal.Email, err)
|
||||
return metadata.NewGetAccountMetricsBadRequest()
|
||||
}
|
||||
duration = v
|
||||
}
|
||||
slice := duration / 50
|
||||
slice := duration / 30
|
||||
|
||||
query := fmt.Sprintf("from(bucket: \"%v\")\n", h.cfg.Bucket) +
|
||||
fmt.Sprintf("|> range(start: -%v)\n", duration) +
|
||||
@ -108,12 +108,12 @@ func (h *getEnvironmentMetricsHandler) Handle(params metadata.GetEnvironmentMetr
|
||||
if params.Duration != nil {
|
||||
v, err := time.ParseDuration(*params.Duration)
|
||||
if err != nil {
|
||||
logrus.Errorf("bad duration '%v' for '%v': %v", params.Duration, principal.Email, err)
|
||||
logrus.Errorf("bad duration '%v' for '%v': %v", *params.Duration, principal.Email, err)
|
||||
return metadata.NewGetAccountMetricsBadRequest()
|
||||
}
|
||||
duration = v
|
||||
}
|
||||
slice := duration / 50
|
||||
slice := duration / 30
|
||||
|
||||
query := fmt.Sprintf("from(bucket: \"%v\")\n", h.cfg.Bucket) +
|
||||
fmt.Sprintf("|> range(start: -%v)\n", duration) +
|
||||
@ -188,12 +188,12 @@ func (h *getShareMetricsHandler) Handle(params metadata.GetShareMetricsParams, p
|
||||
if params.Duration != nil {
|
||||
v, err := time.ParseDuration(*params.Duration)
|
||||
if err != nil {
|
||||
logrus.Errorf("bad duration '%v' for '%v': %v", params.Duration, principal.Email, err)
|
||||
logrus.Errorf("bad duration '%v' for '%v': %v", *params.Duration, principal.Email, err)
|
||||
return metadata.NewGetAccountMetricsBadRequest()
|
||||
}
|
||||
duration = v
|
||||
}
|
||||
slice := duration / 50
|
||||
slice := duration / 30
|
||||
|
||||
query := fmt.Sprintf("from(bucket: \"%v\")\n", h.cfg.Bucket) +
|
||||
fmt.Sprintf("|> range(start: -%v)\n", duration) +
|
||||
|
28
ui/package-lock.json
generated
28
ui/package-lock.json
generated
@ -17,6 +17,7 @@
|
||||
"dagre": "^0.8.5",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"humanize-duration": "^3.27.3",
|
||||
"moment": "^2.29.4",
|
||||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.7.0",
|
||||
"react-data-table-component": "^7.5.2",
|
||||
@ -24,7 +25,7 @@
|
||||
"react-force-graph": "^1.43.0",
|
||||
"react-router-dom": "^6.4.0",
|
||||
"react-sizeme": "^3.0.2",
|
||||
"recharts": "^2.5.0",
|
||||
"recharts": "^2.6.1",
|
||||
"styled-components": "^5.3.5",
|
||||
"svgo": "^3.0.2"
|
||||
},
|
||||
@ -13651,6 +13652,14 @@
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -16545,9 +16554,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/recharts": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.5.0.tgz",
|
||||
"integrity": "sha512-0EQYz3iA18r1Uq8VqGZ4dABW52AKBnio37kJgnztIqprELJXpOEsa0SzkqU1vjAhpCXCv52Dx1hiL9119xsqsQ==",
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.6.1.tgz",
|
||||
"integrity": "sha512-eGNNqQTSg737HB0tfFkPZbPW8ji7Q8joQM0P2yAEkJkB8CO+LJPgLpx/NUxNHJsxoXvSblMFoy5RSVBYfLU+HA==",
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5",
|
||||
"eventemitter3": "^4.0.1",
|
||||
@ -29808,6 +29817,11 @@
|
||||
"minimist": "^1.2.6"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -31796,9 +31810,9 @@
|
||||
}
|
||||
},
|
||||
"recharts": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.5.0.tgz",
|
||||
"integrity": "sha512-0EQYz3iA18r1Uq8VqGZ4dABW52AKBnio37kJgnztIqprELJXpOEsa0SzkqU1vjAhpCXCv52Dx1hiL9119xsqsQ==",
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.6.1.tgz",
|
||||
"integrity": "sha512-eGNNqQTSg737HB0tfFkPZbPW8ji7Q8joQM0P2yAEkJkB8CO+LJPgLpx/NUxNHJsxoXvSblMFoy5RSVBYfLU+HA==",
|
||||
"requires": {
|
||||
"classnames": "^2.2.5",
|
||||
"eventemitter3": "^4.0.1",
|
||||
|
@ -12,6 +12,7 @@
|
||||
"dagre": "^0.8.5",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"humanize-duration": "^3.27.3",
|
||||
"moment": "^2.29.4",
|
||||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.7.0",
|
||||
"react-data-table-component": "^7.5.2",
|
||||
@ -19,7 +20,7 @@
|
||||
"react-force-graph": "^1.43.0",
|
||||
"react-router-dom": "^6.4.0",
|
||||
"react-sizeme": "^3.0.2",
|
||||
"recharts": "^2.5.0",
|
||||
"recharts": "^2.6.1",
|
||||
"styled-components": "^5.3.5",
|
||||
"svgo": "^3.0.2"
|
||||
},
|
||||
|
@ -1,11 +1,12 @@
|
||||
import {mdiAccountBox} from "@mdi/js";
|
||||
import Icon from "@mdi/react";
|
||||
import PropertyTable from "../../PropertyTable";
|
||||
import {Tab, Tabs, Tooltip} from "react-bootstrap";
|
||||
import {Col, Container, Row, Tab, Tabs, Tooltip} from "react-bootstrap";
|
||||
import SecretToggle from "../../SecretToggle";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import * as metadata from "../../../api/metadata";
|
||||
import {Area, AreaChart, CartesianGrid, Line, LineChart, ResponsiveContainer, XAxis, YAxis} from "recharts";
|
||||
import { Bar, BarChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis } from "recharts";
|
||||
import moment from "moment";
|
||||
|
||||
const AccountDetail = (props) => {
|
||||
const customProperties = {
|
||||
@ -28,14 +29,22 @@ const AccountDetail = (props) => {
|
||||
}
|
||||
|
||||
const MetricsTab = (props) => {
|
||||
const [metrics, setMetrics] = useState({});
|
||||
const [tx, setTx] = useState(0);
|
||||
const [rx, setRx] = useState(0)
|
||||
const [metrics30, setMetrics30] = useState(buildMetrics([]));
|
||||
const [metrics7, setMetrics7] = useState(buildMetrics([]));
|
||||
const [metrics1, setMetrics1] = useState(buildMetrics([]));
|
||||
|
||||
useEffect(() => {
|
||||
metadata.getAccountMetrics()
|
||||
.then(resp => {
|
||||
setMetrics(resp.data);
|
||||
setMetrics30(buildMetrics(resp.data));
|
||||
});
|
||||
metadata.getAccountMetrics({duration: "168h"})
|
||||
.then(resp => {
|
||||
setMetrics7(buildMetrics(resp.data));
|
||||
});
|
||||
metadata.getAccountMetrics({duration: "24h"})
|
||||
.then(resp => {
|
||||
setMetrics1(buildMetrics(resp.data));
|
||||
});
|
||||
}, []);
|
||||
|
||||
@ -45,50 +54,114 @@ const MetricsTab = (props) => {
|
||||
metadata.getAccountMetrics()
|
||||
.then(resp => {
|
||||
if(mounted) {
|
||||
setMetrics(resp.data);
|
||||
setMetrics30(buildMetrics(resp.data));
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
metadata.getAccountMetrics({duration: "168h"})
|
||||
.then(resp => {
|
||||
setMetrics7(buildMetrics(resp.data));
|
||||
});
|
||||
metadata.getAccountMetrics({duration: "24h"})
|
||||
.then(resp => {
|
||||
setMetrics1(buildMetrics(resp.data));
|
||||
});
|
||||
}, 5000);
|
||||
return () => {
|
||||
mounted = false;
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let txAccum = 0
|
||||
let rxAccum = 0
|
||||
if(metrics.samples) {
|
||||
metrics.samples.forEach(sample => {
|
||||
txAccum += sample.tx
|
||||
rxAccum += sample.rx
|
||||
})
|
||||
}
|
||||
setTx(txAccum);
|
||||
setRx(rxAccum);
|
||||
}, [metrics])
|
||||
|
||||
console.log(metrics);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<h1>RX: {bytesToSize(rx)}, TX: {bytesToSize(tx)}</h1>
|
||||
</div>
|
||||
<ResponsiveContainer width={"100%"} height={300}>
|
||||
<LineChart data={metrics.samples}>
|
||||
<CartesianGrid strokeDasharay={"3 3"} />
|
||||
<XAxis dataKey={(v) => new Date(v.timestamp)} />
|
||||
<YAxis />
|
||||
<Line type={"linear"} stroke={"red"} dataKey={"rx"} activeDot={{ r: 8 }}/>
|
||||
<Line type={"linear"} stroke={"green"} dataKey={"tx"} />
|
||||
<Tooltip />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
<Container>
|
||||
<Row>
|
||||
<Col>
|
||||
<h3>Last 30 Days:</h3>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><p>Received: {bytesToSize(metrics30.rx)}</p></Col>
|
||||
<Col><p>Sent: {bytesToSize(metrics30.tx)}</p></Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<ResponsiveContainer width={"100%"} height={150}>
|
||||
<BarChart data={metrics30.data}>
|
||||
<CartesianGrid strokeDasharay={"3 3"} />
|
||||
<XAxis dataKey={(v) => v.timestamp} scale={"time"} tickFormatter={(v) => moment(v).format("MMM DD") } style={{ fontSize: '75%'}}/>
|
||||
<YAxis tickFormatter={(v) => bytesToSize(v)} style={{ fontSize: '75%' }}/>
|
||||
<Bar stroke={"#231069"} fill={"#04adef"} dataKey={"rx"} legendType={"circle"}/>
|
||||
<Bar stroke={"#231069"} fill={"#9BF316"} dataKey={"tx"} />
|
||||
<Tooltip />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<h3>Last 7 Days:</h3>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><p>Received: {bytesToSize(metrics7.rx)}</p></Col>
|
||||
<Col><p>Sent: {bytesToSize(metrics7.tx)}</p></Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<ResponsiveContainer width={"100%"} height={150}>
|
||||
<BarChart data={metrics7.data}>
|
||||
<CartesianGrid strokeDasharay={"3 3"} />
|
||||
<XAxis dataKey={(v) => v.timestamp} scale={"time"} tickFormatter={(v) => moment(v).format("MMM DD") } style={{ fontSize: '75%'}}/>
|
||||
<YAxis tickFormatter={(v) => bytesToSize(v)} style={{ fontSize: '75%' }}/>
|
||||
<Bar stroke={"#231069"} fill={"#04adef"} dataKey={"rx"} legendType={"circle"}/>
|
||||
<Bar stroke={"#231069"} fill={"#9BF316"} dataKey={"tx"} />
|
||||
<Tooltip />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<h3>Last 24 Hours:</h3>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><p>Received: {bytesToSize(metrics1.rx)}</p></Col>
|
||||
<Col><p>Sent: {bytesToSize(metrics1.tx)}</p></Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<ResponsiveContainer width={"100%"} height={150}>
|
||||
<BarChart data={metrics1.data}>
|
||||
<CartesianGrid strokeDasharay={"3 3"} />
|
||||
<XAxis dataKey={(v) => v.timestamp} scale={"time"} tickFormatter={(v) => moment(v).format("MMM DD") } style={{ fontSize: '75%'}}/>
|
||||
<YAxis tickFormatter={(v) => bytesToSize(v)} style={{ fontSize: '75%' }}/>
|
||||
<Bar stroke={"#231069"} fill={"#04adef"} dataKey={"rx"} legendType={"circle"}/>
|
||||
<Bar stroke={"#231069"} fill={"#9BF316"} dataKey={"tx"} />
|
||||
<Tooltip />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
const buildMetrics = (m) => {
|
||||
let metrics = {
|
||||
data: m.samples,
|
||||
rx: 0,
|
||||
tx: 0
|
||||
}
|
||||
if(m.samples) {
|
||||
m.samples.forEach(s => {
|
||||
metrics.rx += s.rx;
|
||||
metrics.tx += s.tx;
|
||||
});
|
||||
}
|
||||
return metrics;
|
||||
}
|
||||
|
||||
const bytesToSize = (sz) => {
|
||||
let absSz = sz;
|
||||
if(absSz < 0) {
|
||||
@ -105,7 +178,7 @@ const bytesToSize = (sz) => {
|
||||
exp++;
|
||||
}
|
||||
|
||||
return '' + (sz / div).toFixed(2) + "kMGTPE"[exp];
|
||||
return '' + (sz / div).toFixed(1) + ' ' + "kMGTPE"[exp] + 'B';
|
||||
}
|
||||
|
||||
export default AccountDetail;
|
Loading…
Reference in New Issue
Block a user