From 7db62fdcb5149b029e850071c7a1de770ec03142 Mon Sep 17 00:00:00 2001 From: Xin Hao Zhang Date: Wed, 9 Oct 2024 17:28:52 -0400 Subject: [PATCH] cluster-ui: add auto stats collection setting value to db page This commit adds the Auto stats collction label to the new db page. The value is in the top right corner of the page. Epic: CRDB-37558 Release note (ui change): The value of the auto stats collection enabled cluster setting is now in the top right corner of the db overview page. --- .../cluster-ui/src/api/clusterSettingsApi.ts | 96 ++++++++++++++++++- .../src/constants/tooltipMessages.tsx | 18 ++++ .../src/databaseDetailsV2/tablesView.tsx | 20 +--- .../cluster-ui/src/databasesV2/index.tsx | 22 ++++- 4 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 pkg/ui/workspaces/cluster-ui/src/constants/tooltipMessages.tsx diff --git a/pkg/ui/workspaces/cluster-ui/src/api/clusterSettingsApi.ts b/pkg/ui/workspaces/cluster-ui/src/api/clusterSettingsApi.ts index 443ae92406ba..670f2b7c9b02 100644 --- a/pkg/ui/workspaces/cluster-ui/src/api/clusterSettingsApi.ts +++ b/pkg/ui/workspaces/cluster-ui/src/api/clusterSettingsApi.ts @@ -4,9 +4,13 @@ // included in the /LICENSE file. import { cockroach } from "@cockroachlabs/crdb-protobuf-client"; +import moment from "moment-timezone"; +import useSWRImmutable from "swr/immutable"; import { fetchData } from "src/api"; +import { TimestampToMoment } from "../util"; + import { ADMIN_API_PREFIX } from "./util"; export type SettingsRequestMessage = cockroach.server.serverpb.SettingsRequest; @@ -20,11 +24,97 @@ export function getClusterSettings( req: SettingsRequestMessage, timeout: string, ): Promise { + const urlParams = new URLSearchParams(); + urlParams.append("unredacted_values", "true"); + if (req.keys) { + urlParams.append("keys", req.keys.join(",")); + } + return fetchData( cockroach.server.serverpb.SettingsResponse, - `${ADMIN_API_PREFIX}/settings?unredacted_values=true`, - cockroach.server.serverpb.SettingsRequest, - req, + `${ADMIN_API_PREFIX}/settings?` + urlParams.toString(), + null, + null, timeout, ); } + +// Usage of this request with the useClusterSettings hook +// is preferred over using getClusterSettings and its corresponding +// redux values and sagas. +export type GetClusterSettingRequest = { + names: string[]; +}; + +enum ClusterSettingType { + BOOLEAN = "b", + DURATION = "d", + BYTE_SIZE = "z", + INTEGER = "i", + ENUM = "e", + FLOAT = "f,", + STRING = "s", + VERSION = "m", + UNKNOWN = "", +} + +export type ClusterSetting = { + name: string; + value: string; + type: ClusterSettingType; + description: string; + lastUpdated: moment.Moment | null; +}; + +const formatProtoResponse = ( + data: SettingsResponseMessage, +): Record => { + const settingsMap = {} as Record; + const entries = Object.values(data?.key_values ?? {}); + + entries?.forEach(kv => { + settingsMap[kv.name] = { + name: kv.name, + value: kv.value, + type: kv.type as ClusterSettingType, + description: kv.description, + lastUpdated: TimestampToMoment(kv.last_updated), + }; + }); + + return settingsMap; +}; + +const emptyClusterSetting: ClusterSetting = { + name: "", + value: "", + type: ClusterSettingType.UNKNOWN, + description: "", + lastUpdated: null, +}; + +export const useClusterSettings = (req: GetClusterSettingRequest) => { + const protoReq = new cockroach.server.serverpb.SettingsRequest({ + keys: req.names, + }); + const { data, isLoading, error } = useSWRImmutable(req.names, () => + getClusterSettings(protoReq, "1M").then(formatProtoResponse), + ); + + // If we don't have data we'll return a map of empty settings. + const settingValues = + data ?? + req.names.reduce( + (acc, name) => { + acc[name] = { ...emptyClusterSetting }; + return acc; + }, + {} as Record, + ); + + return { + settingValues, + isLoading, + error, + }; +}; diff --git a/pkg/ui/workspaces/cluster-ui/src/constants/tooltipMessages.tsx b/pkg/ui/workspaces/cluster-ui/src/constants/tooltipMessages.tsx new file mode 100644 index 000000000000..7ad7ca83daa1 --- /dev/null +++ b/pkg/ui/workspaces/cluster-ui/src/constants/tooltipMessages.tsx @@ -0,0 +1,18 @@ +// Copyright 2024 The Cockroach Authors. +// +// Use of this software is governed by the CockroachDB Software License +// included in the /LICENSE file. +import Link from "antd/es/typography/Link"; +import React from "react"; + +import { tableStatsClusterSetting } from "src/util"; + +export const AUTO_STATS_COLLECTION_HELP = ( + + Automatic statistics can help improve query performance. Learn how to{" "} + + manage statistics collection + {" "} + . + +); diff --git a/pkg/ui/workspaces/cluster-ui/src/databaseDetailsV2/tablesView.tsx b/pkg/ui/workspaces/cluster-ui/src/databaseDetailsV2/tablesView.tsx index d25fe18c8307..bb21c7bcc624 100644 --- a/pkg/ui/workspaces/cluster-ui/src/databaseDetailsV2/tablesView.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/databaseDetailsV2/tablesView.tsx @@ -17,6 +17,7 @@ import { NodeRegionsSelector } from "src/components/nodeRegionsSelector/nodeRegi import { RegionNodesLabel } from "src/components/regionNodesLabel"; import { TableMetadataJobControl } from "src/components/tableMetadataLastUpdated/tableMetadataJobControl"; import { Tooltip } from "src/components/tooltip"; +import { AUTO_STATS_COLLECTION_HELP } from "src/constants/tooltipMessages"; import { useRouteParams } from "src/hooks/useRouteParams"; import { PageSection } from "src/layouts"; import { PageConfig, PageConfigItem } from "src/pageConfig"; @@ -31,12 +32,7 @@ import { import useTable, { TableParams } from "src/sharedFromCloud/useTable"; import { Timestamp } from "src/timestamp"; import { StoreID } from "src/types/clusterTypes"; -import { - Bytes, - DATE_WITH_SECONDS_FORMAT_24_TZ, - tabAttr, - tableStatsClusterSetting, -} from "src/util"; +import { Bytes, DATE_WITH_SECONDS_FORMAT_24_TZ, tabAttr } from "src/util"; import { TableColName } from "./constants"; import { TableRow } from "./types"; @@ -141,17 +137,7 @@ const COLUMNS: (TableColumnProps & { sortKey?: TableSortOption })[] = }, { title: ( - - Automatic statistics can help improve query performance. Learn how - to{" "} - - manage statistics collection. - - - } - > + {TableColName.AUTO_STATS_ENABLED} ), diff --git a/pkg/ui/workspaces/cluster-ui/src/databasesV2/index.tsx b/pkg/ui/workspaces/cluster-ui/src/databasesV2/index.tsx index 11a9d014ecff..a08cc9e63121 100644 --- a/pkg/ui/workspaces/cluster-ui/src/databasesV2/index.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/databasesV2/index.tsx @@ -8,6 +8,7 @@ import React, { useMemo } from "react"; import { Link } from "react-router-dom"; import { useNodeStatuses } from "src/api"; +import { useClusterSettings } from "src/api/clusterSettingsApi"; import { DatabaseMetadataRequest, DatabaseSortOptions, @@ -19,6 +20,7 @@ import { TableMetadataJobControl } from "src/components/tableMetadataLastUpdated import { Tooltip } from "src/components/tooltip"; import { PageLayout, PageSection } from "src/layouts"; import { PageConfig, PageConfigItem } from "src/pageConfig"; +import { BooleanSetting } from "src/settings"; import PageCount from "src/sharedFromCloud/pageCount"; import { PageHeader } from "src/sharedFromCloud/pageHeader"; import { Search } from "src/sharedFromCloud/search"; @@ -32,10 +34,14 @@ import useTable, { TableParams } from "src/sharedFromCloud/useTable"; import { StoreID } from "src/types/clusterTypes"; import { Bytes } from "src/util"; +import { AUTO_STATS_COLLECTION_HELP } from "../constants/tooltipMessages"; + import { DatabaseColName } from "./constants"; import { DatabaseRow } from "./databaseTypes"; import { rawDatabaseMetadataToDatabaseRows } from "./utils"; +const AUTO_STATS_ENABLED_CS = "sql.stats.automatic_collection.enabled"; + const COLUMNS: (TableColumnProps & { sortKey?: DatabaseSortOptions; })[] = [ @@ -141,6 +147,9 @@ export const DatabasesPageV2 = () => { createDatabaseMetadataRequestFromParams(params), ); const nodesResp = useNodeStatuses(); + const { settingValues, isLoading: settingsLoading } = useClusterSettings({ + names: [AUTO_STATS_ENABLED_CS], + }); const onNodeRegionsChange = (storeIDs: StoreID[]) => { setFilters({ @@ -194,7 +203,18 @@ export const DatabasesPageV2 = () => { return ( - + + + + } + />