From d184319a731cd0ea7bac1ecf8aa818dfa155ff6d Mon Sep 17 00:00:00 2001 From: Jonathan Perchoc Date: Mon, 16 Dec 2024 14:35:08 +0100 Subject: [PATCH] feat: add queries statistics for mysql ref: DATATR-681 Signed-off-by: Jonathan Perchoc --- .../src/__tests__/helpers/mocks/queries.ts | 10 +- .../[serviceId]/queries/Queries.page.tsx | 7 +- .../[serviceId]/queries/Queries.spec.tsx | 42 ++++++ .../_components/QueryStatistics.component.tsx | 13 +- .../QueryStatisticsTableColumns.component.tsx | 127 ++++++++++++++---- 5 files changed, 154 insertions(+), 45 deletions(-) diff --git a/packages/manager/apps/pci-databases-analytics/src/__tests__/helpers/mocks/queries.ts b/packages/manager/apps/pci-databases-analytics/src/__tests__/helpers/mocks/queries.ts index f13760f8f93e..1630ee0c5d73 100644 --- a/packages/manager/apps/pci-databases-analytics/src/__tests__/helpers/mocks/queries.ts +++ b/packages/manager/apps/pci-databases-analytics/src/__tests__/helpers/mocks/queries.ts @@ -27,13 +27,13 @@ export const mockedQueries: database.service.currentqueries.Query = { export const mockedQueryStatistics: database.mysql.querystatistics.Query = { avgTimerWait: 3, - countStar: 3, + countStar: 11, digest: 'digest', digestText: 'digestText', firstSeen: 'firstSeen', lastSeen: 'lastSeen', - maxTimerWait: 3, - minTimerWait: 3, + maxTimerWait: 9, + minTimerWait: 2.01, quantile95: 3, quantile99: 1, quantile999: 78987, @@ -49,7 +49,7 @@ export const mockedQueryStatistics: database.mysql.querystatistics.Query = { sumNoIndexUsed: 3, sumRowsAffected: 3, sumRowsExamined: 3, - sumRowsSent: 3, + sumRowsSent: 8, sumSelectFullJoin: 3, sumSelectFullRangeJoin: 3, sumSelectRange: 3, @@ -59,7 +59,7 @@ export const mockedQueryStatistics: database.mysql.querystatistics.Query = { sumSortRange: 3, sumSortRows: 3, sumSortScan: 3, - sumTimerWait: 3, + sumTimerWait: 4, sumWarnings: 3, }; diff --git a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/Queries.page.tsx b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/Queries.page.tsx index 9757cf242746..38c812f96c18 100644 --- a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/Queries.page.tsx +++ b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/Queries.page.tsx @@ -2,10 +2,10 @@ import { useTranslation } from 'react-i18next'; import { useServiceData } from '../Service.context'; import * as database from '@/types/cloud/project/database'; import CurrentQueries from './_components/CurrentQueries.component'; -import QueryStatistics from './_components/QueryStatistics.component'; import BreadcrumbItem from '@/components/breadcrumb/BreadcrumbItem.component'; import Guides from '@/components/guides/Guides.component'; import { GuideSections } from '@/types/guide'; +import QueryStatistics from './_components/QueryStatistics.component'; export function breadcrumb() { return ( @@ -30,10 +30,7 @@ const Queries = () => { {service.capabilities.currentQueries?.read === database.service.capability.StateEnum.enabled && } {service.capabilities.queryStatistics?.read === - database.service.capability.StateEnum.enabled && - service.engine === database.EngineEnum.postgresql && ( - - )} + database.service.capability.StateEnum.enabled && } ); }; diff --git a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/Queries.spec.tsx b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/Queries.spec.tsx index 84a0efa0c1f9..faf4e3d356d4 100644 --- a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/Queries.spec.tsx +++ b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/Queries.spec.tsx @@ -18,6 +18,7 @@ import { RouterWithQueryClientWrapper } from '@/__tests__/helpers/wrappers/Route import { mockedService as mockedServiceOrig } from '@/__tests__/helpers/mocks/services'; import { mockedQueries, + mockedQueryStatistics, mockedQueryStatisticsPG, } from '@/__tests__/helpers/mocks/queries'; import { CdbError } from '@/data/api/database'; @@ -246,4 +247,45 @@ describe('Action of queries and statistics', () => { expect(queriesApi.cancelCurrentQuery).toHaveBeenCalled(); }); }); + + it('renders and shows mysql queries statistics table', async () => { + vi.mocked(ServiceContext.useServiceData).mockReturnValue({ + projectId: 'projectId', + service: { + ...mockedService, + engine: database.EngineEnum.mysql, + }, + category: 'operational', + serviceQuery: {} as UseQueryResult, + }); + vi.mocked(queriesApi.getQueryStatistics).mockResolvedValue([ + mockedQueryStatistics, + ]); + + render(, { wrapper: RouterWithQueryClientWrapper }); + await waitFor(() => { + expect( + screen.getByText(mockedQueryStatistics.sumRowsSent), + ).toBeInTheDocument(); + expect( + screen.getByText(mockedQueryStatistics.countStar), + ).toBeInTheDocument(); + expect( + screen.getByText(mockedQueryStatistics.minTimerWait.toFixed(2)), + ).toBeInTheDocument(); + expect( + screen.getByText(mockedQueryStatistics.maxTimerWait.toFixed(2)), + ).toBeInTheDocument(); + expect( + screen.getByText( + ( + mockedQueryStatistics.sumTimerWait / mockedQueryStatistics.countStar + ).toFixed(2), + ), + ).toBeInTheDocument(); + expect( + screen.getByText(mockedQueryStatistics.sumTimerWait.toFixed(2)), + ).toBeInTheDocument(); + }); + }); }); diff --git a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/_components/QueryStatistics.component.tsx b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/_components/QueryStatistics.component.tsx index fd49663f01ad..fef12d34e4aa 100644 --- a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/_components/QueryStatistics.component.tsx +++ b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/_components/QueryStatistics.component.tsx @@ -6,10 +6,11 @@ import DataTable from '@/components/data-table'; import * as database from '@/types/cloud/project/database'; import { Button } from '@/components/ui/button'; import { useToast } from '@/components/ui/use-toast'; -import { getColumns } from './QueryStatisticsTableColumns.component'; import { useGetQueryStatistics } from '@/hooks/api/database/query/useGetQueryStatistics.hook'; import { useResetQueryStatistics } from '@/hooks/api/database/query/useResetQueryStatistics.hook'; import { getCdbApiErrorMessage } from '@/lib/apiHelper'; +import { getColumns } from './QueryStatisticsTableColumns.component'; +import { QueryStatistics as QueryStatisticsType } from '@/data/api/database/queries.api'; const QueryStatistics = () => { const { t } = useTranslation( @@ -46,9 +47,9 @@ const QueryStatistics = () => { }); }; - const columns: ColumnDef< - database.postgresql.querystatistics.Query - >[] = getColumns(); + const columns = getColumns(service.engine) as ColumnDef< + QueryStatisticsType + >[]; return ( <>

{t('queryStatisticsTitle')}

@@ -74,9 +75,7 @@ const QueryStatistics = () => { {queryStatisticsQuery.isSuccess ? ( ) : ( diff --git a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/_components/QueryStatisticsTableColumns.component.tsx b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/_components/QueryStatisticsTableColumns.component.tsx index 6cf4d58285b7..fb069c278f1a 100644 --- a/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/_components/QueryStatisticsTableColumns.component.tsx +++ b/packages/manager/apps/pci-databases-analytics/src/pages/services/[serviceId]/queries/_components/QueryStatisticsTableColumns.component.tsx @@ -4,85 +4,156 @@ import DataTable from '@/components/data-table'; import { ExpandableSqlQuery } from './ExpandableSqlQuery.component'; import * as database from '@/types/cloud/project/database'; -export const getColumns = () => { +export const getColumns = (engine: database.EngineEnum) => { const { t } = useTranslation( 'pci-databases-analytics/services/service/queries', ); + + if (engine === database.EngineEnum.postgresql) { + return [ + { + id: 'query', + header: ({ column }) => ( + + {t('tableQueryStatisticsHeadName')} + + ), + accessorFn: (row) => row.query, + cell: ({ row }) => , + }, + { + id: 'rows', + header: ({ column }) => ( + + {t('tableQueryStatisticsHeadRows')} + + ), + accessorFn: (row) => row.rows, + }, + { + id: 'calls', + header: ({ column }) => ( + + {t('tableQueryStatisticsHeadCalls')} + + ), + accessorFn: (row) => row.calls, + }, + { + id: 'minTime', + header: ({ column }) => ( + + {t('tableQueryStatisticsHeadMinTime')} + + ), + accessorFn: (row) => row.minTime.toFixed(2), + }, + { + id: 'maxTime', + header: ({ column }) => ( + + {t('tableQueryStatisticsHeadMaxTime')} + + ), + accessorFn: (row) => row.maxTime.toFixed(2), + }, + { + id: 'meanTime', + header: ({ column }) => ( + + {t('tableQueryStatisticsHeadMeanTime')} + + ), + accessorFn: (row) => row.meanTime.toFixed(2), + }, + { + id: 'stdDevTime', + header: ({ column }) => ( + + {t('tableQueryStatisticsHeadStdDevTime')} + + ), + accessorFn: (row) => row.stddevTime.toFixed(2), + }, + { + id: 'totalTime', + header: ({ column }) => ( + + {t('tableQueryStatisticsHeadTotalTime')} + + ), + accessorFn: (row) => row.totalTime.toFixed(2), + }, + ] as ColumnDef[]; + } + + // MySQL Columns return [ { - id: 'query', + id: 'digestText', header: ({ column }) => ( {t('tableQueryStatisticsHeadName')} ), - accessorFn: (row) => row.query, - cell: ({ row }) => , + accessorFn: (row) => row.digestText, + cell: ({ row }) => ( + + ), }, { - id: 'rows', + id: 'sumRowsSent', header: ({ column }) => ( {t('tableQueryStatisticsHeadRows')} ), - accessorFn: (row) => row.rows, + accessorFn: (row) => row.sumRowsSent, }, { - id: 'calls', + id: 'countStar', header: ({ column }) => ( {t('tableQueryStatisticsHeadCalls')} ), - accessorFn: (row) => row.calls, + accessorFn: (row) => row.countStar, }, { - id: 'minTime', + id: 'minTimerWait', header: ({ column }) => ( {t('tableQueryStatisticsHeadMinTime')} ), - accessorFn: (row) => row.minTime.toFixed(2), + accessorFn: (row) => row.minTimerWait.toFixed(2), }, { - id: 'maxTime', + id: 'maxTimerWait', header: ({ column }) => ( {t('tableQueryStatisticsHeadMaxTime')} ), - accessorFn: (row) => row.maxTime.toFixed(2), + accessorFn: (row) => row.maxTimerWait.toFixed(2), }, - { - id: 'meamTime', + id: 'meanTime', header: ({ column }) => ( {t('tableQueryStatisticsHeadMeanTime')} ), - accessorFn: (row) => row.meanTime.toFixed(2), - }, - - { - id: 'stdDevTime', - header: ({ column }) => ( - - {t('tableQueryStatisticsHeadStdDevTime')} - - ), - accessorFn: (row) => row.stddevTime.toFixed(2), + accessorFn: (row) => (row.sumTimerWait / row.countStar).toFixed(2), }, { - id: 'totalTime', + id: 'sumTimerWait', header: ({ column }) => ( {t('tableQueryStatisticsHeadTotalTime')} ), - accessorFn: (row) => row.totalTime.toFixed(2), + accessorFn: (row) => row.sumTimerWait.toFixed(2), }, - ] as ColumnDef[]; + ] as ColumnDef[]; };