mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-27 16:54:04 +00:00
Feat: Handle maintenance in UptimeCalculator
(#4406)
Co-authored-by: Frank Elsinga <frank@elsinga.de>
This commit is contained in:
parent
49b6dacb4d
commit
b8858f4605
2 changed files with 94 additions and 18 deletions
26
db/knex_migrations/2024-01-22-0000-stats-extras.js
Normal file
26
db/knex_migrations/2024-01-22-0000-stats-extras.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.alterTable("stat_daily", function (table) {
|
||||||
|
table.text("extras").defaultTo(null).comment("Extra statistics during this time period");
|
||||||
|
})
|
||||||
|
.alterTable("stat_minutely", function (table) {
|
||||||
|
table.text("extras").defaultTo(null).comment("Extra statistics during this time period");
|
||||||
|
})
|
||||||
|
.alterTable("stat_hourly", function (table) {
|
||||||
|
table.text("extras").defaultTo(null).comment("Extra statistics during this time period");
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.alterTable("stat_daily", function (table) {
|
||||||
|
table.dropColumn("extras");
|
||||||
|
})
|
||||||
|
.alterTable("stat_minutely", function (table) {
|
||||||
|
table.dropColumn("extras");
|
||||||
|
})
|
||||||
|
.alterTable("stat_hourly", function (table) {
|
||||||
|
table.dropColumn("extras");
|
||||||
|
});
|
||||||
|
};
|
|
@ -116,14 +116,23 @@ class UptimeCalculator {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for (let bean of minutelyStatBeans) {
|
for (let bean of minutelyStatBeans) {
|
||||||
let key = bean.timestamp;
|
let data = {
|
||||||
this.minutelyUptimeDataList.push(key, {
|
|
||||||
up: bean.up,
|
up: bean.up,
|
||||||
down: bean.down,
|
down: bean.down,
|
||||||
avgPing: bean.ping,
|
avgPing: bean.ping,
|
||||||
minPing: bean.pingMin,
|
minPing: bean.pingMin,
|
||||||
maxPing: bean.pingMax,
|
maxPing: bean.pingMax,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (bean.extras != null) {
|
||||||
|
data = {
|
||||||
|
...data,
|
||||||
|
...JSON.parse(bean.extras),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let key = bean.timestamp;
|
||||||
|
this.minutelyUptimeDataList.push(key, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load hourly data from database (recent 30 days only)
|
// Load hourly data from database (recent 30 days only)
|
||||||
|
@ -133,14 +142,22 @@ class UptimeCalculator {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for (let bean of hourlyStatBeans) {
|
for (let bean of hourlyStatBeans) {
|
||||||
let key = bean.timestamp;
|
let data = {
|
||||||
this.hourlyUptimeDataList.push(key, {
|
|
||||||
up: bean.up,
|
up: bean.up,
|
||||||
down: bean.down,
|
down: bean.down,
|
||||||
avgPing: bean.ping,
|
avgPing: bean.ping,
|
||||||
minPing: bean.pingMin,
|
minPing: bean.pingMin,
|
||||||
maxPing: bean.pingMax,
|
maxPing: bean.pingMax,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (bean.extras != null) {
|
||||||
|
data = {
|
||||||
|
...data,
|
||||||
|
...JSON.parse(bean.extras),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hourlyUptimeDataList.push(bean.timestamp, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load daily data from database (recent 365 days only)
|
// Load daily data from database (recent 365 days only)
|
||||||
|
@ -150,14 +167,22 @@ class UptimeCalculator {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for (let bean of dailyStatBeans) {
|
for (let bean of dailyStatBeans) {
|
||||||
let key = bean.timestamp;
|
let data = {
|
||||||
this.dailyUptimeDataList.push(key, {
|
|
||||||
up: bean.up,
|
up: bean.up,
|
||||||
down: bean.down,
|
down: bean.down,
|
||||||
avgPing: bean.ping,
|
avgPing: bean.ping,
|
||||||
minPing: bean.pingMin,
|
minPing: bean.pingMin,
|
||||||
maxPing: bean.pingMax,
|
maxPing: bean.pingMax,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (bean.extras != null) {
|
||||||
|
data = {
|
||||||
|
...data,
|
||||||
|
...JSON.parse(bean.extras),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dailyUptimeDataList.push(bean.timestamp, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,11 +195,6 @@ class UptimeCalculator {
|
||||||
async update(status, ping = 0) {
|
async update(status, ping = 0) {
|
||||||
let date = this.getCurrentDate();
|
let date = this.getCurrentDate();
|
||||||
|
|
||||||
// Don't count MAINTENANCE into uptime
|
|
||||||
if (status === MAINTENANCE) {
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
let flatStatus = this.flatStatus(status);
|
let flatStatus = this.flatStatus(status);
|
||||||
|
|
||||||
if (flatStatus === DOWN && ping > 0) {
|
if (flatStatus === DOWN && ping > 0) {
|
||||||
|
@ -189,7 +209,12 @@ class UptimeCalculator {
|
||||||
let hourlyData = this.hourlyUptimeDataList[hourlyKey];
|
let hourlyData = this.hourlyUptimeDataList[hourlyKey];
|
||||||
let dailyData = this.dailyUptimeDataList[dailyKey];
|
let dailyData = this.dailyUptimeDataList[dailyKey];
|
||||||
|
|
||||||
if (flatStatus === UP) {
|
if (status === MAINTENANCE) {
|
||||||
|
minutelyData.maintenance = minutelyData.maintenance ? minutelyData.maintenance + 1 : 1;
|
||||||
|
hourlyData.maintenance = hourlyData.maintenance ? hourlyData.maintenance + 1 : 1;
|
||||||
|
dailyData.maintenance = dailyData.maintenance ? dailyData.maintenance + 1 : 1;
|
||||||
|
|
||||||
|
} else if (flatStatus === UP) {
|
||||||
minutelyData.up += 1;
|
minutelyData.up += 1;
|
||||||
hourlyData.up += 1;
|
hourlyData.up += 1;
|
||||||
dailyData.up += 1;
|
dailyData.up += 1;
|
||||||
|
@ -233,7 +258,7 @@ class UptimeCalculator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else if (flatStatus === DOWN) {
|
||||||
minutelyData.down += 1;
|
minutelyData.down += 1;
|
||||||
hourlyData.down += 1;
|
hourlyData.down += 1;
|
||||||
dailyData.down += 1;
|
dailyData.down += 1;
|
||||||
|
@ -263,6 +288,13 @@ class UptimeCalculator {
|
||||||
dailyStatBean.ping = dailyData.avgPing;
|
dailyStatBean.ping = dailyData.avgPing;
|
||||||
dailyStatBean.pingMin = dailyData.minPing;
|
dailyStatBean.pingMin = dailyData.minPing;
|
||||||
dailyStatBean.pingMax = dailyData.maxPing;
|
dailyStatBean.pingMax = dailyData.maxPing;
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const { up, down, avgPing, minPing, maxPing, ...extras } = dailyData;
|
||||||
|
if (Object.keys(extras).length > 0) {
|
||||||
|
dailyStatBean.extras = JSON.stringify(extras);
|
||||||
|
}
|
||||||
|
}
|
||||||
await R.store(dailyStatBean);
|
await R.store(dailyStatBean);
|
||||||
|
|
||||||
let hourlyStatBean = await this.getHourlyStatBean(hourlyKey);
|
let hourlyStatBean = await this.getHourlyStatBean(hourlyKey);
|
||||||
|
@ -271,6 +303,13 @@ class UptimeCalculator {
|
||||||
hourlyStatBean.ping = hourlyData.avgPing;
|
hourlyStatBean.ping = hourlyData.avgPing;
|
||||||
hourlyStatBean.pingMin = hourlyData.minPing;
|
hourlyStatBean.pingMin = hourlyData.minPing;
|
||||||
hourlyStatBean.pingMax = hourlyData.maxPing;
|
hourlyStatBean.pingMax = hourlyData.maxPing;
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const { up, down, avgPing, minPing, maxPing, ...extras } = hourlyData;
|
||||||
|
if (Object.keys(extras).length > 0) {
|
||||||
|
hourlyStatBean.extras = JSON.stringify(extras);
|
||||||
|
}
|
||||||
|
}
|
||||||
await R.store(hourlyStatBean);
|
await R.store(hourlyStatBean);
|
||||||
|
|
||||||
let minutelyStatBean = await this.getMinutelyStatBean(divisionKey);
|
let minutelyStatBean = await this.getMinutelyStatBean(divisionKey);
|
||||||
|
@ -279,6 +318,13 @@ class UptimeCalculator {
|
||||||
minutelyStatBean.ping = minutelyData.avgPing;
|
minutelyStatBean.ping = minutelyData.avgPing;
|
||||||
minutelyStatBean.pingMin = minutelyData.minPing;
|
minutelyStatBean.pingMin = minutelyData.minPing;
|
||||||
minutelyStatBean.pingMax = minutelyData.maxPing;
|
minutelyStatBean.pingMax = minutelyData.maxPing;
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const { up, down, avgPing, minPing, maxPing, ...extras } = minutelyData;
|
||||||
|
if (Object.keys(extras).length > 0) {
|
||||||
|
minutelyStatBean.extras = JSON.stringify(extras);
|
||||||
|
}
|
||||||
|
}
|
||||||
await R.store(minutelyStatBean);
|
await R.store(minutelyStatBean);
|
||||||
|
|
||||||
// Remove the old data
|
// Remove the old data
|
||||||
|
@ -474,7 +520,7 @@ class UptimeCalculator {
|
||||||
flatStatus(status) {
|
flatStatus(status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case UP:
|
case UP:
|
||||||
// case MAINTENANCE:
|
case MAINTENANCE:
|
||||||
return UP;
|
return UP;
|
||||||
case DOWN:
|
case DOWN:
|
||||||
case PENDING:
|
case PENDING:
|
||||||
|
@ -606,7 +652,11 @@ class UptimeCalculator {
|
||||||
avgPing = totalPing / total.up;
|
avgPing = totalPing / total.up;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (total.up + total.down === 0) {
|
||||||
|
uptimeData.uptime = 0;
|
||||||
|
} else {
|
||||||
uptimeData.uptime = total.up / (total.up + total.down);
|
uptimeData.uptime = total.up / (total.up + total.down);
|
||||||
|
}
|
||||||
uptimeData.avgPing = avgPing;
|
uptimeData.avgPing = avgPing;
|
||||||
return uptimeData;
|
return uptimeData;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue