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: added the host list view and filters (#6210) #6501

Merged
merged 3 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/public/Icons/broom.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/public/Icons/infraContainers.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions frontend/public/locales/en-GB/infraMonitoring.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"containers_visualization_message": "The ability to visualise containers is in active development and should be available to you soon.",
"processes_visualization_message": "The ability to visualise processes is in active development and should be available to you soon.",
"working_message": "We're working to extend infrastructure monitoring to take care of a bunch of different cases. Thank you for your patience.",
"waitlist_message": "Join the waitlist for early access or contact support.",
"contact_support": "Contact Support"
}
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 @@ -40,5 +40,6 @@
"SUPPORT": "SigNoz | Support",
"DEFAULT": "Open source Observability Platform | SigNoz",
"ALERT_HISTORY": "SigNoz | Alert Rule History",
"ALERT_OVERVIEW": "SigNoz | Alert Rule Overview"
"ALERT_OVERVIEW": "SigNoz | Alert Rule Overview",
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring"
}
7 changes: 7 additions & 0 deletions frontend/public/locales/en/infraMonitoring.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"containers_visualization_message": "The ability to visualise containers is in active development and should be available to you soon.",
"processes_visualization_message": "The ability to visualise processes is in active development and should be available to you soon.",
"working_message": "We're working to extend infrastructure monitoring to take care of a bunch of different cases. Thank you for your patience.",
"waitlist_message": "Join the waitlist for early access or contact support.",
"contact_support": "Contact Support"
}
3 changes: 2 additions & 1 deletion frontend/public/locales/en/titles.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@
"INTEGRATIONS": "SigNoz | Integrations",
"ALERT_HISTORY": "SigNoz | Alert Rule History",
"ALERT_OVERVIEW": "SigNoz | Alert Rule Overview",
"MESSAGING_QUEUES": "SigNoz | Messaging Queues"
"MESSAGING_QUEUES": "SigNoz | Messaging Queues",
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring"
}
12 changes: 12 additions & 0 deletions frontend/src/AppRoutes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ function App(): JSX.Element {

setRoutes(newRoutes);
}

const isInfraMonitoringEnabled =
allFlags.find((flag) => flag.name === FeatureKeys.HOSTS_INFRA_MONITORING)
?.active || false;

if (!isInfraMonitoringEnabled) {
const newRoutes = routes.filter(
(route) => route?.path !== ROUTES.INFRASTRUCTURE_MONITORING_HOSTS,
);

setRoutes(newRoutes);
}
});

const isOnBasicPlan =
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/AppRoutes/pageComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,10 @@ export const MQDetailPage = Loadable(
/* webpackChunkName: "MQDetailPage" */ 'pages/MessagingQueues/MQDetailPage'
),
);

export const InfrastructureMonitoring = Loadable(
() =>
import(
/* webpackChunkName: "InfrastructureMonitoring" */ 'pages/InfrastructureMonitoring'
),
);
8 changes: 8 additions & 0 deletions frontend/src/AppRoutes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
EditAlertChannelsAlerts,
EditRulesPage,
ErrorDetails,
InfrastructureMonitoring,
IngestionSettings,
InstalledIntegrations,
LicensePage,
Expand Down Expand Up @@ -391,6 +392,13 @@ const routes: AppRoutes[] = [
key: 'MESSAGING_QUEUES_DETAIL',
isPrivate: true,
},
{
path: ROUTES.INFRASTRUCTURE_MONITORING_HOSTS,
exact: true,
component: InfrastructureMonitoring,
key: 'INFRASTRUCTURE_MONITORING_HOSTS',
isPrivate: true,
},
];

export const SUPPORT_ROUTE: AppRoutes = {
Expand Down
37 changes: 37 additions & 0 deletions frontend/src/api/infra/getHostAttributeKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ApiBaseInstance } from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError, AxiosResponse } from 'axios';
import { baseAutoCompleteIdKeysOrder } from 'constants/queryBuilder';
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
import { ErrorResponse, SuccessResponse } from 'types/api';
import {
BaseAutocompleteData,
IQueryAutocompleteResponse,
} from 'types/api/queryBuilder/queryAutocompleteResponse';

export const getHostAttributeKeys = async (
searchText = '',
): Promise<SuccessResponse<IQueryAutocompleteResponse> | ErrorResponse> => {
try {
const response: AxiosResponse<{
data: IQueryAutocompleteResponse;
}> = await ApiBaseInstance.get(
`/hosts/attribute_keys?dataSource=metrics&searchText=${searchText}`,
);

const payload: BaseAutocompleteData[] =
response.data.data.attributeKeys?.map(({ id: _, ...item }) => ({
...item,
id: createIdFromObjectFields(item, baseAutoCompleteIdKeysOrder),
})) || [];

return {
statusCode: 200,
error: null,
message: response.statusText,
payload: { attributeKeys: payload },
};
} catch (e) {
return ErrorResponseHandler(e as AxiosError);
}
};
75 changes: 75 additions & 0 deletions frontend/src/api/infraMonitoring/getHostLists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
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 HostListPayload {
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 HostData {
hostName: string;
active: boolean;
os: string;
cpu: number;
cpuTimeSeries: TimeSeries;
memory: number;
memoryTimeSeries: TimeSeries;
wait: number;
waitTimeSeries: TimeSeries;
load15: number;
load15TimeSeries: TimeSeries;
}

export interface HostListResponse {
status: string;
data: {
type: string;
records: HostData[];
groups: null;
total: number;
};
}

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

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

export const getInfraAttributesValues = async ({
dataSource,
attributeKey,
filterAttributeKeyDataType,
tagType,
searchText,
}: IGetAttributeValuesPayload): Promise<
SuccessResponse<IAttributeValuesResponse> | ErrorResponse
> => {
try {
const response = await ApiBaseInstance.get(
`/hosts/attribute_values?${createQueryParams({
dataSource,
attributeKey,
searchText,
})}&filterAttributeKeyDataType=${filterAttributeKeyDataType}&tagType=${tagType}`,
);

return {
statusCode: 200,
error: null,
message: response.data.status,
payload: response.data.data,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
1 change: 0 additions & 1 deletion frontend/src/api/queryBuilder/getAttributeKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { baseAutoCompleteIdKeysOrder } from 'constants/queryBuilder';
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
import createQueryParams from 'lib/createQueryParams';
import { ErrorResponse, SuccessResponse } from 'types/api';
// ** Types
import { IGetAttributeKeysPayload } from 'types/api/queryBuilder/getAttributeKeys';
import {
BaseAutocompleteData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ function CustomTimePicker({

useEffect(() => {
const value = getSelectedTimeRangeLabel(selectedTime, selectedValue);

setSelectedTimePlaceholderValue(value);
}, [selectedTime, selectedValue]);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.host-containers {
max-width: 600px;
margin: 150px auto;
padding: 0 16px;

.infra-container-card {
display: flex;
flex-direction: column;
justify-content: center;
}

.infra-container-card-text {
font-size: var(--font-size-sm);
color: var(--text-vanilla-400);
line-height: 20px;
letter-spacing: -0.07px;
width: 400px;
font-family: 'Inter';
margin-top: 12px;
}

.infra-container-working-msg {
display: flex;
width: 400px;
padding: 12px;
align-items: flex-start;
gap: 12px;
border-radius: 4px;
background: rgba(171, 189, 255, 0.04);

.ant-space {
align-items: flex-start;
}
}

.infra-container-contact-support-btn {
display: flex;
align-items: center;
justify-content: center;
margin: auto;
}
}

.lightMode {
.infra-container-card-text {
color: var(--text-ink-200);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import './Containers.styles.scss';

import { Space, Typography } from 'antd';
import { useTranslation } from 'react-i18next';

const { Text } = Typography;

function Containers(): JSX.Element {
const { t } = useTranslation(['infraMonitoring']);

return (
<Space direction="vertical" className="host-containers" size={24}>
<div className="infra-container-card">
<img
src="/Icons/infraContainers.svg"
alt="infra-container"
width={32}
height={32}
/>

<Text className="infra-container-card-text">
{t('containers_visualization_message')}
</Text>
</div>

<div className="infra-container-working-msg">
<Space>
<img src="/Icons/broom.svg" alt="broom" width={16} height={16} />
<Text className="infra-container-card-text">{t('working_message')}</Text>
</Space>
</div>
</Space>
);
}

export default Containers;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { HostData } from 'api/infraMonitoring/getHostLists';

export type HostDetailProps = {
host: HostData | null;
isModalTimeSelection: boolean;
onClose: () => void;
};
Loading
Loading