From d6773f391bc4ebbfb2e55c29dd0ade983d0350ef Mon Sep 17 00:00:00 2001 From: Jordi Enric Date: Thu, 29 Aug 2024 11:48:43 +0200 Subject: [PATCH 1/4] show log errors as different colors in chart, update chart click filter --- .../interfaces/Settings/Logs/Logs.types.ts | 1 + .../interfaces/Settings/Logs/Logs.utils.ts | 23 ++++++++++++++++++- .../Settings/Logs/LogsPreviewer.tsx | 13 +++++++++-- apps/studio/components/ui/Charts/BarChart.tsx | 22 +++++++++++------- .../components/ui/Charts/Charts.constants.ts | 1 + .../components/ui/Charts/Charts.types.tsx | 2 +- .../pages/project/[ref]/logs/edge-logs.tsx | 2 +- 7 files changed, 51 insertions(+), 13 deletions(-) diff --git a/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts b/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts index f9c055618af46..ff6bfac43a53d 100644 --- a/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts +++ b/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts @@ -53,6 +53,7 @@ export interface CountData { export interface EventChartData extends Datum { count: number timestamp: string + has_error: boolean } type LFResponse = { diff --git a/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts b/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts index 3410dc3da7b60..e336e62dba26e 100644 --- a/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts +++ b/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts @@ -296,6 +296,24 @@ const calcChartStart = (params: Partial): [Dayjs, string] => return [its.add(-extendValue, trunc), trunc] } +function getErrorCondition(table: LogsTableName): string { + switch (table) { + case 'edge_logs': + return 'response.status_code >= 400' + case 'postgres_logs': + return "parsed.error_severity IN ('ERROR', 'FATAL', 'PANIC')" + case 'function_logs': + return "metadata.level IN ('error', 'fatal')" + case 'auth_logs': + return "metadata.level = 'error' OR metadata.status >= 400" + case 'function_edge_logs': + return 'response.status_code >= 400' + // Add conditions for other log types as needed + default: + return 'false' // Default to no errors if table type is unknown + } +} + /** * * generates log event chart query @@ -308,13 +326,16 @@ export const genChartQuery = ( const [startOffset, trunc] = calcChartStart(params) const where = genWhereStatement(table, filters) + const errorCondition = getErrorCondition(table) + let joins = genCrossJoinUnnests(table) return ` SELECT -- log-event-chart timestamp_trunc(t.timestamp, ${trunc}) as timestamp, - count(t.timestamp) as count + count(t.timestamp) as count, + LOGICAL_OR(${errorCondition}) as has_error FROM ${table} t ${joins} diff --git a/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx b/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx index 22d16b4419941..f928f01c28221 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx @@ -19,6 +19,7 @@ import { LOGS_TABLES, LOG_ROUTES_WITH_REPLICA_SUPPORT, LogsTableName } from './L import type { Filters, LogSearchCallback, LogTemplate, QueryType } from './Logs.types' import { ensureNoTimestampConflict, maybeShowUpgradePrompt } from './Logs.utils' import UpgradePrompt from './UpgradePrompt' +import dayjs from 'dayjs' /** * Acts as a container component for the entire log display @@ -229,10 +230,18 @@ export const LogsPreviewer = ({ { + // from should be 1 hour before the bar + // to should be 1 hour after the bar + const from = dayjs(isoTimestamp as string) + .subtract(1, 'hour') + .toISOString() + const to = dayjs(isoTimestamp as string) + .add(1, 'hour') + .toISOString() handleSearch('event-chart-bar-click', { query: filters.search_query as string, - to: isoTimestamp as string, - from: null, + to: to, + from: from, }) }} /> diff --git a/apps/studio/components/ui/Charts/BarChart.tsx b/apps/studio/components/ui/Charts/BarChart.tsx index ea05d94ae0ecf..4417bd50643df 100644 --- a/apps/studio/components/ui/Charts/BarChart.tsx +++ b/apps/studio/components/ui/Charts/BarChart.tsx @@ -82,7 +82,7 @@ const BarChart = ({ (focusDataIndex !== null && data && data[focusDataIndex] !== undefined && - day(data[focusDataIndex][xAxisKey]).format(customDateFormat)) || + day(String(data[focusDataIndex][xAxisKey])).format(customDateFormat)) || highlightedLabel ) } @@ -114,9 +114,11 @@ const BarChart = ({ highlightedValue={ typeof resolvedHighlightedValue === 'number' ? numberFormatter(resolvedHighlightedValue, valuePrecision) - : resolvedHighlightedValue + : typeof resolvedHighlightedValue === 'string' + ? resolvedHighlightedValue + : undefined } - highlightedLabel={resolvedHighlightedLabel} + highlightedLabel={String(resolvedHighlightedLabel)} minimalHeader={minimalHeader} /> @@ -163,9 +165,11 @@ const BarChart = ({ key={`cell-${index}`} className={`transition-all duration-300 ${onBarClick ? 'cursor-pointer' : ''}`} fill={ - focusDataIndex === index || focusDataIndex === null - ? CHART_COLORS.GREEN_1 - : CHART_COLORS.GREEN_2 + _entry.has_error + ? CHART_COLORS.YELLOW_1 + : focusDataIndex === index || focusDataIndex === null + ? CHART_COLORS.GREEN_1 + : CHART_COLORS.GREEN_2 } enableBackground={12} /> @@ -176,11 +180,13 @@ const BarChart = ({ {data && (
- {xAxisIsDate ? day(data[0][xAxisKey]).format(customDateFormat) : data[0][xAxisKey]} + {xAxisIsDate + ? day(String(data[0][xAxisKey])).format(customDateFormat) + : data[0][xAxisKey]} {xAxisIsDate - ? day(data[data?.length - 1]?.[xAxisKey]).format(customDateFormat) + ? day(String(data[data?.length - 1]?.[xAxisKey])).format(customDateFormat) : data[data?.length - 1]?.[xAxisKey]}
diff --git a/apps/studio/components/ui/Charts/Charts.constants.ts b/apps/studio/components/ui/Charts/Charts.constants.ts index a8bb2e8aca530..671c5e2d70fde 100644 --- a/apps/studio/components/ui/Charts/Charts.constants.ts +++ b/apps/studio/components/ui/Charts/Charts.constants.ts @@ -7,6 +7,7 @@ export const CHART_COLORS = { AXIS: 'hsl(var(--background-overlay-hover))', GREEN_1: 'hsl(var(--brand-default))', // #3ECF8E GREEN_2: 'hsl(var(--brand-500))', + YELLOW_1: 'hsl(var(--warning-600))', } // refer to packages/ui/radix-colors.js for full list of colors diff --git a/apps/studio/components/ui/Charts/Charts.types.tsx b/apps/studio/components/ui/Charts/Charts.types.tsx index 2890e58f4440e..b836c0973ca3f 100644 --- a/apps/studio/components/ui/Charts/Charts.types.tsx +++ b/apps/studio/components/ui/Charts/Charts.types.tsx @@ -38,7 +38,7 @@ export type HeaderType = { displayDateInUtc?: boolean } -export type Datum = Record +export type Datum = Record export interface TimeseriesDatum extends Datum { timestamp: string diff --git a/apps/studio/pages/project/[ref]/logs/edge-logs.tsx b/apps/studio/pages/project/[ref]/logs/edge-logs.tsx index 923dca7a204a8..dcef42de7c791 100644 --- a/apps/studio/pages/project/[ref]/logs/edge-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/edge-logs.tsx @@ -19,6 +19,6 @@ export const LogPage: NextPageWithLayout = () => { ) } -LogPage.getLayout = (page) => {page} +LogPage.getLayout = (page) => {page} export default LogPage From efd7748a237f37427130405344c6e3ef17145f90 Mon Sep 17 00:00:00 2001 From: Jordi Enric Date: Thu, 29 Aug 2024 12:17:38 +0200 Subject: [PATCH 2/4] fix type error --- apps/studio/components/ui/Charts/AreaChart.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/studio/components/ui/Charts/AreaChart.tsx b/apps/studio/components/ui/Charts/AreaChart.tsx index 933999a0cf198..cc32568e87a93 100644 --- a/apps/studio/components/ui/Charts/AreaChart.tsx +++ b/apps/studio/components/ui/Charts/AreaChart.tsx @@ -39,7 +39,7 @@ const AreaChart = ({ (focusDataIndex !== null && data && data[focusDataIndex] !== undefined && - day(data[focusDataIndex][xAxisKey]).format(customDateFormat)) || + day(String(data[focusDataIndex][xAxisKey])).format(customDateFormat)) || highlightedLabel const resolvedHighlightedValue = @@ -66,7 +66,9 @@ const AreaChart = ({ highlightedValue={ typeof resolvedHighlightedValue === 'number' ? numberFormatter(resolvedHighlightedValue, valuePrecision) - : resolvedHighlightedValue + : typeof resolvedHighlightedValue === 'string' + ? resolvedHighlightedValue + : undefined } highlightedLabel={resolvedHighlightedLabel} minimalHeader={minimalHeader} @@ -117,8 +119,8 @@ const AreaChart = ({
{data && (
- {dayjs(data[0][xAxisKey]).format(customDateFormat)} - {dayjs(data[data?.length - 1]?.[xAxisKey]).format(customDateFormat)} + {dayjs(String(data[0][xAxisKey])).format(customDateFormat)} + {dayjs(String(data[data?.length - 1]?.[xAxisKey])).format(customDateFormat)}
)} From dae65d91f1da524e7297259bcfad1e73e1459937 Mon Sep 17 00:00:00 2001 From: Jordi Enric Date: Thu, 29 Aug 2024 15:17:37 +0200 Subject: [PATCH 3/4] fix typerr in test --- apps/studio/tests/pages/projects/LogEventChart.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/studio/tests/pages/projects/LogEventChart.test.tsx b/apps/studio/tests/pages/projects/LogEventChart.test.tsx index bc488e2c289e7..b9f265c28ba1f 100644 --- a/apps/studio/tests/pages/projects/LogEventChart.test.tsx +++ b/apps/studio/tests/pages/projects/LogEventChart.test.tsx @@ -25,8 +25,8 @@ test('renders chart', async () => { render( From 799e93367fb94219ac1acc7df48fc5506b7e85ae Mon Sep 17 00:00:00 2001 From: Jordi Enric Date: Thu, 29 Aug 2024 15:18:20 +0200 Subject: [PATCH 4/4] reduce range to 5 min --- .../Settings/Logs/LogEventChart.tsx | 35 ++++++++++--------- .../Settings/Logs/LogsPreviewer.tsx | 11 +++--- .../studio/components/ui/Charts/AreaChart.tsx | 4 +-- apps/studio/components/ui/Charts/BarChart.tsx | 4 +-- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/apps/studio/components/interfaces/Settings/Logs/LogEventChart.tsx b/apps/studio/components/interfaces/Settings/Logs/LogEventChart.tsx index d403fda3a5b83..a6ae2eab3d3a2 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogEventChart.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogEventChart.tsx @@ -4,22 +4,25 @@ import type { EventChartData } from './Logs.types' export interface LogEventChartProps { data: EventChartData[] - onBarClick: (isoTimestamp: string) => void + onBarClick: (datum: Datum) => void } -const LogEventChart = ({ data, onBarClick }: LogEventChartProps) => ( - { - if (!datum.timestamp) return - onBarClick(datum.timestamp as string) - }} - customDateFormat="MMM D, HH:mm:s" - /> -) +const LogEventChart = ({ data, onBarClick }: LogEventChartProps) => { + return ( + { + if (!datum?.timestamp) return + onBarClick(datum) + }} + customDateFormat="MMM D, HH:mm:s" + xAxisIsDate={true} + /> + ) +} export default LogEventChart diff --git a/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx b/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx index f928f01c28221..682e5aaa5ccee 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx @@ -229,14 +229,15 @@ export const LogsPreviewer = ({ {!isLoading && showChart && ( { - // from should be 1 hour before the bar - // to should be 1 hour after the bar + onBarClick={({ isoTimestamp }) => { + // from should be $RANGE minutes before the bar + // to should be $RANGE minutes after the bar + const RANGE = 5 const from = dayjs(isoTimestamp as string) - .subtract(1, 'hour') + .subtract(RANGE, 'minute') .toISOString() const to = dayjs(isoTimestamp as string) - .add(1, 'hour') + .add(RANGE, 'minute') .toISOString() handleSearch('event-chart-bar-click', { query: filters.search_query as string, diff --git a/apps/studio/components/ui/Charts/AreaChart.tsx b/apps/studio/components/ui/Charts/AreaChart.tsx index cc32568e87a93..09861218cdaf7 100644 --- a/apps/studio/components/ui/Charts/AreaChart.tsx +++ b/apps/studio/components/ui/Charts/AreaChart.tsx @@ -68,9 +68,9 @@ const AreaChart = ({ ? numberFormatter(resolvedHighlightedValue, valuePrecision) : typeof resolvedHighlightedValue === 'string' ? resolvedHighlightedValue - : undefined + : '' } - highlightedLabel={resolvedHighlightedLabel} + highlightedLabel={String(resolvedHighlightedLabel || '')} minimalHeader={minimalHeader} /> diff --git a/apps/studio/components/ui/Charts/BarChart.tsx b/apps/studio/components/ui/Charts/BarChart.tsx index 4417bd50643df..69faf23108315 100644 --- a/apps/studio/components/ui/Charts/BarChart.tsx +++ b/apps/studio/components/ui/Charts/BarChart.tsx @@ -116,9 +116,9 @@ const BarChart = ({ ? numberFormatter(resolvedHighlightedValue, valuePrecision) : typeof resolvedHighlightedValue === 'string' ? resolvedHighlightedValue - : undefined + : '' } - highlightedLabel={String(resolvedHighlightedLabel)} + highlightedLabel={String(resolvedHighlightedLabel || '')} minimalHeader={minimalHeader} />