From a84e462a656ec0d9da1b1299119e09711797eab5 Mon Sep 17 00:00:00 2001 From: Shaheer Kochai Date: Fri, 31 Jan 2025 10:25:47 +0430 Subject: [PATCH] Fix/check the flows of toggling logs timestamp and body columns (#6992) * fix: add default timestamp and body columns to live logs * refactor: use convertKeysToColumnFields instead of re-modifying the default columns * fix: remove the local storage selectColumns when clear view is clicked * fix: improve selectColumns migration handling --- .../ExplorerOptions/ExplorerOptions.tsx | 13 ++- .../container/LiveLogs/LiveLogsList/index.tsx | 6 +- .../ContextView/ContextLogRenderer.tsx | 12 +-- frontend/src/pages/LogsExplorer/index.tsx | 90 +++++++++++++++---- 4 files changed, 92 insertions(+), 29 deletions(-) diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx index 8645894dc2..8d81e69d0a 100644 --- a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx +++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx @@ -25,7 +25,10 @@ import { PANEL_TYPES } from 'constants/queryBuilder'; import ROUTES from 'constants/routes'; import ExportPanelContainer from 'container/ExportPanel/ExportPanelContainer'; import { useOptionsMenu } from 'container/OptionsMenu'; -import { defaultTraceSelectedColumns } from 'container/OptionsMenu/constants'; +import { + defaultLogsSelectedColumns, + defaultTraceSelectedColumns, +} from 'container/OptionsMenu/constants'; import { OptionsQuery } from 'container/OptionsMenu/types'; import { useGetSearchQueryParam } from 'hooks/queryBuilder/useGetSearchQueryParam'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; @@ -408,6 +411,14 @@ function ExplorerOptions({ const handleClearSelect = (): void => { removeCurrentViewFromLocalStorage(); + handleOptionsChange({ + ...options, + selectColumns: + sourcepage === DataSource.TRACES + ? defaultTraceSelectedColumns + : defaultLogsSelectedColumns, + }); + history.replace(DATASOURCE_VS_ROUTES[sourcepage]); }; diff --git a/frontend/src/container/LiveLogs/LiveLogsList/index.tsx b/frontend/src/container/LiveLogs/LiveLogsList/index.tsx index 0be9334849..4bb8ff18e1 100644 --- a/frontend/src/container/LiveLogs/LiveLogsList/index.tsx +++ b/frontend/src/container/LiveLogs/LiveLogsList/index.tsx @@ -13,6 +13,7 @@ import { InfinityWrapperStyled } from 'container/LogsExplorerList/styles'; import { convertKeysToColumnFields } from 'container/LogsExplorerList/utils'; import { Heading } from 'container/LogsTable/styles'; import { useOptionsMenu } from 'container/OptionsMenu'; +import { defaultLogsSelectedColumns } from 'container/OptionsMenu/constants'; import { useActiveLog } from 'hooks/logs/useActiveLog'; import { useCopyLogLink } from 'hooks/logs/useCopyLogLink'; import { useEventSource } from 'providers/EventSource'; @@ -53,7 +54,10 @@ function LiveLogsList({ logs }: LiveLogsListProps): JSX.Element { [logs, activeLogId], ); - const selectedFields = convertKeysToColumnFields(options.selectColumns); + const selectedFields = convertKeysToColumnFields([ + ...defaultLogsSelectedColumns, + ...options.selectColumns, + ]); const getItemContent = useCallback( (_: number, log: ILog): JSX.Element => { diff --git a/frontend/src/container/LogDetailedView/ContextView/ContextLogRenderer.tsx b/frontend/src/container/LogDetailedView/ContextView/ContextLogRenderer.tsx index cb5d85a966..90a8126227 100644 --- a/frontend/src/container/LogDetailedView/ContextView/ContextLogRenderer.tsx +++ b/frontend/src/container/LogDetailedView/ContextView/ContextLogRenderer.tsx @@ -5,6 +5,7 @@ import RawLogView from 'components/Logs/RawLogView'; import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar'; import { LOCALSTORAGE } from 'constants/localStorage'; import ShowButton from 'container/LogsContextList/ShowButton'; +import { convertKeysToColumnFields } from 'container/LogsExplorerList/utils'; import { useOptionsMenu } from 'container/OptionsMenu'; import { defaultLogsSelectedColumns } from 'container/OptionsMenu/constants'; import { FontSize } from 'container/OptionsMenu/types'; @@ -12,21 +13,12 @@ import { ORDERBY_FILTERS } from 'container/QueryBuilder/filters/OrderByFilter/co import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Virtuoso } from 'react-virtuoso'; -import { IField } from 'types/api/logs/fields'; import { ILog } from 'types/api/logs/log'; import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { DataSource, StringOperators } from 'types/common/queryBuilder'; import { useContextLogData } from './useContextLogData'; -const defaultLogsSelectedFields: IField[] = defaultLogsSelectedColumns.map( - (item) => ({ - name: item.key, - type: item.type, - dataType: item.dataType, - }), -); - function ContextLogRenderer({ isEdit, query, @@ -119,7 +111,7 @@ function ContextLogRenderer({ data={logTorender} linesPerRow={1} fontSize={options.fontSize} - selectedFields={defaultLogsSelectedFields} + selectedFields={convertKeysToColumnFields(defaultLogsSelectedColumns)} /> ), [log.id, options.fontSize], diff --git a/frontend/src/pages/LogsExplorer/index.tsx b/frontend/src/pages/LogsExplorer/index.tsx index 701b1931a8..e4b1b82da3 100644 --- a/frontend/src/pages/LogsExplorer/index.tsx +++ b/frontend/src/pages/LogsExplorer/index.tsx @@ -23,7 +23,8 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import useUrlQueryData from 'hooks/useUrlQueryData'; import { isEqual, isNull } from 'lodash-es'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; -import { useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { DataSource } from 'types/common/queryBuilder'; import { WrapperStyled } from './styles'; @@ -86,25 +87,80 @@ function LogsExplorer(): JSX.Element { redirectWithQuery: redirectWithOptionsData, } = useUrlQueryData(URL_OPTIONS, defaultOptionsQuery); - const migrateOptionsQuery = (query: OptionsQuery): OptionsQuery => { - // If version is missing AND timestamp/body are not in selectColumns, this is an old URL - if ( - !query.version && - !query.selectColumns.some((col) => col.key === 'timestamp') && - !query.selectColumns.some((col) => col.key === 'body') - ) { + // Get and parse stored columns from localStorage + const logListOptionsFromLocalStorage = useMemo(() => { + const data = getLocalStorageKey(LOCALSTORAGE.LOGS_LIST_OPTIONS); + + if (!data) return null; + + try { + const parsed = JSON.parse(data); + const hasValidColumns = Array.isArray(parsed?.selectColumns); + + return hasValidColumns ? parsed.selectColumns : null; + } catch { + return null; + } + }, []); + + // Check if the columns have the required columns (timestamp, body) + const hasRequiredColumns = useCallback( + (columns?: Array<{ key: string }> | null): boolean => { + if (!columns?.length) return false; + + const hasTimestamp = columns.some((col) => col.key === 'timestamp'); + const hasBody = columns.some((col) => col.key === 'body'); + + return hasTimestamp && hasBody; + }, + [], + ); + + // Merge the columns with the required columns (timestamp, body) if missing + const mergeWithRequiredColumns = useCallback( + (columns: BaseAutocompleteData[]): BaseAutocompleteData[] => [ + // Add required columns (timestamp, body) if missing + ...(!hasRequiredColumns(columns) ? defaultLogsSelectedColumns : []), + ...columns, + ], + [hasRequiredColumns], + ); + + // Migrate the options query to the new format + const migrateOptionsQuery = useCallback( + (query: OptionsQuery): OptionsQuery => { + // Skip if already migrated + if (query.version) return query; + + // Case 1: query has columns + if (query.selectColumns.length > 0) { + return { + ...query, + version: 1, + selectColumns: mergeWithRequiredColumns(query.selectColumns), + }; + } + + // Case 2: No query columns in but we have localStorage columns + if (logListOptionsFromLocalStorage?.selectColumns?.length > 0) { + return { + ...query, + version: 1, + selectColumns: mergeWithRequiredColumns( + logListOptionsFromLocalStorage.selectColumns, + ), + }; + } + + // Case 3: No columns anywhere, use defaults return { ...query, version: 1, - selectColumns: [ - // Add default timestamp and body columns - ...defaultLogsSelectedColumns, - ...query.selectColumns, - ], + selectColumns: defaultLogsSelectedColumns, }; - } - return query; - }; + }, + [mergeWithRequiredColumns, logListOptionsFromLocalStorage?.selectColumns], + ); useEffect(() => { const migratedQuery = migrateOptionsQuery(optionsQueryData); @@ -112,7 +168,7 @@ function LogsExplorer(): JSX.Element { if (!isEqual(migratedQuery, optionsQueryData)) { redirectWithOptionsData(migratedQuery); } - }, [optionsQueryData, redirectWithOptionsData]); + }, [migrateOptionsQuery, optionsQueryData, redirectWithOptionsData]); const isMultipleQueries = useMemo( () =>