Files
supabase/apps/studio/components/interfaces/HomeNew/ChartDataTransform.utils.ts
Jordi Enric 88ed2aad97 new home: refactor charts to use old sources (#42245)
- refactors new charts in homepage to use stable analytics endpoints
- changes are behind newHomepageUsageV2 flag

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Centralized per-service health metrics hook with per-service data,
loading/error states and refresh.

* **Improvements**
  * Time-series normalization into fixed buckets aligned to an end time.
* Updated UI: success-rate formatting, per-service loading/error
surfaced, refreshed click/refresh behavior; removed delta display.

* **Removals**
  * Legacy project-metrics query and mapping utilities removed.

* **Tests**
* Extensive unit tests added for date ranges, bucket normalization, and
health metric calculations; some obsolete tests removed.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-28 17:02:00 +00:00

89 lines
2.6 KiB
TypeScript

import dayjs from 'dayjs'
import type { LogsBarChartDatum } from './ProjectUsage.metrics'
/**
* Configuration for chart bucket sizes based on time interval
*/
const BUCKET_CONFIG = {
'1hr': {
bucketMinutes: 2, // 2-minute buckets
expectedBuckets: 30, // 60 minutes / 2 = 30 buckets
},
'1day': {
bucketMinutes: 60, // 1-hour buckets
expectedBuckets: 24, // 24 hours
},
'7day': {
bucketMinutes: 360, // 6-hour buckets
expectedBuckets: 28, // 168 hours / 6 = 28 buckets
},
} as const
type IntervalKey = keyof typeof BUCKET_CONFIG
/**
* Normalizes chart data to consistent bucket sizes regardless of backend data density.
*
* For 1hr interval: Creates 30 buckets of 2 minutes each
* For 1day interval: Creates 24 buckets of 1 hour each
* For 7day interval: Creates 28 buckets of 6 hours each
*
* This ensures consistent bar width in charts and proper data aggregation.
*
* @param data - Raw chart data from backend
* @param interval - Time interval key ('1hr', '1day', '7day')
* @param endDate - End date for the chart (defaults to now)
* @returns Array of exactly the expected number of buckets with aggregated data
*/
export function normalizeChartBuckets(
data: LogsBarChartDatum[],
interval: IntervalKey,
endDate: Date = new Date()
): LogsBarChartDatum[] {
const config = BUCKET_CONFIG[interval]
const { bucketMinutes, expectedBuckets } = config
// Calculate start time based on expected buckets
const end = dayjs(endDate)
const start = end.subtract(expectedBuckets * bucketMinutes, 'minute')
// Create empty buckets
const buckets: LogsBarChartDatum[] = []
let currentBucketStart = start
for (let i = 0; i < expectedBuckets; i++) {
buckets.push({
timestamp: currentBucketStart.toISOString(),
ok_count: 0,
warning_count: 0,
error_count: 0,
})
currentBucketStart = currentBucketStart.add(bucketMinutes, 'minute')
}
// If no data, return empty buckets
if (!data || data.length === 0) {
return buckets
}
// Aggregate data into buckets
for (const datum of data) {
const datumTime = dayjs(datum.timestamp)
// Find which bucket this datum belongs to
const bucketIndex = Math.floor(datumTime.diff(start, 'minute') / bucketMinutes)
// Skip data points outside our time range
if (bucketIndex < 0 || bucketIndex >= expectedBuckets) {
continue
}
// Aggregate counts into the appropriate bucket
buckets[bucketIndex].ok_count += datum.ok_count || 0
buckets[bucketIndex].warning_count += datum.warning_count || 0
buckets[bucketIndex].error_count += datum.error_count || 0
}
return buckets
}