Show text on when last data point was added for chart

This commit is contained in:
Joshen Lim committed 2023-05-03 18:50:37 +08:00
1 parent 3b0f0766ce
commit 010903fd26
10 files changed
+153 -33

No files matched your search

@@ -8,6 +8,7 @@ import {
UsageMetric,
useProjectUsageQuery,
} from 'data/usage/project-usage-query'
import dayjs from 'dayjs'
import { Button, IconAlertTriangle } from 'ui'
import { USAGE_APPROACHING_THRESHOLD } from '../Billing.constants'
import BarChart from './BarChart'
@@ -84,31 +85,37 @@ const Activity = ({ projectRef }: ActivityProps) => {
monthly_active_users: {
isLoading: isLoadingMauData,
data: mauData?.data ?? [],
showLastUpdated: mauData?.hasNoData === false,
margin: 18,
},
monthly_active_sso_users: {
isLoading: isLoadingMauSSOData,
data: mauSSOData?.data ?? [],
showLastUpdated: mauSSOData?.hasNoData === false,
margin: 20,
},
storage_image_render_count: {
isLoading: isLoadingAssetTransformationsData,
data: assetTransformationsData?.data ?? [],
showLastUpdated: assetTransformationsData?.hasNoData === false,
margin: 0,
},
func_invocations: {
isLoading: isLoadingFuncInvocationsData,
data: funcInvocationsData?.data ?? [],
showLastUpdated: funcInvocationsData?.hasNoData === false,
margin: 26,
},
realtime_message_count: {
isLoading: isLoadingRealtimeMessagesData,
data: realtimeMessagesData?.data ?? [],
showLastUpdated: realtimeMessagesData?.hasNoData === false,
margin: 38,
},
realtime_peak_connection: {
isLoading: isLoadingRealtimeConnectionsData,
data: realtimeConnectionsData?.data ?? [],
showLastUpdated: realtimeConnectionsData?.hasNoData === false,
margin: 0,
},
}
@@ -125,6 +132,19 @@ const Activity = ({ projectRef }: ActivityProps) => {
typeof usageMeta !== 'number' ? (usageMeta?.usage ?? 0) / (usageMeta?.limit ?? 0) : 0
const usageExcess = (usageMeta?.usage ?? 0) - (usageMeta?.limit ?? 0)
const chartData = chartMeta[attribute.key]?.data ?? []
// [Joshen] Ideally this should come from the API imo, foresee some discrepancies
const lastZeroValue = chartData.find(
(x: any) => x.loopId > 0 && x[attribute.attribute] === 0
)
const lastKnownValue =
lastZeroValue !== undefined
? dayjs(lastZeroValue.period_start)
.subtract(1, 'day')
.format('DD MMM YYYY, HH:mma (ZZ)')
: undefined
return (
<SectionContent
key={attribute.key}
@@ -195,7 +215,16 @@ const Activity = ({ projectRef }: ActivityProps) => {
<>
<div className="space-y-1">
<p>{attribute.name} over time</p>
<p className="text-sm text-scale-1000">{attribute.chartDescription}</p>
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
<p key={`para-${idx}`} className="text-sm text-scale-1000">
{paragraph}
</p>
))}
{lastKnownValue !== undefined && chartMeta[attribute.key].showLastUpdated && (
<span className="text-sm text-scale-1000">
Last updated at: {lastKnownValue}
</span>
)}
</div>
{chartMeta[attribute.key].isLoading ? (
<div className="space-y-2">
@@ -207,7 +236,7 @@ const Activity = ({ projectRef }: ActivityProps) => {
<BarChart
hasQuota
attribute={attribute.attribute}
data={chartMeta[attribute.key]?.data ?? []}
data={chartData}
yLimit={usageMeta?.limit ?? 0}
yLeftMargin={chartMeta[attribute.key].margin}
yFormatter={(value) => value.toLocaleString()}
@@ -8,6 +8,7 @@ import {
UsageMetric,
useProjectUsageQuery,
} from 'data/usage/project-usage-query'
import dayjs from 'dayjs'
import { USAGE_APPROACHING_THRESHOLD } from 'lib/constants'
import { formatBytes } from 'lib/helpers'
import { Button, IconAlertTriangle } from 'ui'
@@ -45,8 +46,16 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {
})
const chartMeta: any = {
db_egress: { isLoading: isLoadingDbEgressData, data: dbEgressData?.data ?? [] },
storage_egress: { isLoading: isLoadingStorageEgressData, data: storageEgressData?.data ?? [] },
db_egress: {
isLoading: isLoadingDbEgressData,
data: dbEgressData?.data ?? [],
showLastUpdated: dbEgressData?.hasNoData === false,
},
storage_egress: {
isLoading: isLoadingStorageEgressData,
data: storageEgressData?.data ?? [],
showLastUpdated: storageEgressData?.hasNoData === false,
},
}
if (categoryMeta === undefined) return null
@@ -61,6 +70,19 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {
typeof usageMeta !== 'number' ? (usageMeta?.usage ?? 0) / (usageMeta?.limit ?? 0) : 0
const usageExcess = (usageMeta?.usage ?? 0) - (usageMeta?.limit ?? 0)
const chartData = chartMeta[attribute.key]?.data ?? []
// [Joshen] Ideally this should come from the API imo, foresee some discrepancies
const lastZeroValue = chartData.find(
(x: any) => x.loopId > 0 && x[attribute.attribute] === 0
)
const lastKnownValue =
lastZeroValue !== undefined
? dayjs(lastZeroValue.period_start)
.subtract(1, 'day')
.format('DD MMM YYYY, HH:mma (ZZ)')
: undefined
return (
<SectionContent key={attribute.key} section={attribute}>
<div className="space-y-2">
@@ -118,7 +140,14 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {
</div>
<div className="space-y-1">
<p>{attribute.name} over time</p>
<p className="text-sm text-scale-1000">{attribute.chartDescription}</p>
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
<p key={`para-${idx}`} className="text-sm text-scale-1000">
{paragraph}
</p>
))}
{lastKnownValue !== undefined && chartMeta[attribute.key].showLastUpdated && (
<span className="text-sm text-scale-1000">Last updated at: {lastKnownValue}</span>
)}
</div>
{chartMeta[attribute.key]?.isLoading ? (
<div className="space-y-2">
@@ -130,7 +159,7 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {
<BarChart
hasQuota
attribute={attribute.attribute}
data={chartMeta[attribute.key]?.data ?? []}
data={chartData}
yLimit={usageMeta?.limit ?? 0}
yLeftMargin={14}
yFormatter={(value) => formatBytes(value, 1, 'GB').replace(/\s/g, '')}
@@ -1,14 +1,13 @@
import { DataPoint } from 'data/analytics/constants'
import {
ResponsiveContainer,
ComposedChart,
CartesianGrid,
YAxis,
XAxis,
Bar,
ReferenceLine,
CartesianGrid,
Cell,
Label,
ComposedChart,
ReferenceLine,
ResponsiveContainer,
XAxis,
YAxis,
} from 'recharts'
import { Y_DOMAIN_CEILING_MULTIPLIER } from './Usage.constants'
@@ -50,7 +49,7 @@ const BarChart = ({
<ResponsiveContainer width="100%" height={200}>
<ComposedChart data={data} margin={{ top: 0, right: 0, left: yLeftMargin, bottom: 0 }}>
<CartesianGrid vertical={false} strokeDasharray="3 3" className="stroke-scale-800" />
<XAxis dataKey="period_start" />
<XAxis dataKey="periodStartFormatted" />
<YAxis
width={28}
axisLine={false}
@@ -1,6 +1,7 @@
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { useInfraMonitoringQuery } from 'data/analytics/infra-monitoring-query'
import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query'
import dayjs from 'dayjs'
import BarChart from './BarChart'
import SectionContent from './SectionContent'
import SectionHeader from './SectionHeader'
@@ -44,9 +45,18 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
})
const chartMeta: any = {
cpu_usage: { isLoading: isLoadingCpuUsageData, data: cpuUsageData?.data ?? [] },
ram_usage: { isLoading: isLoadingMemoryUsageData, data: memoryUsageData?.data ?? [] },
disk_io_budget: { isLoading: isLoadingIoBudgetData, data: ioBudgetData?.data ?? [] },
cpu_usage: {
isLoading: isLoadingCpuUsageData,
data: cpuUsageData?.data ?? [],
},
ram_usage: {
isLoading: isLoadingMemoryUsageData,
data: memoryUsageData?.data ?? [],
},
disk_io_budget: {
isLoading: isLoadingIoBudgetData,
data: ioBudgetData?.data ?? [],
},
}
if (categoryMeta === undefined) return null
@@ -55,6 +65,19 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
<>
<SectionHeader title="Infrastructure" description="Some description here" />
{categoryMeta.attributes.map((attribute) => {
const chartData = chartMeta[attribute.key]?.data ?? []
// [Joshen] Ideally this should come from the API imo, foresee some discrepancies
const lastZeroValue = chartData.find(
(x: any) => x.loopId > 0 && x[attribute.attribute] === 0
)
const lastKnownValue =
lastZeroValue !== undefined
? dayjs(lastZeroValue.period_start)
.subtract(1, 'day')
.format('DD MMM YYYY, HH:mma (ZZ)')
: undefined
return (
<SectionContent key={attribute.key} section={attribute}>
<div className="space-y-1">
@@ -74,6 +97,9 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
{paragraph}
</p>
))}
{lastKnownValue !== undefined && (
<span className="text-sm text-scale-1000">Last updated at: {lastKnownValue}</span>
)}
</div>
{chartMeta[attribute.key].isLoading ? (
<div className="space-y-2">
@@ -84,7 +110,7 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
) : (
<BarChart
attribute={attribute.attribute}
data={chartMeta[attribute.key]?.data ?? []}
data={chartData}
yFormatter={(value) => `${value}%`}
yLimit={100}
/>
@@ -8,6 +8,7 @@ import {
UsageMetric,
useProjectUsageQuery,
} from 'data/usage/project-usage-query'
import dayjs from 'dayjs'
import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants'
import { formatBytes } from 'lib/helpers'
import Link from 'next/link'
@@ -55,9 +56,21 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {
})
const chartMeta: any = {
db_size: { isLoading: isLoadingDbSizeData, data: dbSizeData?.data ?? [] },
storage_size: { isLoading: isLoadingStorageSizeData, data: storageSizeData?.data ?? [] },
func_count: { isLoading: isLoadingFunctionCountData, data: functionCountData?.data ?? [] },
db_size: {
isLoading: isLoadingDbSizeData,
data: dbSizeData?.data ?? [],
showLastUpdated: dbSizeData?.hasNoData === false,
},
storage_size: {
isLoading: isLoadingStorageSizeData,
data: storageSizeData?.data ?? [],
showLastUpdated: storageSizeData?.hasNoData === false,
},
func_count: {
isLoading: isLoadingFunctionCountData,
data: functionCountData?.data ?? [],
showLastUpdated: functionCountData?.hasNoData === false,
},
}
if (categoryMeta === undefined) return null
@@ -72,6 +85,19 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {
typeof usageMeta !== 'number' ? (usageMeta?.usage ?? 0) / (usageMeta?.limit ?? 0) : 0
const usageExcess = (usageMeta?.usage ?? 0) - (usageMeta?.limit ?? 0)
const chartData = chartMeta[attribute.key]?.data ?? []
// [Joshen] Ideally this should come from the API imo, foresee some discrepancies
const lastZeroValue = chartData.find(
(x: any) => x.loopId > 0 && x[attribute.attribute] === 0
)
const lastKnownValue =
lastZeroValue !== undefined
? dayjs(lastZeroValue.period_start)
.subtract(1, 'day')
.format('DD MMM YYYY, HH:mma (ZZ)')
: undefined
return (
<SectionContent key={attribute.key} section={attribute}>
<div className="space-y-2">
@@ -164,7 +190,14 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {
<div className="space-y-1">
<p>{attribute.name} over time</p>
<p className="text-sm text-scale-1000">{attribute.chartDescription}</p>
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
<p key={`para-${idx}`} className="text-sm text-scale-1000">
{paragraph}
</p>
))}
{lastKnownValue !== undefined && chartMeta[attribute.key].showLastUpdated && (
<span className="text-sm text-scale-1000">Last updated at: {lastKnownValue}</span>
)}
</div>
{chartMeta[attribute.key].isLoading ? (
<div className="space-y-2">
@@ -176,7 +209,7 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {
<BarChart
hasQuota
attribute={attribute.attribute}
data={chartMeta[attribute.key]?.data ?? []}
data={chartData}
yLimit={usageMeta?.limit ?? 0}
yLeftMargin={14}
yFormatter={(value) =>
@@ -49,7 +49,7 @@ export const USAGE_CATEGORIES: {
description:
'SSD Disks are attached to your servers and the disk performance of your workload is determined by the Disk IO bandwidth of this connection.',
chartDescription:
'If the remaining bandwidth is less than 100%, it indicates that your workload has burst beyond the baseline IO throughput during the day.\nIf this metric drops to zero, the workload has used up all the burst IO throughput minutes during the day and is running at the baseline performance.\nThe amount of remaining bandwidth resets at the beginning of each day, and the data shown here is refreshed over a period of 24 hours.',
'The amount of remaining bandwidth resets at the beginning of each day, and the data shown here is refreshed over a period of 24 hours.',
},
],
},
@@ -3,6 +3,7 @@ import { useParams } from 'common'
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { useProjectsQuery } from 'data/projects/projects-query'
import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query'
import { useProjectUsageQuery } from 'data/usage/project-usage-query'
import Link from 'next/link'
import { useRef, useState } from 'react'
import { Button, IconAlertCircle, IconCheckCircle, IconLoader, Listbox } from 'ui'
@@ -10,9 +11,8 @@ import Activity from './Activity'
import Bandwidth from './Bandwidth'
import Infrastructure from './Infrastructure'
import SizeAndCounts from './SizeAndCounts'
import { useProjectUsageQuery } from 'data/usage/project-usage-query'
import { getUsageStatus } from './Usage.utils'
import { USAGE_CATEGORIES, USAGE_STATUS } from './Usage.constants'
import { getUsageStatus } from './Usage.utils'
const Usage = () => {
const { ref } = useParams()
+2
View File
@@ -1,6 +1,7 @@
export type DataPoint = {
loopId: number | string
period_start: string
periodStartFormatted?: string
} & {
// Attribute name will be the key
[key: string]: string
@@ -12,4 +13,5 @@ export interface AnalyticsData {
total: number
totalAverage: number
yAxisLimit: number
hasNoData?: boolean
}
+6 -4
View File
@@ -1,10 +1,10 @@
import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query'
import dayjs from 'dayjs'
import { get } from 'lib/common/fetch'
import { API_URL } from 'lib/constants'
import { useCallback } from 'react'
import { analyticsKeys } from './keys'
import { AnalyticsData } from './constants'
import dayjs from 'dayjs'
import { analyticsKeys } from './keys'
export type DailyStatsVariables = {
projectRef?: string
@@ -141,19 +141,21 @@ export const useDailyStatsQuery = <TData = DailyStatsData>(
return {
loopId: idx,
period_start: dayjs(startDate).add(idx, 'day').format(dateFormat),
periodStartFormatted: dayjs(startDate).add(idx, 'day').format(dateFormat),
[attribute]: 0,
}
})
return { ...data, data: mockData }
return { ...data, data: mockData, hasNoData: true }
} else {
return {
...data,
hasNoData: false,
data: data.data.map((x) => {
return {
...x,
[attribute]:
modifier !== undefined ? modifier(Number(x[attribute])) : Number(x[attribute]),
period_start:
periodStartFormatted:
Number(x.period_start) > 0
? dayjs(x.period_start).format(dateFormat)
: x.period_start,
@@ -1,10 +1,10 @@
import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query'
import dayjs from 'dayjs'
import { get } from 'lib/common/fetch'
import { API_URL } from 'lib/constants'
import { useCallback } from 'react'
import { analyticsKeys } from './keys'
import { AnalyticsData } from './constants'
import dayjs from 'dayjs'
import { analyticsKeys } from './keys'
export type InfraMonitoringVariables = {
projectRef?: string
@@ -73,7 +73,7 @@ export const useInfraMonitoringQuery = <TData = InfraMonitoringData>(
...x,
[attribute]:
modifier !== undefined ? modifier(Number(x[attribute])) : Number(x[attribute]),
period_start: dayjs(x.period_start).format(dateFormat),
periodStartFormatted: dayjs(x.period_start).format(dateFormat),
}
}),
}