From 7c1238b492c160f2b2366eaa4e27fe7544ceedbe Mon Sep 17 00:00:00 2001 From: Yann Stepienik Date: Sun, 29 Oct 2023 15:08:21 +0000 Subject: [PATCH] [release] v0.12.0-unstable16 --- .../src/pages/dashboard/components/plot.jsx | 120 +++++++----------- .../src/pages/dashboard/components/table.jsx | 79 ++++++------ .../src/pages/dashboard/components/utils.jsx | 24 +++- client/src/pages/dashboard/index.jsx | 96 +++++++++++++- package.json | 2 +- src/metrics/index.go | 4 +- src/metrics/system.go | 5 +- 7 files changed, 204 insertions(+), 126 deletions(-) diff --git a/client/src/pages/dashboard/components/plot.jsx b/client/src/pages/dashboard/components/plot.jsx index 1ea333e..2371709 100644 --- a/client/src/pages/dashboard/components/plot.jsx +++ b/client/src/pages/dashboard/components/plot.jsx @@ -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 - + {title} - - {withSelector && -
+
))}
} - - - - - diff --git a/client/src/pages/dashboard/components/table.jsx b/client/src/pages/dashboard/components/table.jsx index 15ad55b..7f6d8f3 100644 --- a/client/src/pages/dashboard/components/table.jsx +++ b/client/src/pages/dashboard/components/table.jsx @@ -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 @@ -177,34 +210,6 @@ const TableComponent = ({ title, data, displayMax, render, defaultSlot = 'latest {title} - - - - - - - diff --git a/client/src/pages/dashboard/components/utils.jsx b/client/src/pages/dashboard/components/utils.jsx index 75789f3..1fea307 100644 --- a/client/src/pages/dashboard/components/utils.jsx +++ b/client/src/pages/dashboard/components/utils.jsx @@ -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; } -} \ No newline at end of file +} + +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); +} diff --git a/client/src/pages/dashboard/index.jsx b/client/src/pages/dashboard/index.jsx index 9bc6909..a32b9fa 100644 --- a/client/src/pages/dashboard/index.jsx +++ b/client/src/pages/dashboard/index.jsx @@ -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 ( <> {/* */} - {metrics &&
+ {metrics &&
+ + Server Monitoring + + + + + + {zoom.xaxis.min && } + + {/* Dashboard @@ -136,19 +215,19 @@ const DashboardDefault = () => { */} - + - key.startsWith("cosmos.system.docker.cpu") || key.startsWith("cosmos.system.docker.ram")).map((key) => metrics[key]) }/> - + - key.startsWith("cosmos.system.docker.net")).map((key) => metrics[key]) }/> - { return {formattedValue} @@ -160,6 +239,9 @@ const DashboardDefault = () => { }/> currentValue { return newValue @@ -183,6 +185,6 @@ func Run() { func Init() { InitAggl() - GetSystemMetrics() + //GetSystemMetrics() Run() } \ No newline at end of file diff --git a/src/metrics/system.go b/src/metrics/system.go index 16f3b57..aa67b79 100644 --- a/src/metrics/system.go +++ b/src/metrics/system.go @@ -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", }) } } \ No newline at end of file