mirror of
https://github.com/SigNoz/signoz.git
synced 2026-02-26 18:32:35 +00:00
Compare commits
19 Commits
main
...
feat/infra
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa2e0d8104 | ||
|
|
ea5d89e72c | ||
|
|
a518b1688b | ||
|
|
44a94e7746 | ||
|
|
38d334b9aa | ||
|
|
3f27e49eac | ||
|
|
0b8e87ec96 | ||
|
|
df2916bf7f | ||
|
|
0c62c075f9 | ||
|
|
f42d95d5f5 | ||
|
|
32c0dfa28f | ||
|
|
68e831c4b0 | ||
|
|
ed79d40492 | ||
|
|
ad8223c792 | ||
|
|
5d691476b1 | ||
|
|
358977e203 | ||
|
|
7ffb3e30b5 | ||
|
|
ded7b78360 | ||
|
|
76e9074ca7 |
@@ -37,8 +37,8 @@ export interface K8sClustersListResponse {
|
||||
records: K8sClustersData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ export interface K8sDaemonSetsListResponse {
|
||||
records: K8sDaemonSetsData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ export interface K8sDeploymentsListResponse {
|
||||
records: K8sDeploymentsData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,8 @@ export interface K8sJobsListResponse {
|
||||
records: K8sJobsData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ export interface K8sNamespacesListResponse {
|
||||
records: K8sNamespacesData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ export interface K8sNodesListResponse {
|
||||
records: K8sNodesData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ export interface K8sPodsListResponse {
|
||||
records: K8sPodsData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ export interface K8sVolumesListResponse {
|
||||
records: K8sVolumesData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ export interface K8sStatefulSetsListResponse {
|
||||
records: K8sStatefulSetsData[];
|
||||
groups: null;
|
||||
total: number;
|
||||
sentAnyHostMetricsData: boolean;
|
||||
isSendingK8SAgentMetrics: boolean;
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import { usePageSize } from '../utils';
|
||||
@@ -331,6 +332,9 @@ function K8sClustersList({
|
||||
|
||||
const clustersData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const formattedClustersData = useMemo(
|
||||
() => formatDataForTable(clustersData, groupBy),
|
||||
@@ -655,6 +659,18 @@ function K8sClustersList({
|
||||
const showTableLoadingState =
|
||||
(isFetching || isLoading) && formattedClustersData.length === 0;
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'cluster',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedClustersData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -669,54 +685,42 @@ function K8sClustersList({
|
||||
entity={K8sCategory.NODES}
|
||||
showAutoRefresh={!selectedClusterData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
{emptyState}
|
||||
|
||||
<Table
|
||||
className="k8s-list-table clusters-list-table"
|
||||
dataSource={showTableLoadingState ? [] : formattedClustersData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: showTableLoadingState ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{!emptyState && (
|
||||
<Table
|
||||
className="k8s-list-table clusters-list-table"
|
||||
dataSource={showTableLoadingState ? [] : formattedClustersData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<ClusterDetails
|
||||
cluster={selectedClusterData}
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import { usePageSize } from '../utils';
|
||||
@@ -328,6 +329,9 @@ function K8sDaemonSetsList({
|
||||
data,
|
||||
]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const formattedDaemonSetsData = useMemo(
|
||||
() => formatDataForTable(daemonSetsData, groupBy),
|
||||
@@ -661,6 +665,18 @@ function K8sDaemonSetsList({
|
||||
const showTableLoadingState =
|
||||
(isFetching || isLoading) && formattedDaemonSetsData.length === 0;
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'daemon set',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedDaemonSetsData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -675,56 +691,44 @@ function K8sDaemonSetsList({
|
||||
entity={K8sCategory.DAEMONSETS}
|
||||
showAutoRefresh={!selectedDaemonSetData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
{emptyState}
|
||||
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'daemonSets-list-table', {
|
||||
'expanded-daemonsets-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedDaemonSetsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: showTableLoadingState ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{!emptyState && (
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'daemonSets-list-table', {
|
||||
'expanded-daemonsets-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedDaemonSetsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<DaemonSetDetails
|
||||
daemonSet={selectedDaemonSetData}
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import { usePageSize } from '../utils';
|
||||
@@ -329,6 +330,9 @@ function K8sDeploymentsList({
|
||||
data,
|
||||
]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const formattedDeploymentsData = useMemo(
|
||||
() => formatDataForTable(deploymentsData, groupBy),
|
||||
@@ -668,6 +672,18 @@ function K8sDeploymentsList({
|
||||
const showTableLoadingState =
|
||||
(isFetching || isLoading) && formattedDeploymentsData.length === 0;
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'deployment',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedDeploymentsData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -682,56 +698,44 @@ function K8sDeploymentsList({
|
||||
entity={K8sCategory.NODES}
|
||||
showAutoRefresh={!selectedDeploymentData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
{emptyState}
|
||||
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'deployments-list-table', {
|
||||
'expanded-deployments-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedDeploymentsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: showTableLoadingState ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{!emptyState && (
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'deployments-list-table', {
|
||||
'expanded-deployments-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedDeploymentsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<DeploymentDetails
|
||||
deployment={selectedDeploymentData}
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import { usePageSize } from '../utils';
|
||||
@@ -321,6 +322,9 @@ function K8sJobsList({
|
||||
|
||||
const jobsData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const formattedJobsData = useMemo(
|
||||
() => formatDataForTable(jobsData, groupBy),
|
||||
@@ -629,6 +633,18 @@ function K8sJobsList({
|
||||
});
|
||||
};
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'job',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedJobsData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -643,57 +659,44 @@ function K8sJobsList({
|
||||
entity={K8sCategory.JOBS}
|
||||
showAutoRefresh={!selectedJobData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
{emptyState}
|
||||
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'jobs-list-table', {
|
||||
'expanded-jobs-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={isFetching || isLoading ? [] : formattedJobsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: isFetching || isLoading,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText:
|
||||
isFetching || isLoading ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{!emptyState && (
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'jobs-list-table', {
|
||||
'expanded-jobs-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={isFetching || isLoading ? [] : formattedJobsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: isFetching || isLoading,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<JobDetails
|
||||
job={selectedJobData}
|
||||
|
||||
150
frontend/src/container/InfraMonitoringK8s/K8sEmptyState.tsx
Normal file
150
frontend/src/container/InfraMonitoringK8s/K8sEmptyState.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { Skeleton, Spin, Typography } from 'antd';
|
||||
|
||||
interface K8sEmptyStateProps {
|
||||
sentAnyMetricsData: boolean;
|
||||
endTimeBeforeRetention: boolean;
|
||||
entityName: string;
|
||||
isLoading: boolean;
|
||||
isFetching: boolean;
|
||||
hasRecords: boolean;
|
||||
hasFilters: boolean;
|
||||
isError: boolean;
|
||||
errorMessage: string;
|
||||
}
|
||||
|
||||
export function getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName,
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords,
|
||||
hasFilters,
|
||||
isError,
|
||||
errorMessage,
|
||||
}: K8sEmptyStateProps): React.ReactNode {
|
||||
if (isError) {
|
||||
return <Typography>{errorMessage || 'Something went wrong'}</Typography>;
|
||||
}
|
||||
|
||||
const showTableLoadingState = (isLoading || isFetching) && !hasRecords;
|
||||
|
||||
if (showTableLoadingState) {
|
||||
return (
|
||||
<div className="hosts-list-loading-state">
|
||||
<Skeleton.Input
|
||||
className="hosts-list-loading-state-item"
|
||||
size="large"
|
||||
block
|
||||
active
|
||||
/>
|
||||
<Skeleton.Input
|
||||
className="hosts-list-loading-state-item"
|
||||
size="large"
|
||||
block
|
||||
active
|
||||
/>
|
||||
<Skeleton.Input
|
||||
className="hosts-list-loading-state-item"
|
||||
size="large"
|
||||
block
|
||||
active
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const showEmptyState =
|
||||
!isFetching &&
|
||||
!isLoading &&
|
||||
!hasRecords &&
|
||||
!sentAnyMetricsData &&
|
||||
!hasFilters;
|
||||
|
||||
if (showEmptyState) {
|
||||
return (
|
||||
<div className="hosts-empty-state-container">
|
||||
<div className="hosts-empty-state-container-content">
|
||||
<img className="eyes-emoji" src="/Images/eyesEmoji.svg" alt="eyes emoji" />
|
||||
<div className="no-hosts-message">
|
||||
<Typography.Title level={5} className="no-hosts-message-title">
|
||||
No {entityName} metrics data received yet.
|
||||
</Typography.Title>
|
||||
<Typography.Text className="no-hosts-message-text">
|
||||
Please refer to the{' '}
|
||||
<a
|
||||
href="https://signoz.io/docs/infrastructure-monitoring/k8s-metrics/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Kubernetes Infrastructure Monitoring docs
|
||||
</a>{' '}
|
||||
to learn how to send K8s metrics to SigNoz.
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const showEndTimeBeforeRetentionMessage =
|
||||
!isFetching &&
|
||||
!isLoading &&
|
||||
!hasRecords &&
|
||||
endTimeBeforeRetention &&
|
||||
!hasFilters;
|
||||
|
||||
if (showEndTimeBeforeRetentionMessage) {
|
||||
return (
|
||||
<div className="hosts-empty-state-container">
|
||||
<div className="hosts-empty-state-container-content">
|
||||
<img className="eyes-emoji" src="/Images/eyesEmoji.svg" alt="eyes emoji" />
|
||||
<div className="no-hosts-message">
|
||||
<Typography.Title level={5} className="no-hosts-message-title">
|
||||
Queried time range is before earliest {entityName} metrics
|
||||
</Typography.Title>
|
||||
<Typography.Text className="no-hosts-message-text">
|
||||
Your requested end time is earlier than the earliest detected time of{' '}
|
||||
{entityName} metrics data, please adjust your end time.
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const showNoRecordsMessage =
|
||||
!isFetching &&
|
||||
!isLoading &&
|
||||
!hasRecords &&
|
||||
!showEmptyState &&
|
||||
!showEndTimeBeforeRetentionMessage;
|
||||
|
||||
if (showNoRecordsMessage) {
|
||||
return (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
<Typography.Title level={5} className="no-filtered-hosts-title">
|
||||
No {entityName} metrics found
|
||||
</Typography.Title>
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
No {entityName} metrics in the selected time range and filters. Please
|
||||
adjust your time range or filters.
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function K8sTableLoadingIndicator(): JSX.Element {
|
||||
return <Spin indicator={<LoadingOutlined size={14} spin />} />;
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import { usePageSize } from '../utils';
|
||||
@@ -327,6 +328,9 @@ function K8sNamespacesList({
|
||||
data,
|
||||
]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const formattedNamespacesData = useMemo(
|
||||
() => formatDataForTable(namespacesData, groupBy),
|
||||
@@ -664,6 +668,18 @@ function K8sNamespacesList({
|
||||
const showTableLoadingState =
|
||||
(isFetching || isLoading) && formattedNamespacesData.length === 0;
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'namespace',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedNamespacesData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -678,54 +694,42 @@ function K8sNamespacesList({
|
||||
entity={K8sCategory.NODES}
|
||||
showAutoRefresh={!selectedNamespaceData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
|
||||
<Table
|
||||
className="k8s-list-table namespaces-list-table"
|
||||
dataSource={showTableLoadingState ? [] : formattedNamespacesData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: showTableLoadingState ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{emptyState ? (
|
||||
<>{emptyState}</>
|
||||
) : (
|
||||
<Table
|
||||
className="k8s-list-table namespaces-list-table"
|
||||
dataSource={showTableLoadingState ? [] : formattedNamespacesData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<NamespaceDetails
|
||||
namespace={selectedNamespaceData}
|
||||
isModalTimeSelection
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import { usePageSize } from '../utils';
|
||||
@@ -326,6 +327,9 @@ function K8sNodesList({
|
||||
|
||||
const nodesData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const formattedNodesData = useMemo(
|
||||
() => formatDataForTable(nodesData, groupBy),
|
||||
@@ -643,6 +647,18 @@ function K8sNodesList({
|
||||
const showTableLoadingState =
|
||||
(isFetching || isLoading) && formattedNodesData.length === 0;
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'node',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedNodesData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -657,54 +673,42 @@ function K8sNodesList({
|
||||
entity={K8sCategory.NODES}
|
||||
showAutoRefresh={!selectedNodeData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
|
||||
<Table
|
||||
className="k8s-list-table nodes-list-table"
|
||||
dataSource={showTableLoadingState ? [] : formattedNodesData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: showTableLoadingState ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{emptyState ? (
|
||||
<>{emptyState}</>
|
||||
) : (
|
||||
<Table
|
||||
className="k8s-list-table nodes-list-table"
|
||||
dataSource={showTableLoadingState ? [] : formattedNodesData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<NodeDetails
|
||||
node={selectedNodeData}
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import {
|
||||
@@ -335,6 +336,9 @@ function K8sPodsList({
|
||||
|
||||
const podsData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const nestedPodsData = useMemo(() => {
|
||||
if (!selectedRowData || !groupedByRowData?.payload?.data.records) {
|
||||
@@ -694,6 +698,18 @@ function K8sPodsList({
|
||||
const showTableLoadingState =
|
||||
(isFetching || isLoading) && formattedPodsData.length === 0;
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'pod',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedPodsData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -712,56 +728,44 @@ function K8sPodsList({
|
||||
entity={K8sCategory.PODS}
|
||||
showAutoRefresh={!selectedPodData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
|
||||
<Table
|
||||
className={classNames('k8s-list-table', {
|
||||
'expanded-k8s-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedPodsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: showTableLoadingState ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{emptyState ? (
|
||||
<>{emptyState}</>
|
||||
) : (
|
||||
<Table
|
||||
className={classNames('k8s-list-table', {
|
||||
'expanded-k8s-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedPodsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{selectedPodData && (
|
||||
<PodDetails
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import { usePageSize } from '../utils';
|
||||
@@ -335,6 +336,9 @@ function K8sStatefulSetsList({
|
||||
data,
|
||||
]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const formattedStatefulSetsData = useMemo(
|
||||
() => formatDataForTable(statefulSetsData, groupBy),
|
||||
@@ -664,6 +668,18 @@ function K8sStatefulSetsList({
|
||||
const showTableLoadingState =
|
||||
(isFetching || isLoading) && formattedStatefulSetsData.length === 0;
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'stateful set',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedStatefulSetsData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -678,56 +694,44 @@ function K8sStatefulSetsList({
|
||||
entity={K8sCategory.STATEFULSETS}
|
||||
showAutoRefresh={!selectedStatefulSetData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
{emptyState}
|
||||
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'statefulSets-list-table', {
|
||||
'expanded-statefulsets-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedStatefulSetsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: showTableLoadingState ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{!emptyState && (
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'statefulSets-list-table', {
|
||||
'expanded-statefulsets-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedStatefulSetsData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<StatefulSetDetails
|
||||
statefulSet={selectedStatefulSetData}
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
K8sCategory,
|
||||
} from '../constants';
|
||||
import { getK8sEmptyState } from '../K8sEmptyState';
|
||||
import K8sHeader from '../K8sHeader';
|
||||
import LoadingContainer from '../LoadingContainer';
|
||||
import { usePageSize } from '../utils';
|
||||
@@ -274,6 +275,9 @@ function K8sVolumesList({
|
||||
|
||||
const volumesData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||
const totalCount = data?.payload?.data?.total || 0;
|
||||
const sentAnyMetricsData = data?.payload?.data?.sentAnyMetricsData ?? false;
|
||||
const endTimeBeforeRetention =
|
||||
data?.payload?.data?.endTimeBeforeRetention ?? false;
|
||||
|
||||
const formattedVolumesData = useMemo(
|
||||
() => formatDataForTable(volumesData, groupBy),
|
||||
@@ -587,6 +591,18 @@ function K8sVolumesList({
|
||||
const showTableLoadingState =
|
||||
(isFetching || isLoading) && formattedVolumesData.length === 0;
|
||||
|
||||
const emptyState = getK8sEmptyState({
|
||||
sentAnyMetricsData,
|
||||
endTimeBeforeRetention,
|
||||
entityName: 'volume',
|
||||
isLoading,
|
||||
isFetching,
|
||||
hasRecords: formattedVolumesData.length > 0,
|
||||
hasFilters: queryFilters?.items?.length > 0,
|
||||
isError,
|
||||
errorMessage: data?.error ?? '',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="k8s-list">
|
||||
<K8sHeader
|
||||
@@ -601,56 +617,44 @@ function K8sVolumesList({
|
||||
entity={K8sCategory.NODES}
|
||||
showAutoRefresh={!selectedVolumeData}
|
||||
/>
|
||||
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
|
||||
{emptyState}
|
||||
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'volumes-list-table', {
|
||||
'expanded-volumes-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedVolumesData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: showTableLoadingState ? null : (
|
||||
<div className="no-filtered-hosts-message-container">
|
||||
<div className="no-filtered-hosts-message-content">
|
||||
<img
|
||||
src="/Icons/emptyState.svg"
|
||||
alt="thinking-emoji"
|
||||
className="empty-state-svg"
|
||||
/>
|
||||
|
||||
<Typography.Text className="no-filtered-hosts-message">
|
||||
This query had no results. Edit your query and try again!
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
{!emptyState && (
|
||||
<Table
|
||||
className={classNames('k8s-list-table', 'volumes-list-table', {
|
||||
'expanded-volumes-list-table': isGroupedByAttribute,
|
||||
})}
|
||||
dataSource={showTableLoadingState ? [] : formattedVolumesData}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
onChange: onPaginationChange,
|
||||
}}
|
||||
scroll={{ x: true }}
|
||||
loading={{
|
||||
spinning: showTableLoadingState,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
locale={{
|
||||
emptyText: null,
|
||||
}}
|
||||
tableLayout="fixed"
|
||||
onChange={handleTableChange}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => handleRowClick(record),
|
||||
className: 'clickable-row',
|
||||
})}
|
||||
expandable={{
|
||||
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,
|
||||
expandIcon: expandRowIconRenderer,
|
||||
expandedRowKeys,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<VolumeDetails
|
||||
volume={selectedVolumeData}
|
||||
|
||||
@@ -202,6 +202,14 @@ func (p *ClustersRepo) getTopClusterGroups(ctx context.Context, orgID valuer.UUI
|
||||
return topClusterGroups, allClusterGroups, nil
|
||||
}
|
||||
|
||||
func (p *ClustersRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForNodes {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return p.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (p *ClustersRepo) GetClusterList(ctx context.Context, orgID valuer.UUID, req model.ClusterListRequest) (model.ClusterListResponse, error) {
|
||||
resp := model.ClusterListResponse{}
|
||||
|
||||
@@ -220,6 +228,22 @@ func (p *ClustersRepo) GetClusterList(ctx context.Context, orgID valuer.UUID, re
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := p.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.ClusterListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.ClusterListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := NodesTableListQuery.Clone()
|
||||
|
||||
@@ -269,6 +269,17 @@ func (d *DaemonSetsRepo) getTopDaemonSetGroups(ctx context.Context, orgID valuer
|
||||
return topDaemonSetGroups, allDaemonSetGroups, nil
|
||||
}
|
||||
|
||||
func (d *DaemonSetsRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForWorkloads {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
for _, metricName := range metricNamesForDaemonSets {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return d.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (d *DaemonSetsRepo) GetDaemonSetList(ctx context.Context, orgID valuer.UUID, req model.DaemonSetListRequest) (model.DaemonSetListResponse, error) {
|
||||
resp := model.DaemonSetListResponse{}
|
||||
|
||||
@@ -287,6 +298,22 @@ func (d *DaemonSetsRepo) GetDaemonSetList(ctx context.Context, orgID valuer.UUID
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := d.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.DaemonSetListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.DaemonSetListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := WorkloadTableListQuery.Clone()
|
||||
|
||||
@@ -269,6 +269,17 @@ func (d *DeploymentsRepo) getTopDeploymentGroups(ctx context.Context, orgID valu
|
||||
return topDeploymentGroups, allDeploymentGroups, nil
|
||||
}
|
||||
|
||||
func (d *DeploymentsRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForWorkloads {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
for _, metricName := range metricNamesForDeployments {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return d.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (d *DeploymentsRepo) GetDeploymentList(ctx context.Context, orgID valuer.UUID, req model.DeploymentListRequest) (model.DeploymentListResponse, error) {
|
||||
resp := model.DeploymentListResponse{}
|
||||
|
||||
@@ -287,6 +298,22 @@ func (d *DeploymentsRepo) GetDeploymentList(ctx context.Context, orgID valuer.UU
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := d.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.DeploymentListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.DeploymentListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := WorkloadTableListQuery.Clone()
|
||||
|
||||
@@ -313,6 +313,17 @@ func (d *JobsRepo) getTopJobGroups(ctx context.Context, orgID valuer.UUID, req m
|
||||
return topJobGroups, allJobGroups, nil
|
||||
}
|
||||
|
||||
func (d *JobsRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForWorkloads {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
for _, metricName := range metricNamesForJobs {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return d.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (d *JobsRepo) GetJobList(ctx context.Context, orgID valuer.UUID, req model.JobListRequest) (model.JobListResponse, error) {
|
||||
resp := model.JobListResponse{}
|
||||
|
||||
@@ -331,6 +342,22 @@ func (d *JobsRepo) GetJobList(ctx context.Context, orgID valuer.UUID, req model.
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := d.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.JobListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.JobListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := WorkloadTableListQuery.Clone()
|
||||
|
||||
@@ -196,6 +196,14 @@ func (p *NamespacesRepo) getTopNamespaceGroups(ctx context.Context, orgID valuer
|
||||
return topNamespaceGroups, allNamespaceGroups, nil
|
||||
}
|
||||
|
||||
func (p *NamespacesRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForPods {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return p.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (p *NamespacesRepo) GetNamespaceList(ctx context.Context, orgID valuer.UUID, req model.NamespaceListRequest) (model.NamespaceListResponse, error) {
|
||||
resp := model.NamespaceListResponse{}
|
||||
|
||||
@@ -214,6 +222,22 @@ func (p *NamespacesRepo) GetNamespaceList(ctx context.Context, orgID valuer.UUID
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := p.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.NamespaceListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.NamespaceListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := PodsTableListQuery.Clone()
|
||||
|
||||
@@ -226,6 +226,14 @@ func (p *NodesRepo) getTopNodeGroups(ctx context.Context, orgID valuer.UUID, req
|
||||
return topNodeGroups, allNodeGroups, nil
|
||||
}
|
||||
|
||||
func (p *NodesRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForNodes {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return p.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (p *NodesRepo) GetNodeList(ctx context.Context, orgID valuer.UUID, req model.NodeListRequest) (model.NodeListResponse, error) {
|
||||
resp := model.NodeListResponse{}
|
||||
|
||||
@@ -244,6 +252,22 @@ func (p *NodesRepo) GetNodeList(ctx context.Context, orgID valuer.UUID, req mode
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := p.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.NodeListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.NodeListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := NodesTableListQuery.Clone()
|
||||
|
||||
@@ -371,6 +371,14 @@ func (p *PodsRepo) getTopPodGroups(ctx context.Context, orgID valuer.UUID, req m
|
||||
return topPodGroups, allPodGroups, nil
|
||||
}
|
||||
|
||||
func (p *PodsRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForPods {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return p.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (p *PodsRepo) GetPodList(ctx context.Context, orgID valuer.UUID, req model.PodListRequest) (model.PodListResponse, error) {
|
||||
resp := model.PodListResponse{}
|
||||
|
||||
@@ -389,6 +397,22 @@ func (p *PodsRepo) GetPodList(ctx context.Context, orgID valuer.UUID, req model.
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := p.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.PodListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.PodListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := PodsTableListQuery.Clone()
|
||||
|
||||
@@ -210,6 +210,14 @@ func (p *ProcessesRepo) getTopProcessGroups(ctx context.Context, orgID valuer.UU
|
||||
return topProcessGroups, allProcessGroups, nil
|
||||
}
|
||||
|
||||
func (p *ProcessesRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForProcesses {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return p.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (p *ProcessesRepo) GetProcessList(ctx context.Context, orgID valuer.UUID, req model.ProcessListRequest) (model.ProcessListResponse, error) {
|
||||
resp := model.ProcessListResponse{}
|
||||
if req.Limit == 0 {
|
||||
@@ -229,6 +237,22 @@ func (p *ProcessesRepo) GetProcessList(ctx context.Context, orgID valuer.UUID, r
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := p.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.ProcessListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.ProcessListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := ProcessesTableListQuery.Clone()
|
||||
|
||||
@@ -229,6 +229,14 @@ func (p *PvcsRepo) getTopVolumeGroups(ctx context.Context, orgID valuer.UUID, re
|
||||
return topVolumeGroups, allVolumeGroups, nil
|
||||
}
|
||||
|
||||
func (p *PvcsRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForVolumes {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return p.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (p *PvcsRepo) GetPvcList(ctx context.Context, orgID valuer.UUID, req model.VolumeListRequest) (model.VolumeListResponse, error) {
|
||||
resp := model.VolumeListResponse{}
|
||||
|
||||
@@ -247,6 +255,22 @@ func (p *PvcsRepo) GetPvcList(ctx context.Context, orgID valuer.UUID, req model.
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := p.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.VolumeListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.VolumeListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := PvcsTableListQuery.Clone()
|
||||
|
||||
@@ -269,6 +269,17 @@ func (d *StatefulSetsRepo) getTopStatefulSetGroups(ctx context.Context, orgID va
|
||||
return topStatefulSetGroups, allStatefulSetGroups, nil
|
||||
}
|
||||
|
||||
func (d *StatefulSetsRepo) GetMetricsExistenceAndEarliestTime(ctx context.Context) (uint64, uint64, error) {
|
||||
names := []string{}
|
||||
for _, metricName := range metricNamesForWorkloads {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
for _, metricName := range metricNamesForStatefulSets {
|
||||
names = append(names, metricName)
|
||||
}
|
||||
return d.reader.GetMetricsExistenceAndEarliestTime(ctx, names)
|
||||
}
|
||||
|
||||
func (d *StatefulSetsRepo) GetStatefulSetList(ctx context.Context, orgID valuer.UUID, req model.StatefulSetListRequest) (model.StatefulSetListResponse, error) {
|
||||
resp := model.StatefulSetListResponse{}
|
||||
|
||||
@@ -287,6 +298,22 @@ func (d *StatefulSetsRepo) GetStatefulSetList(ctx context.Context, orgID valuer.
|
||||
resp.Type = model.ResponseTypeGroupedList
|
||||
}
|
||||
|
||||
if count, minFirstReportedUnixMilli, err := d.GetMetricsExistenceAndEarliestTime(ctx); err == nil {
|
||||
if count == 0 {
|
||||
resp.SentAnyMetricsData = false
|
||||
resp.Records = []model.StatefulSetListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
resp.SentAnyMetricsData = true
|
||||
if req.End < int64(minFirstReportedUnixMilli) {
|
||||
resp.EndTimeBeforeRetention = true
|
||||
resp.Records = []model.StatefulSetListRecord{}
|
||||
resp.Total = 0
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
step := int64(math.Max(float64(common.MinAllowedStepInterval(req.Start, req.End)), 60))
|
||||
|
||||
query := WorkloadTableListQuery.Clone()
|
||||
|
||||
@@ -86,9 +86,11 @@ type ProcessListRequest struct {
|
||||
}
|
||||
|
||||
type ProcessListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []ProcessListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []ProcessListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
type ProcessListRecord struct {
|
||||
@@ -112,9 +114,11 @@ type PodListRequest struct {
|
||||
}
|
||||
|
||||
type PodListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []PodListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []PodListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *PodListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
@@ -190,9 +194,11 @@ type NodeListRequest struct {
|
||||
}
|
||||
|
||||
type NodeListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []NodeListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []NodeListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *NodeListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
@@ -251,9 +257,11 @@ type NamespaceListRequest struct {
|
||||
}
|
||||
|
||||
type NamespaceListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []NamespaceListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []NamespaceListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *NamespaceListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
@@ -300,9 +308,11 @@ type ClusterListRequest struct {
|
||||
}
|
||||
|
||||
type ClusterListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []ClusterListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []ClusterListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *ClusterListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
@@ -354,9 +364,11 @@ type DeploymentListRequest struct {
|
||||
}
|
||||
|
||||
type DeploymentListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []DeploymentListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []DeploymentListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *DeploymentListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
@@ -433,9 +445,11 @@ type DaemonSetListRequest struct {
|
||||
}
|
||||
|
||||
type DaemonSetListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []DaemonSetListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []DaemonSetListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *DaemonSetListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
@@ -512,9 +526,11 @@ type StatefulSetListRequest struct {
|
||||
}
|
||||
|
||||
type StatefulSetListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []StatefulSetListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []StatefulSetListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *StatefulSetListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
@@ -591,9 +607,11 @@ type JobListRequest struct {
|
||||
}
|
||||
|
||||
type JobListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []JobListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []JobListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *JobListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
@@ -680,9 +698,11 @@ type VolumeListRequest struct {
|
||||
}
|
||||
|
||||
type VolumeListResponse struct {
|
||||
Type ResponseType `json:"type"`
|
||||
Records []VolumeListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
Type ResponseType `json:"type"`
|
||||
Records []VolumeListRecord `json:"records"`
|
||||
Total int `json:"total"`
|
||||
SentAnyMetricsData bool `json:"sentAnyMetricsData"`
|
||||
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention"`
|
||||
}
|
||||
|
||||
func (r *VolumeListResponse) SortBy(orderBy *v3.OrderBy) {
|
||||
|
||||
Reference in New Issue
Block a user