Skip to content

Commit 55c963c

Browse files
feat: Log Count for correlation page (#428)
Co-authored-by: Koustav Das <78158736+Koustavd18@users.noreply.github.com> Co-authored-by: Koustav <kdkdas8@gmail.com>
1 parent 68fd658 commit 55c963c

24 files changed

+1461
-524
lines changed

src/api/query.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type CorrelationLogs = {
1818
startTime: Date;
1919
endTime: Date;
2020
limit: number;
21+
pageOffset: number;
2122
correlationCondition?: string;
2223
selectedFields?: string[];
2324
};
@@ -68,6 +69,12 @@ export const getCorrelationQueryLogsWithHeaders = (logsQuery: CorrelationLogs) =
6869
return Axios().post<LogsResponseWithHeaders>(endPoint, queryBuilder.getCorrelationQuery(), {});
6970
};
7071

72+
export const getCorrelationQueryCount = (logsQuery: CorrelationLogs) => {
73+
const queryBuilder = new CorrelationQueryBuilder(logsQuery);
74+
const endPoint = LOG_QUERY_URL();
75+
return Axios().post<Log[]>(endPoint, makeCustomQueryRequestData(logsQuery, queryBuilder.getCountQuery()), {});
76+
};
77+
7178
export const getStreamDataWithHeaders = (logsQuery: CorrelationLogs) => {
7279
const queryBuilder = new CorrelationQueryBuilder(logsQuery);
7380
const endPoint = LOG_QUERY_URL({ fields: true }, queryBuilder.getResourcePath());
@@ -76,7 +83,7 @@ export const getStreamDataWithHeaders = (logsQuery: CorrelationLogs) => {
7683

7784
// ------ Custom sql query
7885

79-
const makeCustomQueryRequestData = (logsQuery: LogsQuery, query: string) => {
86+
const makeCustomQueryRequestData = (logsQuery: LogsQuery | CorrelationLogs, query: string) => {
8087
const { startTime, endTime } = logsQuery;
8188
return { query, startTime: optimizeTime(startTime), endTime: optimizeTime(endTime) };
8289
};

src/components/Navbar/components/CorrelationIcon.tsx

+22-15
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,28 @@ export const CorrelationIcon = forwardRef<
77
strokeWidth?: number;
88
}
99
>(({ stroke, strokeWidth }, ref) => (
10-
<svg ref={ref} height="1.2rem" width="1.2rem" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
11-
<path
12-
d="M13.3333 17.3333L14.6667 18.6667C15.0203 19.0203 15.4999 19.219 16 19.219C16.5001 19.219 16.9797 19.0203 17.3333 18.6667L22.6667 13.3333C23.0203 12.9797 23.219 12.5001 23.219 12C23.219 11.4999 23.0203 11.0203 22.6667 10.6667L17.3333 5.33333C16.9797 4.97971 16.5001 4.78105 16 4.78105C15.4999 4.78105 15.0203 4.97971 14.6667 5.33333L9.33333 10.6667C8.97971 11.0203 8.78105 11.4999 8.78105 12C8.78105 12.5001 8.97971 12.9797 9.33333 13.3333L10.6667 14.6667"
13-
stroke={stroke}
14-
strokeWidth={strokeWidth}
15-
strokeLinecap="round"
16-
strokeLinejoin="round"
17-
/>
18-
<path
19-
d="M10.6667 6.66667L9.33333 5.33333C8.97971 4.97971 8.5001 4.78105 8 4.78105C7.4999 4.78105 7.02029 4.97971 6.66667 5.33333L1.33333 10.6667C0.979711 11.0203 0.781049 11.4999 0.781049 12C0.781049 12.5001 0.979711 12.9797 1.33333 13.3333L6.66667 18.6667C7.02029 19.0203 7.4999 19.219 8 19.219C8.5001 19.219 8.97971 19.0203 9.33333 18.6667L14.6667 13.3333C15.0203 12.9797 15.219 12.5001 15.219 12C15.219 11.4999 15.0203 11.0203 14.6667 10.6667L13.3333 9.33333"
20-
stroke={stroke}
21-
strokeWidth={strokeWidth}
22-
strokeLinecap="round"
23-
strokeLinejoin="round"
24-
/>
10+
<svg ref={ref} height="1.2rem" width="1.2rem" viewBox="0 0 32 26" fill="none" xmlns="http://www.w3.org/2000/svg">
11+
<g clipPath="url(#clip0_481_602)">
12+
<path
13+
d="M16.3953 21.6621L18.0485 23.3153C18.4869 23.7537 19.0815 24 19.7015 24C20.3215 24 20.9161 23.7537 21.3545 23.3153L27.9669 16.7029C28.4053 16.2645 28.6516 15.6699 28.6516 15.0499C28.6516 14.4299 28.4053 13.8353 27.9669 13.3969L21.3545 6.78457C20.9161 6.34615 20.3215 6.09985 19.7015 6.09985C19.0815 6.09985 18.4869 6.34615 18.0485 6.78457L11.4362 13.3969C10.9978 13.8353 10.7515 14.4299 10.7515 15.0499C10.7515 15.6699 10.9978 16.2645 11.4362 16.7029L13.0893 18.3561"
14+
stroke={stroke}
15+
strokeWidth={strokeWidth}
16+
strokeLinecap="round"
17+
strokeLinejoin="round"
18+
/>
19+
<path
20+
d="M13.0892 8.43764L11.4361 6.78457C10.9977 6.34615 10.4031 6.09985 9.78305 6.09985C9.16303 6.09985 8.56841 6.34615 8.12999 6.78457L1.51772 13.3969C1.07931 13.8353 0.833008 14.4299 0.833008 15.0499C0.833008 15.6699 1.07931 16.2645 1.51772 16.7029L8.12999 23.3153C8.56841 23.7537 9.16303 24 9.78305 24C10.4031 24 10.9977 23.7537 11.4361 23.3153L18.0484 16.7029C18.4868 16.2645 18.7332 15.6699 18.7332 15.0499C18.7332 14.4299 18.4868 13.8353 18.0484 13.3969L16.3953 11.7438"
21+
stroke={stroke}
22+
strokeWidth={strokeWidth}
23+
strokeLinecap="round"
24+
strokeLinejoin="round"
25+
/>
26+
<rect x="7" y="-0.199951" width="25" height="10.5" rx="3" fill="#2DD4BF" />
27+
<path
28+
d="M11.5503 5.49194H9.90674L9.89795 4.58667H11.2778C11.521 4.58667 11.7202 4.55591 11.8755 4.49438C12.0308 4.42993 12.1465 4.33765 12.2227 4.21753C12.3018 4.09448 12.3413 3.94507 12.3413 3.76929C12.3413 3.57007 12.3032 3.40894 12.2271 3.28589C12.1538 3.16284 12.0381 3.07349 11.8799 3.01782C11.7246 2.96216 11.5239 2.93433 11.2778 2.93433H10.3638V8.30005H9.04541V1.90161H11.2778C11.6499 1.90161 11.9824 1.93677 12.2754 2.00708C12.5713 2.07739 12.8218 2.18433 13.0269 2.32788C13.2319 2.47144 13.3887 2.65308 13.4971 2.8728C13.6055 3.0896 13.6597 3.34741 13.6597 3.64624C13.6597 3.90991 13.5996 4.15308 13.4795 4.37573C13.3623 4.59839 13.1763 4.78003 12.9214 4.92065C12.6694 5.06128 12.3398 5.13892 11.9326 5.15356L11.5503 5.49194ZM11.4932 8.30005H9.54639L10.0605 7.27173H11.4932C11.7246 7.27173 11.9136 7.23511 12.0601 7.16187C12.2065 7.08569 12.3149 6.98315 12.3853 6.85425C12.4556 6.72534 12.4907 6.57739 12.4907 6.4104C12.4907 6.2229 12.4585 6.0603 12.394 5.92261C12.3325 5.78491 12.2329 5.67944 12.0952 5.6062C11.9575 5.53003 11.7759 5.49194 11.5503 5.49194H10.2803L10.2891 4.58667H11.8711L12.1743 4.94263C12.564 4.93677 12.8774 5.00562 13.1147 5.14917C13.355 5.28979 13.5293 5.4729 13.6377 5.69849C13.749 5.92407 13.8047 6.16577 13.8047 6.42358C13.8047 6.83374 13.7153 7.17944 13.5366 7.46069C13.3579 7.73901 13.0957 7.94849 12.75 8.08911C12.4072 8.22974 11.9883 8.30005 11.4932 8.30005ZM19.0869 7.27173V8.30005H15.6812V7.27173H19.0869ZM16.1118 1.90161V8.30005H14.7935V1.90161H16.1118ZM18.6431 4.50757V5.50952H15.6812V4.50757H18.6431ZM19.0825 1.90161V2.93433H15.6812V1.90161H19.0825ZM22.8047 1.90161V8.30005H21.4907V1.90161H22.8047ZM24.7734 1.90161V2.93433H19.5527V1.90161H24.7734ZM27.6519 2.99585L25.9116 8.30005H24.5098L26.8872 1.90161H27.7793L27.6519 2.99585ZM29.0977 8.30005L27.353 2.99585L27.2124 1.90161H28.1133L30.5039 8.30005H29.0977ZM29.0186 5.91821V6.95093H25.6392V5.91821H29.0186Z"
29+
fill="black"
30+
/>
31+
</g>
2532
</svg>
2633
));
2734

src/hooks/useCorrelationQueryLogs.tsx

+17-14
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
import { getCorrelationQueryLogsWithHeaders } from '@/api/query';
2-
import useMountedState from './useMountedState';
3-
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
4-
import _ from 'lodash';
5-
import { AxiosError } from 'axios';
6-
import { useStreamStore } from '@/pages/Stream/providers/StreamProvider';
71
import {
82
CORRELATION_LOAD_LIMIT,
93
correlationStoreReducers,
104
useCorrelationStore,
115
} from '@/pages/Correlation/providers/CorrelationProvider';
6+
7+
import { AxiosError } from 'axios';
8+
import { LogsResponseWithHeaders } from '@/@types/parseable/api/query';
9+
import _ from 'lodash';
10+
import { getCorrelationQueryLogsWithHeaders } from '@/api/query';
1211
import { notifyError } from '@/utils/notification';
12+
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
13+
import useMountedState from './useMountedState';
1314
import { useQuery } from 'react-query';
14-
import { LogsResponseWithHeaders } from '@/@types/parseable/api/query';
15+
import { useState } from 'react';
16+
import { useStreamStore } from '@/pages/Stream/providers/StreamProvider';
1517

16-
const { setStreamData } = correlationStoreReducers;
18+
const { setStreamData, setIsCorrelatedFlag } = correlationStoreReducers;
1719

1820
export const useCorrelationQueryLogs = () => {
1921
const [error, setError] = useMountedState<string | null>(null);
@@ -22,6 +24,7 @@ export const useCorrelationQueryLogs = () => {
2224
const [currentStream] = useAppStore((store) => store.currentStream);
2325
const timePartitionColumn = _.get(streamInfo, 'time_partition', 'p_timestamp');
2426
const [timeRange] = useAppStore((store) => store.timeRange);
27+
const [loadingState, setLoading] = useState<boolean>(true);
2528
const [
2629
{
2730
tableOpts: { currentOffset },
@@ -39,13 +42,10 @@ export const useCorrelationQueryLogs = () => {
3942
correlationCondition: correlationCondition,
4043
};
4144

42-
const {
43-
isLoading: logsLoading,
44-
isRefetching: logsRefetching,
45-
refetch: getCorrelationData,
46-
} = useQuery(
45+
const { refetch: getCorrelationData } = useQuery(
4746
['fetch-logs', defaultQueryOpts],
4847
async () => {
48+
setLoading(true);
4949
const queryOpts = { ...defaultQueryOpts, streamNames };
5050
const response = await getCorrelationQueryLogsWithHeaders(queryOpts);
5151
return [response];
@@ -54,6 +54,7 @@ export const useCorrelationQueryLogs = () => {
5454
enabled: false,
5555
refetchOnWindowFocus: false,
5656
onSuccess: async (responses) => {
57+
setLoading(false);
5758
responses.map((data: { data: LogsResponseWithHeaders }) => {
5859
const logs = data.data;
5960
const isInvalidResponse = _.isEmpty(logs) || _.isNil(logs);
@@ -63,13 +64,15 @@ export const useCorrelationQueryLogs = () => {
6364
if (fields.length > 0 && !correlationCondition) {
6465
return setCorrelationStore((store) => setStreamData(store, currentStream || '', records));
6566
} else if (fields.length > 0 && correlationCondition) {
67+
setCorrelationStore((store) => setIsCorrelatedFlag(store, true));
6668
return setCorrelationStore((store) => setStreamData(store, 'correlatedStream', records));
6769
} else {
6870
notifyError({ message: `${currentStream} doesn't have any fields` });
6971
}
7072
});
7173
},
7274
onError: (data: AxiosError) => {
75+
setLoading(false);
7376
const errorMessage = data.response?.data as string;
7477
setError(_.isString(errorMessage) && !_.isEmpty(errorMessage) ? errorMessage : 'Failed to query logs');
7578
},
@@ -78,7 +81,7 @@ export const useCorrelationQueryLogs = () => {
7881

7982
return {
8083
error,
81-
loading: logsLoading || logsRefetching,
84+
loadingState,
8285
getCorrelationData,
8386
};
8487
};

src/hooks/useCorrelations.tsx

+2-38
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
import { useMutation, useQuery } from 'react-query';
22
import _ from 'lodash';
33

4-
import {
5-
deleteSavedCorrelation,
6-
getCorrelationById,
7-
getCorrelations,
8-
saveCorrelation,
9-
updateCorrelation,
10-
} from '@/api/correlations';
4+
import { deleteSavedCorrelation, getCorrelations, saveCorrelation, updateCorrelation } from '@/api/correlations';
115
import { correlationStoreReducers, useCorrelationStore } from '@/pages/Correlation/providers/CorrelationProvider';
126
import { notifyError, notifySuccess } from '@/utils/notification';
137
import { AxiosError, isAxiosError } from 'axios';
148
import { appStoreReducers, useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
15-
import dayjs from 'dayjs';
169

1710
const {
1811
setCorrelations,
@@ -22,7 +15,7 @@ const {
2215
cleanCorrelationStore,
2316
toggleSavedCorrelationsModal,
2417
} = correlationStoreReducers;
25-
const { setTimeRange, syncTimeRange } = appStoreReducers;
18+
const { syncTimeRange } = appStoreReducers;
2619
export const useCorrelationsQuery = () => {
2720
const [{ correlationId }, setCorrelatedStore] = useCorrelationStore((store) => store);
2821
const [, setAppStore] = useAppStore((store) => store);
@@ -44,30 +37,6 @@ export const useCorrelationsQuery = () => {
4437
},
4538
});
4639

47-
const {
48-
mutate: getCorrelationByIdMutation,
49-
isError: fetchCorrelationIdError,
50-
isSuccess: fetchCorrelationIdSuccess,
51-
isLoading: fetchCorrelationIdLoading,
52-
} = useMutation((correlationId: string) => getCorrelationById(correlationId), {
53-
onSuccess: (data: any) => {
54-
data.data.startTime &&
55-
data.data.endTime &&
56-
setAppStore((store) =>
57-
setTimeRange(store, {
58-
startTime: dayjs(data.data.startTime),
59-
endTime: dayjs(data.data.endTime),
60-
type: 'custom',
61-
}),
62-
);
63-
setCorrelatedStore((store) => setCorrelationId(store, data.data.id));
64-
setCorrelatedStore((store) => setActiveCorrelation(store, data.data));
65-
},
66-
onError: () => {
67-
notifyError({ message: 'Failed to fetch correlation' });
68-
},
69-
});
70-
7140
const { mutate: deleteSavedCorrelationMutation, isLoading: isDeleting } = useMutation(
7241
(data: { correlationId: string; onSuccess?: () => void }) => deleteSavedCorrelation(data.correlationId),
7342
{
@@ -143,11 +112,6 @@ export const useCorrelationsQuery = () => {
143112
deleteSavedCorrelationMutation,
144113
isDeleting,
145114

146-
fetchCorrelationIdError,
147-
fetchCorrelationIdSuccess,
148-
fetchCorrelationIdLoading,
149-
getCorrelationByIdMutation,
150-
151115
saveCorrelationMutation,
152116
isCorrelationSaving,
153117

src/layouts/MainLayout/providers/AppProvider.tsx

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { LogStreamData } from '@/@types/parseable/api/stream';
2-
import initContext from '@/utils/initContext';
1+
import { FIXED_DURATIONS, FixedDuration } from '@/constants/timeConstants';
2+
import dayjs, { Dayjs } from 'dayjs';
3+
34
import { AboutData } from '@/@types/parseable/api/about';
4-
import _ from 'lodash';
55
import { AxiosResponse } from 'axios';
6+
import { LogStreamData } from '@/@types/parseable/api/stream';
67
import { SavedFilterType } from '@/@types/parseable/api/savedFilters';
7-
import { FIXED_DURATIONS, FixedDuration } from '@/constants/timeConstants';
8-
import dayjs, { Dayjs } from 'dayjs';
8+
import _ from 'lodash';
9+
import initContext from '@/utils/initContext';
910
import timeRangeUtils from '@/utils/timeRangeUtils';
1011

1112
const { makeTimeRangeLabel } = timeRangeUtils;
@@ -57,6 +58,7 @@ type AppStore = {
5758
helpModalOpen: boolean;
5859
createStreamModalOpen: boolean;
5960
currentStream: null | string;
61+
streamForCorrelation: null | string;
6062
userRoles: UserRoles | null;
6163
userSpecificStreams: null | LogStreamData;
6264
userAccessMap: { [key: string]: boolean };
@@ -76,6 +78,7 @@ type AppStoreReducers = {
7678
toggleMaximize: (store: AppStore) => ReducerOutput;
7779
toggleHelpModal: (store: AppStore, val?: boolean) => ReducerOutput;
7880
changeStream: (store: AppStore, stream: string) => ReducerOutput;
81+
setStreamForCorrelation: (store: AppStore, stream: string) => ReducerOutput;
7982
setUserRoles: (store: AppStore, roles: UserRoles | null) => ReducerOutput;
8083
setshiftInterval: (store: AppStore, interval: number) => ReducerOutput;
8184
syncTimeRange: (store: AppStore) => ReducerOutput;
@@ -93,6 +96,7 @@ const initialState: AppStore = {
9396
maximized: false,
9497
helpModalOpen: false,
9598
currentStream: null,
99+
streamForCorrelation: null,
96100
userRoles: null,
97101
userSpecificStreams: null,
98102
userAccessMap: {},
@@ -208,6 +212,10 @@ const changeStream = (store: AppStore, stream: string) => {
208212
return { currentStream: stream, activeSavedFilters };
209213
};
210214

215+
const setStreamForCorrelation = (_store: AppStore, stream: string) => {
216+
return { streamForCorrelation: stream };
217+
};
218+
211219
const setUserRoles = (_store: AppStore, roles: UserRoles | null) => {
212220
return { userRoles: roles };
213221
};
@@ -240,6 +248,7 @@ const appStoreReducers: AppStoreReducers = {
240248
toggleMaximize,
241249
toggleHelpModal,
242250
changeStream,
251+
setStreamForCorrelation,
243252
setUserRoles,
244253
setUserSpecificStreams,
245254
setUserAccessMap,

src/pages/Correlation/Views/CorrelationFooter.tsx

+41-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { FC, useCallback } from 'react';
1+
import { FC, useCallback, useEffect } from 'react';
22
import { usePagination } from '@mantine/hooks';
3-
import { Box, Center, Group, Menu, Pagination, Stack } from '@mantine/core';
3+
import { Box, Center, Group, Menu, Pagination, Stack, Tooltip } from '@mantine/core';
44
import _ from 'lodash';
55
import { Text } from '@mantine/core';
66
import { IconSelector } from '@tabler/icons-react';
@@ -9,9 +9,37 @@ import classes from '../styles/Footer.module.css';
99
import { LOGS_FOOTER_HEIGHT } from '@/constants/theme';
1010
import { correlationStoreReducers, useCorrelationStore } from '@/pages/Correlation/providers/CorrelationProvider';
1111
import { LOG_QUERY_LIMITS, LOAD_LIMIT } from '@/pages/Stream/providers/LogsProvider';
12+
import { HumanizeNumber } from '@/utils/formatBytes';
1213

1314
const { setCurrentOffset, setCurrentPage, setPageAndPageData } = correlationStoreReducers;
1415

16+
const TotalCount = (props: { totalCount: number }) => {
17+
return (
18+
<Tooltip label={props.totalCount}>
19+
<Text style={{ fontSize: '0.7rem' }}>{HumanizeNumber(props.totalCount)}</Text>
20+
</Tooltip>
21+
);
22+
};
23+
24+
const TotalLogsCount = (props: { hasTableLoaded: boolean; isTableEmpty: boolean }) => {
25+
const [{ totalCount, perPage, pageData }] = useCorrelationStore((store) => store.tableOpts);
26+
const displayedCount = _.size(pageData);
27+
const showingCount = displayedCount < perPage ? displayedCount : perPage;
28+
if (typeof totalCount !== 'number' || typeof displayedCount !== 'number') return <Stack />;
29+
30+
return (
31+
<Stack style={{ alignItems: 'center', justifyContent: 'center', flexDirection: 'row' }} gap={6}>
32+
{!props.isTableEmpty ? (
33+
<>
34+
<Text style={{ fontSize: '0.7rem' }}>{`Showing ${showingCount} out of`}</Text>
35+
<TotalCount totalCount={totalCount} />
36+
<Text style={{ fontSize: '0.7rem' }}>records</Text>
37+
</>
38+
) : null}
39+
</Stack>
40+
);
41+
};
42+
1543
const LimitControl: FC = () => {
1644
const [opened, setOpened] = useMountedState(false);
1745
const [perPage, setCorrelationStore] = useCorrelationStore((store) => store.tableOpts.perPage);
@@ -58,12 +86,18 @@ const LimitControl: FC = () => {
5886

5987
const CorrelationFooter = (props: { loaded: boolean; hasNoData: boolean; isFetchingCount: boolean }) => {
6088
const [tableOpts, setCorrelationStore] = useCorrelationStore((store) => store.tableOpts);
61-
const { totalPages, currentOffset, currentPage, perPage, totalCount } = tableOpts;
89+
const [isCorrelatedData] = useCorrelationStore((store) => store.isCorrelatedData);
90+
const { totalPages, currentOffset, currentPage, perPage, totalCount, targetPage } = tableOpts;
6291

6392
const onPageChange = useCallback((page: number) => {
64-
setCorrelationStore((store) => setPageAndPageData(store, page));
93+
setCorrelationStore((store) => setPageAndPageData(store, page, perPage));
6594
}, []);
6695

96+
useEffect(() => {
97+
if (!props.loaded) return;
98+
pagination.setPage(targetPage ? targetPage : 1);
99+
}, [props.loaded]);
100+
67101
const pagination = usePagination({ total: totalPages ?? 1, initialPage: 1, onChange: onPageChange });
68102
const onChangeOffset = useCallback(
69103
(key: 'prev' | 'next') => {
@@ -87,11 +121,9 @@ const CorrelationFooter = (props: { loaded: boolean; hasNoData: boolean; isFetch
87121
return (
88122
<Stack className={classes.footerContainer} gap={0} style={{ height: LOGS_FOOTER_HEIGHT }}>
89123
<Stack w="100%" justify="center" align="flex-start">
90-
{/* <TotalLogsCount
91-
hasTableLoaded={props.loaded}
92-
isFetchingCount={props.isFetchingCount}
93-
isTableEmpty={props.hasNoData}
94-
/> */}
124+
{isCorrelatedData && totalCount > 0 && (
125+
<TotalLogsCount hasTableLoaded={props.loaded} isTableEmpty={props.hasNoData} />
126+
)}
95127
</Stack>
96128
<Stack w="100%" justify="center">
97129
{props.loaded ? (

0 commit comments

Comments
 (0)