|
12 | 12 | */
|
13 | 13 |
|
14 | 14 | import { useQuery } from '@tanstack/react-query'
|
15 |
| -import { Children, useEffect, useMemo, useState, type ReactNode } from 'react' |
| 15 | +import { Children, useMemo, useState, type ReactNode } from 'react' |
16 | 16 | import type { LoaderFunctionArgs } from 'react-router'
|
17 | 17 |
|
18 |
| -import { apiq, queryClient } from '@oxide/api' |
| 18 | +import { apiq, OXQL_GROUP_BY_ERROR, queryClient } from '@oxide/api' |
19 | 19 |
|
20 | 20 | import { CopyCodeModal } from '~/components/CopyCode'
|
21 | 21 | import { MoreActionsMenu } from '~/components/MoreActionsMenu'
|
22 | 22 | import { getInstanceSelector, useProjectSelector } from '~/hooks/use-params'
|
23 |
| -import { useMetricsContext } from '~/pages/project/instances/common' |
24 | 23 | import { LearnMore } from '~/ui/lib/CardBlock'
|
25 | 24 | import * as Dropdown from '~/ui/lib/DropdownMenu'
|
26 | 25 | import { classed } from '~/util/classed'
|
@@ -51,23 +50,34 @@ export type OxqlMetricProps = OxqlQuery & {
|
51 | 50 | }
|
52 | 51 |
|
53 | 52 | export function OxqlMetric({ title, description, unit, ...queryObj }: OxqlMetricProps) {
|
54 |
| - // only start reloading data once an intial dataset has been loaded |
55 |
| - const { setIsIntervalPickerEnabled } = useMetricsContext() |
56 |
| - const { project } = useProjectSelector() |
57 | 53 | const query = toOxqlStr(queryObj)
|
58 |
| - const { data: metrics, error } = useQuery( |
| 54 | + const { project } = useProjectSelector() |
| 55 | + const { |
| 56 | + data: metrics, |
| 57 | + error, |
| 58 | + isLoading, |
| 59 | + } = useQuery( |
59 | 60 | apiq('timeseriesQuery', { body: { query }, query: { project } })
|
60 | 61 | // avoid graphs flashing blank while loading when you change the time
|
61 | 62 | // { placeholderData: (x) => x }
|
62 | 63 | )
|
63 |
| - useEffect(() => { |
64 |
| - if (metrics) { |
65 |
| - // this is too slow right now; disabling until we can make it faster |
66 |
| - // setIsIntervalPickerEnabled(true) |
67 |
| - } |
68 |
| - }, [metrics, setIsIntervalPickerEnabled]) |
| 64 | + |
| 65 | + // HACK: omicron has a bug where it blows up on an attempt to group by on |
| 66 | + // empty result set because it can't determine whether the data is aligned. |
| 67 | + // Most likely it should consider empty data sets trivially aligned and just |
| 68 | + // flow the emptiness on through, but in the meantime we have to detect |
| 69 | + // this error and pretend it is not an error. |
| 70 | + // See https://github.com/oxidecomputer/omicron/issues/7715 |
| 71 | + const errorMeansEmpty = error?.message === OXQL_GROUP_BY_ERROR |
| 72 | + const hasError = !!error && !errorMeansEmpty |
| 73 | + |
69 | 74 | const { startTime, endTime } = queryObj
|
70 |
| - const { chartData, timeseriesCount } = useMemo(() => composeOxqlData(metrics), [metrics]) |
| 75 | + const { chartData, timeseriesCount } = useMemo( |
| 76 | + () => |
| 77 | + errorMeansEmpty ? { chartData: [], timeseriesCount: 0 } : composeOxqlData(metrics), |
| 78 | + [metrics, errorMeansEmpty] |
| 79 | + ) |
| 80 | + |
71 | 81 | const { data, label, unitForSet, yAxisTickFormatter } = useMemo(() => {
|
72 | 82 | if (unit === 'Bytes') return getBytesChartProps(chartData)
|
73 | 83 | if (unit === 'Count') return getCountChartProps(chartData)
|
@@ -103,7 +113,9 @@ export function OxqlMetric({ title, description, unit, ...queryObj }: OxqlMetric
|
103 | 113 | unit={unitForSet}
|
104 | 114 | data={data}
|
105 | 115 | yAxisTickFormatter={yAxisTickFormatter}
|
106 |
| - hasError={!!error} |
| 116 | + hasError={hasError} |
| 117 | + // isLoading only covers first load --- future-proof against the reintroduction of interval refresh |
| 118 | + loading={isLoading} |
107 | 119 | />
|
108 | 120 | </ChartContainer>
|
109 | 121 | )
|
|
0 commit comments