diff --git a/frontend/src/components/LogsFormatOptionsMenu/LogsFormatOptionsMenu.tsx b/frontend/src/components/LogsFormatOptionsMenu/LogsFormatOptionsMenu.tsx index 740ceaf5b7f..91d6aa30aae 100644 --- a/frontend/src/components/LogsFormatOptionsMenu/LogsFormatOptionsMenu.tsx +++ b/frontend/src/components/LogsFormatOptionsMenu/LogsFormatOptionsMenu.tsx @@ -417,11 +417,13 @@ export default function LogsFormatOptionsMenu({ {key} - addColumn.onRemove(id as string)} - /> + {addColumn?.value?.length > 1 && ( + addColumn.onRemove(id as string)} + /> + )} ))} {addColumn && addColumn?.value?.length === 0 && ( diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx index 85ce464db48..8645894dc2f 100644 --- a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx +++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx @@ -37,7 +37,7 @@ import useErrorNotification from 'hooks/useErrorNotification'; import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange'; import { useNotifications } from 'hooks/useNotifications'; import { mapCompositeQueryFromQuery } from 'lib/newQueryBuilder/queryBuilderMappers/mapCompositeQueryFromQuery'; -import { cloneDeep, isEqual } from 'lodash-es'; +import { cloneDeep, isEqual, omit } from 'lodash-es'; import { Check, ConciergeBell, @@ -256,13 +256,17 @@ function ExplorerOptions({ const { handleExplorerTabChange } = useHandleExplorerTabChange(); const { options, handleOptionsChange } = useOptionsMenu({ - storageKey: LOCALSTORAGE.TRACES_LIST_OPTIONS, - dataSource: DataSource.TRACES, + storageKey: + sourcepage === DataSource.TRACES + ? LOCALSTORAGE.TRACES_LIST_OPTIONS + : LOCALSTORAGE.LOGS_LIST_OPTIONS, + dataSource: sourcepage, aggregateOperator: StringOperators.NOOP, }); type ExtraData = { selectColumns?: BaseAutocompleteData[]; + version?: number; }; const updateOrRestoreSelectColumns = ( @@ -283,14 +287,20 @@ function ExplorerOptions({ console.error('Error parsing extraData:', error); } + let backwardCompatibleOptions = options; + + if (!extraData?.version) { + backwardCompatibleOptions = omit(options, 'version'); + } + if (extraData.selectColumns?.length) { handleOptionsChange({ - ...options, + ...backwardCompatibleOptions, selectColumns: extraData.selectColumns, }); } else if (!isEqual(defaultTraceSelectedColumns, options.selectColumns)) { handleOptionsChange({ - ...options, + ...backwardCompatibleOptions, selectColumns: defaultTraceSelectedColumns, }); } @@ -423,6 +433,7 @@ function ExplorerOptions({ extraData: JSON.stringify({ color, selectColumns: options.selectColumns, + version: 1, }), notifications, panelType: panelType || PANEL_TYPES.LIST, diff --git a/frontend/src/container/OptionsMenu/constants.ts b/frontend/src/container/OptionsMenu/constants.ts index 7bf6a007d1d..2e3c20e7c74 100644 --- a/frontend/src/container/OptionsMenu/constants.ts +++ b/frontend/src/container/OptionsMenu/constants.ts @@ -5,31 +5,33 @@ import { FontSize, OptionsQuery } from './types'; export const URL_OPTIONS = 'options'; export const defaultOptionsQuery: OptionsQuery = { - selectColumns: [ - { - key: 'timestamp', - dataType: DataTypes.String, - type: 'tag', - isColumn: true, - isJSON: false, - id: 'timestamp--string--tag--true', - isIndexed: false, - }, - { - key: 'body', - dataType: DataTypes.String, - type: 'tag', - isColumn: true, - isJSON: false, - id: 'body--string--tag--true', - isIndexed: false, - }, - ], + selectColumns: [], maxLines: 2, format: 'raw', fontSize: FontSize.SMALL, }; +export const defaultLogsSelectedColumns = [ + { + key: 'timestamp', + dataType: DataTypes.String, + type: 'tag', + isColumn: true, + isJSON: false, + id: 'timestamp--string--tag--true', + isIndexed: false, + }, + { + key: 'body', + dataType: DataTypes.String, + type: 'tag', + isColumn: true, + isJSON: false, + id: 'body--string--tag--true', + isIndexed: false, + }, +]; + export const defaultTraceSelectedColumns = [ { key: 'serviceName', diff --git a/frontend/src/container/OptionsMenu/types.ts b/frontend/src/container/OptionsMenu/types.ts index 2c57d66b283..b2382cd487d 100644 --- a/frontend/src/container/OptionsMenu/types.ts +++ b/frontend/src/container/OptionsMenu/types.ts @@ -17,6 +17,7 @@ export interface OptionsQuery { maxLines: number; format: LogViewMode; fontSize: FontSize; + version?: number; } export interface InitialOptions diff --git a/frontend/src/container/OptionsMenu/useOptionsMenu.ts b/frontend/src/container/OptionsMenu/useOptionsMenu.ts index e81fca43aa4..93f99348fbd 100644 --- a/frontend/src/container/OptionsMenu/useOptionsMenu.ts +++ b/frontend/src/container/OptionsMenu/useOptionsMenu.ts @@ -21,6 +21,7 @@ import { import { DataSource } from 'types/common/queryBuilder'; import { + defaultLogsSelectedColumns, defaultOptionsQuery, defaultTraceSelectedColumns, URL_OPTIONS, @@ -172,7 +173,7 @@ const useOptionsMenu = ({ if (dataSource === DataSource.LOGS) { // add timestamp and body to the list of attributes return [ - ...defaultOptionsQuery.selectColumns, + ...defaultLogsSelectedColumns, ...searchedAttributesData.payload.attributeKeys.filter( (attribute) => attribute.key !== 'body', ), diff --git a/frontend/src/pages/LogsExplorer/index.tsx b/frontend/src/pages/LogsExplorer/index.tsx index 5e4d1cf55f7..bbcbae311eb 100644 --- a/frontend/src/pages/LogsExplorer/index.tsx +++ b/frontend/src/pages/LogsExplorer/index.tsx @@ -9,11 +9,18 @@ import QuickFilters from 'components/QuickFilters/QuickFilters'; import { LOCALSTORAGE } from 'constants/localStorage'; import LogExplorerQuerySection from 'container/LogExplorerQuerySection'; import LogsExplorerViews from 'container/LogsExplorerViews'; +import { + defaultLogsSelectedColumns, + defaultOptionsQuery, + URL_OPTIONS, +} from 'container/OptionsMenu/constants'; +import { OptionsQuery } from 'container/OptionsMenu/types'; import LeftToolbarActions from 'container/QueryBuilder/components/ToolbarActions/LeftToolbarActions'; import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions'; import Toolbar from 'container/Toolbar/Toolbar'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; -import { isNull } from 'lodash-es'; +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 { DataSource } from 'types/common/queryBuilder'; @@ -73,6 +80,39 @@ function LogsExplorer(): JSX.Element { } }, [currentQuery.builder.queryData, currentQuery.builder.queryData.length]); + const { + queryData: optionsQueryData, + 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') + ) { + return { + ...query, + version: 1, + selectColumns: [ + // Add default timestamp and body columns + ...defaultLogsSelectedColumns, + ...query.selectColumns, + ], + }; + } + return query; + }; + + useEffect(() => { + const migratedQuery = migrateOptionsQuery(optionsQueryData); + // Only redirect if the query was actually modified + if (!isEqual(migratedQuery, optionsQueryData)) { + redirectWithOptionsData(migratedQuery); + } + }, [optionsQueryData, redirectWithOptionsData]); + const isMultipleQueries = useMemo( () => currentQuery.builder.queryData?.length > 1 ||