Merge branch 'develop' into feat--add-react-query-dev-tools-in-dev-env

This commit is contained in:
Shaheer Kochai 2024-07-08 10:53:14 +04:30 committed by GitHub
commit 75815897b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 177 additions and 51 deletions

View File

@ -6,5 +6,6 @@
"share": "Share",
"save": "Save",
"edit": "Edit",
"logged_in": "Logged In"
"logged_in": "Logged In",
"pending_data_placeholder": "Just a bit of patience, just a little bits enough ⎯ were getting your {{dataSource}}!"
}

View File

@ -120,11 +120,7 @@ describe('LogsExplorerViews -', () => {
// switch to table view
await userEvent.click(queryByTestId('table-view') as HTMLElement);
expect(
queryByText(
'Just a bit of patience, just a little bits enough ⎯ were getting your logs!',
),
).toBeInTheDocument();
expect(queryByText('pending_data_placeholder')).toBeInTheDocument();
});
it('check error state', async () => {

View File

@ -1,8 +1,11 @@
import './LogsLoading.styles.scss';
import { Typography } from 'antd';
import { useTranslation } from 'react-i18next';
import { DataSource } from 'types/common/queryBuilder';
export function LogsLoading(): JSX.Element {
const { t } = useTranslation('common');
return (
<div className="loading-logs">
<div className="loading-logs-content">
@ -13,8 +16,7 @@ export function LogsLoading(): JSX.Element {
/>
<Typography>
Just a bit of patience, just a little bits enough were getting your
logs!
{t('pending_data_placeholder', { dataSource: DataSource.LOGS })}
</Typography>
</div>
</div>

View File

@ -39,6 +39,7 @@
font-weight: 500;
line-height: 18px; /* 128.571% */
letter-spacing: -0.07px;
cursor: pointer;
}
}
}

View File

@ -6,6 +6,7 @@ import history from 'lib/history';
import { ArrowUpRight } from 'lucide-react';
import { DataSource } from 'types/common/queryBuilder';
import { isCloudUser } from 'utils/app';
import DOCLINKS from 'utils/docLinks';
export default function NoLogs({
dataSource,
@ -25,8 +26,10 @@ export default function NoLogs({
? ROUTES.GET_STARTED_APPLICATION_MONITORING
: ROUTES.GET_STARTED_LOGS_MANAGEMENT,
);
} else if (dataSource === 'traces') {
window.open(DOCLINKS.TRACES_EXPLORER_EMPTY_STATE, '_blank');
} else {
window.open(`https://signoz.io/docs/userguide/${dataSource}/`, '_blank');
window.open(`${DOCLINKS.USER_GUIDE}${dataSource}/`, '_blank');
}
};
return (

View File

@ -22,7 +22,7 @@ describe('PipelinePage container test', () => {
expect(asFragment()).toMatchSnapshot();
});
it('should handle search', async () => {
it.skip('should handle search', async () => {
const setPipelineValue = jest.fn();
const { getByPlaceholderText, container } = render(
<MemoryRouter>

View File

@ -7,6 +7,7 @@ import LogsError from 'container/LogsError/LogsError';
import { LogsLoading } from 'container/LogsLoading/LogsLoading';
import NoLogs from 'container/NoLogs/NoLogs';
import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config';
import { TracesLoading } from 'container/TracesExplorer/TraceLoading/TraceLoading';
import { useIsDarkMode } from 'hooks/useDarkMode';
import useUrlQuery from 'hooks/useUrlQuery';
import GetMinMax from 'lib/getMinMax';
@ -146,7 +147,8 @@ function TimeSeriesView({
style={{ height: '100%', width: '100%' }}
ref={graphRef}
>
{isLoading && <LogsLoading />}
{isLoading &&
(dataSource === DataSource.LOGS ? <LogsLoading /> : <TracesLoading />)}
{chartData &&
chartData[0] &&

View File

@ -14,6 +14,7 @@ import { convertDataValueToMs } from './utils';
function TimeSeriesViewContainer({
dataSource = DataSource.TRACES,
isFilterApplied,
}: TimeSeriesViewProps): JSX.Element {
const { stagedQuery, currentQuery, panelType } = useQueryBuilder();
@ -70,8 +71,7 @@ function TimeSeriesViewContainer({
return (
<TimeSeriesView
// TODO handle this when revamping trace explorer
isFilterApplied={false}
isFilterApplied={isFilterApplied}
isError={isError}
isLoading={isLoading}
data={responseData}
@ -83,6 +83,7 @@ function TimeSeriesViewContainer({
interface TimeSeriesViewProps {
dataSource?: DataSource;
isFilterApplied: boolean;
}
TimeSeriesViewContainer.defaultProps = {

View File

@ -4,6 +4,8 @@ import { LOCALSTORAGE } from 'constants/localStorage';
import { QueryParams } from 'constants/query';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import EmptyLogsSearch from 'container/EmptyLogsSearch/EmptyLogsSearch';
import NoLogs from 'container/NoLogs/NoLogs';
import { useOptionsMenu } from 'container/OptionsMenu';
import TraceExplorerControls from 'container/TracesExplorer/Controls';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
@ -20,11 +22,16 @@ import { AppState } from 'store/reducers';
import { DataSource } from 'types/common/queryBuilder';
import { GlobalReducer } from 'types/reducer/globalTime';
import { TracesLoading } from '../TraceLoading/TraceLoading';
import { defaultSelectedColumns, PER_PAGE_OPTIONS } from './configs';
import { Container, ErrorText, tableStyles } from './styles';
import { getListColumns, getTraceLink, transformDataWithDate } from './utils';
function ListView(): JSX.Element {
interface ListViewProps {
isFilterApplied: boolean;
}
function ListView({ isFilterApplied }: ListViewProps): JSX.Element {
const { stagedQuery, panelType } = useQueryBuilder();
const { selectedTime: globalSelectedTime, maxTime, minTime } = useSelector<
@ -49,7 +56,7 @@ function ListView(): JSX.Element {
QueryParams.pagination,
);
const { data, isFetching, isError } = useGetQueryRange(
const { data, isFetching, isLoading, isError } = useGetQueryRange(
{
query: stagedQuery || initialQueriesMap.traces,
graphType: panelType || PANEL_TYPES.LIST,
@ -122,18 +129,36 @@ function ListView(): JSX.Element {
[columns, onDragColumns],
);
const isDataPresent =
!isLoading &&
!isFetching &&
!isError &&
transformedQueryTableData.length === 0;
return (
<Container>
<TraceExplorerControls
isLoading={isFetching}
totalCount={totalCount}
config={config}
perPageOptions={PER_PAGE_OPTIONS}
/>
{transformedQueryTableData.length !== 0 && (
<TraceExplorerControls
isLoading={isFetching}
totalCount={totalCount}
config={config}
perPageOptions={PER_PAGE_OPTIONS}
/>
)}
{isError && <ErrorText>{data?.error || 'Something went wrong'}</ErrorText>}
{!isError && (
{(isLoading || (isFetching && transformedQueryTableData.length === 0)) && (
<TracesLoading />
)}
{isDataPresent && !isFilterApplied && (
<NoLogs dataSource={DataSource.TRACES} />
)}
{isDataPresent && isFilterApplied && <EmptyLogsSearch />}
{!isError && transformedQueryTableData.length !== 0 && (
<ResizeTable
tableLayout="fixed"
pagination={false}

View File

@ -0,0 +1,19 @@
.loading-traces {
padding: 24px 0;
height: 240px;
display: flex;
justify-content: center;
align-items: flex-start;
.loading-traces-content {
display: flex;
align-items: flex-start;
flex-direction: column;
.loading-gif {
height: 72px;
margin-left: -24px;
}
}
}

View File

@ -0,0 +1,24 @@
import './TraceLoading.styles.scss';
import { Typography } from 'antd';
import { useTranslation } from 'react-i18next';
import { DataSource } from 'types/common/queryBuilder';
export function TracesLoading(): JSX.Element {
const { t } = useTranslation('common');
return (
<div className="loading-traces">
<div className="loading-traces-content">
<img
className="loading-gif"
src="/Icons/loading-plane.gif"
alt="wait-icon"
/>
<Typography>
{t('pending_data_placeholder', { dataSource: DataSource.TRACES })}
</Typography>
</div>
</div>
);
}

View File

@ -7,7 +7,6 @@ import { generatePath, Link } from 'react-router-dom';
import { ListItem } from 'types/api/widgets/getQuery';
export const PER_PAGE_OPTIONS: number[] = [10, ...DEFAULT_PER_PAGE_OPTIONS];
export const TRACES_DETAILS_LINK = 'https://signoz.io/docs/userguide/traces/';
export const columns: ColumnsType<ListItem['data']> = [
{

View File

@ -4,6 +4,8 @@ import { DEFAULT_ENTITY_VERSION } from 'constants/app';
import { QueryParams } from 'constants/query';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import EmptyLogsSearch from 'container/EmptyLogsSearch/EmptyLogsSearch';
import NoLogs from 'container/NoLogs/NoLogs';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { Pagination } from 'hooks/queryPagination';
@ -11,13 +13,20 @@ import useUrlQueryData from 'hooks/useUrlQueryData';
import { memo, useMemo } from 'react';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { DataSource } from 'types/common/queryBuilder';
import { GlobalReducer } from 'types/reducer/globalTime';
import DOCLINKS from 'utils/docLinks';
import TraceExplorerControls from '../Controls';
import { columns, PER_PAGE_OPTIONS, TRACES_DETAILS_LINK } from './configs';
import { TracesLoading } from '../TraceLoading/TraceLoading';
import { columns, PER_PAGE_OPTIONS } from './configs';
import { ActionsContainer, Container } from './styles';
function TracesView(): JSX.Element {
interface TracesViewProps {
isFilterApplied: boolean;
}
function TracesView({ isFilterApplied }: TracesViewProps): JSX.Element {
const { stagedQuery, panelType } = useQueryBuilder();
const { selectedTime: globalSelectedTime, maxTime, minTime } = useSelector<
@ -29,7 +38,7 @@ function TracesView(): JSX.Element {
QueryParams.pagination,
);
const { data, isLoading } = useGetQueryRange(
const { data, isLoading, isFetching, isError } = useGetQueryRange(
{
query: stagedQuery || initialQueriesMap.traces,
graphType: panelType || PANEL_TYPES.TRACE,
@ -65,28 +74,49 @@ function TracesView(): JSX.Element {
return (
<Container>
<ActionsContainer>
<Typography>
This tab only shows Root Spans. More details
<Typography.Link href={TRACES_DETAILS_LINK} target="_blank">
{' '}
here
</Typography.Link>
</Typography>
<TraceExplorerControls
isLoading={isLoading}
totalCount={responseData?.length || 0}
perPageOptions={PER_PAGE_OPTIONS}
{(tableData || []).length !== 0 && (
<ActionsContainer>
<Typography>
This tab only shows Root Spans. More details
<Typography.Link href={DOCLINKS.TRACES_DETAILS_LINK} target="_blank">
{' '}
here
</Typography.Link>
</Typography>
<TraceExplorerControls
isLoading={isLoading}
totalCount={responseData?.length || 0}
perPageOptions={PER_PAGE_OPTIONS}
/>
</ActionsContainer>
)}
{(isLoading || (isFetching && (tableData || []).length === 0)) && (
<TracesLoading />
)}
{!isLoading &&
!isFetching &&
!isError &&
!isFilterApplied &&
(tableData || []).length === 0 && <NoLogs dataSource={DataSource.TRACES} />}
{!isLoading &&
!isFetching &&
(tableData || []).length === 0 &&
!isError &&
isFilterApplied && <EmptyLogsSearch />}
{(tableData || []).length !== 0 && (
<ResizeTable
loading={isLoading}
columns={columns}
tableLayout="fixed"
dataSource={tableData}
scroll={{ x: true }}
pagination={false}
/>
</ActionsContainer>
<ResizeTable
loading={isLoading}
columns={columns}
tableLayout="fixed"
dataSource={tableData}
scroll={{ x: true }}
pagination={false}
/>
)}
</Container>
);
}

View File

@ -23,7 +23,7 @@ import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange';
import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history';
import { cloneDeep, set } from 'lodash-es';
import { cloneDeep, isEmpty, set } from 'lodash-es';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { Dashboard } from 'types/api/dashboard/getAll';
@ -62,6 +62,12 @@ function TracesExplorer(): JSX.Element {
const currentTab = panelType || PANEL_TYPES.LIST;
const listQuery = useMemo(() => {
if (!stagedQuery || stagedQuery.builder.queryData.length < 1) return null;
return stagedQuery.builder.queryData.find((item) => !item.disabled) || null;
}, [stagedQuery]);
const isMultipleQueries = useMemo(
() =>
currentQuery.builder.queryData.length > 1 ||
@ -101,6 +107,7 @@ function TracesExplorer(): JSX.Element {
const tabsItems = getTabsItems({
isListViewDisabled: isMultipleQueries || isGroupByExist,
isFilterApplied: !isEmpty(listQuery?.filters.items),
});
const exportDefaultQuery = useMemo(

View File

@ -9,10 +9,12 @@ import { DataSource } from 'types/common/queryBuilder';
interface GetTabsItemsProps {
isListViewDisabled: boolean;
isFilterApplied: boolean;
}
export const getTabsItems = ({
isListViewDisabled,
isFilterApplied,
}: GetTabsItemsProps): TabsProps['items'] => [
{
label: (
@ -23,7 +25,7 @@ export const getTabsItems = ({
/>
),
key: PANEL_TYPES.LIST,
children: <ListView />,
children: <ListView isFilterApplied={isFilterApplied} />,
disabled: isListViewDisabled,
},
{
@ -35,13 +37,18 @@ export const getTabsItems = ({
/>
),
key: PANEL_TYPES.TRACE,
children: <TracesView />,
children: <TracesView isFilterApplied={isFilterApplied} />,
disabled: isListViewDisabled,
},
{
label: <TabLabel label="Time Series" isDisabled={false} />,
key: PANEL_TYPES.TIME_SERIES,
children: <TimeSeriesView dataSource={DataSource.TRACES} />,
children: (
<TimeSeriesView
dataSource={DataSource.TRACES}
isFilterApplied={isFilterApplied}
/>
),
},
{
label: 'Table View',

View File

@ -0,0 +1,9 @@
const DOCLINKS = {
TRACES_EXPLORER_EMPTY_STATE:
'https://signoz.io/docs/instrumentation/overview/?utm_source=product&utm_medium=traces-explorer-empty-state',
USER_GUIDE: 'https://signoz.io/docs/userguide/',
TRACES_DETAILS_LINK:
'https://signoz.io/docs/product-features/trace-explorer/?utm_source=product&utm_medium=traces-explorer-trace-tab#traces-view',
};
export default DOCLINKS;