{withSelector &&
-
+
+
-
+ >
}
export default PlotComponent;
\ No newline at end of file
diff --git a/client/src/pages/dashboard/components/table.jsx b/client/src/pages/dashboard/components/table.jsx
index bc4f839..5c13ab8 100644
--- a/client/src/pages/dashboard/components/table.jsx
+++ b/client/src/pages/dashboard/components/table.jsx
@@ -21,7 +21,12 @@ import {
TableCell,
TableContainer,
Table,
- TableBody
+ TableBody,
+ Dialog,
+ DialogTitle,
+ DialogContent,
+ DialogContentText,
+ DialogActions
} from '@mui/material';
import MainCard from '../../../components/MainCard';
@@ -34,6 +39,7 @@ import { object } from 'prop-types';
import { FormaterForMetric } from './utils';
import { set } from 'lodash';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
+import PlotComponent from './plot';
function formatDate(now, time) {
// use as UTC
@@ -128,6 +134,7 @@ const TableComponent = ({ title, data, displayMax, render, xAxis, slot, zoom}) =
const [orderBy, setOrderBy] = useState('name');
const [headCells, setHeadCells] = useState([]);
const [rows, setRows] = useState([]);
+ const [openModal, setOpenModal] = useState(false);
useEffect(() => {
let heads = {};
@@ -189,11 +196,13 @@ const TableComponent = ({ title, data, displayMax, render, xAxis, slot, zoom}) =
fnrows.push({
name,
[cat]: render ? render(item, v, formatter(v)) : formatter(v),
- ["__" + cat]: v
+ ["__" + cat]: v,
+ "__key": [item.Key]
});
} else {
fnrows.find((row) => row.name === name)[cat] = render ? render(item, v, formatter(v)) : formatter(v)
fnrows.find((row) => row.name === name)["__" + cat] = v
+ fnrows.find((row) => row.name === name)["__key"].push(item.Key)
}
});
@@ -233,12 +242,41 @@ const TableComponent = ({ title, data, displayMax, render, xAxis, slot, zoom}) =
}, [data, slot, xAxis, zoom]);
- return
+ return <>
+
+ {openModal && }
+
+
{title}
+
{
+ setOpenModal(row.__key);
+ }}
>
{headCells.map((headCell) => {
return
+ >
}
export default TableComponent;
\ No newline at end of file
diff --git a/client/src/pages/dashboard/components/utils.jsx b/client/src/pages/dashboard/components/utils.jsx
index 63a8955..38a7b53 100644
--- a/client/src/pages/dashboard/components/utils.jsx
+++ b/client/src/pages/dashboard/components/utils.jsx
@@ -4,13 +4,13 @@ export const simplifyNumber = (num) => {
num = Math.round(num * 100) / 100;
if (Math.abs(num) >= 1e12) {
- return (num / 1e12).toFixed(1) + 'T'; // Convert to Millions
+ return (num / 1e12).toFixed(1) + ' T'; // Convert to Millions
} else if (Math.abs(num) >= 1e9) {
- return (num / 1e9).toFixed(1) + 'G'; // Convert to Millions
+ return (num / 1e9).toFixed(1) + ' G'; // Convert to Millions
} else if (Math.abs(num) >= 1e6) {
- return (num / 1e6).toFixed(1) + 'M'; // Convert to Millions
+ return (num / 1e6).toFixed(1) + ' M'; // Convert to Millions
} else if (Math.abs(num) >= 1e3) {
- return (num / 1e3).toFixed(1) + 'K'; // Convert to Thousands
+ return (num / 1e3).toFixed(1) + ' K'; // Convert to Thousands
} else {
return num.toString();
}
@@ -18,12 +18,11 @@ export const simplifyNumber = (num) => {
export const FormaterForMetric = (metric, displayMax) => {
return (num) => {
- if(!num) return 0;
-
+
if(metric.Scale)
num /= metric.Scale;
- num = simplifyNumber(num);
+ num = simplifyNumber(num) + metric.Unit;
if(displayMax && metric.Max) {
num += ` / ${simplifyNumber(metric.Max)}`
diff --git a/client/src/pages/dashboard/containerMetrics.jsx b/client/src/pages/dashboard/containerMetrics.jsx
new file mode 100644
index 0000000..d9b06b7
--- /dev/null
+++ b/client/src/pages/dashboard/containerMetrics.jsx
@@ -0,0 +1,234 @@
+import { useEffect, useState } from 'react';
+
+// material-ui
+import {
+ Avatar,
+ AvatarGroup,
+ Box,
+ Button,
+ Grid,
+ List,
+ ListItemAvatar,
+ ListItemButton,
+ ListItemSecondaryAction,
+ ListItemText,
+ MenuItem,
+ Stack,
+ TextField,
+ Typography,
+ Alert,
+ LinearProgress,
+ CircularProgress
+} from '@mui/material';
+
+// project import
+import OrdersTable from './OrdersTable';
+import IncomeAreaChart from './IncomeAreaChart';
+import MonthlyBarChart from './MonthlyBarChart';
+import ReportAreaChart from './ReportAreaChart';
+import SalesColumnChart from './SalesColumnChart';
+import MainCard from '../../components/MainCard';
+import AnalyticEcommerce from '../../components/cards/statistics/AnalyticEcommerce';
+
+// assets
+import { GiftOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons';
+import avatar1 from '../../assets/images/users/avatar-1.png';
+import avatar2 from '../../assets/images/users/avatar-2.png';
+import avatar3 from '../../assets/images/users/avatar-3.png';
+import avatar4 from '../../assets/images/users/avatar-4.png';
+import IsLoggedIn from '../../isLoggedIn';
+
+import * as API from '../../api';
+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 = {
+ width: 36,
+ height: 36,
+ fontSize: '1rem'
+};
+
+// action style
+const actionSX = {
+ mt: 0.75,
+ ml: 1,
+ top: 'auto',
+ right: 'auto',
+ alignSelf: 'flex-start',
+ transform: 'none'
+};
+
+// sales report status
+const status = [
+ {
+ value: 'today',
+ label: 'Today'
+ },
+ {
+ value: 'month',
+ label: 'This Month'
+ },
+ {
+ value: 'year',
+ label: 'This Year'
+ }
+];
+
+// ==============================|| DASHBOARD - DEFAULT ||============================== //
+
+const ContainerMetrics = ({containerName}) => {
+ const [value, setValue] = useState('today');
+ const [slot, setSlot] = useState('latest');
+
+ const [zoom, setZoom] = useState({
+ xaxis: {}
+ });
+
+ const [coStatus, setCoStatus] = useState(null);
+ const [metrics, setMetrics] = useState(null);
+ const [isCreatingDB, setIsCreatingDB] = useState(false);
+
+ const resetZoom = () => {
+ setZoom({
+ xaxis: {}
+ });
+ }
+
+ const metricsKey = {
+ CPU: "cosmos.system.docker.cpu." + containerName,
+ RAM: "cosmos.system.docker.ram." + containerName,
+ NET_RX: "cosmos.system.docker.netRx." + containerName,
+ NET_TX: "cosmos.system.docker.netTx." + containerName,
+ };
+
+ const refreshMetrics = () => {
+ API.metrics.get([
+ "cosmos.system.docker.cpu",
+ "cosmos.system.docker.ram",
+ "cosmos.system.docker.netRx",
+ "cosmos.system.docker.netTx",
+ ].map(c => c + "." + containerName)).then((res) => {
+ let finalMetrics = {};
+ if(res.data) {
+ res.data.forEach((metric) => {
+ finalMetrics[metric.Key] = metric;
+ });
+ setMetrics(finalMetrics);
+ }
+ setTimeout(refreshMetrics, 10000);
+ });
+ };
+
+ const refreshStatus = () => {
+ API.getStatus().then((res) => {
+ setCoStatus(res.data);
+ });
+ }
+
+ useEffect(() => {
+ 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 &&
+
+
+ {containerName} Monitoring
+
+
+
+
+
+ {zoom.xaxis.min && }
+
+
+
+
+
+
+
+
+
+
+
+
}
+ >
+ );
+};
+
+export default ContainerMetrics;
diff --git a/client/src/pages/dashboard/index.jsx b/client/src/pages/dashboard/index.jsx
index 5153681..c33adfe 100644
--- a/client/src/pages/dashboard/index.jsx
+++ b/client/src/pages/dashboard/index.jsx
@@ -44,6 +44,7 @@ import PlotComponent from './components/plot';
import TableComponent from './components/table';
import { HomeBackground, TransparentHeader } from '../home';
import { formatDate } from './components/utils';
+import MiniPlotComponent from './components/mini-plot';
// avatar style
const avatarSX = {
@@ -85,8 +86,7 @@ const DashboardDefault = () => {
const [slot, setSlot] = useState('latest');
const [zoom, setZoom] = useState({
- xaxis: {},
- yaxis: {}
+ xaxis: {}
});
const [coStatus, setCoStatus] = useState(null);
@@ -95,13 +95,12 @@ const DashboardDefault = () => {
const resetZoom = () => {
setZoom({
- xaxis: {},
- yaxis: {}
+ xaxis: {}
});
}
const refreshMetrics = () => {
- API.metrics.get().then((res) => {
+ API.metrics.get(["cosmos.system.*"]).then((res) => {
let finalMetrics = {};
if(res.data) {
res.data.forEach((metric) => {
@@ -109,7 +108,6 @@ const DashboardDefault = () => {
});
setMetrics(finalMetrics);
}
- setTimeout(refreshMetrics, 10000);
});
};
@@ -121,7 +119,14 @@ const DashboardDefault = () => {
useEffect(() => {
refreshStatus();
- refreshMetrics();
+
+ let interval = setInterval(() => {
+ refreshMetrics();
+ }, 10000);
+
+ return () => {
+ clearInterval(interval);
+ };
}, []);
let xAxis = [];
@@ -199,8 +204,7 @@ const DashboardDefault = () => {
size="small"
onClick={() => {
setZoom({
- xaxis: {},
- yaxis: {}
+ xaxis: {}
});
}}
color={'primary'}
@@ -230,14 +234,17 @@ 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])
@@ -245,25 +252,31 @@ const DashboardDefault = () => {
{
+ let percent = value / metric.Max * 100;
return
{formattedValue}
-
+ 95 ? 'error' : (percent > 75 ? 'warning' : 'info')}
+ value={percent} />
}}
data={
Object.keys(metrics).filter((key) => key.startsWith("cosmos.system.disk")).map((key) => metrics[key])
}/>
- key.startsWith("cosmos.system.temp")).map((key) => metrics[key])}
- />
-
+
+ key.startsWith("cosmos.system.temp")).map((key) => metrics[key])}
+ />
+
+
{/*
diff --git a/client/src/pages/servapps/containers/index.jsx b/client/src/pages/servapps/containers/index.jsx
index 117f9a2..2ba7f51 100644
--- a/client/src/pages/servapps/containers/index.jsx
+++ b/client/src/pages/servapps/containers/index.jsx
@@ -17,6 +17,7 @@ import DockerContainerSetup from './setup';
import NetworkContainerSetup from './network';
import VolumeContainerSetup from './volumes';
import DockerTerminal from './terminal';
+import ContainerMetrics from '../../dashboard/containerMetrics';
const ContainerIndex = () => {
const { containerName } = useParams();
@@ -59,6 +60,10 @@ const ContainerIndex = () => {
title: 'Logs',
children:
},
+ {
+ title: 'Monitoring',
+ children:
+ },
{
title: 'Terminal',
children:
diff --git a/client/src/pages/servapps/containers/overview.jsx b/client/src/pages/servapps/containers/overview.jsx
index 3022c14..b623f23 100644
--- a/client/src/pages/servapps/containers/overview.jsx
+++ b/client/src/pages/servapps/containers/overview.jsx
@@ -9,6 +9,7 @@ import * as API from '../../../api';
import RestartModal from '../../config/users/restart';
import GetActions from '../actionBar';
import { ServAppIcon } from '../../../utils/servapp-icon';
+import MiniPlotComponent from '../../dashboard/components/mini-plot';
const info = {
backgroundColor: 'rgba(0, 0, 0, 0.1)',
@@ -168,6 +169,17 @@ const ContainerOverview = ({ containerInfo, config, refresh, updatesAvailable, s
}}
/>
+ Monitoring
+
+
+
+
diff --git a/client/src/pages/servapps/servapps.jsx b/client/src/pages/servapps/servapps.jsx
index fc8abea..6fc86c0 100644
--- a/client/src/pages/servapps/servapps.jsx
+++ b/client/src/pages/servapps/servapps.jsx
@@ -20,6 +20,7 @@ import ResponsiveButton from '../../components/responseiveButton';
import DockerComposeImport from './containers/docker-compose';
import { ContainerNetworkWarning } from '../../components/containers';
import { ServAppIcon } from '../../utils/servapp-icon';
+import MiniPlotComponent from '../dashboard/components/mini-plot';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
@@ -296,6 +297,12 @@ const ServApps = () => {
{/* } */}
+
+
+
diff --git a/client/src/routes/MainRoutes.jsx b/client/src/routes/MainRoutes.jsx
index 84b7f49..bec75ba 100644
--- a/client/src/routes/MainRoutes.jsx
+++ b/client/src/routes/MainRoutes.jsx
@@ -42,7 +42,7 @@ const MainRoutes = {
element:
},
{
- path: '/cosmos-ui/dashboard',
+ path: '/cosmos-ui/monitoring',
element:
},
{
diff --git a/client/src/store/reducers/menu.jsx b/client/src/store/reducers/menu.jsx
index 00aba2e..048550b 100644
--- a/client/src/store/reducers/menu.jsx
+++ b/client/src/store/reducers/menu.jsx
@@ -3,7 +3,7 @@ import { createSlice } from '@reduxjs/toolkit';
// initial state
const initialState = {
- openItem: ['dashboard'],
+ openItem: ['home'],
openComponent: 'buttons',
drawerOpen: false,
componentDrawerOpen: true
diff --git a/package.json b/package.json
index f0003f7..b5f4f42 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cosmos-server",
- "version": "0.12.0-unstable23",
+ "version": "0.12.0-unstable24",
"description": "",
"main": "test-server.js",
"bugs": {
diff --git a/src/metrics/aggl.go b/src/metrics/aggl.go
index 2ba9b63..3a19ae7 100644
--- a/src/metrics/aggl.go
+++ b/src/metrics/aggl.go
@@ -2,10 +2,12 @@ package metrics
import (
"time"
+ "fmt"
+ "strings"
"github.com/jasonlvhit/gocron"
"go.mongodb.org/mongo-driver/bson"
- "go.mongodb.org/mongo-driver/mongo/options"
+ "go.mongodb.org/mongo-driver/mongo"
"github.com/azukaar/cosmos-server/src/utils"
)
@@ -30,13 +32,14 @@ type DataDefDB struct {
Key string
AggloType string
Scale int
+ Unit string
}
-func AggloMetrics() []DataDefDB {
+func AggloMetrics(metricsList []string) []DataDefDB {
lock <- true
defer func() { <-lock }()
- utils.Log("Metrics: Agglomeration started")
+ utils.Log("Metrics: Agglomeration of metrics")
utils.Debug("Time: " + time.Now().String())
@@ -47,8 +50,30 @@ func AggloMetrics() []DataDefDB {
}
// get all metrics from database
+ findOpts := map[string]interface{}{
+ }
+
+
+ // If metricsList is not empty, filter by metrics with wildcard matching
+ if len(metricsList) > 0 {
+ // Convert wildcards to regex and store them in an array
+ var regexPatterns []bson.M
+ for _, metric := range metricsList {
+ if strings.Contains(metric, "*") {
+ // Convert wildcard to regex. Replace * with .*
+ regexPattern := "^" + strings.ReplaceAll(metric, "*", ".*")
+ regexPatterns = append(regexPatterns, bson.M{"Key": bson.M{"$regex": regexPattern}})
+ } else {
+ // If there's no wildcard, match the metric directly
+ regexPatterns = append(regexPatterns, bson.M{"Key": metric})
+ }
+ }
+ // Use the $or operator to match any of the patterns
+ findOpts["$or"] = regexPatterns
+ }
+
var metrics []DataDefDB
- cursor, err := c.Find(nil, map[string]interface{}{})
+ cursor, err := c.Find(nil, findOpts)
if err != nil {
utils.Error("Metrics: Error fetching metrics", err)
return []DataDefDB{}
@@ -162,21 +187,36 @@ func CommitAggl(metrics []DataDefDB) {
defer func() { <-lock }()
utils.Log("Metrics: Agglomeration done. Saving to DB")
-
+
c, errCo := utils.GetCollection(utils.GetRootAppId(), "metrics")
if errCo != nil {
- utils.Error("Metrics - Database Connect", errCo)
- return
+ utils.Error("Metrics - Database Connect", errCo)
+ return
}
- // save metrics
- for _, metric := range metrics {
- options := options.Update().SetUpsert(true)
+ chunkSize := 100
- _, err := c.UpdateOne(nil, bson.M{"Key": metric.Key}, bson.M{"$set": bson.M{"Values": metric.Values, "ValuesAggl": metric.ValuesAggl}}, options)
+ for i := 0; i < len(metrics); i += chunkSize {
+ end := i + chunkSize
+ if end > len(metrics) {
+ end = len(metrics)
+ }
+
+ chunk := metrics[i:end]
+ models := []mongo.WriteModel{}
+
+ for _, metric := range chunk {
+ update := mongo.NewUpdateOneModel().
+ SetFilter(bson.M{"Key": metric.Key}).
+ SetUpdate(bson.M{"$set": bson.M{"Values": metric.Values, "ValuesAggl": metric.ValuesAggl}}).
+ SetUpsert(true)
+ models = append(models, update)
+ }
+
+ _, err := c.BulkWrite(nil, models)
if err != nil {
- utils.Error("Metrics: Error saving metrics", err)
+ utils.Error(fmt.Sprintf("Metrics: Error saving metrics chunk starting at index %d", i), err)
return
}
}
@@ -185,7 +225,11 @@ func CommitAggl(metrics []DataDefDB) {
}
func AggloAndCommitMetrics() {
- CommitAggl(AggloMetrics())
+ if utils.GetMainConfig().MonitoringDisabled {
+ return
+ }
+
+ CommitAggl(AggloMetrics([]string{}))
}
func InitAggl() {
diff --git a/src/metrics/api.go b/src/metrics/api.go
index 1ee0fd7..af40e76 100644
--- a/src/metrics/api.go
+++ b/src/metrics/api.go
@@ -3,6 +3,7 @@ package metrics
import (
"net/http"
"encoding/json"
+ "strings"
"github.com/azukaar/cosmos-server/src/utils"
)
@@ -12,10 +13,23 @@ func API_GetMetrics(w http.ResponseWriter, req *http.Request) {
return
}
+ //get query string "metrics"
+ query := req.URL.Query()
+ metrics := query.Get("metrics")
+
+ // split by comma
+ metricsList := []string{}
+ if metrics != "" {
+ metricsList = strings.Split(metrics, ",")
+ }
+
+
if(req.Method == "GET") {
+ w.Header().Set("Content-Type", "application/json")
+
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",
- "data": AggloMetrics(),
+ "data": AggloMetrics(metricsList),
})
} else {
utils.Error("MetricsGet: Method not allowed" + req.Method, nil)
diff --git a/src/metrics/index.go b/src/metrics/index.go
index 4e941ca..ac75406 100644
--- a/src/metrics/index.go
+++ b/src/metrics/index.go
@@ -17,6 +17,8 @@ type DataDef struct {
AggloType string
SetOperation string
Scale int
+ Unit string
+ Decumulate bool
}
type DataPush struct {
@@ -29,6 +31,8 @@ type DataPush struct {
AvgIndex int
AggloType string
Scale int
+ Unit string
+ Decumulate bool
}
var dataBuffer = map[string]DataPush{}
@@ -44,6 +48,8 @@ func MergeMetric(SetOperation string, currentValue int, newValue int, avgIndex i
} else {
return currentValue
}
+ } else if SetOperation == "sum" {
+ return currentValue + newValue
} else if SetOperation == "min" {
if newValue < currentValue {
return newValue
@@ -102,6 +108,7 @@ func SaveMetrics() {
"Label": dp.Label,
"AggloType": dp.AggloType,
"Scale": scale,
+ "Unit": dp.Unit,
},
}
@@ -132,8 +139,11 @@ func ModuloTime(start time.Time, modulo time.Duration) time.Time {
return time.Unix(0, roundedElapsed)
}
+var lastInserted = map[string]int{}
+
func PushSetMetric(key string, value int, def DataDef) {
go func() {
+ originalValue := value
key = "cosmos." + key
date := ModuloTime(time.Now(), def.Period)
cacheKey := key + date.String()
@@ -141,9 +151,20 @@ func PushSetMetric(key string, value int, def DataDef) {
lock <- true
defer func() { <-lock }()
+ if def.Decumulate {
+ if lastInserted[key] != 0 {
+ value = value - lastInserted[key]
+ } else {
+ value = 0
+ }
+ }
+
+
if dp, ok := dataBuffer[cacheKey]; ok {
+ value = MergeMetric(def.SetOperation, dp.Value, value, dp.AvgIndex)
+
dp.Max = def.Max
- dp.Value = MergeMetric(def.SetOperation, dp.Value, value, dp.AvgIndex)
+ dp.Value = value
if def.SetOperation == "avg" {
dp.AvgIndex++
}
@@ -159,18 +180,29 @@ func PushSetMetric(key string, value int, def DataDef) {
Label: def.Label,
AggloType: def.AggloType,
Scale: def.Scale,
+ Unit: def.Unit,
}
}
+
+ lastInserted[key] = originalValue
}()
}
func Run() {
utils.Debug("Metrics - Run")
-
+
nextTime := ModuloTime(time.Now().Add(time.Second*30), time.Second*30)
nextTime = nextTime.Add(time.Second * 2)
-
utils.Debug("Metrics - Next run at " + nextTime.String())
+
+ if utils.GetMainConfig().MonitoringDisabled {
+ time.AfterFunc(nextTime.Sub(time.Now()), func() {
+ Run()
+ })
+
+ return
+ }
+
time.AfterFunc(nextTime.Sub(time.Now()), func() {
go func() {
GetSystemMetrics()
@@ -182,8 +214,12 @@ func Run() {
}
func Init() {
+ lastInserted = map[string]int{}
+
InitAggl()
Run()
- go GetSystemMetrics()
+ if !utils.GetMainConfig().MonitoringDisabled {
+ go GetSystemMetrics()
+ }
}
\ No newline at end of file
diff --git a/src/metrics/system.go b/src/metrics/system.go
index 5d46c17..b9e44a8 100644
--- a/src/metrics/system.go
+++ b/src/metrics/system.go
@@ -60,6 +60,7 @@ func GetSystemMetrics() {
Period: time.Second * 30,
Label: "CPU " + strconv.Itoa(i),
AggloType: "avg",
+ Unit: "%",
})
}
}
@@ -78,6 +79,7 @@ func GetSystemMetrics() {
Period: time.Second * 30,
Label: "RAM",
AggloType: "avg",
+ Unit: "B",
})
// Get Network Usage
@@ -92,65 +94,40 @@ func GetSystemMetrics() {
Max: 0,
Period: time.Second * 30,
Label: "Network Received",
- AggloType: "avg",
+ SetOperation: "max",
+ AggloType: "sum",
+ Decumulate: true,
+ Unit: "B",
})
PushSetMetric("system.netTx", int(netIO[0].BytesSent), DataDef{
Max: 0,
Period: time.Second * 30,
Label: "Network Sent",
- AggloType: "avg",
+ SetOperation: "max",
+ AggloType: "sum",
+ Decumulate: true,
+ Unit: "B",
})
PushSetMetric("system.netErr", int(netIO[0].Errin + netIO[0].Errout), DataDef{
Max: 0,
Period: time.Second * 30,
Label: "Network Errors",
- AggloType: "avg",
+ SetOperation: "max",
+ AggloType: "sum",
+ Decumulate: true,
})
PushSetMetric("system.netDrop", int(netIO[0].Dropin + netIO[0].Dropout), DataDef{
Max: 0,
Period: time.Second * 30,
Label: "Network Drops",
- AggloType: "avg",
+ SetOperation: "max",
+ AggloType: "sum",
+ Decumulate: true,
})
- // docker stats
- dockerStats, err := docker.StatsAll()
- if err != nil {
- utils.Error("Metrics - Error fetching Docker stats:", err)
- return
- }
-
- for _, ds := range dockerStats {
- PushSetMetric("system.docker.cpu." + ds.Name, int(ds.CPUUsage), DataDef{
- Max: 100,
- Period: time.Second * 30,
- Label: "Docker CPU " + ds.Name,
- AggloType: "avg",
- Scale: 1000,
- })
- PushSetMetric("system.docker.ram." + ds.Name, int(ds.MemUsage), DataDef{
- Max: 100,
- Period: time.Second * 30,
- Label: "Docker RAM " + ds.Name,
- AggloType: "avg",
- })
- PushSetMetric("system.docker.netRx." + ds.Name, int(ds.NetworkRx), DataDef{
- Max: 0,
- Period: time.Second * 30,
- Label: "Docker Network Received " + ds.Name,
- AggloType: "avg",
- })
- PushSetMetric("system.docker.netTx." + ds.Name, int(ds.NetworkTx), DataDef{
- Max: 0,
- Period: time.Second * 30,
- Label: "Docker Network Sent " + ds.Name,
- AggloType: "avg",
- })
- }
-
// Get Disk Usage
parts, err := disk.PartitionsWithContext(ctx, true)
if err != nil {
@@ -202,6 +179,7 @@ func GetSystemMetrics() {
Max: 0,
Period: time.Second * 30,
Label: "Temperature " + temp.SensorKey,
+ Unit: "°C",
})
}
}
@@ -213,4 +191,48 @@ func GetSystemMetrics() {
Label: "Temperature - All",
})
}
+
+
+ // docker stats
+ dockerStats, err := docker.StatsAll()
+ if err != nil {
+ utils.Error("Metrics - Error fetching Docker stats:", err)
+ return
+ }
+
+ for _, ds := range dockerStats {
+ PushSetMetric("system.docker.cpu." + ds.Name, int(ds.CPUUsage), DataDef{
+ Max: 100,
+ Period: time.Second * 30,
+ Label: "Docker CPU " + ds.Name,
+ AggloType: "avg",
+ Scale: 1000,
+ Unit: "%",
+ })
+ PushSetMetric("system.docker.ram." + ds.Name, int(ds.MemUsage), DataDef{
+ Max: 0,
+ Period: time.Second * 30,
+ Label: "Docker RAM " + ds.Name,
+ AggloType: "avg",
+ Unit: "B",
+ })
+ PushSetMetric("system.docker.netRx." + ds.Name, int(ds.NetworkRx), DataDef{
+ Max: 0,
+ Period: time.Second * 30,
+ Label: "Docker Network Received " + ds.Name,
+ SetOperation: "max",
+ AggloType: "sum",
+ Decumulate: true,
+ Unit: "B",
+ })
+ PushSetMetric("system.docker.netTx." + ds.Name, int(ds.NetworkTx), DataDef{
+ Max: 0,
+ Period: time.Second * 30,
+ Label: "Docker Network Sent " + ds.Name,
+ SetOperation: "max",
+ AggloType: "sum",
+ Decumulate: true,
+ Unit: "B",
+ })
+ }
}
\ No newline at end of file
diff --git a/src/utils/types.go b/src/utils/types.go
index 4eec5a5..9930af2 100644
--- a/src/utils/types.go
+++ b/src/utils/types.go
@@ -91,6 +91,7 @@ type Config struct {
HomepageConfig HomepageConfig
ThemeConfig ThemeConfig
ConstellationConfig ConstellationConfig
+ MonitoringDisabled bool
}
type HomepageConfig struct {