[release] v0.12.0-unstable16
This commit is contained in:
parent
e380c80591
commit
7c1238b492
|
@ -24,30 +24,10 @@ import { useTheme } from '@mui/material/styles';
|
|||
|
||||
// third-party
|
||||
import ReactApexChart from 'react-apexcharts';
|
||||
import { FormaterForMetric } from './utils';
|
||||
import { FormaterForMetric, toUTC } from './utils';
|
||||
|
||||
function formatDate(now, time) {
|
||||
// use as UTC
|
||||
// now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are 0-based
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
|
||||
return time ? `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` : `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
function toUTC(date, time) {
|
||||
let now = new Date(date);
|
||||
now.setMinutes(now.getMinutes() + now.getTimezoneOffset());
|
||||
return formatDate(now, time);
|
||||
}
|
||||
|
||||
const PlotComponent = ({ title, data, SimpleDesign, withSelector, defaultSlot = 'latest' }) => {
|
||||
const [slot, setSlot] = useState(defaultSlot);
|
||||
const PlotComponent = ({ title, slot, data, SimpleDesign, withSelector, xAxis, zoom, setZoom }) => {
|
||||
const theme = useTheme();
|
||||
const { primary, secondary } = theme.palette.text;
|
||||
const line = theme.palette.divider;
|
||||
|
@ -83,28 +63,6 @@ const PlotComponent = ({ title, data, SimpleDesign, withSelector, defaultSlot =
|
|||
const [options, setOptions] = useState(areaChartOptions);
|
||||
|
||||
useEffect(() => {
|
||||
let xAxis = [];
|
||||
|
||||
if(slot === 'latest') {
|
||||
for(let i = 0; i < 100; i++) {
|
||||
xAxis.unshift(i);
|
||||
}
|
||||
}
|
||||
else if(slot === 'hourly') {
|
||||
for(let i = 0; i < 48; i++) {
|
||||
let now = new Date();
|
||||
now.setHours(now.getHours() - i);
|
||||
now.setMinutes(0);
|
||||
now.setSeconds(0);
|
||||
xAxis.unshift(formatDate(now, true));
|
||||
}
|
||||
} else if(slot === 'daily') {
|
||||
for(let i = 0; i < 30; i++) {
|
||||
let now = new Date();
|
||||
now.setDate(now.getDate() - i);
|
||||
xAxis.unshift(formatDate(now));
|
||||
}
|
||||
}
|
||||
|
||||
let toProcess = data;
|
||||
if(withSelector) {
|
||||
|
@ -150,6 +108,8 @@ const PlotComponent = ({ title, data, SimpleDesign, withSelector, defaultSlot =
|
|||
color: line
|
||||
},
|
||||
tickAmount: xAxis.length,
|
||||
min: zoom.xaxis && zoom.xaxis.min,
|
||||
max: zoom.xaxis && zoom.xaxis.max,
|
||||
},
|
||||
yaxis: toProcess.map((thisdata, ida) => ({
|
||||
opposite: ida === 1,
|
||||
|
@ -163,13 +123,28 @@ const PlotComponent = ({ title, data, SimpleDesign, withSelector, defaultSlot =
|
|||
},
|
||||
title: {
|
||||
text: SimpleDesign ? '' : thisdata.Label,
|
||||
}
|
||||
},
|
||||
min: zoom.yaxis && zoom.yaxis.min,
|
||||
max: zoom.yaxis && zoom.yaxis.max,
|
||||
})),
|
||||
grid: {
|
||||
borderColor: line
|
||||
},
|
||||
tooltip: {
|
||||
theme: theme.palette.mode,
|
||||
},
|
||||
chart: {
|
||||
events: {
|
||||
zoomed: function(chartContext, { xaxis, yaxis }) {
|
||||
// Handle the zoom event here
|
||||
console.log('Zoomed:', xaxis, yaxis);
|
||||
setZoom({ xaxis, yaxis });
|
||||
},
|
||||
selection: function(chartContext, { xaxis, yaxis }) {
|
||||
// Handle the selection event here
|
||||
console.log('Selected:', xaxis, yaxis);
|
||||
},
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -181,17 +156,38 @@ const PlotComponent = ({ title, data, SimpleDesign, withSelector, defaultSlot =
|
|||
}));
|
||||
}, [slot, data, selected]);
|
||||
|
||||
useEffect(() => {
|
||||
// if different
|
||||
if(zoom && zoom.xaxis && zoom.yaxis && (!options.xaxis || !options.yaxis || !options.yaxis[0] || (
|
||||
zoom.xaxis.min !== options.xaxis.min ||
|
||||
zoom.xaxis.max !== options.xaxis.max ||
|
||||
zoom.yaxis.min !== options.yaxis[0].min ||
|
||||
zoom.yaxis.max !== options.yaxis[0].max
|
||||
))){
|
||||
setOptions((prevState) => ({
|
||||
...prevState,
|
||||
xaxis: {
|
||||
...prevState.xaxis,
|
||||
min: zoom.xaxis.min,
|
||||
max: zoom.xaxis.max,
|
||||
},
|
||||
yaxis: prevState.yaxis.map((y, id) => ({
|
||||
...y,
|
||||
min: zoom.yaxis.min,
|
||||
max: zoom.yaxis.max,
|
||||
}))
|
||||
}));
|
||||
}
|
||||
}, [zoom]);
|
||||
|
||||
return <Grid item xs={12} md={7} lg={8} >
|
||||
<Grid container alignItems="center" justifyContent="space-between">
|
||||
<Grid container alignItems="center" >
|
||||
<Grid item>
|
||||
<Typography variant="h5">{title}</Typography>
|
||||
</Grid>
|
||||
<Grid item >
|
||||
<Stack direction="row" alignItems="center" spacing={0}>
|
||||
|
||||
{withSelector &&
|
||||
<div style={{ marginRight: 15 }}>
|
||||
<div style={{ marginLeft: 15 }}>
|
||||
<TextField
|
||||
id="standard-select-currency"
|
||||
size="small"
|
||||
|
@ -206,32 +202,6 @@ const PlotComponent = ({ title, data, SimpleDesign, withSelector, defaultSlot =
|
|||
</MenuItem>
|
||||
))}
|
||||
</TextField></div>}
|
||||
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setSlot('latest')}
|
||||
color={slot === 'latest' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'latest' ? 'outlined' : 'text'}
|
||||
>
|
||||
Latest
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setSlot('hourly')}
|
||||
color={slot === 'hourly' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'hourly' ? 'outlined' : 'text'}
|
||||
>
|
||||
Hourly
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setSlot('daily')}
|
||||
color={slot === 'daily' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'daily' ? 'outlined' : 'text'}
|
||||
>
|
||||
Daily
|
||||
</Button>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<MainCard content={false} sx={{ mt: 1.5 }} >
|
||||
|
|
|
@ -98,8 +98,7 @@ function OrderTableHead({ order, orderBy, headCells }) {
|
|||
);
|
||||
}
|
||||
|
||||
const TableComponent = ({ title, data, displayMax, render, defaultSlot = 'latest' }) => {
|
||||
const [slot, setSlot] = useState(defaultSlot);
|
||||
const TableComponent = ({ title, data, displayMax, render, xAxis, slot, zoom}) => {
|
||||
const theme = useTheme();
|
||||
const { primary, secondary } = theme.palette.text;
|
||||
const line = theme.palette.divider;
|
||||
|
@ -115,7 +114,42 @@ const TableComponent = ({ title, data, displayMax, render, defaultSlot = 'latest
|
|||
|
||||
data.forEach((item) => {
|
||||
let k = item.Key.split('.')
|
||||
let v = item.Values.length ? item.Values[item.Values.length - 1] : 0;
|
||||
let v = item.Values.length ? item.Values[item.Values.length - 1].Value : 0;
|
||||
if (slot === 'hourly' || slot === 'daily') {
|
||||
let avgIndex = 0;
|
||||
v = xAxis
|
||||
.filter((date, index) => {
|
||||
if (zoom && zoom.xaxis && zoom.xaxis.min && zoom.xaxis.max) {
|
||||
return index >= zoom.xaxis.min && index <= zoom.xaxis.max;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((date) => {
|
||||
let key = slot === 'hourly' ? "hour_" : "day_";
|
||||
let k = key + toUTC(date, slot === 'hourly');
|
||||
if (k in item.ValuesAggl) {
|
||||
return item.ValuesAggl[k].Value;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
.reduce((a, b) => {
|
||||
if (!b) {
|
||||
return a;
|
||||
}
|
||||
if (item.AggloType == "min") {
|
||||
return Math.min(a, b);
|
||||
} else if (item.AggloType == "max") {
|
||||
return Math.max(a, b);
|
||||
} else if (item.AggloType == "avg") {
|
||||
avgIndex++;
|
||||
return a + b;
|
||||
}
|
||||
}, 0);
|
||||
if (item.AggloType == "avg") {
|
||||
v = v / avgIndex;
|
||||
}
|
||||
}
|
||||
let name = k[k.length - 1];
|
||||
let cat = k[k.length - 2];
|
||||
|
||||
|
@ -126,12 +160,12 @@ const TableComponent = ({ title, data, displayMax, render, defaultSlot = 'latest
|
|||
if(!fnrows.find((row) => row.name === name)) {
|
||||
fnrows.push({
|
||||
name,
|
||||
[cat]: render ? render(item, v.Value, formatter(v.Value)) : formatter(v.Value),
|
||||
["__" + cat]: v.Value
|
||||
[cat]: render ? render(item, v, formatter(v)) : formatter(v),
|
||||
["__" + cat]: v
|
||||
});
|
||||
} else {
|
||||
fnrows.find((row) => row.name === name)[cat] = render ? render(item, v.Value, formatter(v.Value)) : formatter(v.Value)
|
||||
fnrows.find((row) => row.name === name)["__" + cat] = v.Value
|
||||
fnrows.find((row) => row.name === name)[cat] = render ? render(item, v, formatter(v)) : formatter(v)
|
||||
fnrows.find((row) => row.name === name)["__" + cat] = v
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -140,7 +174,6 @@ const TableComponent = ({ title, data, displayMax, render, defaultSlot = 'latest
|
|||
let flag = false;
|
||||
Object.keys(row).forEach((key) => {
|
||||
if(key !== 'name' && row["__" + key]) {
|
||||
console.log(key, row["__" + key])
|
||||
flag = true;
|
||||
}
|
||||
});
|
||||
|
@ -169,7 +202,7 @@ const TableComponent = ({ title, data, displayMax, render, defaultSlot = 'latest
|
|||
setHeadCells(fnhc);
|
||||
setRows(fnrows);
|
||||
|
||||
}, [data, slot]);
|
||||
}, [data, slot, xAxis, zoom]);
|
||||
|
||||
|
||||
return <Grid item xs={12} md={5} lg={4}>
|
||||
|
@ -177,34 +210,6 @@ const TableComponent = ({ title, data, displayMax, render, defaultSlot = 'latest
|
|||
<Grid item>
|
||||
<Typography variant="h5">{title}</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Stack direction="row" alignItems="center" spacing={0}>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setSlot('latest')}
|
||||
color={slot === 'latest' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'latest' ? 'outlined' : 'text'}
|
||||
>
|
||||
Latest
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setSlot('hourly')}
|
||||
color={slot === 'hourly' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'hourly' ? 'outlined' : 'text'}
|
||||
>
|
||||
Hourly
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setSlot('daily')}
|
||||
color={slot === 'daily' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'daily' ? 'outlined' : 'text'}
|
||||
>
|
||||
Daily
|
||||
</Button>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<MainCard content={false} sx={{ mt: 1.5 }}>
|
||||
<Box>
|
||||
|
|
|
@ -15,8 +15,6 @@ export const simplifyNumber = (num) => {
|
|||
}
|
||||
|
||||
export const FormaterForMetric = (metric, displayMax) => {
|
||||
console.log(metric)
|
||||
|
||||
return (num) => {
|
||||
if(!num) return 0;
|
||||
|
||||
|
@ -31,4 +29,24 @@ export const FormaterForMetric = (metric, displayMax) => {
|
|||
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const formatDate = (now, time) => {
|
||||
// use as UTC
|
||||
// now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are 0-based
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
|
||||
return time ? `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` : `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
export const toUTC = (date, time) => {
|
||||
let now = new Date(date);
|
||||
now.setMinutes(now.getMinutes() + now.getTimezoneOffset());
|
||||
return formatDate(now, time);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import AnimateButton from '../../components/@extended/AnimateButton';
|
|||
import PlotComponent from './components/plot';
|
||||
import TableComponent from './components/table';
|
||||
import { HomeBackground, TransparentHeader } from '../home';
|
||||
import { formatDate } from './components/utils';
|
||||
|
||||
// avatar style
|
||||
const avatarSX = {
|
||||
|
@ -80,12 +81,24 @@ const status = [
|
|||
|
||||
const DashboardDefault = () => {
|
||||
const [value, setValue] = useState('today');
|
||||
const [slot, setSlot] = useState('week');
|
||||
const [slot, setSlot] = useState('latest');
|
||||
|
||||
const [zoom, setZoom] = useState({
|
||||
xaxis: {},
|
||||
yaxis: {}
|
||||
});
|
||||
|
||||
const [coStatus, setCoStatus] = useState(null);
|
||||
const [metrics, setMetrics] = useState(null);
|
||||
const [isCreatingDB, setIsCreatingDB] = useState(false);
|
||||
|
||||
const resetZoom = () => {
|
||||
setZoom({
|
||||
xaxis: {},
|
||||
yaxis: {}
|
||||
});
|
||||
}
|
||||
|
||||
const refreshMetrics = () => {
|
||||
API.metrics.get().then((res) => {
|
||||
let finalMetrics = {};
|
||||
|
@ -107,14 +120,80 @@ const DashboardDefault = () => {
|
|||
refreshStatus();
|
||||
refreshMetrics();
|
||||
}, []);
|
||||
|
||||
let xAxis = [];
|
||||
|
||||
if(slot === 'latest') {
|
||||
for(let i = 0; i < 100; i++) {
|
||||
xAxis.unshift(i);
|
||||
}
|
||||
}
|
||||
else if(slot === 'hourly') {
|
||||
for(let i = 0; i < 48; i++) {
|
||||
let now = new Date();
|
||||
now.setHours(now.getHours() - i);
|
||||
now.setMinutes(0);
|
||||
now.setSeconds(0);
|
||||
xAxis.unshift(formatDate(now, true));
|
||||
}
|
||||
} else if(slot === 'daily') {
|
||||
for(let i = 0; i < 30; i++) {
|
||||
let now = new Date();
|
||||
now.setDate(now.getDate() - i);
|
||||
xAxis.unshift(formatDate(now));
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <HomeBackground status={coStatus} />
|
||||
<TransparentHeader /> */}
|
||||
<IsLoggedIn />
|
||||
{metrics && <div style={{marginTop: '30px', zIndex:2, position: 'relative'}}>
|
||||
{metrics && <div style={{zIndex:2, position: 'relative'}}>
|
||||
<Grid container rowSpacing={4.5} columnSpacing={2.75} >
|
||||
<Grid item xs={12} sx={{ mb: -2.25 }}>
|
||||
<Typography variant="h4">Server Monitoring</Typography>
|
||||
<Stack direction="row" alignItems="center" spacing={0} style={{marginTop: 10}}>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {setSlot('latest'); resetZoom()}}
|
||||
color={slot === 'latest' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'latest' ? 'outlined' : 'text'}
|
||||
>
|
||||
Latest
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {setSlot('hourly'); resetZoom()}}
|
||||
color={slot === 'hourly' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'hourly' ? 'outlined' : 'text'}
|
||||
>
|
||||
Hourly
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {setSlot('daily'); resetZoom()}}
|
||||
color={slot === 'daily' ? 'primary' : 'secondary'}
|
||||
variant={slot === 'daily' ? 'outlined' : 'text'}
|
||||
>
|
||||
Daily
|
||||
</Button>
|
||||
|
||||
{zoom.xaxis.min && <Button
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setZoom({
|
||||
xaxis: {},
|
||||
yaxis: {}
|
||||
});
|
||||
}}
|
||||
color={'primary'}
|
||||
variant={'outlined'}
|
||||
>
|
||||
Reset Zoom
|
||||
</Button>}
|
||||
</Stack>
|
||||
</Grid>
|
||||
{/*
|
||||
<Grid item xs={12} sx={{ mb: -2.25 }}>
|
||||
<Typography variant="h5">Dashboard</Typography>
|
||||
|
@ -136,19 +215,19 @@ const DashboardDefault = () => {
|
|||
*/}
|
||||
|
||||
|
||||
<PlotComponent title={'Resources'} data={[metrics["cosmos.system.cpu.0"], metrics["cosmos.system.ram"]]}/>
|
||||
<PlotComponent xAxis={xAxis} zoom={zoom} setZoom={setZoom} slot={slot} title={'Resources'} data={[metrics["cosmos.system.cpu.0"], metrics["cosmos.system.ram"]]}/>
|
||||
|
||||
<TableComponent title="Containers - Network" data={
|
||||
<TableComponent xAxis={xAxis} zoom={zoom} setZoom={setZoom} slot={slot} title="Containers - Resources" data={
|
||||
Object.keys(metrics).filter((key) => key.startsWith("cosmos.system.docker.cpu") || key.startsWith("cosmos.system.docker.ram")).map((key) => metrics[key])
|
||||
}/>
|
||||
|
||||
<PlotComponent title={'Network'} data={[metrics["cosmos.system.netTx"], metrics["cosmos.system.netRx"]]}/>
|
||||
<PlotComponent xAxis={xAxis} zoom={zoom} setZoom={setZoom} slot={slot} title={'Network'} data={[metrics["cosmos.system.netTx"], metrics["cosmos.system.netRx"]]}/>
|
||||
|
||||
<TableComponent title="Containers - Network" data={
|
||||
<TableComponent xAxis={xAxis} zoom={zoom} setZoom={setZoom} slot={slot} title="Containers - Network" data={
|
||||
Object.keys(metrics).filter((key) => key.startsWith("cosmos.system.docker.net")).map((key) => metrics[key])
|
||||
}/>
|
||||
|
||||
<TableComponent title="Disk Usage" displayMax={true}
|
||||
<TableComponent xAxis={xAxis} zoom={zoom} setZoom={setZoom} slot={slot} title="Disk Usage" displayMax={true}
|
||||
render={(metric, value, formattedValue) => {
|
||||
return <span>
|
||||
{formattedValue}
|
||||
|
@ -160,6 +239,9 @@ const DashboardDefault = () => {
|
|||
}/>
|
||||
|
||||
<PlotComponent
|
||||
zoom={zoom} setZoom={setZoom}
|
||||
xAxis={xAxis}
|
||||
slot={slot}
|
||||
title={'Temperature'}
|
||||
withSelector={'cosmos.system.temp.all'}
|
||||
SimpleDesign
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "cosmos-server",
|
||||
"version": "0.12.0-unstable15",
|
||||
"version": "0.12.0-unstable16",
|
||||
"description": "",
|
||||
"main": "test-server.js",
|
||||
"bugs": {
|
||||
|
|
|
@ -38,6 +38,8 @@ var lock = make(chan bool, 1)
|
|||
func MergeMetric(SetOperation string, currentValue int, newValue int, avgIndex int) int {
|
||||
if SetOperation == "" {
|
||||
return newValue
|
||||
} else if newValue == 0 {
|
||||
return currentValue
|
||||
} else if SetOperation == "max" {
|
||||
if newValue > currentValue {
|
||||
return newValue
|
||||
|
@ -183,6 +185,6 @@ func Run() {
|
|||
|
||||
func Init() {
|
||||
InitAggl()
|
||||
GetSystemMetrics()
|
||||
//GetSystemMetrics()
|
||||
Run()
|
||||
}
|
|
@ -166,6 +166,7 @@ func GetSystemMetrics() {
|
|||
}
|
||||
|
||||
realMount := part.Mountpoint
|
||||
mountKey := strings.Replace(part.Mountpoint, ".", "_", -1)
|
||||
|
||||
if os.Getenv("HOSTNAME") != "" {
|
||||
realMount = "/mnt/host" + part.Mountpoint
|
||||
|
@ -175,7 +176,7 @@ func GetSystemMetrics() {
|
|||
if err != nil {
|
||||
utils.Error("Metrics - Error fetching Disk usage for " + realMount + " : ", err)
|
||||
} else {
|
||||
PushSetMetric("system.disk." + part.Mountpoint, int(u.Used), DataDef{
|
||||
PushSetMetric("system.disk." + mountKey, int(u.Used), DataDef{
|
||||
Max: u.Total,
|
||||
Period: time.Second * 120,
|
||||
Label: "Disk " + part.Mountpoint,
|
||||
|
@ -207,7 +208,7 @@ func GetSystemMetrics() {
|
|||
PushSetMetric("system.temp.all", avgTemp / avgTempCount, DataDef{
|
||||
Max: 0,
|
||||
Period: time.Second * 30,
|
||||
Label: "Temperature",
|
||||
Label: "Temperature - All",
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue