Skip to content

Commit

Permalink
User configurable refresh rates
Browse files Browse the repository at this point in the history
  • Loading branch information
insmac committed Dec 4, 2024
1 parent 3d3d44d commit 4c71d5f
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 14 deletions.
44 changes: 36 additions & 8 deletions packages/web-console/src/scenes/Editor/Metrics/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import styled from "styled-components"
import { Box, Button, Select } from "@questdb/react-components"
import { Text, Link } from "../../../components"
import { useEditor } from "../../../providers"
import { MetricDuration } from "./utils"
import { Time } from "@styled-icons/boxicons-regular"
import { MetricDuration, RefreshRate, autoRefreshRates } from "./utils"
import { Time, Refresh } from "@styled-icons/boxicons-regular"
import { AddMetricDialog } from "./add-metric-dialog"
import type { Metric } from "../../../store/buffers"
import { Metric as MetricComponent } from "./metric"
Expand Down Expand Up @@ -74,11 +74,22 @@ const GlobalInfo = styled(Box).attrs({

const formatDurationLabel = (duration: MetricDuration) => `Last ${duration}`

const formatRefreshRateLabel = (
rate: RefreshRate,
duration: MetricDuration,
) => {
if (rate === RefreshRate.AUTO) {
return `${RefreshRate.AUTO} (${autoRefreshRates[duration]})`
}
return rate
}

export const Metrics = () => {
const { activeBuffer, updateBuffer, buffers } = useEditor()
const [metricDuration, setMetricDuration] = useState<MetricDuration>(
MetricDuration.ONE_HOUR,
)
const [refreshRate, setRefreshRate] = useState<RefreshRate>(RefreshRate.AUTO)
const [dialogOpen, setDialogOpen] = useState(false)
const [metrics, setMetrics] = useState<Metric[]>([])
const telemetryConfig = useSelector(selectors.telemetry.getConfig)
Expand Down Expand Up @@ -130,28 +141,34 @@ export const Metrics = () => {
if (buffer) {
const metrics = buffer?.metricsViewState?.metrics
const metricDuration = buffer?.metricsViewState?.metricDuration
const refreshRate = buffer?.metricsViewState?.refreshRate
if (metrics) {
setMetrics(metrics)
}
if (metricDuration) {
setMetricDuration(metricDuration)
}
if (refreshRate) {
setRefreshRate(refreshRate)
}
}
}, [buffer])

useEffect(() => {
if (
buffer?.id &&
metricDuration !== buffer?.metricsViewState?.metricDuration
) {
if (buffer?.id) {
const merged = merge(buffer, {
metricsViewState: {
metricDuration,
...(metricDuration !== buffer?.metricsViewState?.metricDuration && {
metricDuration,
}),
...(refreshRate !== buffer?.metricsViewState?.refreshRate && {
refreshRate,
}),
},
})
updateBuffer(buffer.id, merged)
}
}, [metricDuration])
}, [metricDuration, refreshRate])

if (telemetryConfig && !telemetryConfig.enabled) {
return (
Expand Down Expand Up @@ -195,6 +212,16 @@ export const Metrics = () => {
<AddMetricDialog open={dialogOpen} onOpenChange={setDialogOpen} />
<Box align="center" gap="1rem">
<Text color="gray2">{getLocalTimeZone()}</Text>
<Select
name="refresh_rate"
value={refreshRate}
options={Object.values(RefreshRate).map((rate) => ({
label: formatRefreshRateLabel(rate, metricDuration),
value: rate,
}))}
onChange={(e) => setRefreshRate(e.target.value as RefreshRate)}
prefixIcon={<Refresh size="18px" />}
/>
<Select
name="duration"
value={metricDuration}
Expand Down Expand Up @@ -232,6 +259,7 @@ export const Metrics = () => {
key={index}
metric={metric}
metricDuration={metricDuration}
refreshRate={refreshRate}
onRemove={handleRemoveMetric}
onTableChange={handleTableChange}
onColorChange={handleColorChange}
Expand Down
18 changes: 16 additions & 2 deletions packages/web-console/src/scenes/Editor/Metrics/metric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {
MetricType,
LastNotNull,
ResultType,
RefreshRate,
refreshRates,
autoRefreshRates,
} from "./utils"
import { widgets } from "./widgets"
import { QuestContext } from "../../../providers"
Expand Down Expand Up @@ -45,13 +48,15 @@ const ActionButton = styled(Button)`
export const Metric = ({
metric,
metricDuration,
refreshRate,
onRemove,
onTableChange,
onColorChange,
onMetricDurationChange,
}: {
metric: MetricItem
metricDuration: MetricDuration
refreshRate: RefreshRate
onRemove: (metric: MetricItem) => void
onTableChange: (metric: MetricItem, tableId: number) => void
onColorChange: (metric: MetricItem, color: string) => void
Expand Down Expand Up @@ -128,7 +133,16 @@ export const Metric = ({

const setupListeners = () => {
if (autoRefreshTables) {
intervalRef.current = setInterval(() => fetchMetric(), 30000)
if (refreshRate === RefreshRate.OFF) {
clearInterval(intervalRef.current)
} else {
intervalRef.current = setInterval(
() => fetchMetric(),
refreshRate === RefreshRate.AUTO
? refreshRates[autoRefreshRates[metricDuration]]
: refreshRates[refreshRate],
)
}
window.addEventListener("focus", focusListener)
focusListenerRef.current = true
} else {
Expand All @@ -155,7 +169,7 @@ export const Metric = ({
focusListenerRef.current = false
}
}
}, [autoRefreshTables, metricDuration, metric.tableId])
}, [autoRefreshTables, metricDuration, metric.tableId, refreshRate])

const focusListener = useCallback(() => {
if (focusListenerRef.current) {
Expand Down
45 changes: 45 additions & 0 deletions packages/web-console/src/scenes/Editor/Metrics/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export type Widget = {
}

export enum MetricDuration {
FIVE_MINUTES = "5m",
FIFTEEN_MINUTES = "15m",
ONE_HOUR = "1h",
THREE_HOURS = "3h",
SIX_HOURS = "6h",
Expand All @@ -43,7 +45,44 @@ export enum SampleBy {
ONE_HOUR = "1h",
}

export enum RefreshRate {
AUTO = "Auto",
ONE_SECOND = "1s",
FIVE_SECONDS = "5s",
TEN_SECONDS = "10s",
THIRTY_SECONDS = "30s",
ONE_MINUTE = "1m",
OFF = "Off",
}

export const refreshRates: Record<RefreshRate, number> = {
[RefreshRate.AUTO]: 0,
[RefreshRate.OFF]: 0,
[RefreshRate.ONE_SECOND]: 1 * 1000,
[RefreshRate.FIVE_SECONDS]: 5 * 1000,
[RefreshRate.TEN_SECONDS]: 10 * 1000,
[RefreshRate.THIRTY_SECONDS]: 30 * 1000,
[RefreshRate.ONE_MINUTE]: 60 * 1000,
}

export const autoRefreshRates: Record<
MetricDuration,
Exclude<RefreshRate, RefreshRate.AUTO>
> = {
[MetricDuration.FIVE_MINUTES]: RefreshRate.ONE_SECOND,
[MetricDuration.FIFTEEN_MINUTES]: RefreshRate.FIVE_SECONDS,
[MetricDuration.ONE_HOUR]: RefreshRate.TEN_SECONDS,
[MetricDuration.THREE_HOURS]: RefreshRate.THIRTY_SECONDS,
[MetricDuration.SIX_HOURS]: RefreshRate.THIRTY_SECONDS,
[MetricDuration.TWELVE_HOURS]: RefreshRate.THIRTY_SECONDS,
[MetricDuration.TWENTY_FOUR_HOURS]: RefreshRate.THIRTY_SECONDS,
[MetricDuration.THREE_DAYS]: RefreshRate.ONE_MINUTE,
[MetricDuration.SEVEN_DAYS]: RefreshRate.ONE_MINUTE,
}

export const durationInMinutes: Record<MetricDuration, number> = {
[MetricDuration.FIVE_MINUTES]: 5,
[MetricDuration.FIFTEEN_MINUTES]: 15,
[MetricDuration.ONE_HOUR]: 60,
[MetricDuration.THREE_HOURS]: 60 * 3,
[MetricDuration.SIX_HOURS]: 60 * 6,
Expand All @@ -54,6 +93,8 @@ export const durationInMinutes: Record<MetricDuration, number> = {
}

export const defaultSampleByForDuration: Record<MetricDuration, SampleBy> = {
[MetricDuration.FIVE_MINUTES]: SampleBy.ONE_SECOND,
[MetricDuration.FIFTEEN_MINUTES]: SampleBy.ONE_SECOND,
[MetricDuration.ONE_HOUR]: SampleBy.ONE_SECOND,
[MetricDuration.THREE_HOURS]: SampleBy.ONE_SECOND,
[MetricDuration.SIX_HOURS]: SampleBy.ONE_SECOND,
Expand Down Expand Up @@ -108,6 +149,10 @@ export const minutesToSeconds = (durationInMinutes: number) =>
durationInMinutes * 60

export const xAxisFormat = {
[MetricDuration.FIVE_MINUTES]: (rawValue: number) =>
utcToLocal(rawValue, "HH:mm:ss"),
[MetricDuration.FIFTEEN_MINUTES]: (rawValue: number) =>
utcToLocal(rawValue, "HH:mm"),
[MetricDuration.ONE_HOUR]: (rawValue: number) =>
utcToLocal(rawValue, "HH:mm"),
[MetricDuration.THREE_HOURS]: (rawValue: number) =>
Expand Down
10 changes: 7 additions & 3 deletions packages/web-console/src/scenes/Editor/Metrics/widgets/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ export const minutesToSeconds = (durationInMinutes: number) =>
export const getTimeFilter = (
minutes: number,
) => `created > date_trunc('minute', dateadd('${
minutes >= 1440 ? "d" : "h"
minutes >= 1440 ? "d" : minutes >= 60 ? "h" : "s"
}', -${
minutes >= 1440 ? minutesToDays(minutes) : minutesToHours(minutes)
minutes >= 1440
? minutesToDays(minutes)
: minutes >= 60
? minutesToHours(minutes)
: minutesToSeconds(minutes)
}, now()))
and created < date_trunc('minute', now())`
and created < date_trunc('${minutes >= 60 ? "minute" : "second"}', now())`
3 changes: 2 additions & 1 deletion packages/web-console/src/scenes/Schema/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ import { NotificationType } from "../../types"
import { Checkbox } from "./checkbox"
import { AddChart } from "@styled-icons/material"
import { useEditor } from "../../providers/EditorProvider"
import { MetricDuration } from "../../scenes/Editor/Metrics/utils"
import { MetricDuration, RefreshRate } from "../../scenes/Editor/Metrics/utils"

type Props = Readonly<{
hideMenu?: boolean
Expand Down Expand Up @@ -470,6 +470,7 @@ const Schema = ({
metricsViewState: {
metrics: [],
metricDuration: MetricDuration.ONE_HOUR,
refreshRate: RefreshRate.AUTO,
},
})
}}
Expand Down
2 changes: 2 additions & 0 deletions packages/web-console/src/store/buffers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { RefreshRate } from "./../scenes/Editor/Metrics/utils"
/*******************************************************************************
* ___ _ ____ ____
* / _ \ _ _ ___ ___| |_| _ \| __ )
Expand Down Expand Up @@ -41,6 +42,7 @@ export type Metric = {

export type MetricsViewState = {
metricDuration?: MetricDuration
refreshRate?: RefreshRate
sampleBy?: string
metrics?: Metric[]
}
Expand Down

0 comments on commit 4c71d5f

Please sign in to comment.