Skip to content

Commit

Permalink
feat: added filters and time selection in traces tab
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulkeswani101 committed Nov 6, 2024
1 parent 332f548 commit 2ecd830
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -1,30 +1,18 @@
.host-metric-traces {
.ant-table {
background: #121212;
color: #fff;
margin-top: 1rem;

.ant-table-thead>tr>th {
background: #121212;
color: #fff;
border-bottom: 1px solid #303030;
}
.host-metric-traces-header {
display: flex;
justify-content: space-between;
margin-bottom: 2rem;

.ant-table-tbody>tr>td {
background: #121212;
color: #fff;
border-bottom: 1px solid #303030;
}

.ant-table-tbody>tr:hover>td {
background: #1a1a1a;
}
.filter-section {
width: 35.7rem;
}
}

.duration-cell {
display: inline-block;
padding: 2px 8px;
background: #d64937;
border-radius: 4px;
color: #fff;
}
}
.ant-table-content {
overflow: hidden !important;
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
import './HostMetricTraces.styles.scss';

import { Skeleton } from 'antd';
import { ResizeTable } from 'components/ResizeTable';
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
import { LOCALSTORAGE } from 'constants/localStorage';
import { QueryParams } from 'constants/query';
import EmptyLogsSearch from 'container/EmptyLogsSearch/EmptyLogsSearch';
import NoLogs from 'container/NoLogs/NoLogs';
import { useOptionsMenu } from 'container/OptionsMenu';
import QueryBuilderSearch from 'container/QueryBuilder/filters/QueryBuilderSearch';
import { ErrorText } from 'container/TimeSeriesView/styles';
import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
import {
CustomTimeType,
Time,
} from 'container/TopNav/DateTimeSelectionV2/config';
import TraceExplorerControls from 'container/TracesExplorer/Controls';
import {
defaultSelectedColumns,
PER_PAGE_OPTIONS,
} from 'container/TracesExplorer/ListView/configs';
import { TracesLoading } from 'container/TracesExplorer/TraceLoading/TraceLoading';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { Pagination } from 'hooks/queryPagination';
import useUrlQueryData from 'hooks/useUrlQueryData';
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
import { useEffect, useMemo, useState } from 'react';
import GetMinMax from 'lib/getMinMax';
import { useCallback, 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 as uuidv4 } from 'uuid';

import { columns, getHostTracesQueryPayload } from './constants';

Expand All @@ -15,25 +40,124 @@ interface Props {
startTime: number;
endTime: number;
};
isModalTimeSelection: boolean;
}

function HostMetricTraces({ hostName, timeRange }: Props): JSX.Element {
function HostMetricTraces({
hostName,
timeRange,
isModalTimeSelection,
}: Props): JSX.Element {
const [traces, setTraces] = useState<any[]>([]);
const [offset] = useState<number>(0);
const [modalTimeRange, setModalTimeRange] = useState(timeRange);
const [, setSelectedInterval] = useState<Time>('5m');
const [filters, setFilters] = useState<IBuilderQuery['filters']>({
op: 'AND',
items: [],
});

const { config } = useOptionsMenu({
storageKey: LOCALSTORAGE.TRACES_LIST_OPTIONS,
dataSource: DataSource.TRACES,
aggregateOperator: 'count',
initialOptions: {
selectColumns: defaultSelectedColumns,
},
});

const { currentQuery } = useQueryBuilder();
const updatedCurrentQuery = useMemo(
() => ({
...currentQuery,
builder: {
...currentQuery.builder,
queryData: [
{
...currentQuery.builder.queryData[0],
dataSource: DataSource.TRACES,
aggregateOperator: 'noop',
aggregateAttribute: {
...currentQuery.builder.queryData[0].aggregateAttribute,
},
},
],
},
}),
[currentQuery],
);

const query = updatedCurrentQuery?.builder?.queryData[0] || null;

const handleChangeTagFilters = useCallback(
(value: IBuilderQuery['filters']) => {
setFilters({
op: 'AND',
items: [
{
id: uuidv4(),
key: {
key: 'host.name',
dataType: DataTypes.String,
type: 'resource',
isColumn: false,
isJSON: false,
id: 'host.name--string--resource--false',
},
op: '=',
value: hostName,
},
...value.items,
],
});
},
[hostName],
);

const handleTimeChange = useCallback(
(interval: Time | CustomTimeType, dateTimeRange?: [number, number]): void => {
setSelectedInterval(interval as Time);
if (interval === 'custom' && dateTimeRange) {
setModalTimeRange({
startTime: dateTimeRange[0],
endTime: dateTimeRange[1],
});
} else {
const { maxTime, minTime } = GetMinMax(interval);
setModalTimeRange({
startTime: minTime / 1000000,
endTime: maxTime / 1000000,
});
}
},
[],
);

const queryPayload = useMemo(
() =>
getHostTracesQueryPayload(
hostName,
timeRange.startTime,
timeRange.endTime,
modalTimeRange.startTime,
modalTimeRange.endTime,
offset,
filters,
),
[hostName, timeRange.startTime, timeRange.endTime, offset],
[modalTimeRange.startTime, modalTimeRange.endTime, offset, filters],
);

const { data, isLoading } = useQuery({
queryKey: ['hostMetricTraces', queryPayload, DEFAULT_ENTITY_VERSION],
const { queryData: paginationQueryData } = useUrlQueryData<Pagination>(
QueryParams.pagination,
);

const { data, isLoading, isFetching, isError } = useQuery({
queryKey: [
'hostMetricTraces',
modalTimeRange.startTime,
modalTimeRange.endTime,
offset,
filters,
DEFAULT_ENTITY_VERSION,
paginationQueryData,
],
queryFn: () => GetMetricQueryRange(queryPayload, DEFAULT_ENTITY_VERSION),
});

Expand All @@ -50,27 +174,62 @@ function HostMetricTraces({ hostName, timeRange }: Props): JSX.Element {
}
}, [data, offset]);

if (isLoading && traces.length === 0) {
return <Skeleton active />;
}
const isDataEmpty =
!isLoading && !isFetching && !isError && traces.length === 0;
const hasAdditionalFilters = filters.items.length > 1;

const totalCount =
data?.payload?.data?.newResult?.data?.result?.[0]?.list?.length || 0;

return (
<div className="host-metric-traces">
<ResizeTable
tableLayout="fixed"
pagination={false}
scroll={{ x: true }}
loading={isLoading && traces.length === 0}
dataSource={traces}
columns={columns}
/>
{isLoading && traces.length > 0 && (
<Skeleton
style={{
height: '100%',
padding: '16px',
}}
/>
<div className="host-metric-traces-header">
<div className="filter-section">
{query && (
<QueryBuilderSearch query={query} onChange={handleChangeTagFilters} />
)}
</div>
<div className="datetime-section">
<DateTimeSelectionV2
showAutoRefresh={false}
showRefreshText={false}
hideShareModal
isModalTimeSelection={isModalTimeSelection}
onTimeChange={handleTimeChange}
defaultRelativeTime="5m"
/>
</div>
</div>

{isError && <ErrorText>{data?.error || 'Something went wrong'}</ErrorText>}

{(isLoading || (isFetching && traces.length === 0)) && <TracesLoading />}

{isDataEmpty && !hasAdditionalFilters && (
<NoLogs dataSource={DataSource.TRACES} />
)}

{isDataEmpty && hasAdditionalFilters && (
<EmptyLogsSearch dataSource={DataSource.TRACES} panelType="LIST" />
)}

{!isError && traces.length > 0 && (
<>
<TraceExplorerControls
isLoading={isLoading}
totalCount={totalCount}
config={config}
perPageOptions={PER_PAGE_OPTIONS}
/>
<ResizeTable
tableLayout="fixed"
pagination={false}
scroll={{ x: true }}
loading={isFetching}
dataSource={traces}
columns={columns}
/>
</>
)}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PANEL_TYPES } from 'constants/queryBuilder';
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import { DataSource } from 'types/common/queryBuilder';

Expand All @@ -11,14 +12,14 @@ export const columns = [
dataIndex: 'timestamp',
key: 'timestamp',
title: 'Timestamp',
width: 145,
width: 200,
render: (timestamp: string): string => new Date(timestamp).toLocaleString(),
},
{
title: 'Service Name',
dataIndex: ['data', 'serviceName'],
key: 'serviceName-string-tag',
width: 145,
width: 150,
},
{
title: 'Name',
Expand Down Expand Up @@ -48,10 +49,10 @@ export const columns = [
];

export const getHostTracesQueryPayload = (
hostName: string,
start: number,
end: number,
offset = 0,
filters: IBuilderQuery['filters'],
): GetQueryResultsProps => ({
query: {
promql: [],
Expand All @@ -73,24 +74,7 @@ export const getHostTracesQueryPayload = (
timeAggregation: 'rate',
spaceAggregation: 'sum',
functions: [],
filters: {
items: [
{
id: 'host-filter',
key: {
key: 'host.name',
dataType: DataTypes.String,
type: 'resource',
isColumn: false,
isJSON: false,
id: 'host.name--string--resource--false',
},
op: '=',
value: hostName,
},
],
op: 'AND',
},
filters,
expression: 'A',
disabled: false,
stepInterval: 60,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,6 @@ function HostMetricLogsDetailedView({

const query = updatedCurrentQuery?.builder?.queryData[0] || null;

// const { handleChangeQueryData } = useQueryOperations({
// index: 0,
// query,
// isListViewPanel: true,
// entityVersion: '',
// });

const handleChangeTagFilters = useCallback(
(value: IBuilderQuery['filters']) => {
setFilters({
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/components/HostMetricsDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,11 @@ function HostMetricDetail({
/>
)}
{selectedView === VIEW_TYPES.TRACES && (
<HostMetricTraces hostName={host.hostName} timeRange={timeRange} />
<HostMetricTraces
hostName={host.hostName}
timeRange={timeRange}
isModalTimeSelection={isModalTimeSelection}
/>
)}
</>
)}
Expand Down

0 comments on commit 2ecd830

Please sign in to comment.