Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement daemonSets list table for infra monitoring #6631

Draft
wants to merge 9 commits into
base: feat/infra-monitoring-k8s
Choose a base branch
from
3 changes: 2 additions & 1 deletion frontend/public/locales/en-GB/titles.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@
"DEFAULT": "Open source Observability Platform | SigNoz",
"ALERT_HISTORY": "SigNoz | Alert Rule History",
"ALERT_OVERVIEW": "SigNoz | Alert Rule Overview",
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring"
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring",
"INFRASTRUCTURE_MONITORING_KUBERNETES": "SigNoz | Infra Monitoring"
}
3 changes: 2 additions & 1 deletion frontend/public/locales/en/titles.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@
"ALERT_HISTORY": "SigNoz | Alert Rule History",
"ALERT_OVERVIEW": "SigNoz | Alert Rule Overview",
"MESSAGING_QUEUES": "SigNoz | Messaging Queues",
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring"
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring",
"INFRASTRUCTURE_MONITORING_KUBERNETES": "SigNoz | Infra Monitoring"
}
7 changes: 7 additions & 0 deletions frontend/src/AppRoutes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,13 @@ const routes: AppRoutes[] = [
key: 'INFRASTRUCTURE_MONITORING_HOSTS',
isPrivate: true,
},
{
path: ROUTES.INFRASTRUCTURE_MONITORING_KUBERNETES,
exact: true,
component: InfrastructureMonitoring,
key: 'INFRASTRUCTURE_MONITORING_KUBERNETES',
isPrivate: true,
},
];

export const SUPPORT_ROUTE: AppRoutes = {
Expand Down
69 changes: 69 additions & 0 deletions frontend/src/api/infraMonitoring/getK8sDaemonSetsList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { ApiBaseInstance } from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';

export interface K8sDaemonSetsListPayload {
filters: TagFilter;
groupBy?: BaseAutocompleteData[];
offset?: number;
limit?: number;
orderBy?: {
columnName: string;
order: 'asc' | 'desc';
};
}

export interface K8sDaemonSetsData {
daemonSetName: string;
cpuUsage: number;
memoryUsage: number;
desiredPods: number;
availablePods: number;
cpuRequest: number;
memoryRequest: number;
cpuLimit: number;
memoryLimit: number;
restarts: number;
meta: {
k8s_daemonSet_name: string;
k8s_namespace_name: string;
};
}

export interface K8sDaemonSetsListResponse {
status: string;
data: {
type: string;
records: K8sDaemonSetsData[];
groups: null;
total: number;
sentAnyHostMetricsData: boolean;
isSendingK8SAgentMetrics: boolean;
};
}

export const getK8sDaemonSetsList = async (
props: K8sDaemonSetsListPayload,
signal?: AbortSignal,
headers?: Record<string, string>,
): Promise<SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse> => {
try {
const response = await ApiBaseInstance.post('/daemonsets/list', props, {
signal,
headers,
});

return {
statusCode: 200,
error: null,
message: 'Success',
payload: response.data,
params: props,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
64 changes: 64 additions & 0 deletions frontend/src/api/infraMonitoring/getK8sNodesList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { ApiBaseInstance } from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';

export interface K8sNodesListPayload {
filters: TagFilter;
groupBy?: BaseAutocompleteData[];
offset?: number;
limit?: number;
orderBy?: {
columnName: string;
order: 'asc' | 'desc';
};
}

export interface K8sNodesData {
nodeUID: string;
nodeCPUUsage: number;
nodeCPUAllocatable: number;
nodeMemoryUsage: number;
nodeMemoryAllocatable: number;
meta: {
k8s_node_name: string;
k8s_node_uid: string;
};
}

export interface K8sNodesListResponse {
status: string;
data: {
type: string;
records: K8sNodesData[];
groups: null;
total: number;
sentAnyHostMetricsData: boolean;
isSendingK8SAgentMetrics: boolean;
};
}

export const getK8sNodesList = async (
props: K8sNodesListPayload,
signal?: AbortSignal,
headers?: Record<string, string>,
): Promise<SuccessResponse<K8sNodesListResponse> | ErrorResponse> => {
try {
const response = await ApiBaseInstance.post('/nodes/list', props, {
signal,
headers,
});

return {
statusCode: 200,
error: null,
message: 'Success',
payload: response.data,
params: props,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
93 changes: 93 additions & 0 deletions frontend/src/api/infraMonitoring/getK8sPodsList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { ApiBaseInstance } from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';

export interface K8sPodsListPayload {
filters: TagFilter;
groupBy?: BaseAutocompleteData[];
offset?: number;
limit?: number;
orderBy?: {
columnName: string;
order: 'asc' | 'desc';
};
}

export interface TimeSeriesValue {
timestamp: number;
value: string;
}

export interface TimeSeries {
labels: Record<string, string>;
labelsArray: Array<Record<string, string>>;
values: TimeSeriesValue[];
}

export interface K8sPodsData {
podUID: string;
podCPU: number;
podCPURequest: number;
podCPULimit: number;
podMemory: number;
podMemoryRequest: number;
podMemoryLimit: number;
restartCount: number;
meta: {
k8s_cronjob_name: string;
k8s_daemonset_name: string;
k8s_deployment_name: string;
k8s_job_name: string;
k8s_namespace_name: string;
k8s_node_name: string;
k8s_pod_name: string;
k8s_pod_uid: string;
k8s_statefulset_name: string;
k8s_cluster_name: string;
};
countByPhase: {
pending: number;
running: number;
succeeded: number;
failed: number;
unknown: number;
};
}

export interface K8sPodsListResponse {
status: string;
data: {
type: string;
records: K8sPodsData[];
groups: null;
total: number;
sentAnyHostMetricsData: boolean;
isSendingK8SAgentMetrics: boolean;
};
}

export const getK8sPodsList = async (
props: K8sPodsListPayload,
signal?: AbortSignal,
headers?: Record<string, string>,
): Promise<SuccessResponse<K8sPodsListResponse> | ErrorResponse> => {
try {
const response = await ApiBaseInstance.post('/pods/list', props, {
signal,
headers,
});

return {
statusCode: 200,
error: null,
message: 'Success',
payload: response.data,
params: props,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
width: calc(100% - 24px);
cursor: pointer;

&.filter-disabled {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
display: flex;
align-items: center;
gap: 6px;
width: 100%;
justify-content: flex-start;

.text {
color: var(--bg-vanilla-400);
Expand Down Expand Up @@ -50,6 +52,8 @@
display: flex;
align-items: center;
gap: 12px;
width: 100%;
justify-content: flex-end;

.divider-filter {
width: 1px;
Expand Down
27 changes: 19 additions & 8 deletions frontend/src/components/QuickFilters/QuickFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ export interface IQuickFiltersConfig {
interface IQuickFiltersProps {
config: IQuickFiltersConfig[];
handleFilterVisibilityChange: () => void;
source?: string | null;
}

export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
const { config, handleFilterVisibilityChange } = props;
const { config, handleFilterVisibilityChange, source } = props;

const {
currentQuery,
Expand Down Expand Up @@ -83,16 +84,22 @@ export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {

const lastQueryName =
currentQuery.builder.queryData?.[lastUsedQuery || 0]?.queryName;

const isInfraMonitoring = source === 'infra-monitoring';

return (
<div className="quick-filters">
<section className="header">
<section className="left-actions">
<FilterOutlined />
<Typography.Text className="text">Filters for</Typography.Text>
<Tooltip title={`Filter currently in sync with query ${lastQueryName}`}>
<Typography.Text className="sync-tag">{lastQueryName}</Typography.Text>
</Tooltip>
</section>
{!isInfraMonitoring && (
<section className="left-actions">
<FilterOutlined />
<Typography.Text className="text">Filters for</Typography.Text>
<Tooltip title={`Filter currently in sync with query ${lastQueryName}`}>
<Typography.Text className="sync-tag">{lastQueryName}</Typography.Text>
</Tooltip>
</section>
)}

<section className="right-actions">
<Tooltip title="Reset All">
<SyncOutlined className="sync-icon" onClick={handleReset} />
Expand Down Expand Up @@ -122,3 +129,7 @@ export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
</div>
);
}

QuickFilters.defaultProps = {
source: null,
};
1 change: 1 addition & 0 deletions frontend/src/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const ROUTES = {
MESSAGING_QUEUES: '/messaging-queues',
MESSAGING_QUEUES_DETAIL: '/messaging-queues/detail',
INFRASTRUCTURE_MONITORING_HOSTS: '/infrastructure-monitoring/hosts',
INFRASTRUCTURE_MONITORING_KUBERNETES: '/infrastructure-monitoring/kubernetes',
} as const;

export default ROUTES;
7 changes: 4 additions & 3 deletions frontend/src/container/AppLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,9 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
const isDashboardListView = (): boolean => routeKey === 'ALL_DASHBOARD';
const isAlertHistory = (): boolean => routeKey === 'ALERT_HISTORY';
const isAlertOverview = (): boolean => routeKey === 'ALERT_OVERVIEW';
const isInfraMonitoringHosts = (): boolean =>
routeKey === 'INFRASTRUCTURE_MONITORING_HOSTS';
const isInfraMonitoring = (): boolean =>
routeKey === 'INFRASTRUCTURE_MONITORING_HOSTS' ||
routeKey === 'INFRASTRUCTURE_MONITORING_KUBERNETES';
const isPathMatch = (regex: RegExp): boolean => regex.test(pathname);

const isDashboardView = (): boolean =>
Expand Down Expand Up @@ -403,7 +404,7 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
isAlertHistory() ||
isAlertOverview() ||
isMessagingQueues() ||
isInfraMonitoringHosts()
isInfraMonitoring()
? 0
: '0 1rem',

Expand Down
3 changes: 2 additions & 1 deletion frontend/src/container/InfraMonitoringHosts/HostsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ function HostsList(): JSX.Element {
const showHostsEmptyState =
!isFetching &&
!isLoading &&
(!sentAnyHostMetricsData || isSendingIncorrectK8SAgentMetrics);
(!sentAnyHostMetricsData || isSendingIncorrectK8SAgentMetrics) &&
!filters.items.length;

return (
<div className="hosts-list">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@
.column-header-right {
text-align: right;
}
.column-header-left {
text-align: left;
}
.ant-table-tbody > tr > td {
border-bottom: none;
}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/container/InfraMonitoringHosts/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const getHostListsQuery = (): HostListPayload => ({
groupBy: [],
orderBy: { columnName: 'cpu', order: 'desc' },
});

export const getTabsItems = (): TabsProps['items'] => [
{
label: <TabLabel label="List View" isDisabled={false} tooltipText="" />,
Expand Down
Loading
Loading