mirror of
https://github.com/supabase/supabase.git
synced 2026-07-03 00:24:25 +08:00
- 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 -->
89 lines
2.6 KiB
TypeScript
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
|
|
}
|