fix: normalize usage timeline buckets

This commit is contained in:
a.tolmachev
2026-04-01 22:35:45 +03:00
parent b650941c06
commit 3a7348f685
+91 -1
View File
@@ -76,6 +76,96 @@ document.addEventListener('DOMContentLoaded', function () {
return 'Wk ' + (index + 1);
}
function toUtcBucketStart(date, period) {
var bucket = new Date(date.getTime());
bucket.setUTCMilliseconds(0);
bucket.setUTCSeconds(0);
bucket.setUTCMinutes(0);
bucket.setUTCHours(0);
if (period === '30d' || period === 'this_month') {
var day = bucket.getUTCDay();
var offset = day === 0 ? 6 : (day - 1);
bucket.setUTCDate(bucket.getUTCDate() - offset);
return bucket;
}
if (period === '90d') {
bucket.setUTCDate(1);
return bucket;
}
return bucket;
}
function shiftUtcBucket(date, period, amount) {
var shifted = new Date(date.getTime());
if (period === '30d' || period === 'this_month') {
shifted.setUTCDate(shifted.getUTCDate() + (amount * 7));
return shifted;
}
if (period === '90d') {
shifted.setUTCMonth(shifted.getUTCMonth() + amount);
return shifted;
}
shifted.setUTCDate(shifted.getUTCDate() + amount);
return shifted;
}
function bucketKey(date) {
return date.toISOString().slice(0, 19) + 'Z';
}
function expectedBucketCount(period, endBucket) {
if (period === '7d') {
return 7;
}
if (period === '30d') {
return 5;
}
if (period === '90d') {
return 4;
}
if (period === 'this_month') {
var firstDay = new Date(Date.UTC(endBucket.getUTCFullYear(), endBucket.getUTCMonth(), 1));
var firstWeek = toUtcBucketStart(firstDay, period);
var diffMs = endBucket.getTime() - firstWeek.getTime();
return Math.max(1, Math.floor(diffMs / (7 * 24 * 60 * 60 * 1000)) + 1);
}
return 7;
}
function normalizeTimeline(timeline, period) {
if (!timeline.length) {
return [];
}
var byBucket = {};
timeline.forEach(function(point) {
byBucket[point.bucket_start] = point;
});
var latestBucket = timeline.reduce(function(current, point) {
return point.bucket_start > current.bucket_start ? point : current;
}, timeline[0]);
var endBucket = toUtcBucketStart(new Date(latestBucket.bucket_start), period);
var bucketCount = expectedBucketCount(period, endBucket);
var startBucket = shiftUtcBucket(endBucket, period, -(bucketCount - 1));
var normalized = [];
for (var index = 0; index < bucketCount; index += 1) {
var bucketDate = shiftUtcBucket(startBucket, period, index);
var key = bucketKey(bucketDate);
normalized.push(byBucket[key] || {
bucket_start: key,
calls_ok: 0,
calls_error: 0,
});
}
return normalized;
}
function renderEmpty(title, message) {
chartWrap.innerHTML =
'<div class="empty-state" style="width:100%;">' +
@@ -125,7 +215,7 @@ document.addEventListener('DOMContentLoaded', function () {
}
function renderChart() {
var timeline = state.usage ? state.usage.timeline : [];
var timeline = state.usage ? normalizeTimeline(state.usage.timeline || [], state.period) : [];
chartWrap.innerHTML = '';
if (!timeline.length) {