[release] v0.12.0-unstable5

This commit is contained in:
Yann Stepienik 2023-10-28 13:44:14 +01:00
parent 8a547e1b9c
commit 33590ce369
8 changed files with 147 additions and 111 deletions

View file

@ -1,3 +1,8 @@
## Version 0.12.0
- New Dashboard
- New metrics gathering system
- Added Button to force reset HTTPS cert in settings
## Version 0.11.3
- Fix missing even subscriber on export

View file

@ -687,6 +687,15 @@ const ConfigManagement = () => {
</Stack>
</Grid>
<Grid item xs={12}>
<CosmosCheckbox
label={"Force HTTPS Certificate Renewal On Next Save"}
name="ForceHTTPSCertificateRenewal"
formik={formik}
/>
</Grid>
</Grid>
</MainCard>

View file

@ -45,9 +45,12 @@ function toUTC(date, time) {
return formatDate(now, time);
}
const PlotComponent = ({ data, defaultSlot = 'day' }) => {
const PlotComponent = ({ title, data, defaultSlot = 'latest' }) => {
const [slot, setSlot] = useState(defaultSlot);
const theme = useTheme();
const { primary, secondary } = theme.palette.text;
const line = theme.palette.divider;
const [series, setSeries] = useState([]);
// chart options
const areaChartOptions = {
@ -69,116 +72,108 @@ const PlotComponent = ({ data, defaultSlot = 'day' }) => {
strokeDashArray: 0
}
};
let hourlyDates = [];
for(let i = 0; i < 48; i++) {
let now = new Date();
now.setHours(now.getHours() - i);
now.setMinutes(0);
now.setSeconds(0);
// get as YYYY-MM-DD HH:MM:SS
hourlyDates.unshift(formatDate(now, true));
}
let dailyDates = [];
for(let i = 0; i < 30; i++) {
let now = new Date();
now.setDate(now.getDate() - i);
dailyDates.unshift(formatDate(now));
}
const { primary, secondary } = theme.palette.text;
const line = theme.palette.divider;
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));
}
}
const dataSeries = [];
data.forEach((serie) => {
dataSeries.push({
name: serie.Label,
dataAxis: xAxis.map((date) => {
if(slot === 'latest') {
return serie.Values[serie.Values.length - 1 - date] ?
serie.Values[serie.Values.length - 1 - date].Value :
0;
} else {
let key = slot === 'hourly' ? "hour_" : "day_";
let k = key + toUTC(date, slot === 'hourly');
if (k in serie.ValuesAggl) {
return serie.ValuesAggl[k].Value;
} else {
return 0;
}
}
})
});
});
setOptions((prevState) => ({
...prevState,
colors: [theme.palette.primary.main, theme.palette.secondary.main],
xaxis: {
categories:
slot === 'hourly'
? hourlyDates.map((date) => date.split(' ')[1])
: dailyDates,
categories:
slot === 'hourly'
? xAxis.map((date) => date.split(' ')[1])
: xAxis,
labels: {
style: {
fontSize: '11px',
fontSize: slot === 'latest' ? '0' : '11px',
}
},
axisBorder: {
show: true,
color: line
},
tickAmount: slot === 'hourly' ? hourlyDates.length : dailyDates.length,
tickAmount: xAxis.length,
},
yaxis: [{
yaxis: data.map((thisdata, ida) => ({
opposite: ida === 1,
labels: {
style: {
colors: [secondary]
},
formatter: (num) => {
if (Math.abs(num) >= 1e9) {
return (num / 1e9).toFixed(1) + 'G'; // Convert to Millions
} else if (Math.abs(num) >= 1e6) {
return (num / 1e6).toFixed(1) + 'M'; // Convert to Millions
} else if (Math.abs(num) >= 1e3) {
return (num / 1e3).toFixed(1) + 'K'; // Convert to Thousands
} else {
return num.toString();
}
}
},
title: {
text: data[0].Label,
text: thisdata.Label,
}
},
{
opposite: true,
labels: {
style: {
colors: [secondary]
}
},
title: {
text: data[1].Label,
}
}
],
})),
grid: {
borderColor: line
},
tooltip: {
theme: 'light'
theme: theme.palette.mode,
}
}));
}, [primary, secondary, line, theme, slot]);
let dataSeries = [];
data.forEach((serie) => {
dataSeries.push({
name: serie.Label,
dataDaily: dailyDates.map((date) => {
let k = "day_" + toUTC(date);
if (k in serie.ValuesAggl) {
return serie.ValuesAggl[k].Value;
} else {
console.log(k)
return 0;
}
}),
dataHourly: hourlyDates.map((date) => {
let k = "hour_" + toUTC(date, true);
if (k in serie.ValuesAggl) {
return serie.ValuesAggl[k].Value;
} else {
return 0;
}
}),
});
});
const [series, setSeries] = useState(dataSeries.map((serie) => {
return {
name: serie.name,
data: slot === 'hourly' ? serie.dataHourly : serie.dataDaily
}
}));
useEffect(() => {
setSeries(dataSeries.map((serie) => {
return {
name: serie.name,
data: slot === 'hourly' ? serie.dataHourly : serie.dataDaily
data: serie.dataAxis
}
}));
}, [slot, data]);
@ -187,10 +182,18 @@ const PlotComponent = ({ data, defaultSlot = 'day' }) => {
return <Grid item xs={12} md={7} lg={8}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h5">Server Resources</Typography>
<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')}
@ -211,8 +214,8 @@ const PlotComponent = ({ data, defaultSlot = 'day' }) => {
</Grid>
</Grid>
<MainCard content={false} sx={{ mt: 1.5 }}>
<Box sx={{ pt: 1, pr: 2 }} className="force-light">
<ReactApexChart options={options} series={series} type="area" height={450} />;
<Box sx={{ pt: 1, pr: 2 }}>
<ReactApexChart options={options} series={series} type="area" height={450} />
</Box>
</MainCard>
</Grid>

View file

@ -175,7 +175,29 @@ const DashboardDefault = () => {
{/* row 2 */}
<PlotComponent data={[metrics["cosmos.system.cpu.0"], metrics["cosmos.system.ram"]]}/>
<PlotComponent title={'Resources'} data={[metrics["cosmos.system.cpu.0"], metrics["cosmos.system.ram"]]}/>
<Grid item xs={12} md={5} lg={4}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h5">Income Overview</Typography>
</Grid>
<Grid item />
</Grid>
<MainCard sx={{ mt: 2 }} content={false}>
<Box sx={{ p: 3, pb: 0 }}>
<Stack spacing={2}>
<Typography variant="h6" color="textSecondary">
This Week Statistics
</Typography>
<Typography variant="h3">$7,650</Typography>
</Stack>
</Box>
<MonthlyBarChart />
</MainCard>
</Grid>
<PlotComponent title={'Network'} data={[metrics["cosmos.system.netTx"], metrics["cosmos.system.netRx"]]}/>
<Grid item xs={12} md={5} lg={4}>
<Grid container alignItems="center" justifyContent="space-between">
@ -209,6 +231,7 @@ const DashboardDefault = () => {
<OrdersTable />
</MainCard>
</Grid>
<Grid item xs={12} md={5} lg={4}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>

View file

@ -1,6 +1,6 @@
{
"name": "cosmos-server",
"version": "0.12.0-unstable4",
"version": "0.12.0-unstable5",
"description": "",
"main": "test-server.js",
"bugs": {
@ -67,7 +67,7 @@
"start": "env COSMOS_CONFIG_FOLDER=/mnt/e/work/Cosmos-Server/zz_test_config/ CONFIG_FILE=./config_dev.json EZ=UTC ACME_STAGING=true build/cosmos",
"build": "sh build.sh",
"dev": "npm run build && npm run start",
"dockerdevbuild": "sh build.sh && docker build -f dockerfile.local --tag cosmos-dev .",
"dockerdevbuild": "docker build -f dockerfile.local --tag cosmos-dev .",
"dockerdevrun": "docker stop cosmos-dev; docker rm cosmos-dev; docker run --cap-add NET_ADMIN -d -p 7200:443 -p 80:80 -p 53:53 -p 443:443 -p 4242:4242 -e DOCKER_HOST=tcp://host.docker.internal:2375 -e COSMOS_MONGODB=$MONGODB -e COSMOS_LOG_LEVEL=DEBUG -v /:/mnt/host --restart=unless-stopped -h cosmos-dev --name cosmos-dev cosmos-dev",
"dockerdev": "npm run client-build && npm run dockerdevbuild && npm run dockerdevrun",
"demo": "vite build --base=/cosmos-ui/ --mode demo",

View file

@ -31,7 +31,7 @@ type DataDefDB struct {
AggloType string
}
func AggloMetrics() {
func AggloMetrics() []DataDefDB {
lock <- true
defer func() { <-lock }()
@ -42,7 +42,7 @@ func AggloMetrics() {
c, errCo := utils.GetCollection(utils.GetRootAppId(), "metrics")
if errCo != nil {
utils.Error("Metrics - Database Connect", errCo)
return
return []DataDefDB{}
}
// get all metrics from database
@ -50,13 +50,13 @@ func AggloMetrics() {
cursor, err := c.Find(nil, map[string]interface{}{})
if err != nil {
utils.Error("Metrics: Error fetching metrics", err)
return
return []DataDefDB{}
}
defer cursor.Close(nil)
if err = cursor.All(nil, &metrics); err != nil {
utils.Error("Metrics: Error decoding metrics", err)
return
return []DataDefDB{}
}
// populate aggregation pools
@ -153,8 +153,18 @@ func AggloMetrics() {
metrics[metInd] = metric
}
return metrics
}
func CommitAggl(metrics []DataDefDB) {
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
}
// save metrics
for _, metric := range metrics {
options := options.Update().SetUpsert(true)
@ -166,12 +176,18 @@ func AggloMetrics() {
return
}
}
utils.Log("Metrics: Agglomeration saved to DB")
}
func AggloAndCommitMetrics() {
CommitAggl(AggloMetrics())
}
func InitAggl() {
go func() {
s := gocron.NewScheduler()
s.Every(1).Hour().From(gocron.NextTick()).Do(AggloMetrics)
s.Every(1).Hour().From(gocron.NextTick()).Do(AggloAndCommitMetrics)
// s.Every(3).Minute().From(gocron.NextTick()).Do(AggloMetrics)
s.Start()

View file

@ -13,29 +13,9 @@ func API_GetMetrics(w http.ResponseWriter, req *http.Request) {
}
if(req.Method == "GET") {
c, errCo := utils.GetCollection(utils.GetRootAppId(), "metrics")
if errCo != nil {
utils.Error("Metrics - Database Connect", errCo)
return
}
// get all metrics from database
var metrics []DataDefDB
cursor, err := c.Find(nil, map[string]interface{}{})
if err != nil {
utils.Error("Metrics: Error fetching metrics", err)
return
}
defer cursor.Close(nil)
if err = cursor.All(nil, &metrics); err != nil {
utils.Error("Metrics: Error decoding metrics", err)
return
}
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",
"data": metrics,
"data": AggloMetrics(),
})
} else {
utils.Error("SettingGet: Method not allowed" + req.Method, nil)

View file

@ -124,7 +124,7 @@ func GetSystemMetrics() {
}
for _, part := range parts {
if strings.HasPrefix(part.Mountpoint, "/dev") || strings.HasPrefix(part.Mountpoint, "/mnt") {
if strings.HasPrefix(part.Mountpoint, "/dev") || (strings.HasPrefix(part.Mountpoint, "/mnt") && !strings.HasPrefix(part.Mountpoint, "/mnt/host")) {
realMount := part.Mountpoint
if os.Getenv("HOSTANME") != "" {