Skip to content

Commit

Permalink
chore: update node events logic
Browse files Browse the repository at this point in the history
  • Loading branch information
amlannandy committed Jan 2, 2025
1 parent 2253a75 commit 6cbded6
Showing 1 changed file with 149 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/* eslint-disable no-nested-ternary */
import './NodeEvents.styles.scss';

import { Table, TableColumnsType, Typography } from 'antd';
import { Color } from '@signozhq/design-tokens';
import { Button, Table, TableColumnsType } from 'antd';
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
import { EventContents } from 'container/InfraMonitoringK8s/commonUtils';
import LoadingContainer from 'container/InfraMonitoringK8s/LoadingContainer';
import LogsError from 'container/LogsError/LogsError';
import { ORDERBY_FILTERS } from 'container/QueryBuilder/filters/OrderByFilter/config';
import QueryBuilderSearch from 'container/QueryBuilder/filters/QueryBuilderSearch';
Expand All @@ -13,11 +16,14 @@ import {
} from 'container/TopNav/DateTimeSelectionV2/config';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
import { ChevronDown, ChevronRight } from 'lucide-react';
import { useMemo } from 'react';
import { isArray } from 'lodash-es';
import { ChevronDown, ChevronLeft, ChevronRight, Loader2 } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useQuery } from 'react-query';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';
import { v4 } from 'uuid';

import { getNodesEventsQueryPayload } from './constants';
import NoEventsContainer from './NoEventsContainer';
Expand All @@ -39,6 +45,7 @@ interface EventDataType {
span_id?: string;
trace_flags?: number;
trace_id?: string;
severity?: string;
}

interface INodeEventsProps {
Expand All @@ -56,6 +63,8 @@ interface INodeEventsProps {
selectedInterval: Time;
}

const EventsPageSize = 10;

export default function Events({
timeRange,
handleChangeEventFilters,
Expand All @@ -65,6 +74,15 @@ export default function Events({
selectedInterval,
}: INodeEventsProps): JSX.Element {
const { currentQuery } = useQueryBuilder();

const [formattedNodeEvents, setFormattedNodeEvents] = useState<
EventDataType[]
>([]);

const [hasReachedEndOfEvents, setHasReachedEndOfEvents] = useState(false);

const [page, setPage] = useState(1);

const updatedCurrentQuery = useMemo(
() => ({
...currentQuery,
Expand Down Expand Up @@ -98,46 +116,126 @@ export default function Events({
filters,
);

basePayload.query.builder.queryData[0].pageSize = 100;
basePayload.query.builder.queryData[0].pageSize = 10;
basePayload.query.builder.queryData[0].orderBy = [
{ columnName: 'timestamp', order: ORDERBY_FILTERS.DESC },
];

return basePayload;
}, [timeRange.startTime, timeRange.endTime, filters]);

const { data, isLoading, isError } = useQuery({
const { data: eventsData, isLoading, isFetching, isError } = useQuery({
queryKey: ['nodeEvents', timeRange.startTime, timeRange.endTime, filters],
queryFn: () => GetMetricQueryRange(queryPayload, DEFAULT_ENTITY_VERSION),
enabled: !!queryPayload,
});

const columns: TableColumnsType<EventDataType> = [
{ title: 'Severity', dataIndex: 'severity', key: 'severity' },
{ title: 'Timestamp', dataIndex: 'timestamp', key: 'timestamp' },
{ title: 'Severity', dataIndex: 'severity', key: 'severity', width: 100 },
{
title: 'Timestamp',
dataIndex: 'timestamp',
width: 200,
ellipsis: true,
key: 'timestamp',
},
{ title: 'Body', dataIndex: 'body', key: 'body' },
];

const formattedNodeEvents = useMemo(() => {
const responsePayload =
data?.payload.data.newResult.data.result[0].list || [];
useEffect(() => {
if (eventsData?.payload?.data?.newResult?.data?.result) {
const responsePayload =
eventsData?.payload.data.newResult.data.result[0].list || [];

const formattedData = responsePayload?.map((event) => ({
timestamp: event.timestamp,
severity: event.data.severity_text,
body: event.data.body,
id: event.data.id,
key: event.data.id,
resources_string: event.data.resources_string,
}));
const formattedData = responsePayload?.map(
(event): EventDataType => ({
timestamp: event.timestamp,
severity: event.data.severity_text,
body: event.data.body,
id: event.data.id,
key: event.data.id,
resources_string: event.data.resources_string,
}),
);

return formattedData || [];
}, [data]);
setFormattedNodeEvents(formattedData);

if (
!responsePayload ||
(responsePayload &&
isArray(responsePayload) &&
responsePayload.length < EventsPageSize)
) {
setHasReachedEndOfEvents(true);
} else {
setHasReachedEndOfEvents(false);
}
}
}, [eventsData]);

const handleExpandRow = (record: EventDataType): JSX.Element => (
<EventContents data={record.resources_string} />
);

const handlePrev = (): void => {
if (!formattedNodeEvents.length) return;

setPage(page - 1);

const firstEvent = formattedNodeEvents[0];

const newItems = [
...filters.items.filter((item) => item.key?.key !== 'id'),
{
id: v4(),
key: {
key: 'id',
type: '',
dataType: DataTypes.String,
isColumn: true,
},
op: '>',
value: firstEvent.id,
},
];

const newFilters = {
op: 'AND',
items: newItems,
} as IBuilderQuery['filters'];

handleChangeEventFilters(newFilters);
};

const handleNext = (): void => {
if (!formattedNodeEvents.length) return;

setPage(page + 1);
const lastEvent = formattedNodeEvents[formattedNodeEvents.length - 1];

const newItems = [
...filters.items.filter((item) => item.key?.key !== 'id'),
{
id: v4(),
key: {
key: 'id',
type: '',
dataType: DataTypes.String,
isColumn: true,
},
op: '<',
value: lastEvent.id,
},
];

const newFilters = {
op: 'AND',
items: newItems,
} as IBuilderQuery['filters'];

handleChangeEventFilters(newFilters);
};

const handleExpandRowIcon = ({
expanded,
onExpand,
Expand Down Expand Up @@ -200,19 +298,7 @@ export default function Events({
</div>
</div>

{isLoading && (
<div className="loading-logs">
<div className="loading-logs-content">
<img
className="loading-gif"
src="/Icons/loading-plane.gif"
alt="wait-icon"
/>

<Typography>Loading Events. Please wait...</Typography>
</div>
</div>
)}
{isLoading && <LoadingContainer />}

{!isLoading && !isError && formattedNodeEvents.length === 0 && (
<NoEventsContainer />
Expand All @@ -224,6 +310,7 @@ export default function Events({
<div className="node-events-list-container">
<div className="node-events-list-card">
<Table<EventDataType>
loading={isLoading && page > 1}
columns={columns}
expandable={{
expandedRowRender: handleExpandRow,
Expand All @@ -232,10 +319,39 @@ export default function Events({
}}
dataSource={formattedNodeEvents}
pagination={false}
rowKey={(record): string => record.id}
/>
</div>
</div>
)}

{!isError && formattedNodeEvents.length > 0 && (
<div className="node-events-footer">
<Button
className="node-events-footer-button periscope-btn ghost"
type="link"
onClick={handlePrev}
disabled={page === 1 || isFetching || isLoading}
>
{!isFetching && <ChevronLeft size={14} />}
Prev
</Button>

<Button
className="node-events-footer-button periscope-btn ghost"
type="link"
onClick={handleNext}
disabled={hasReachedEndOfEvents || isFetching || isLoading}
>
Next
{!isFetching && <ChevronRight size={14} />}
</Button>

{(isFetching || isLoading) && (
<Loader2 className="animate-spin" size={16} color={Color.BG_ROBIN_500} />
)}
</div>
)}
</div>
);
}

0 comments on commit 6cbded6

Please sign in to comment.