From ff2175183070b92dabde9c15b9a5d604552a1604 Mon Sep 17 00:00:00 2001 From: Jad Chahed Date: Thu, 11 Jul 2024 22:49:36 +0200 Subject: [PATCH] refactor: daily charts Signed-off-by: Jad Chahed --- website/package.json | 2 + website/src/assets/styles/tailwind.css | 32 +- website/src/common/DailySummary.tsx | 30 +- website/src/components/ui/chart.tsx | 16 + website/src/components/ui/scroll-area.tsx | 62 ++++ website/src/components/ui/separator.tsx | 16 + website/src/components/ui/skeleton.tsx | 16 + website/src/hooks/useDailySummaryData.ts | 20 +- website/src/pages/DailyPage/DailyPage.tsx | 315 +----------------- .../src/pages/DailyPage/components/Chart.tsx | 135 -------- .../DailyPage/components/DailyCharts.tsx | 307 +++++++++++++++++ .../components/DailyDailySummary.tsx | 87 +++++ .../pages/DailyPage/components/DailyHero.tsx | 16 +- .../DailyPage/components/DailySummary.tsx | 82 ----- website/src/pages/Layout.tsx | 1 - website/yarn.lock | 28 ++ 16 files changed, 601 insertions(+), 564 deletions(-) create mode 100644 website/src/components/ui/scroll-area.tsx delete mode 100644 website/src/pages/DailyPage/components/Chart.tsx create mode 100644 website/src/pages/DailyPage/components/DailyCharts.tsx create mode 100644 website/src/pages/DailyPage/components/DailyDailySummary.tsx delete mode 100644 website/src/pages/DailyPage/components/DailySummary.tsx diff --git a/website/package.json b/website/package.json index b8d83ed9e..85ef14884 100644 --- a/website/package.json +++ b/website/package.json @@ -15,6 +15,7 @@ "@nivo/line": "^0.83.0", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-scroll-area": "^1.1.0", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.0.2", @@ -39,6 +40,7 @@ "uuid": "^9.0.0" }, "devDependencies": { + "@types/bytes": "^3.1.4", "@types/node": "^20.14.9", "@types/react": "^18.2.55", "@types/react-dom": "^18.2.19", diff --git a/website/src/assets/styles/tailwind.css b/website/src/assets/styles/tailwind.css index 160bd4736..3f575bddd 100644 --- a/website/src/assets/styles/tailwind.css +++ b/website/src/assets/styles/tailwind.css @@ -50,16 +50,23 @@ limitations under the License. --ring: 24.6 95% 53.1%; --radius: 0.5rem; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - --front: 0 0% 10%; --back: 0 0% 100%; --theme: 48 100% 50%; + + --chart-qpsReads: 220, 100%, 50%; + --chart-qpsTotal: 39, 100%, 50%; + --chart-qpsWrites: 0, 59%, 41%; + --chart-qpsOther: 300, 100%, 25%; + --chart-tps: 39, 100%, 50%; + --chart-latency: 39, 100%, 50%; + --chart-cpuTimeTotal: 39, 100%, 50%; + --chart-cpuTimeVtgate: 220, 100%, 50%; + --chart-cpuTimeVttablet: 0, 59%, 41%; + --chart-memBytesTotal: 39, 100%, 50%; + --chart-memBytesVtgate: 220, 100%, 50%; + --chart-memBytesVttablet: 0, 59%, 41%; } .dark { @@ -102,6 +109,19 @@ limitations under the License. --back: 0 0% 10%; --theme: 48 100% 50%; + + --chart-qpsReads: 220, 100%, 50%; + --chart-qpsTotal: 39, 100%, 50%; + --chart-qpsWrites: 0, 59%, 41%; + --chart-qpsOther: 300, 100%, 25%; + --chart-tps: 39, 100%, 50%; + --chart-latency: 39, 100%, 50%; + --chart-cpuTimeTotal: 39, 100%, 50%; + --chart-cpuTimeVtgate: 220, 100%, 50%; + --chart-cpuTimeVttablet: 0, 59%, 41%; + --chart-memBytesTotal: 39, 100%, 50%; + --chart-memBytesVtgate: 220, 100%, 50%; + --chart-memBytesVttablet: 0, 59%, 41%; } } diff --git a/website/src/common/DailySummary.tsx b/website/src/common/DailySummary.tsx index bc171a781..a832c05e0 100644 --- a/website/src/common/DailySummary.tsx +++ b/website/src/common/DailySummary.tsx @@ -14,19 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { - Card, - CardContent, - CardHeader, - CardTitle, -} from "@/components/ui/card"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { ChartConfig, ChartContainer, ChartTooltip, } from "@/components/ui/chart"; import { DailySummarydata } from "@/types"; -import PropTypes from "prop-types"; import { Line, LineChart, XAxis } from "recharts"; import { twMerge } from "tailwind-merge"; @@ -36,7 +30,7 @@ export type DailySummaryProps = { setBenchmarktype: (type: string) => void; }; -export default function DailySummary(props : DailySummaryProps) { +export default function DailySummary(props: DailySummaryProps) { const { data, benchmarkType, setBenchmarktype } = props; type ChartData = { name: string; totalQps: number }; const chartData: ChartData[] = []; @@ -46,10 +40,6 @@ export default function DailySummary(props : DailySummaryProps) { label: "Total QPS", color: "hsl(var(--primary))", }, - mobile: { - label: "Total QPS", - color: "hsl(var(--primary))", - }, } satisfies ChartConfig; if (data.data !== null) { @@ -66,9 +56,13 @@ export default function DailySummary(props : DailySummaryProps) { }; return ( - getBenchmarkType()}> + getBenchmarkType()} + > {data.name} @@ -125,9 +119,3 @@ const CustomTooltip = ({ return null; }; - -CustomTooltip.propTypes = { - active: PropTypes.bool, - payload: PropTypes.array, - label: PropTypes.string, -}; diff --git a/website/src/components/ui/chart.tsx b/website/src/components/ui/chart.tsx index 4f613da21..3f4dc4876 100644 --- a/website/src/components/ui/chart.tsx +++ b/website/src/components/ui/chart.tsx @@ -1,3 +1,19 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + import * as React from "react" import * as RechartsPrimitive from "recharts" diff --git a/website/src/components/ui/scroll-area.tsx b/website/src/components/ui/scroll-area.tsx new file mode 100644 index 000000000..c1e7cf392 --- /dev/null +++ b/website/src/components/ui/scroll-area.tsx @@ -0,0 +1,62 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/library/utils" + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + {children} + + + + +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = "vertical", ...props }, ref) => ( + + + +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } diff --git a/website/src/components/ui/separator.tsx b/website/src/components/ui/separator.tsx index d0c715a80..b64067a58 100644 --- a/website/src/components/ui/separator.tsx +++ b/website/src/components/ui/separator.tsx @@ -1,3 +1,19 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + import * as React from "react" import * as SeparatorPrimitive from "@radix-ui/react-separator" diff --git a/website/src/components/ui/skeleton.tsx b/website/src/components/ui/skeleton.tsx index 5cd7c1239..f11197978 100644 --- a/website/src/components/ui/skeleton.tsx +++ b/website/src/components/ui/skeleton.tsx @@ -1,3 +1,19 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + import { cn } from "@/library/utils" function Skeleton({ diff --git a/website/src/hooks/useDailySummaryData.ts b/website/src/hooks/useDailySummaryData.ts index a8c8c2de6..76c23a672 100644 --- a/website/src/hooks/useDailySummaryData.ts +++ b/website/src/hooks/useDailySummaryData.ts @@ -1,3 +1,19 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + import useApiCall from "@/utils/Hook"; import { DailySummarydata, Workloads } from "@/types"; @@ -8,12 +24,12 @@ export default function useDailySummaryData(workloads: Workloads[]) { const { data: dataDailySummary, isLoading: isLoadingDailySummary, - error: errorDailySummary, + error: dailySummaryError, } = useApiCall(`${import.meta.env.VITE_API_URL}daily/summary?workloads=${workloadsQuery}`); return { dataDailySummary, isLoadingDailySummary, - errorDailySummary, + dailySummaryError, }; }; \ No newline at end of file diff --git a/website/src/pages/DailyPage/DailyPage.tsx b/website/src/pages/DailyPage/DailyPage.tsx index ec23808cb..c622caa3e 100644 --- a/website/src/pages/DailyPage/DailyPage.tsx +++ b/website/src/pages/DailyPage/DailyPage.tsx @@ -14,39 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { useState, useEffect } from "react"; -import RingLoader from "react-spinners/RingLoader"; +import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; -import useApiCall from "@/utils/Hook"; -import DailySummary from "@/common/DailySummary"; -import { MacroData, MacroDataValue, Workloads } from "@/types"; - -import { secondToMicrosecond } from "@/utils/Utils"; -import DailyHero from "./components/DailyHero"; -import useDailySummaryData from "@/hooks/useDailySummaryData"; import { Separator } from "@/components/ui/separator"; -import { Skeleton } from "@/components/ui/skeleton"; -import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; -import { CartesianGrid, XAxis, Line, LineChart } from "recharts"; -import { - ChartTooltipContent, - ChartTooltip, - ChartContainer, -} from "@/components/ui/chart"; -import ResponsiveChart from "./components/Chart"; - -interface DailySummarydata { - name: string; - data: { total_qps: MacroDataValue }[]; -} - -type NumberDataPoint = { x: string; y: number }; -type StringDataPoint = { x: string; y: string }; - -type ChartDataItem = - | { id: string; data: NumberDataPoint[] } - | { id: string; data: StringDataPoint[] }; +import DailyCharts from "./components/DailyCharts"; +import DailyHero from "./components/DailyHero"; +import DailDailySummary from "./components/DailyDailySummary"; export default function DailyPage() { const urlParams = new URLSearchParams(window.location.search); @@ -54,294 +28,19 @@ export default function DailyPage() { urlParams.get("type") ?? "OLTP" ); - const { - data: dataDaily, - error: dailyError, - textLoading: dailyTextLoading, - } = useApiCall( - `${import.meta.env.VITE_API_URL}daily?workloads=${benchmarkType}` - ); - const navigate = useNavigate(); useEffect(() => { navigate(`?type=${benchmarkType}`); }, [benchmarkType]); - const TPSData: { id: string; data: NumberDataPoint[] }[] = [ - { - id: "TPS", - data: [], - }, - ]; - - const QPSData: { id: string; data: NumberDataPoint[] }[] = [ - { - id: "Reads", - data: [], - }, - { - id: "Total", - data: [], - }, - - { - id: "Writes", - data: [], - }, - - { - id: "Other", - data: [], - }, - ]; - - const latencyData: { id: string; data: NumberDataPoint[] }[] = [ - { - id: "Latency", - data: [], - }, - ]; - - const CPUTimeData: { id: string; data: StringDataPoint[] }[] = [ - { - id: "Total", - data: [], - }, - { - id: "vtgate", - data: [], - }, - { - id: "vttablet", - data: [], - }, - ]; - - const MemBytesData: { id: string; data: NumberDataPoint[] }[] = [ - { - id: "Total", - data: [], - }, - { - id: "vtgate", - data: [], - }, - { - id: "vttablet", - data: [], - }, - ]; - - for (const item of dataDaily) { - const xValue = item.git_ref.slice(0, 8); - - // TPS Data - - TPSData[0].data.push({ - x: xValue, - y: item.tps.center, - }); - - // QPS Data - - QPSData[0].data.push({ - x: xValue, - y: item.reads_qps.center, - }); - - QPSData[1].data.push({ - x: xValue, - y: item.total_qps.center, - }); - - QPSData[2].data.push({ - x: xValue, - y: item.writes_qps.center, - }); - - QPSData[3].data.push({ - x: xValue, - y: item.other_qps.center, - }); - - // Latency Data - - latencyData[0].data.push({ - x: xValue, - y: item.latency.center, - }); - - // CPUTime Data - - CPUTimeData[0].data.push({ - x: xValue, - y: secondToMicrosecond(item.total_components_cpu_time.center), - }); - - CPUTimeData[1].data.push({ - x: xValue, - y: secondToMicrosecond(item.components_cpu_time.vtgate.center), - }); - - CPUTimeData[2].data.push({ - x: xValue, - y: secondToMicrosecond(item.components_cpu_time.vttablet.center), - }); - - //MemStatsAllocBytes Data - - MemBytesData[0].data.push({ - x: xValue, - y: item.total_components_mem_stats_alloc_bytes.center, - }); - - MemBytesData[1].data.push({ - x: xValue, - y: item.components_mem_stats_alloc_bytes.vtgate.center, - }); - - MemBytesData[2].data.push({ - x: xValue, - y: item.components_mem_stats_alloc_bytes.vttablet.center, - }); - } - - const allChartData: { - data: ChartDataItem[]; - title: string; - colors: string[]; - }[] = [ - { - data: QPSData, - title: "QPS (Queries per second)", - colors: ["#fad900", "orange", "brown", "purple"], - }, - { - data: TPSData, - title: "TPS (Transactions per second)", - colors: ["#fad900"], - }, - { - data: latencyData, - title: "Latency (ms)", - colors: ["#fad900"], - }, - { - data: CPUTimeData, - title: "CPU / query (μs)", - colors: ["#fad900", "orange", "brown"], - }, - { - data: MemBytesData, - title: "Allocated / query (bytes)", - colors: ["#fad900", "orange", "brown"], - }, - ]; - - const workloads: Workloads[] = [ - "OLTP", - "OLTP-READONLY", - "OLTP-SET", - "TPCC", - "TPCC_FK", - "TPCC_UNSHARDED", - "TPCC_FK_UNMANAGED", - ]; - - const { dataDailySummary, isLoadingDailySummary, errorDailySummary } = - useDailySummaryData(workloads); - - const [expandedStates, setExpandedStates] = useState( - Array(allChartData.length).fill(true) - ); - - const toggleExpand = (index: number) => { - setExpandedStates((prevStates) => { - const newStates = [...prevStates]; - newStates[index] = !newStates[index]; - return newStates; - }); - }; return ( <> -
- {isLoadingDailySummary && ( - <> - {workloads.map((_, index) => { - return ( - - ); - })} - - )} - - {!errorDailySummary && - dataDailySummary && - dataDailySummary.length > 0 && ( - <> - {dataDailySummary.map((dailySummary, index) => { - return ( - - ); - })} - - - - )} -
- - {dailyTextLoading && ( -
- -
- )} - - {!dailyTextLoading && benchmarkType !== "" && ( -
- {allChartData.map((chartData, index) => ( - - toggleExpand(index)} - > -
- - {chartData.title} - - -
-
- {expandedStates[index] && ( - -
- -
-
- )} -
- ))} -
- )} - - {(errorDailySummary || dailyError) && ( -
{dailyError}
- )} + + + ); } diff --git a/website/src/pages/DailyPage/components/Chart.tsx b/website/src/pages/DailyPage/components/Chart.tsx deleted file mode 100644 index 7ee88caca..000000000 --- a/website/src/pages/DailyPage/components/Chart.tsx +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2023 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from "react"; -import PropTypes from "prop-types"; - -import { ResponsiveLine } from "@nivo/line"; - -const ResponsiveChart = ({ data, title, colors }) => { - return ( - data[0].data.length > 0 && ( - <> - {/*

{title}

*/} - ( -
-
-
- commit : {point.data.x} - - {title.split("(")[0]} : {point.data.y} - -
-
- )} - areaBaselineValue={50} - margin={{ top: 50, right: 110, bottom: 50, left: 60 }} - xScale={{ type: "point" }} - yScale={{ - type: "linear", - min: "0", - max: "auto", - reverse: false, - }} - yFormat=" >-.2f" - axisTop={null} - axisRight={null} - pointSize={10} - isInteractive={true} - pointBorderWidth={2} - pointBorderColor={{ from: "serieColor" }} - pointLabelYOffset={-12} - areaOpacity={0.1} - useMesh={true} - legends={[ - { - anchor: "bottom-right", - direction: "column", - justify: false, - translateX: 100, - translateY: 0, - itemsSpacing: 0, - itemDirection: "left-to-right", - itemWidth: 80, - itemHeight: 20, - itemOpacity: 0.75, - symbolSize: 12, - symbolShape: "circle", - symbolBorderColor: "rgba(0, 0, 0, .5)", - effects: [ - { - on: "hover", - style: { - itemBackground: "rgba(0, 0, 0, .03)", - itemOpacity: 1, - }, - }, - ], - }, - ]} - /> - - ) - ); -}; - -ResponsiveChart.propTypes = { - data: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - data: PropTypes.arrayOf( - PropTypes.shape({ - x: PropTypes.string.isRequired, - y: PropTypes.number.isRequired, - }) - ).isRequired, - }) - ).isRequired, - title: PropTypes.string.isRequired, - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - isFirstChart: PropTypes.bool.isRequired, -}; - -export default ResponsiveChart; diff --git a/website/src/pages/DailyPage/components/DailyCharts.tsx b/website/src/pages/DailyPage/components/DailyCharts.tsx new file mode 100644 index 000000000..c03b85970 --- /dev/null +++ b/website/src/pages/DailyPage/components/DailyCharts.tsx @@ -0,0 +1,307 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { ChartContainer, ChartTooltip } from "@/components/ui/chart"; +import { Skeleton } from "@/components/ui/skeleton"; +import { MacroData, Workloads } from "@/types"; +import useApiCall from "@/utils/Hook"; +import { secondToMicrosecond } from "@/utils/Utils"; +import { useEffect, useState } from "react"; +import { CartesianGrid, Legend, Line, LineChart, XAxis, YAxis } from "recharts"; + +export type DailyChartsProps = { + benchmarkType: string; +}; + +type NumberDataPoint = { x: string; y: number }; +type StringDataPoint = { x: string; y: string }; + +type ChartDataItem = + | { id: string; data: NumberDataPoint[] } + | { id: string; data: StringDataPoint[] }; + +type ChartDatas = { + data: ChartDataItem[]; + title: string; + colors: string[]; +}; + +const chartConfig: { [key: string]: { label: string; color: string } } = { + qpsReads: { + label: "Reads", + color: "hsl(var(--chart-qpsReads))", + }, + qpsWrites: { + label: "Writes", + color: "hsl(var(--chart-qpsWrites))", + }, + qpsOther: { + label: "Other", + color: "hsl(var(--chart-qpsOther))", + }, + qpsTotal: { + label: "Total", + color: "hsl(var(--chart-qpsTotal))", + }, + tps: { + label: "TPS", + color: "hsl(var(--chart-tps))", + }, + latency: { + label: "Latency", + color: "hsl(var(--chart-latency))", + }, + cpuTimeTotal: { + label: "Total", + color: "hsl(var(--chart-cpuTimeTotal))", + }, + cpuTimeVtgate: { + label: "Vtgate", + color: "hsl(var(--chart-cpuTimeVtgate))", + }, + cpuTimeVttablet: { + label: "Vttablet", + color: "hsl(var(--chart-cpuTimeVttablet))", + }, + memBytesVtgate: { + label: "Vtgate", + color: "hsl(var(--chart-memBytesVtgate))", + }, + memBytesVttablet: { + label: "Vttablet", + color: "hsl(var(--chart-memBytesVttablet))", + }, + memBytesTotal: { + label: "Total", + color: "hsl(var(--chart-memBytesTotal))", + }, +}; + +export default function DailyCharts(props: DailyChartsProps) { + const { benchmarkType } = props; + const workloads: Workloads[] = [ + "OLTP", + "OLTP-READONLY", + "OLTP-SET", + "TPCC", + "TPCC_FK", + "TPCC_UNSHARDED", + "TPCC_FK_UNMANAGED", + ]; + + const workloadsQuery = workloads.join("&workloads="); + + const { + data: dataDaily, + error: dailyError, + textLoading: dailyTextLoading, + } = useApiCall( + `${import.meta.env.VITE_API_URL}daily?workloads=${workloadsQuery}` + ); + + const chartData = dataDaily.map((item) => ({ + gitRef: item.git_ref.slice(0, 8), + qpsReads: item.reads_qps.center, + qpsWrites: item.writes_qps.center, + qpsOther: item.other_qps.center, + qpsTotal: item.total_qps.center, + tps: item.tps.center, + latency: item.latency.center, + cpuTimeTotal: Number( + (item.total_components_cpu_time.center * 1000000).toFixed(2) + ), + cpuTimeVtgate: Number( + (item.components_cpu_time.vtgate.center * 1000000).toFixed(2) + ), + cpuTimeVttablet: Number( + (item.components_cpu_time.vttablet.center * 1000000).toFixed(2) + ), + memBytesTotal: item.total_components_mem_stats_alloc_bytes.center, + memBytesVtgate: item.components_mem_stats_alloc_bytes.vtgate.center, + memBytesVttablet: item.components_mem_stats_alloc_bytes.vttablet.center, + })); + + const chartMetadas = [ + { + title: "QPS (Queries per second)", + dataKeys: ["qpsReads", "qpsTotal", "qpsWrites", "qpsOther"], + }, + { + title: "TPS (Transactions per second)", + dataKeys: ["tps"], + }, + { + title: "Latency (ms)", + dataKeys: ["latency"], + }, + { + title: "CPU / query (μs)", + dataKeys: ["cpuTimeTotal", "cpuTimeVtgate", "cpuTimeVttablet"], + }, + { + title: "Allocated / query (bytes)", + dataKeys: ["memBytesTotal", "memBytesVtgate", "memBytesVttablet"], + }, + ]; + + const [expandedStates, setExpandedStates] = useState( + Array(chartMetadas.length).fill(true) + ); + + const toggleExpand = (index: number) => { + setExpandedStates((prevStates) => { + const newStates = [...prevStates]; + newStates[index] = !newStates[index]; + return newStates; + }); + }; + + useEffect(() => { + setExpandedStates(Array(chartMetadas.length).fill(true)); + }, [chartMetadas.length]); + + return ( + <> +
+
+

+ {benchmarkType} +

+
{" "} + {dailyTextLoading + ? chartMetadas.map((_, index) => ( + + )) + : chartMetadas.map((chartMetadata, chartMetadataIndex) => ( + + toggleExpand(chartMetadataIndex)} + > +
+ + {chartMetadata.title} + + +
+
+ {expandedStates[chartMetadataIndex] && ( + +
+ + + + + + } + /> + {chartMetadata.dataKeys.map( + (dataKey, dataKeyIndex) => ( + + ) + )} + + + +
+
+ )} +
+ ))} +
+ {dailyError && ( +
{dailyError}
+ )} + + ); +} + +const CustomTooltip = ({ + active, + payload, + label, +}: { + active?: boolean; + payload?: { color: string; name: string; value: number }[]; + label?: string; +}) => { + if (payload) { + // Sort payload to have the same order as the chartConfig + payload.sort((a, b) => { + return ( + Object.keys(chartConfig).indexOf(a.name) - + Object.keys(chartConfig).indexOf(b.name) + ); + }); + } + if (active && payload && payload.length) { + return ( +
+

Commit: {label}

+ {payload.map((entry, index) => ( +

+ + + {`${chartConfig[entry.name].label}: `}{" "} + {`${entry.value.toFixed(0)}`} + +

+ ))} +
+ ); + } + + return null; +}; diff --git a/website/src/pages/DailyPage/components/DailyDailySummary.tsx b/website/src/pages/DailyPage/components/DailyDailySummary.tsx new file mode 100644 index 000000000..64d5b43dd --- /dev/null +++ b/website/src/pages/DailyPage/components/DailyDailySummary.tsx @@ -0,0 +1,87 @@ +/* +Copyright 2023 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import DailySummary from "@/common/DailySummary"; +import { Skeleton } from "@/components/ui/skeleton"; +import useDailySummaryData from "@/hooks/useDailySummaryData"; +import { Workloads } from "@/types"; + +export type DailDailySummaryProps = { + benchmarkType: string; + setBenchmarktype: (type: string) => void; +}; + +export default function DailyDailySummary(props: DailDailySummaryProps) { + const { benchmarkType, setBenchmarktype } = props; + const workloads: Workloads[] = [ + "OLTP", + "OLTP-READONLY", + "OLTP-SET", + "TPCC", + "TPCC_FK", + "TPCC_UNSHARDED", + "TPCC_FK_UNMANAGED", + ]; + + const { dataDailySummary, isLoadingDailySummary, dailySummaryError } = + useDailySummaryData(workloads); + return ( + <> +
+ {isLoadingDailySummary && ( + <> + {workloads.map((_, index) => { + return ( + + ); + })} + + )} + + {dailySummaryError && ( +
+ {dailySummaryError} +
+ )} + + {!dailySummaryError && + dataDailySummary && + dataDailySummary.length > 0 && ( + <> + {dataDailySummary.map((dailySummary, index) => { + return ( + + ); + })} + + )} +
+

+ Y-Axis: Total QPS +   X-Axis:{" "} + Time +

+ + ); +} diff --git a/website/src/pages/DailyPage/components/DailyHero.tsx b/website/src/pages/DailyPage/components/DailyHero.tsx index c5cc777c7..e5291db92 100644 --- a/website/src/pages/DailyPage/components/DailyHero.tsx +++ b/website/src/pages/DailyPage/components/DailyHero.tsx @@ -13,24 +13,22 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ + import Hero, { HeroProps } from "@/common/Hero"; const heroProps: HeroProps = { title: "Daily", description: ( <> - We run all macro benchmark workloads against the main branch - every day. This is done to ensure the consistency of the results over - time. On this page, you can find graphs that show you the - results of all workloads over the last 30 days. Click - on a workload to see the historical results of that workload. + We run all macro benchmark workloads against the main branch every + day. This is done to ensure the consistency of the results over time. On + this page, you can find graphs that show you the results of all workloads + over the last 30 days. Click on a workload to see the historical results + of that workload. ), }; - export default function DailyHero() { - return ( - - ); + return ; } diff --git a/website/src/pages/DailyPage/components/DailySummary.tsx b/website/src/pages/DailyPage/components/DailySummary.tsx deleted file mode 100644 index ea5b6b22e..000000000 --- a/website/src/pages/DailyPage/components/DailySummary.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2023 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import PropTypes from "prop-types"; -import { ResponsiveLine } from "@nivo/line"; -import { twMerge } from "tailwind-merge"; - -const DailySummary = ({ data, setBenchmarktype, benchmarkType }) => { - const orange = "#E77002"; - - const transformedData = []; - - if (data.data !== null) { - transformedData.push({ - id: "QPSTotal", - data: data.data.map((item) => ({ - // x: item.CreatedAt, - y: item.total_qps.center, - })), - }); - } - - const getBenchmarkType = () => { - setBenchmarktype(data.name); - }; - - return ( -
{ - getBenchmarkType(); - }} - > - {data ? ( -
- -
- ) : null} -
-
-

{data.name}

- -
-
- ); -}; - -DailySummary.propTypes = { - data: PropTypes.shape({ - name: PropTypes.string.isRequired, - data: PropTypes.array, - }), - setBenchmarktype: PropTypes.func.isRequired, - isSelected: PropTypes.bool, -}; - -export default DailySummary; diff --git a/website/src/pages/Layout.tsx b/website/src/pages/Layout.tsx index f1ddd9cef..918775e4c 100644 --- a/website/src/pages/Layout.tsx +++ b/website/src/pages/Layout.tsx @@ -27,7 +27,6 @@ const Layout = () => {