mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-19 18:56:48 +02:00
time calculation & cleanup
This commit is contained in:
parent
9402c0fa00
commit
804bb39f52
2 changed files with 25 additions and 81 deletions
|
@ -263,50 +263,43 @@ router.get("/api/status-page/:slug/badge", cache("5 minutes"), async (request, r
|
|||
* @returns {Promise<Array>} Array of aggregated heartbeat data
|
||||
*/
|
||||
async function getAggregatedHeartbeats(uptimeCalculator, days) {
|
||||
const targetBuckets = 100; // Always show ~100 buckets for consistent display
|
||||
const now = dayjs.utc();
|
||||
const result = [];
|
||||
|
||||
// Calculate the actual time range we have
|
||||
const startTime = now.subtract(days, "day").startOf("minute");
|
||||
const endTime = now;
|
||||
const totalMinutes = endTime.diff(startTime, "minute");
|
||||
|
||||
// Calculate how many buckets we can actually show (max 100)
|
||||
const targetBuckets = Math.min(100, totalMinutes);
|
||||
const bucketSizeMinutes = Math.max(1, Math.floor(totalMinutes / targetBuckets));
|
||||
|
||||
// Determine data granularity based on days
|
||||
let dataPoints;
|
||||
let granularity;
|
||||
let bucketSizeMinutes;
|
||||
|
||||
if (days <= 1) {
|
||||
// For 1 day or less, use minutely data
|
||||
granularity = "minute";
|
||||
dataPoints = uptimeCalculator.getDataArray(days * 24 * 60, granularity);
|
||||
bucketSizeMinutes = Math.max(1, Math.floor((days * 24 * 60) / targetBuckets));
|
||||
} else if (days <= 30) {
|
||||
// For 2-30 days, use hourly data
|
||||
granularity = "hour";
|
||||
dataPoints = uptimeCalculator.getDataArray(days * 24, granularity);
|
||||
bucketSizeMinutes = Math.max(60, Math.floor((days * 24 * 60) / targetBuckets));
|
||||
} else {
|
||||
// For 31+ days, use daily data
|
||||
granularity = "day";
|
||||
dataPoints = uptimeCalculator.getDataArray(days, granularity);
|
||||
bucketSizeMinutes = Math.max(1440, Math.floor((days * 24 * 60) / targetBuckets));
|
||||
}
|
||||
|
||||
// Create time buckets
|
||||
const startTime = now.subtract(days, "day").startOf("minute");
|
||||
const endTime = now;
|
||||
const buckets = [];
|
||||
const actualBuckets = Math.floor(totalMinutes / bucketSizeMinutes);
|
||||
|
||||
for (let i = 0; i < targetBuckets; i++) {
|
||||
for (let i = 0; i < actualBuckets; i++) {
|
||||
const bucketStart = startTime.add(i * bucketSizeMinutes, "minute");
|
||||
let bucketEnd = bucketStart.add(bucketSizeMinutes, "minute");
|
||||
|
||||
// Don't create buckets that start after current time
|
||||
if (bucketStart.isAfter(endTime)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Ensure bucket doesn't extend beyond current time
|
||||
if (bucketEnd.isAfter(endTime)) {
|
||||
bucketEnd = endTime;
|
||||
}
|
||||
const bucketEnd = bucketStart.add(bucketSizeMinutes, "minute");
|
||||
|
||||
buckets.push({
|
||||
start: bucketStart.unix(),
|
||||
|
@ -374,29 +367,6 @@ async function getAggregatedHeartbeats(uptimeCalculator, days) {
|
|||
});
|
||||
}
|
||||
|
||||
// Ensure we always return targetBuckets number of items by padding at the start
|
||||
while (result.length < targetBuckets) {
|
||||
const firstStartTime = result.length > 0 ? dayjs(result[0]._startTime || result[0].time) : now.subtract(days, "day");
|
||||
const paddedStart = firstStartTime.subtract(bucketSizeMinutes, "minute");
|
||||
const paddedEnd = firstStartTime;
|
||||
|
||||
result.unshift({
|
||||
status: null,
|
||||
time: paddedEnd.toISOString(),
|
||||
msg: "",
|
||||
ping: null,
|
||||
_aggregated: true,
|
||||
_startTime: paddedStart.toISOString(),
|
||||
_endTime: paddedEnd.toISOString(),
|
||||
_counts: {
|
||||
up: 0,
|
||||
down: 0,
|
||||
maintenance: 0,
|
||||
pending: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -155,30 +155,24 @@ export default {
|
|||
|
||||
// Always do client-side aggregation using fixed time buckets
|
||||
const now = dayjs();
|
||||
const buckets = [];
|
||||
|
||||
// Use same logic as server-side: 100 buckets
|
||||
const targetBuckets = 100;
|
||||
const days = this.normalizedHeartbeatBarDays;
|
||||
const bucketSizeMinutes = Math.max(1, Math.floor((days * 24 * 60) / targetBuckets));
|
||||
|
||||
// Create time buckets from oldest to newest
|
||||
// Calculate the actual time range
|
||||
const startTime = now.subtract(days, "day").startOf("minute");
|
||||
const endTime = now;
|
||||
const totalMinutes = endTime.diff(startTime, "minute");
|
||||
|
||||
for (let i = 0; i < targetBuckets; i++) {
|
||||
let bucketStart = startTime.add(i * bucketSizeMinutes, "minute");
|
||||
let bucketEnd = bucketStart.add(bucketSizeMinutes, "minute");
|
||||
// Calculate bucket size to fit the display width
|
||||
const targetBuckets = Math.min(this.maxBeat > 0 ? this.maxBeat : 100, totalMinutes);
|
||||
const bucketSizeMinutes = Math.max(1, Math.floor(totalMinutes / targetBuckets));
|
||||
|
||||
// Don't create buckets that start after current time
|
||||
if (bucketStart.isAfter(endTime)) {
|
||||
break;
|
||||
}
|
||||
// Create time buckets
|
||||
const buckets = [];
|
||||
const actualBuckets = Math.floor(totalMinutes / bucketSizeMinutes);
|
||||
|
||||
// Ensure bucket doesn't extend beyond current time
|
||||
if (bucketEnd.isAfter(endTime)) {
|
||||
bucketEnd = endTime;
|
||||
}
|
||||
for (let i = 0; i < actualBuckets; i++) {
|
||||
const bucketStart = startTime.add(i * bucketSizeMinutes, "minute");
|
||||
const bucketEnd = bucketStart.add(bucketSizeMinutes, "minute");
|
||||
|
||||
buckets.push({
|
||||
start: bucketStart,
|
||||
|
@ -225,26 +219,6 @@ export default {
|
|||
}
|
||||
});
|
||||
|
||||
// Ensure we always return targetBuckets number of items by padding at the start
|
||||
while (buckets.length < targetBuckets) {
|
||||
const firstStart = buckets.length > 0 ? buckets[0].start : now.subtract(days, "day");
|
||||
const paddedStart = firstStart.subtract(bucketSizeMinutes, "minute");
|
||||
const paddedEnd = firstStart;
|
||||
|
||||
buckets.unshift({
|
||||
start: paddedStart,
|
||||
end: paddedEnd,
|
||||
beats: [],
|
||||
status: null,
|
||||
time: paddedEnd.toISOString()
|
||||
});
|
||||
}
|
||||
|
||||
// Limit to maxBeat for display
|
||||
if (buckets.length > this.maxBeat) {
|
||||
return buckets.slice(buckets.length - this.maxBeat);
|
||||
}
|
||||
|
||||
return buckets;
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue