From a2e72a503ece2dd9d1bff7dfcda950a46487cf6b Mon Sep 17 00:00:00 2001 From: TzeYiing Date: Tue, 2 May 2023 18:31:33 +0900 Subject: [PATCH] feat: add append prop to ReportWidget, add top routes table --- .../interfaces/Reports/ReportWidget.tsx | 21 ++--- .../interfaces/Reports/Reports.constants.ts | 22 +++++ .../Reports/renderers/ApiRenderers.tsx | 87 ++++++++++++++++++- .../project/[ref]/reports/api-overview.tsx | 11 ++- 4 files changed, 125 insertions(+), 16 deletions(-) diff --git a/studio/components/interfaces/Reports/ReportWidget.tsx b/studio/components/interfaces/Reports/ReportWidget.tsx index ccb1edc4cc7..9de112607b0 100644 --- a/studio/components/interfaces/Reports/ReportWidget.tsx +++ b/studio/components/interfaces/Reports/ReportWidget.tsx @@ -15,14 +15,15 @@ export interface ReportWidgetProps { tooltip?: string className?: string renderer: (props: ReportWidgetRendererProps) => React.ReactNode - expandable?: (props: ReportWidgetRendererProps) => React.ReactNode - expandableText?: string + append?: (props: ReportWidgetRendererProps) => React.ReactNode + // for overriding props, such as data + appendProps?: Partial // omitting params will hide the "View in logs explorer" button params?: BaseReportParams | LogsEndpointParams isLoading: boolean } -export interface ReportWidgetRendererProps extends ReportWidgetProps { +export interface ReportWidgetRendererProps extends ReportWidgetProps { router: NextRouter projectRef: string } @@ -99,7 +100,7 @@ const ReportWidget: React.FC = (props) => { - + )} @@ -107,16 +108,8 @@ const ReportWidget: React.FC = (props) => { {props.data === undefined ? null : props.renderer({ ...props, router, projectRef })} - {props.expandable && ( - - - - - - {props.expandable && props.expandable({ ...props, router, projectRef })} - - - )} + {props.append && + props.append({ ...props, ...(props.appendProps || {}), router, projectRef })} ) diff --git a/studio/components/interfaces/Reports/Reports.constants.ts b/studio/components/interfaces/Reports/Reports.constants.ts index 025b39a3401..8bf1ab102cf 100644 --- a/studio/components/interfaces/Reports/Reports.constants.ts +++ b/studio/components/interfaces/Reports/Reports.constants.ts @@ -74,6 +74,28 @@ export const PRESET_CONFIG: Record = { ORDER BY timestamp ASC`, }, + topRoutes: { + queryType: "logs", + sql: (filters)=> ` + select + request.path as path, + request.method as method, + request.search as search, + count(t.id) as count + from edge_logs t + cross join unnest(metadata) as m + cross join unnest(m.response) as response + cross join unnest(m.request) as request + cross join unnest(request.headers) as headers + ${generateRexepWhere(filters)} + group by + request.path, request.method, request.search + order by + count desc + limit + 5 + ` + }, errorCounts: { queryType: 'logs', sql: (filters) => ` diff --git a/studio/components/interfaces/Reports/renderers/ApiRenderers.tsx b/studio/components/interfaces/Reports/renderers/ApiRenderers.tsx index 70a689b9eaa..1d52fb86020 100644 --- a/studio/components/interfaces/Reports/renderers/ApiRenderers.tsx +++ b/studio/components/interfaces/Reports/renderers/ApiRenderers.tsx @@ -1,5 +1,12 @@ -import { ReportWidgetProps } from '../ReportWidget' +import { ReportWidgetProps, ReportWidgetRendererProps } from '../ReportWidget' import BarChart from 'components/ui/Charts/BarChart' +import Table from 'components/to-be-cleaned/Table' +import { + jsonSyntaxHighlight, + TextFormatter, +} from 'components/interfaces/Settings/Logs/LogsFormatters' +import { Button, Collapsible, IconChevronRight } from 'ui' +import { queryParamsToObject } from '../Reports.utils' export const renderTotalRequests = ( props: ReportWidgetProps<{ @@ -24,6 +31,46 @@ export const renderTotalRequests = ( ) } +export const renderTopApiRoutes = ( + props: ReportWidgetRendererProps<{ + method: string + path: string + search: string + count: number + }> +) => { + const headerClasses = '!text-xs !py-2 p-0 font-bold !bg-scale-400' + const cellClasses = '!text-xs !py-2 truncate' + return ( + <> + + Request + Count + + } + body={ + <> + {props.data.map((datum) => ( + <> + + + + + + {datum.count} + + + + ))} + + } + /> + + ) +} + export const renderErrorCounts = ( props: ReportWidgetProps<{ timestamp: string @@ -74,3 +121,41 @@ export const renderResponseSpeed = ( /> ) } + +interface RouteTdContentProps { + method: string + path: string + search: string +} +const RouteTdContent = (datum: RouteTdContentProps) => ( + + +
+ + +
+ + +
+
+
+ +
+        
+
+
+
+) diff --git a/studio/pages/project/[ref]/reports/api-overview.tsx b/studio/pages/project/[ref]/reports/api-overview.tsx index 0a8ce4ba0df..3af36737286 100644 --- a/studio/pages/project/[ref]/reports/api-overview.tsx +++ b/studio/pages/project/[ref]/reports/api-overview.tsx @@ -12,6 +12,7 @@ import { renderTotalRequests, renderErrorCounts, renderResponseSpeed, + renderTopApiRoutes, } from 'components/interfaces/Reports/renderers/ApiRenderers' import { useState, useEffect } from 'react' import ReportHeader from 'components/interfaces/Reports/ReportHeader' @@ -64,6 +65,8 @@ export const ApiReport: NextPageWithLayout = () => { title="Total Requests" data={report.data.totalRequests || []} renderer={renderTotalRequests} + append={renderTopApiRoutes} + appendProps={{data: report.data.topRoutes || [] }} /> { projectRef ?? 'default' ) const totalRequests = queryHooks.totalRequests() + const topRoutes = queryHooks.topRoutes() const errorCounts = queryHooks.errorCounts() const responseSpeed = queryHooks.responseSpeed() - const activeHooks = [totalRequests, errorCounts, responseSpeed] + const activeHooks = [totalRequests, topRoutes, errorCounts, responseSpeed] const [filters, setFilters] = useState([]) const addFilter = (filter: ReportFilterItem) => { // use a deep equal when comparing objects. @@ -127,6 +131,9 @@ const useApiReport = () => { if (totalRequests[1].changeQuery) { totalRequests[1].changeQuery(PRESET_CONFIG.api.queries.totalRequests.sql(filters)) } + if (topRoutes[1].changeQuery) { + topRoutes[1].changeQuery(PRESET_CONFIG.api.queries.topRoutes.sql(filters)) + } if (errorCounts[1].changeQuery) { errorCounts[1].changeQuery(PRESET_CONFIG.api.queries.errorCounts.sql(filters)) } @@ -151,11 +158,13 @@ const useApiReport = () => { totalRequests: totalRequests[0].logData, errorCounts: errorCounts[0].logData, responseSpeed: responseSpeed[0].logData, + topRoutes: topRoutes[0].logData, }, params: { totalRequests: totalRequests[0].params, errorCounts: errorCounts[0].params, responseSpeed: responseSpeed[0].params, + topRoutes: topRoutes[0].params, }, mergeParams: handleSetParams, filters,