diff --git a/.changeset/flat-carrots-smoke.md b/.changeset/flat-carrots-smoke.md new file mode 100644 index 000000000..a0176837b --- /dev/null +++ b/.changeset/flat-carrots-smoke.md @@ -0,0 +1,7 @@ +--- +"@hyperdx/common-utils": patch +"@hyperdx/api": patch +"@hyperdx/app": patch +--- + +chore: Standardize granularities diff --git a/packages/app/src/ChartUtils.tsx b/packages/app/src/ChartUtils.tsx index 6f04d266c..03c956114 100644 --- a/packages/app/src/ChartUtils.tsx +++ b/packages/app/src/ChartUtils.tsx @@ -11,6 +11,10 @@ import { ResponseJSON, } from '@hyperdx/common-utils/dist/clickhouse'; import { isMetricChartConfig } from '@hyperdx/common-utils/dist/core/renderChartConfig'; +import { + convertDateRangeToGranularityString, + Granularity, +} from '@hyperdx/common-utils/dist/core/utils'; import { AggregateFunction as AggFnV2, ChartConfigWithDateRange, @@ -100,24 +104,6 @@ export const getMetricAggFns = ( ]; }; -export enum Granularity { - FifteenSecond = '15 second', - ThirtySecond = '30 second', - OneMinute = '1 minute', - FiveMinute = '5 minute', - TenMinute = '10 minute', - FifteenMinute = '15 minute', - ThirtyMinute = '30 minute', - OneHour = '1 hour', - TwoHour = '2 hour', - SixHour = '6 hour', - TwelveHour = '12 hour', - OneDay = '1 day', - TwoDay = '2 day', - SevenDay = '7 day', - ThirtyDay = '30 day', -} - export const DEFAULT_CHART_CONFIG: Omit< SavedChartConfig, 'source' | 'connection' @@ -268,50 +254,6 @@ export function TableToggle({ ); } -export function convertDateRangeToGranularityString( - dateRange: [Date, Date], - maxNumBuckets: number, -): Granularity { - const start = dateRange[0].getTime(); - const end = dateRange[1].getTime(); - const diffSeconds = Math.floor((end - start) / 1000); - const granularitySizeSeconds = Math.ceil(diffSeconds / maxNumBuckets); - - if (granularitySizeSeconds <= 15) { - return Granularity.FifteenSecond; - } else if (granularitySizeSeconds <= 30) { - return Granularity.ThirtySecond; - } else if (granularitySizeSeconds <= 60) { - return Granularity.OneMinute; - } else if (granularitySizeSeconds <= 5 * 60) { - return Granularity.FiveMinute; - } else if (granularitySizeSeconds <= 10 * 60) { - return Granularity.TenMinute; - } else if (granularitySizeSeconds <= 15 * 60) { - return Granularity.FifteenMinute; - } else if (granularitySizeSeconds <= 30 * 60) { - return Granularity.ThirtyMinute; - } else if (granularitySizeSeconds <= 3600) { - return Granularity.OneHour; - } else if (granularitySizeSeconds <= 2 * 3600) { - return Granularity.TwoHour; - } else if (granularitySizeSeconds <= 6 * 3600) { - return Granularity.SixHour; - } else if (granularitySizeSeconds <= 12 * 3600) { - return Granularity.TwelveHour; - } else if (granularitySizeSeconds <= 24 * 3600) { - return Granularity.OneDay; - } else if (granularitySizeSeconds <= 2 * 24 * 3600) { - return Granularity.TwoDay; - } else if (granularitySizeSeconds <= 7 * 24 * 3600) { - return Granularity.SevenDay; - } else if (granularitySizeSeconds <= 30 * 24 * 3600) { - return Granularity.ThirtyDay; - } - - return Granularity.ThirtyDay; -} - export const ChartKeyJoiner = ' ยท '; export const PreviousPeriodSuffix = ' (previous)'; diff --git a/packages/app/src/DBChartPage.tsx b/packages/app/src/DBChartPage.tsx index 76b851faf..0302b49b8 100644 --- a/packages/app/src/DBChartPage.tsx +++ b/packages/app/src/DBChartPage.tsx @@ -1,8 +1,8 @@ -import { useCallback, useRef, useState } from 'react'; +import { useRef, useState } from 'react'; import dynamic from 'next/dynamic'; import Head from 'next/head'; -import { parseAsJson, parseAsStringEnum, useQueryState } from 'nuqs'; -import { useForm, useWatch } from 'react-hook-form'; +import { parseAsJson, useQueryState } from 'nuqs'; +import { useForm } from 'react-hook-form'; import { useHotkeys } from 'react-hotkeys-hook'; import { SavedChartConfig, SourceKind } from '@hyperdx/common-utils/dist/types'; import { @@ -24,7 +24,7 @@ import { } from '@tabler/icons-react'; import api from '@/api'; -import { DEFAULT_CHART_CONFIG, Granularity } from '@/ChartUtils'; +import { DEFAULT_CHART_CONFIG } from '@/ChartUtils'; import EditTimeChartForm from '@/components/DBEditTimeChartForm'; import { InputControlled } from '@/components/InputControlled'; import { SourceSelectControlled } from '@/components/SourceSelect'; diff --git a/packages/app/src/GranularityPicker.tsx b/packages/app/src/GranularityPicker.tsx index b70b1f137..181fa726e 100644 --- a/packages/app/src/GranularityPicker.tsx +++ b/packages/app/src/GranularityPicker.tsx @@ -1,9 +1,8 @@ import { memo } from 'react'; import { useController, UseControllerProps } from 'react-hook-form'; +import { Granularity } from '@hyperdx/common-utils/dist/core/utils'; import { Select } from '@mantine/core'; -import { Granularity } from './ChartUtils'; - export default function GranularityPicker({ value, onChange, @@ -38,6 +37,10 @@ export default function GranularityPicker({ value: Granularity.TenMinute, label: '10 Minutes Granularity', }, + { + value: Granularity.FifteenMinute, + label: '15 Minutes Granularity', + }, { value: Granularity.ThirtyMinute, label: '30 Minutes Granularity', diff --git a/packages/app/src/KubernetesDashboardPage.tsx b/packages/app/src/KubernetesDashboardPage.tsx index c958e4294..8f1c4efe7 100644 --- a/packages/app/src/KubernetesDashboardPage.tsx +++ b/packages/app/src/KubernetesDashboardPage.tsx @@ -6,6 +6,7 @@ import cx from 'classnames'; import sub from 'date-fns/sub'; import { useQueryState } from 'nuqs'; import { useForm, useWatch } from 'react-hook-form'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { SourceKind, TSource } from '@hyperdx/common-utils/dist/types'; import { Alert, @@ -44,7 +45,6 @@ import { SourceSelectControlled } from './components/SourceSelect'; import { useQueriedChartConfig } from './hooks/useChartConfig'; import { useDashboardRefresh } from './hooks/useDashboardRefresh'; import { - convertDateRangeToGranularityString, convertV1ChartConfigToV2, K8S_CPU_PERCENTAGE_NUMBER_FORMAT, K8S_MEM_NUMBER_FORMAT, @@ -1304,10 +1304,8 @@ function KubernetesDashboardPage() { config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { @@ -1341,10 +1339,8 @@ function KubernetesDashboardPage() { config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { @@ -1467,10 +1463,8 @@ function KubernetesDashboardPage() { config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { @@ -1504,10 +1498,8 @@ function KubernetesDashboardPage() { config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { @@ -1554,10 +1546,8 @@ function KubernetesDashboardPage() { config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { @@ -1591,10 +1581,8 @@ function KubernetesDashboardPage() { config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { diff --git a/packages/app/src/NamespaceDetailsSidePanel.tsx b/packages/app/src/NamespaceDetailsSidePanel.tsx index 5a62d04b8..dc0912d7d 100644 --- a/packages/app/src/NamespaceDetailsSidePanel.tsx +++ b/packages/app/src/NamespaceDetailsSidePanel.tsx @@ -1,23 +1,19 @@ import * as React from 'react'; -import Link from 'next/link'; import { StringParam, useQueryParam, withDefault } from 'use-query-params'; import { tcFromSource } from '@hyperdx/common-utils/dist/core/metadata'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { TSource } from '@hyperdx/common-utils/dist/types'; import { - Anchor, Badge, - Box, Card, Drawer, Flex, Grid, - ScrollArea, SegmentedControl, Text, } from '@mantine/core'; import { - convertDateRangeToGranularityString, convertV1ChartConfigToV2, K8S_CPU_PERCENTAGE_NUMBER_FORMAT, K8S_MEM_NUMBER_FORMAT, @@ -365,10 +361,8 @@ export default function NamespaceDetailsSidePanel({ config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { @@ -398,10 +392,8 @@ export default function NamespaceDetailsSidePanel({ config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { diff --git a/packages/app/src/NodeDetailsSidePanel.tsx b/packages/app/src/NodeDetailsSidePanel.tsx index a1ea28453..bd00d1a58 100644 --- a/packages/app/src/NodeDetailsSidePanel.tsx +++ b/packages/app/src/NodeDetailsSidePanel.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { StringParam, useQueryParam, withDefault } from 'use-query-params'; import { tcFromSource } from '@hyperdx/common-utils/dist/core/metadata'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { TSource } from '@hyperdx/common-utils/dist/types'; import { Badge, @@ -13,7 +14,6 @@ import { } from '@mantine/core'; import { - convertDateRangeToGranularityString, convertV1ChartConfigToV2, K8S_CPU_PERCENTAGE_NUMBER_FORMAT, K8S_MEM_NUMBER_FORMAT, @@ -374,10 +374,8 @@ export default function NodeDetailsSidePanel({ config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { @@ -407,10 +405,8 @@ export default function NodeDetailsSidePanel({ config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { diff --git a/packages/app/src/PodDetailsSidePanel.tsx b/packages/app/src/PodDetailsSidePanel.tsx index 7e49d27b9..6ca2063f1 100644 --- a/packages/app/src/PodDetailsSidePanel.tsx +++ b/packages/app/src/PodDetailsSidePanel.tsx @@ -1,10 +1,9 @@ import * as React from 'react'; -import Link from 'next/link'; import { StringParam, useQueryParam, withDefault } from 'use-query-params'; import { tcFromSource } from '@hyperdx/common-utils/dist/core/metadata'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { TSource } from '@hyperdx/common-utils/dist/types'; import { - Anchor, Box, Card, Drawer, @@ -16,7 +15,6 @@ import { } from '@mantine/core'; import { - convertDateRangeToGranularityString, convertV1ChartConfigToV2, K8S_CPU_PERCENTAGE_NUMBER_FORMAT, K8S_MEM_NUMBER_FORMAT, @@ -374,10 +372,8 @@ export default function PodDetailsSidePanel({ config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { @@ -408,10 +404,8 @@ export default function PodDetailsSidePanel({ config={convertV1ChartConfigToV2( { dateRange, - granularity: convertDateRangeToGranularityString( - dateRange, - 60, - ), + granularity: + convertDateRangeToGranularityString(dateRange), seriesReturnType: 'column', series: [ { diff --git a/packages/app/src/ServicesDashboardPage.tsx b/packages/app/src/ServicesDashboardPage.tsx index 4c15c22a9..3efea25af 100644 --- a/packages/app/src/ServicesDashboardPage.tsx +++ b/packages/app/src/ServicesDashboardPage.tsx @@ -9,7 +9,7 @@ import { } from 'nuqs'; import { UseControllerProps, useForm, useWatch } from 'react-hook-form'; import { tcFromSource } from '@hyperdx/common-utils/dist/core/metadata'; -import { DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS } from '@hyperdx/common-utils/dist/core/renderChartConfig'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { ChartConfigWithDateRange, ChartConfigWithOptDateRange, @@ -41,7 +41,6 @@ import { } from '@tabler/icons-react'; import { - convertDateRangeToGranularityString, ERROR_RATE_PERCENTAGE_NUMBER_FORMAT, INTEGER_NUMBER_FORMAT, MS_NUMBER_FORMAT, @@ -450,10 +449,8 @@ function HttpTab({ }, ], dateRange: searchedTimeRange, - granularity: convertDateRangeToGranularityString( - searchedTimeRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ), + granularity: + convertDateRangeToGranularityString(searchedTimeRange), } as ChartConfigWithOptDateRange, isSubquery: true, }, @@ -890,10 +887,8 @@ function DatabaseTab({ ], // Date range and granularity add an `__hdx_time_bucket` column to select and group by dateRange: searchedTimeRange, - granularity: convertDateRangeToGranularityString( - searchedTimeRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ), + granularity: + convertDateRangeToGranularityString(searchedTimeRange), } as CteChartConfig, }, { @@ -1008,10 +1003,8 @@ function DatabaseTab({ ], // Date range and granularity add an `__hdx_time_bucket` column to select and group by dateRange: searchedTimeRange, - granularity: convertDateRangeToGranularityString( - searchedTimeRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ), + granularity: + convertDateRangeToGranularityString(searchedTimeRange), } as CteChartConfig, }, { diff --git a/packages/app/src/components/DBHeatmapChart.tsx b/packages/app/src/components/DBHeatmapChart.tsx index 29c0db318..07888f35a 100644 --- a/packages/app/src/components/DBHeatmapChart.tsx +++ b/packages/app/src/components/DBHeatmapChart.tsx @@ -7,17 +7,14 @@ import { ClickHouseQueryError, inferTimestampColumn, } from '@hyperdx/common-utils/dist/clickhouse'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { ChartConfigWithDateRange } from '@hyperdx/common-utils/dist/types'; import { DisplayType } from '@hyperdx/common-utils/dist/types'; import { Box, Button, Code, Divider, Group, Modal, Text } from '@mantine/core'; import { useDisclosure, useElementSize } from '@mantine/hooks'; import { IconArrowsDiagonal } from '@tabler/icons-react'; -import { - convertDateRangeToGranularityString, - isAggregateFunction, - timeBucketByGranularity, -} from '@/ChartUtils'; +import { isAggregateFunction, timeBucketByGranularity } from '@/ChartUtils'; import { useQueriedChartConfig } from '@/hooks/useChartConfig'; import { NumberFormat } from '@/types'; import { FormatTime } from '@/useFormatTime'; diff --git a/packages/app/src/components/DBInfraPanel.tsx b/packages/app/src/components/DBInfraPanel.tsx index 23478d4bd..3fe454e13 100644 --- a/packages/app/src/components/DBInfraPanel.tsx +++ b/packages/app/src/components/DBInfraPanel.tsx @@ -1,5 +1,9 @@ import { useMemo, useState } from 'react'; import { add, min, sub } from 'date-fns'; +import { + convertDateRangeToGranularityString, + Granularity, +} from '@hyperdx/common-utils/dist/core/utils'; import { TSource } from '@hyperdx/common-utils/dist/types'; import { Box, @@ -12,11 +16,9 @@ import { } from '@mantine/core'; import { convertV1ChartConfigToV2 } from '@/ChartUtils'; -import { getEventBody, useSource } from '@/source'; +import { useSource } from '@/source'; import { - convertDateRangeToGranularityString, - Granularity, K8S_CPU_PERCENTAGE_NUMBER_FORMAT, K8S_FILESYSTEM_NUMBER_FORMAT, K8S_MEM_NUMBER_FORMAT, @@ -65,7 +67,7 @@ const InfraSubpanelGroup = ({ }, [size]); const granularity = useMemo(() => { - return convertDateRangeToGranularityString(dateRange, 60); + return convertDateRangeToGranularityString(dateRange); }, [dateRange]); return ( diff --git a/packages/app/src/hooks/useChartConfig.tsx b/packages/app/src/hooks/useChartConfig.tsx index a9f7bd6a2..0b7e532c3 100644 --- a/packages/app/src/hooks/useChartConfig.tsx +++ b/packages/app/src/hooks/useChartConfig.tsx @@ -8,11 +8,11 @@ import { ClickhouseClient } from '@hyperdx/common-utils/dist/clickhouse/browser' import { tryOptimizeConfigWithMaterializedView } from '@hyperdx/common-utils/dist/core/materializedViews'; import { Metadata } from '@hyperdx/common-utils/dist/core/metadata'; import { - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, isMetricChartConfig, isUsingGranularity, renderChartConfig, } from '@hyperdx/common-utils/dist/core/renderChartConfig'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { format } from '@hyperdx/common-utils/dist/sqlFormatter'; import { ChartConfigWithDateRange, @@ -24,10 +24,7 @@ import { UseQueryOptions, } from '@tanstack/react-query'; -import { - convertDateRangeToGranularityString, - toStartOfInterval, -} from '@/ChartUtils'; +import { toStartOfInterval } from '@/ChartUtils'; import { useClickhouseClient } from '@/clickhouse'; import { IS_MTVIEWS_ENABLED } from '@/config'; import { buildMTViewSelectQuery } from '@/hdxMTViews'; @@ -93,10 +90,7 @@ export const getGranularityAlignedTimeWindows = ( const granularity = config.granularity === 'auto' - ? convertDateRangeToGranularityString( - config.dateRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ) + ? convertDateRangeToGranularityString(config.dateRange) : config.granularity; const windows = []; diff --git a/packages/app/src/hooks/useDashboardRefresh.tsx b/packages/app/src/hooks/useDashboardRefresh.tsx index cb742db28..adf4fbda5 100644 --- a/packages/app/src/hooks/useDashboardRefresh.tsx +++ b/packages/app/src/hooks/useDashboardRefresh.tsx @@ -1,12 +1,10 @@ 'use client'; import React from 'react'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { useDocumentVisibility } from '@mantine/hooks'; -import { - convertDateRangeToGranularityString, - convertGranularityToSeconds, -} from '@/ChartUtils'; +import { convertGranularityToSeconds } from '@/ChartUtils'; export const useDashboardRefresh = ({ searchedTimeRange, @@ -38,10 +36,8 @@ export const useDashboardRefresh = ({ }, 1000); }, [onTimeRangeSelect, searchedTimeRange]); - const granularityOverride = convertDateRangeToGranularityString( - searchedTimeRange, - 60, - ); + const granularityOverride = + convertDateRangeToGranularityString(searchedTimeRange); // Auto-refresh interval const intervalRef = React.useRef(null); diff --git a/packages/app/src/hooks/usePatterns.tsx b/packages/app/src/hooks/usePatterns.tsx index 82dccc039..5cf353034 100644 --- a/packages/app/src/hooks/usePatterns.tsx +++ b/packages/app/src/hooks/usePatterns.tsx @@ -1,13 +1,10 @@ import { useMemo } from 'react'; import stripAnsi from 'strip-ansi'; +import { convertDateRangeToGranularityString } from '@hyperdx/common-utils/dist/core/utils'; import { ChartConfigWithDateRange } from '@hyperdx/common-utils/dist/types'; import { useQuery } from '@tanstack/react-query'; -import { - convertDateRangeToGranularityString, - timeBucketByGranularity, - toStartOfInterval, -} from '@/ChartUtils'; +import { timeBucketByGranularity, toStartOfInterval } from '@/ChartUtils'; import { selectColumnMapWithoutAdditionalKeys, useConfigWithPrimaryAndPartitionKey, diff --git a/packages/app/src/utils/alerts.ts b/packages/app/src/utils/alerts.ts index 3e492d26c..92056a0f2 100644 --- a/packages/app/src/utils/alerts.ts +++ b/packages/app/src/utils/alerts.ts @@ -6,18 +6,14 @@ import { } from 'date-fns'; import _ from 'lodash'; import { z } from 'zod'; +import { Granularity } from '@hyperdx/common-utils/dist/core/utils'; import { - Alert, - AlertBaseSchema, AlertChannelType, AlertInterval, - AlertSource, AlertThresholdType, ChartAlertBaseSchema, } from '@hyperdx/common-utils/dist/types'; -import { Granularity } from '@/ChartUtils'; - export function intervalToGranularity(interval: AlertInterval) { if (interval === '1m') return Granularity.OneMinute; if (interval === '5m') return Granularity.FiveMinute; diff --git a/packages/common-utils/src/core/materializedViews.ts b/packages/common-utils/src/core/materializedViews.ts index dcbb90b3f..a173f72d2 100644 --- a/packages/common-utils/src/core/materializedViews.ts +++ b/packages/common-utils/src/core/materializedViews.ts @@ -9,7 +9,6 @@ import { } from '@/types'; import { Metadata, TableConnection } from './metadata'; -import { DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS } from './renderChartConfig'; import { convertDateRangeToGranularityString, convertGranularityToSeconds, @@ -139,10 +138,7 @@ function mvConfigSupportsGranularity( // Determine the effective granularity if the granularity is 'auto' const chartGranularity = normalizedGranularity === 'auto' && chartConfig.dateRange - ? convertDateRangeToGranularityString( - chartConfig.dateRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ) + ? convertDateRangeToGranularityString(chartConfig.dateRange) : normalizedGranularity; const chartGranularitySeconds = convertGranularityToSeconds(chartGranularity); diff --git a/packages/common-utils/src/core/renderChartConfig.ts b/packages/common-utils/src/core/renderChartConfig.ts index e630e0415..f5ac41b89 100644 --- a/packages/common-utils/src/core/renderChartConfig.ts +++ b/packages/common-utils/src/core/renderChartConfig.ts @@ -48,9 +48,6 @@ function createMetricNameFilter( return SqlString.format('MetricName = ?', [metricName]); } -/** The default maximum number of buckets setting when determining a bucket duration for 'auto' granularity */ -export const DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS = 60; - // FIXME: SQLParser.ColumnRef is incomplete type ColumnRef = SQLParser.ColumnRef & { array_index?: { @@ -512,10 +509,7 @@ function timeBucketExpr({ const unsafeInterval = { UNSAFE_RAW_SQL: interval === 'auto' && Array.isArray(dateRange) - ? convertDateRangeToGranularityString( - dateRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ) + ? convertDateRangeToGranularityString(dateRange) : interval, }; @@ -1036,10 +1030,7 @@ function renderDeltaExpression( ) { const interval = chartConfig.granularity === 'auto' && Array.isArray(chartConfig.dateRange) - ? convertDateRangeToGranularityString( - chartConfig.dateRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ) + ? convertDateRangeToGranularityString(chartConfig.dateRange) : chartConfig.granularity; const intervalInSeconds = convertGranularityToSeconds(interval ?? ''); @@ -1186,10 +1177,7 @@ async function translateMetricChartConfig( includedDataInterval: chartConfig.granularity === 'auto' && Array.isArray(chartConfig.dateRange) - ? convertDateRangeToGranularityString( - chartConfig.dateRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ) + ? convertDateRangeToGranularityString(chartConfig.dateRange) : chartConfig.granularity, }, metadata, @@ -1277,7 +1265,7 @@ async function translateMetricChartConfig( // Render the various clauses from the user input so they can be woven into the CTE queries. The dateRange // is manipulated to search forward/back one bucket window to ensure that there is enough data to compute // a reasonable value on the ends of the series. - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion + const cteChartConfig = { ...chartConfig, from: { @@ -1294,10 +1282,7 @@ async function translateMetricChartConfig( includedDataInterval: chartConfig.granularity === 'auto' && Array.isArray(chartConfig.dateRange) - ? convertDateRangeToGranularityString( - chartConfig.dateRange, - DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, - ) + ? convertDateRangeToGranularityString(chartConfig.dateRange) : chartConfig.granularity, } as ChartConfigWithOptDateRangeEx; diff --git a/packages/common-utils/src/core/utils.ts b/packages/common-utils/src/core/utils.ts index 99bc849b7..702408c6b 100644 --- a/packages/common-utils/src/core/utils.ts +++ b/packages/common-utils/src/core/utils.ts @@ -18,6 +18,9 @@ import { TSourceUnion, } from '@/types'; +/** The default maximum number of buckets setting when determining a bucket duration for 'auto' granularity */ +export const DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS = 60; + export const isBrowser: boolean = typeof window !== 'undefined' && typeof window.document !== 'undefined'; @@ -218,6 +221,10 @@ export function replaceJsonExpressions(sql: string) { return { sqlWithReplacements, replacements }; } +/** + * To best support Pre-aggregation in Materialized Views, any new + * granularities should be multiples of all smaller granularities. + * */ export enum Granularity { FifteenSecond = '15 second', ThirtySecond = '30 second', @@ -251,7 +258,7 @@ export function hashCode(str: string) { export function convertDateRangeToGranularityString( dateRange: [Date, Date], - maxNumBuckets: number, + maxNumBuckets: number = DEFAULT_AUTO_GRANULARITY_MAX_BUCKETS, ): Granularity { const start = dateRange[0].getTime(); const end = dateRange[1].getTime(); @@ -266,9 +273,9 @@ export function convertDateRangeToGranularityString( return Granularity.OneMinute; } else if (granularitySizeSeconds <= 5 * 60) { return Granularity.FiveMinute; - } else if (granularitySizeSeconds <= 10 * 60) { - return Granularity.TenMinute; } else if (granularitySizeSeconds <= 15 * 60) { + // 10 minute granularity is skipped so that every auto-inferred granularity is a multiple + // of all smaller granularities, which makes it more likely that a materialized view can be used. return Granularity.FifteenMinute; } else if (granularitySizeSeconds <= 30 * 60) { return Granularity.ThirtyMinute;