mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-11 23:18:59 +08:00
Merge branch 'develop' into feat--add-react-query-dev-tools-in-dev-env
This commit is contained in:
commit
75815897b0
@ -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 bit’s enough ⎯ we’re getting your {{dataSource}}!"
|
||||
}
|
||||
|
@ -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 bit’s enough ⎯ we’re getting your logs!',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(queryByText('pending_data_placeholder')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('check error state', async () => {
|
||||
|
@ -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 bit’s enough ⎯ we’re getting your
|
||||
logs!
|
||||
{t('pending_data_placeholder', { dataSource: DataSource.LOGS })}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -39,6 +39,7 @@
|
||||
font-weight: 500;
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 (
|
||||
|
@ -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>
|
||||
|
@ -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] &&
|
||||
|
@ -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 = {
|
||||
|
@ -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}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
||||
);
|
||||
}
|
@ -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']> = [
|
||||
{
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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',
|
||||
|
9
frontend/src/utils/docLinks.ts
Normal file
9
frontend/src/utils/docLinks.ts
Normal 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;
|
Loading…
x
Reference in New Issue
Block a user