Skip to content
This repository was archived by the owner on May 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions src/components/Navbar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Box, Stack, Tooltip } from '@mantine/core';
import { Box, Divider, Stack, Tooltip } from '@mantine/core';
import { IconLogout, IconUser, IconBinaryTree2, IconInfoCircle, IconUserCog, IconHome, IconServerCog } from '@tabler/icons-react';
import { FC, useCallback, useEffect } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { useHeaderContext } from '@/layouts/MainLayout/Context';
import { useDisclosure } from '@mantine/hooks';
import { HOME_ROUTE, LOGS_ROUTE, SYSTEMS_ROUTE, USERS_MANAGEMENT_ROUTE } from '@/constants/routes';
import { HOME_ROUTE, LOGS_ROUTE, CLUSTER_ROUTE, USERS_MANAGEMENT_ROUTE } from '@/constants/routes';
import InfoModal from './infoModal';
import { getStreamsSepcificAccess, getUserSepcificStreams } from './rolesHandler';
import Cookies from 'js-cookie';
Expand All @@ -30,6 +30,9 @@ const navItems = [
path: '/logs',
route: LOGS_ROUTE,
},
];

const previlagedActions = [
{
icon: IconUserCog,
label: 'Users',
Expand All @@ -38,11 +41,11 @@ const navItems = [
},
{
icon: IconServerCog,
label: 'Systems',
path: '/systems',
route: SYSTEMS_ROUTE,
label: 'Cluster',
path: '/cluster',
route: CLUSTER_ROUTE,
}
];
]

const navActions = [
{
Expand Down Expand Up @@ -138,7 +141,24 @@ const Navbar: FC = () => {
<div className={styles.navbarMain}>
<Stack justify="center" align="center" gap={0}>
{navItems.map((navItem, index) => {
const isActiveItem = navItem.route === currentRoute;
return (
<Stack
className={`${styles.navItemContainer} ${isActiveItem && styles.navItemActive}`}
gap={0}
onClick={() => navigateToPage(navItem.route)}
key={index}>
<Tooltip label={navItem.label} position="right">
<navItem.icon className={styles.navIcon} stroke={isActiveItem ? 1.2 : 1} size={'1.8rem'} />
</Tooltip>
</Stack>
);
})}
</Stack>
<Stack gap={4}>
{previlagedActions.map((navItem, index) => {
if (navItem.route === USERS_MANAGEMENT_ROUTE && !userSpecificAccessMap.hasUserAccess) return null;
if (navItem.route === CLUSTER_ROUTE && !userSpecificAccessMap.hasUserAccess) return null;

const isActiveItem = navItem.route === currentRoute;
return (
Expand All @@ -153,8 +173,7 @@ const Navbar: FC = () => {
</Stack>
);
})}
</Stack>
<Stack gap={0}>
<Divider />
{navActions.map((navAction, index) => {
const isActiveItem = false;
const onClick =
Expand Down
1 change: 1 addition & 0 deletions src/components/Navbar/rolesHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const adminAccess = [
'DeleteUser',
'PutRoles',
'GetRole',
'Cluster'
];
const editorAccess = [
'Ingest',
Expand Down
4 changes: 2 additions & 2 deletions src/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const STATS_ROUTE = '/:streamName/stats';
export const CONFIG_ROUTE = '/:streamName/config';
export const USERS_MANAGEMENT_ROUTE = '/users';
export const OIDC_NOT_CONFIGURED_ROUTE = '/oidc-not-configured';
export const SYSTEMS_ROUTE = '/systems';
export const CLUSTER_ROUTE = '/cluster';

export const PATHS = {
all: '/*',
Expand All @@ -19,5 +19,5 @@ export const PATHS = {
config: '/:streamName/config',
users: '/users',
oidcNotConfigured: '/oidc-not-configured',
systems: '/systems',
cluster: '/cluster',
} as { [key: string]: string };
3 changes: 2 additions & 1 deletion src/layouts/MainLayout/Context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ const accessKeyMap: { [key: string]: string } = {
hasDeleteAccess: 'DeleteStream',
hasUpdateAlertAccess: 'PutAlert',
hasGetAlertAccess: 'GetAlert',
hasCreateStreamAccess: 'CreateStream'
hasCreateStreamAccess: 'CreateStream',
hasClusterAccess: 'Cluster'
};

const generateUserAcccessMap = (accessRoles: string[] | null) => {
Expand Down
5 changes: 2 additions & 3 deletions src/pages/Logs/EventTimeLineGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const calcAverage = (data: GraphRecord[]) => {
const getAllTimestamps = (startTime: Dayjs) => {
const timestamps = [];
for (let i = 0; i < START_RANGE; i++) {
// Your code to be executed 30 times goes here
const ts = startTime.add(i + 1, 'minute')
timestamps.push(ts.toISOString().split('.')[0]+"Z")
}
Expand Down Expand Up @@ -87,7 +86,7 @@ function ChartTooltip({ payload }: ChartTooltipProps) {
const { minute, aboveAvgPercent } = payload[0]?.payload || {};
const isAboveAvg = aboveAvgPercent > 0;
const startTime = dayjs(minute).utc(true);
const endTime = dayjs(minute).add(59, 'seconds');
const endTime = dayjs(minute).add(60, 'seconds');
return (
<Paper px="md" py="sm" withBorder shadow="md" radius="md">
<Text fw={600} mb={5}>
Expand Down Expand Up @@ -154,7 +153,7 @@ const EventTimeLineGraph = () => {

const { minute } = samplePayload.payload || {};
const startTime = dayjs(minute);
const endTime = dayjs(minute).add(59, 'seconds');
const endTime = dayjs(minute).add(60, 'seconds');
subLogQuery.set((query) => {
query.startTime = startTime.toDate();
query.endTime = endTime.toDate();
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Logs/LogTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ const LogTable: FC = () => {
? PRIMARY_HEADER_HEIGHT + LOGS_PRIMARY_TOOLBAR_HEIGHT + LOGS_SECONDARY_TOOLBAR_HEIGHT
: 0;

const totalCount = Array.isArray(fetchQueryMutation?.data) ? fetchQueryMutation.data[0]?.count : null;
const totalCount = Array.isArray(fetchQueryMutation?.data) ? fetchQueryMutation.data[0]?.["COUNT(*)"] : null;
const loadedCount = pageLogData?.data.length || null;
return (
<Box
Expand Down
116 changes: 80 additions & 36 deletions src/pages/Systems/Ingestors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,27 @@ const TrLoadingState = () => (
);

function sanitizeIngestorUrl(url: string) {
if (url.startsWith("http://")) {
url = url.slice(7);
} else if (url.startsWith("https://")) {
url = url.slice(8);
}
if (url.endsWith("/")) {
url = url.slice(0, -1);
}
return url;
if (url.startsWith('http://')) {
url = url.slice(7);
} else if (url.startsWith('https://')) {
url = url.slice(8);
}

if (url.endsWith('/')) {
url = url.slice(0, -1);
}

return url;
}

const TableRow = (props: IngestorTableRow) => {
const { ingestor, metrics } = props;
const isOfflineIngestor = !ingestor.reachable;
const { deleteIngestorMutation, deleteIngestorIsLoading } = useDeleteIngestor();
const {getClusterInfoRefetch} = useClusterInfo()
const { getClusterInfoRefetch } = useClusterInfo();
return (
<Table.Tr key={ingestor.domain_name}>
<Table.Td>
<Table.Td style={{paddingLeft: '1.5rem'}}>
<Stack style={{ flexDirection: 'row' }} gap={8}>
{ingestor.domain_name}
{!ingestor.reachable && (
Expand All @@ -54,27 +54,43 @@ const TableRow = (props: IngestorTableRow) => {
<TrLoadingState />
) : (
<>
<Table.Td align="center">
<Table.Td align="center" style={{ borderRight: '1px solid #dcdcdc', borderLeft: '1px solid #dcdcdc' }}>
<Tooltip label={metrics?.parseable_events_ingested}>
<Text style={{ fontSize: 14 }}>
{isOfflineIngestor ? '–' : HumanizeNumber(metrics?.parseable_events_ingested || 0)}
</Text>
</Tooltip>
</Table.Td>
<Table.Td style={{ borderRight: '1px solid #dcdcdc', width: 120, padding: 0 }}>
<Text className={classes.cellText} style={{ textAlign: 'center', width: 120 }}>
{isOfflineIngestor ? '–' : formatBytes(metrics?.parseable_storage_size.data || 0)}
</Text>
</Table.Td>
<Table.Td style={{ borderRight: '1px solid #dcdcdc', width: 200, padding: 0 }}>
<Text className={classes.cellText} style={{ textAlign: 'left', width: 200, wordWrap: 'break-word', padding: '1rem' }}>
{ingestor.storage_path || 'Unknown'}
</Text>
</Table.Td>
<Table.Td align="center">
{isOfflineIngestor ? '–' : formatBytes(metrics?.parseable_storage_size.data || 0)}
<Table.Td style={{ borderRight: '1px solid #dcdcdc', width: 120, padding: 0 }}>
<Text className={classes.cellText} style={{ textAlign: 'center', width: 120 }}>
{isOfflineIngestor ? '–' : HumanizeNumber(metrics?.parseable_staging_files || 0)}
</Text>
</Table.Td>
<Table.Td align="center">
{isOfflineIngestor ? '–' : formatBytes(metrics?.process_resident_memory_bytes || 0)}
<Table.Td style={{ borderRight: '1px solid #dcdcdc', width: 120, padding: 0 }}>
<Text className={classes.cellText} style={{ textAlign: 'center', width: 120 }}>
{isOfflineIngestor ? '–' : formatBytes(metrics?.parseable_storage_size.staging || 0)}
</Text>
</Table.Td>
<Table.Td align="center">
{isOfflineIngestor ? '–' : HumanizeNumber(metrics?.parseable_staging_files || 0)}
<Table.Td style={{ borderRight: '1px solid #dcdcdc', width: 200, padding: 0 }}>
<Text className={classes.cellText} style={{ textAlign: 'left', width: 200, wordWrap: 'break-word', padding: '1rem' }}>
{ingestor.staging_path || 'Unknown'}
</Text>
</Table.Td>
<Table.Td align="center">
{isOfflineIngestor ? '–' : formatBytes(metrics?.parseable_storage_size.staging || 0)}
<Table.Td align="center" style={{ borderRight: '1px solid #dcdcdc' }}>
<Text style={{ fontSize: 14 }}>
{isOfflineIngestor ? '–' : formatBytes(metrics?.process_resident_memory_bytes || 0)}
</Text>
</Table.Td>
<Table.Td>{ingestor.staging_path || 'Unknown'}</Table.Td>
<Table.Td> {ingestor.storage_path || 'Unknown'}</Table.Td>
</>
)}
<Table.Td align="center">
Expand All @@ -84,7 +100,13 @@ const TableRow = (props: IngestorTableRow) => {
</Table.Td>
<Table.Td align="center">
{!ingestor.reachable ? (
<Box onClick={() => deleteIngestorMutation({ ingestorUrl: sanitizeIngestorUrl(ingestor.domain_name), onSuccess: getClusterInfoRefetch })}>
<Box
onClick={() =>
deleteIngestorMutation({
ingestorUrl: sanitizeIngestorUrl(ingestor.domain_name),
onSuccess: getClusterInfoRefetch,
})
}>
{deleteIngestorIsLoading ? (
<Loader size="sm" />
) : (
Expand All @@ -107,14 +129,36 @@ type IngestorTable = {
const TableHead = () => (
<Table.Thead>
<Table.Tr>
<Table.Th>Domain</Table.Th>
<Table.Th style={{ textAlign: 'center' }}>Events Ingested</Table.Th>
<Table.Th style={{ textAlign: 'center' }}>Storage</Table.Th>
<Table.Th style={{ textAlign: 'center' }}>Memory Usage</Table.Th>
<Table.Th style={{ textAlign: 'center' }}>Staging Files</Table.Th>
<Table.Th style={{ textAlign: 'center' }}>Staging Size</Table.Th>
<Table.Th style={{ maxWidth: 100 }}>Staging Path</Table.Th>
<Table.Th style={{ maxWidth: 100 }}>Storage Path</Table.Th>
<Table.Th style={{paddingLeft: '1.5rem'}}>Domain</Table.Th>
<Table.Th style={{ textAlign: 'center', borderRight: '1px solid #dcdcdc', borderLeft: '1px solid #dcdcdc' }}>
Events Ingested
</Table.Th>
<Table.Th style={{ textAlign: 'center', borderRight: '1px solid #dcdcdc', padding: 0, flex: 1 }} colSpan={2}>
<Stack py={'0.5rem'}>S3</Stack>
<Box style={{ display: 'flex', flexDirection: 'row', flex: 1, borderTop: '1px solid #dcdcdc' }}>
<Text className={classes.cellTitle} style={{ borderRight: '1px solid #dcdcdc', width: 120 }}>
Size
</Text>
<Text className={classes.cellTitle} style={{ textAlign: 'center', width: 200 }}>
Path
</Text>
</Box>
</Table.Th>
<Table.Th style={{ textAlign: 'center', borderRight: '1px solid #dcdcdc', padding: 0, flex: 1 }} colSpan={3}>
<Stack py={'0.5rem'}>Staging</Stack>
<Box style={{ display: 'flex', flexDirection: 'row', flex: 1, borderTop: '1px solid #dcdcdc' }}>
<Text className={classes.cellTitle} style={{ borderRight: '1px solid #dcdcdc', width: 120 }}>
Files
</Text>
<Text className={classes.cellTitle} style={{ borderRight: '1px solid #dcdcdc', width: 120 }}>
Size
</Text>
<Text className={classes.cellTitle} style={{ textAlign: 'center', width: 200 }}>
Path
</Text>
</Box>
</Table.Th>
<Table.Th style={{ textAlign: 'center', borderRight: '1px solid #dcdcdc' }}>Memory Usage</Table.Th>
<Table.Th style={{ textAlign: 'center' }}>Status</Table.Th>
<Table.Th style={{ textAlign: 'center', width: '1rem' }}></Table.Th>
</Table.Tr>
Expand All @@ -126,7 +170,7 @@ const IngestorsTable = (props: IngestorTable) => {
if (!ingestors || !allMetrics) return null;

return (
<Table verticalSpacing="md">
<Table verticalSpacing="md" border={1} className={classes.ingestorTable}>
<TableHead />
<Table.Tbody>
{ingestors.map((ingestor) => {
Expand All @@ -151,8 +195,8 @@ const Ingestors: FC = () => {
const totalActiveMachines = clusterInfoData?.data.filter((ingestor) => ingestor.reachable).length;
const totalMachines = clusterInfoData?.data.length;
return (
<Stack className={classes.sectionContainer}>
<Stack className={classes.sectionTitleContainer}>
<Stack className={classes.sectionContainer} style={{ padding: 0 }}>
<Stack className={classes.sectionTitleContainer} style={{ padding: '1.5rem ' }}>
<Stack style={{ flexDirection: 'row', alignItems: 'center' }} gap={8}>
<IconBrandDatabricks stroke={1.2} />
<Text className={classes.sectionTitle}>Ingestors</Text>
Expand Down
10 changes: 10 additions & 0 deletions src/pages/Systems/styles/Systems.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,14 @@
.infoText {
font-size: 0.875rem;
/* font-weight: 600; */
}

.cellTitle {
font-size: 14px;
font-weight: 600;
padding: 0.5rem 1.25rem;
}

.cellText {
font-size: 14px;
}
6 changes: 4 additions & 2 deletions src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
LOGS_ROUTE,
OIDC_NOT_CONFIGURED_ROUTE,
USERS_MANAGEMENT_ROUTE,
SYSTEMS_ROUTE
CLUSTER_ROUTE
} from '@/constants/routes';
import FullPageLayout from '@/layouts/FullPageLayout';
import NotFound from '@/pages/Errors/NotFound';
Expand All @@ -29,7 +29,9 @@ const AppRouter: FC = () => {
<Route element={<AccessSpecificRoute accessRequired={['Query', 'GetSchema']} />}>
<Route path={LOGS_ROUTE} element={<LogsElement />} />
</Route>
<Route path={SYSTEMS_ROUTE} element={<SystemsElement/>} />
<Route element={<AccessSpecificRoute accessRequired={['Cluster']} />}>
<Route path={CLUSTER_ROUTE} element={<SystemsElement />} />
</Route>
</Route>
</Route>
<Route path={LOGIN_ROUTE} element={<LoginElement />} />
Expand Down