diff --git a/frontend/src/container/LocalTopNav/index.tsx b/frontend/src/container/LocalTopNav/index.tsx index 40010f5784..3de2f823ef 100644 --- a/frontend/src/container/LocalTopNav/index.tsx +++ b/frontend/src/container/LocalTopNav/index.tsx @@ -1,4 +1,5 @@ import { Col, Row, Space } from 'antd'; +import NewExplorerCTA from 'container/NewExplorerCTA'; import ShowBreadcrumbs from '../TopNav/Breadcrumbs'; import DateTimeSelector from '../TopNav/DateTimeSelection'; @@ -18,6 +19,7 @@ function LocalTopNav({ + {actions} {renderPermissions?.isDateTimeEnabled && (
diff --git a/frontend/src/container/NewExplorerCTA/config.ts b/frontend/src/container/NewExplorerCTA/config.ts index 783f576142..b2feeff572 100644 --- a/frontend/src/container/NewExplorerCTA/config.ts +++ b/frontend/src/container/NewExplorerCTA/config.ts @@ -1,3 +1,11 @@ +import ROUTES from 'constants/routes'; + export const RIBBON_STYLES = { top: '-0.75rem', }; + +export const buttonText = { + [ROUTES.LOGS_EXPLORER]: 'Switch to Old Logs Explorer', + [ROUTES.TRACE]: 'Try new Traces Explorer', + [ROUTES.LOGS]: 'Switch to New Logs Explorer', +}; diff --git a/frontend/src/container/NewExplorerCTA/index.tsx b/frontend/src/container/NewExplorerCTA/index.tsx index 93283b34a8..f93d2e636f 100644 --- a/frontend/src/container/NewExplorerCTA/index.tsx +++ b/frontend/src/container/NewExplorerCTA/index.tsx @@ -2,47 +2,57 @@ import { CompassOutlined } from '@ant-design/icons'; import { Badge, Button } from 'antd'; import ROUTES from 'constants/routes'; import history from 'lib/history'; -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { useLocation } from 'react-router-dom'; -import { RIBBON_STYLES } from './config'; +import { buttonText, RIBBON_STYLES } from './config'; function NewExplorerCTA(): JSX.Element | null { const location = useLocation(); const isTraceOrLogsExplorerPage = useMemo( - () => location.pathname === ROUTES.LOGS || location.pathname === ROUTES.TRACE, + () => + location.pathname === ROUTES.LOGS_EXPLORER || + location.pathname === ROUTES.TRACE || + location.pathname === ROUTES.LOGS, [location.pathname], ); - const onClickHandler = (): void => { - if (location.pathname === ROUTES.LOGS) { - history.push(ROUTES.LOGS_EXPLORER); + const onClickHandler = useCallback((): void => { + if (location.pathname === ROUTES.LOGS_EXPLORER) { + history.push(ROUTES.LOGS); } else if (location.pathname === ROUTES.TRACE) { history.push(ROUTES.TRACES_EXPLORER); + } else if (location.pathname === ROUTES.LOGS) { + history.push(ROUTES.LOGS_EXPLORER); } - }; + }, [location.pathname]); - const buttonText = useMemo( - () => - `Try new ${ROUTES.LOGS === location.pathname ? 'Logs' : 'Traces'} Explorer`, - [location.pathname], - ); - - if (!isTraceOrLogsExplorerPage) { - return null; - } - - return ( - + const button = useMemo( + () => ( + ), + [location.pathname, onClickHandler], + ); + + if (!isTraceOrLogsExplorerPage) { + return null; + } + + if (location.pathname === ROUTES.LOGS_EXPLORER) { + return button; + } + + return ( + + {button} ); } diff --git a/frontend/src/container/SideNav/menuItems.tsx b/frontend/src/container/SideNav/menuItems.tsx index dd5c271fad..f1305f3d19 100644 --- a/frontend/src/container/SideNav/menuItems.tsx +++ b/frontend/src/container/SideNav/menuItems.tsx @@ -31,7 +31,7 @@ const menuItems: SidebarMenu[] = [ icon: , }, { - key: ROUTES.LOGS, + key: ROUTES.LOGS_EXPLORER, label: 'Logs', icon: , }, diff --git a/frontend/src/container/TraceDetail/SelectedSpanDetails/config.ts b/frontend/src/container/TraceDetail/SelectedSpanDetails/config.ts new file mode 100644 index 0000000000..46d0a5fc90 --- /dev/null +++ b/frontend/src/container/TraceDetail/SelectedSpanDetails/config.ts @@ -0,0 +1,71 @@ +import { initialAutocompleteData, OPERATORS } from 'constants/queryBuilder'; +import getStep from 'lib/getStep'; +import { + BaseAutocompleteData, + DataTypes, +} from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData'; +import { EQueryType } from 'types/common/dashboard'; +import { DataSource, LogsAggregatorOperator } from 'types/common/queryBuilder'; +import { v4 as uuid } from 'uuid'; + +export const getTraceToLogsQuery = ( + traceId: string, + minTime: number, + maxTime: number, +): Query => { + const key: BaseAutocompleteData = { + id: uuid(), + dataType: DataTypes.String, + isColumn: true, + type: '', + isJSON: false, + key: 'trace_id', + }; + + const filters: TagFilter = { + items: [ + { + id: uuid(), + op: OPERATORS.IN, + value: traceId, + key, + }, + ], + op: 'AND', + }; + + const query: Query = { + id: uuid(), + queryType: EQueryType.QUERY_BUILDER, + clickhouse_sql: [], + promql: [], + builder: { + queryData: [ + { + filters, + dataSource: DataSource.LOGS, + disabled: false, + limit: null, + aggregateAttribute: initialAutocompleteData, + aggregateOperator: LogsAggregatorOperator.NOOP, + expression: 'A', + groupBy: [], + having: [], + legend: '', + orderBy: [], + queryName: 'A', + reduceTo: 'min', + stepInterval: getStep({ + start: minTime, + end: maxTime, + inputFormat: 'ns', + }), + }, + ], + queryFormulas: [], + }, + }; + + return query; +}; diff --git a/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx b/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx index db9fde5ecb..5afca32311 100644 --- a/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx +++ b/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx @@ -1,13 +1,19 @@ import { Button, Modal, Tabs, Tooltip, Typography } from 'antd'; import Editor from 'components/Editor'; import { StyledSpace } from 'components/Styled'; +import { QueryParams } from 'constants/query'; import ROUTES from 'constants/routes'; import { useIsDarkMode } from 'hooks/useDarkMode'; +import createQueryParams from 'lib/createQueryParams'; import history from 'lib/history'; import { useMemo, useState } from 'react'; +import { useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; +import { AppState } from 'store/reducers'; import { ITraceTree } from 'types/api/trace/getTraceItem'; +import { GlobalReducer } from 'types/reducer/globalTime'; +import { getTraceToLogsQuery } from './config'; import Events from './Events'; import { CardContainer, @@ -21,6 +27,10 @@ import Tags from './Tags'; function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element { const { tree, firstSpanStartTime } = props; + const { maxTime, minTime } = useSelector( + (state) => state.globalTime, + ); + const { id: traceId } = useParams(); const isDarkMode = useIsDarkMode(); @@ -75,9 +85,15 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element { ]; const onLogsHandler = (): void => { - const query = encodeURIComponent(`trace_id IN ('${traceId}')`); + const query = getTraceToLogsQuery(traceId, minTime, maxTime); - history.push(`${ROUTES.LOGS}?q=${query}`); + history.push( + `${ROUTES.LOGS_EXPLORER}?${createQueryParams({ + [QueryParams.compositeQuery]: JSON.stringify(query), + [QueryParams.startTime]: minTime, + [QueryParams.endTime]: maxTime, + })}`, + ); }; return (