Unverified Commit 51081565 authored by pal-sig's avatar pal-sig Committed by GitHub
Browse files

Feat(FE): retention UI (#353)

* feat: get set retention api is updated

* feat: Settings retention UI is updated
parent 53d52254
develop 1244-edit-alert 1725-expection 24-may-2022-testing 414-uri alertmanager-discovery ankit01-oss-patch-1 bug/synk-security-fixes bump-json-iterator bump-prometheus change-sample-alert chore-telemetry chore/analytics chore/change-validation-message chore/improve-metrics-perf chore/improve-perf-remote-read chore/install-script-update chore/migration-0.8.0 chore/migration-file-path chore/moving-to-clickhouse-v2 chore/remove-query-service-codeowners chore/update-otelcollector-0.43.0 clickhouse-helm dashboarad-vars dashboard-bug-fix debug-dep debug-dep-migrate effgo enable-alerts feat-doc-contribute feat-statsd-receiver feat/addHasErrorColumn feat/amol-ee feat/clickhouse-db-optimizations feat/custom-func-getSubTreeSpans feat/dynamic-tooltip feat/ee feat/exclude-filter-support feat/featureFlagging feat/fields-compression feat/gRPC-code-method feat/getFilteredSpans feat/getSpanFilters feat/gh-bot feat/newTraceFilter feat/searchTraceId feat/support-custom-events feat/support-error-tab-page feat/support-events feat/tagValueSuggestion feat/trace-detail feat/trace-resource-attributes feat/udf-function-getSubTreeSpans feat/usage feat/usage-reporting filter-set fix-ami-linux-docker fix-double-client fix-filtered-spans fix-husky fix-user fix/414-error-trace-filter-APIs fix/aggregate fix/error-exception-page-typo fix/error-exception-sql-issue fix/errorDetailURL fix/exceptionPageOptimization fix/exclude-operation fix/null-values fix/serviceMapDependencies fix/setTTLapis fix/telemetry-bug issue-1228 issue-1252 issue-1293 issue-1294 issue-1442 issue-1485-develop issue-1511 issue-1583 issue-618 issue-pod-687 labels_object main makeavish-patch-1 makeavish-patch-2 metric-suggest-apis-chv2 metrics-builder-all metrics-table new-metrics new-metrics-enums palashgdev-patch-1 palashgdev-patch-2 perf/trace-detail-page playwright pranay01-patch-1 pranshuchittora/feat/dynamic-step-size prashant/add-codeowners prashant/add-deploy-docs prashant/ci-k3s-enchancements prashant/contributing-docs prashant/docker-data-path prashant/e2e-k3s-changes prashant/frontend-docker prashant/hotrod-log-options prashant/hotrod-template prashant/hotrod-yaml prashant/install-script-changes prashant/integrate-behaviorbot prashant/migrate-helm-charts prashant/minor-k3s-changes prashant/nginx-cache-improvement prashant/remove-ports prashant/rename-config prashant/single-hotrod-manifest prashant/two-compose-yaml prashant/version-ping-mini-css-extract-plugin prashant/versioning prod-feedback release/v0.10 release/v0.10.0 release/v0.10.1 release/v0.10.2 release/v0.11 release/v0.11.0 release/v0.11.1 release/v0.11.2 release/v0.11.3 release/v0.6 release/v0.6.0 release/v0.6.1 release/v0.6.2 release/v0.7 release/v0.7.0 release/v0.7.1 release/v0.7.2 release/v0.7.3 release/v0.7.4 release/v0.7.5 release/v0.8 release/v0.8.0 release/v0.8.1 release/v0.8.2 release/v0.9 release/v0.9.0 release/v0.9.1 release/v0.9.2 revert-382-fix-eslint-error revert-386-remove-package revert-456-storybook revert-628-chore/migration-file-path revert-770-trace-styles revert-814-release/v0.7.0 revert-835-pc/feat/shared-styles-for-styled-components snyk-fix-0c242a73fc20c472e37f0b59a7c93a5a snyk-fix-194ab2b3455dd9e2099068fc3ac5f20f snyk-fix-3d7b28e56a36018c4b5cf8438365ff27 snyk-fix-4ef12a6988dec7696867e0b2accb8289 snyk-fix-7ee2560cd9d67a9821899135c05c1175 snyk-fix-8f3a2f55a70c214b57d1a3b3bce7d0cf snyk-fix-a7789225303bf723cc0665d987e0bf24 snyk-fix-badf8cd7fc1f284699352ace871e5075 snyk-fix-d5e919722918d14db890a368b9964203 trace-search troubleshoot ttl-plus uuid-server wip-release-0.11.1 v0.11.3 v0.11.3-rc.1 v0.11.2 v0.11.2-rc.3 v0.11.2-rc.2 v0.11.2-rc.1 v0.11.1 v0.11.1-rc.1 v0.11.0 v0.11.0-rc.1 v0.11 v0.10.2 v0.10.1 v0.10.1-rc.1 v0.10.0 v0.10.0-rc2 v0.10.0-rc1 v0.10 v0.9.2 v0.9.2-rc1 v0.9.1 v0.9.0 v0.9.0-rc2 v0.9.0-rc1 v0.9 v0.8.2 v0.8.1 v0.8.1-rc5 v0.8.1-rc4 v0.8.1-rc3 v0.8.1-rc2 v0.8.1-rc1 v0.8.0 v0.8.0-rc6 v0.8.0-rc5 v0.8.0-rc4 v0.8.0-rc3 v0.8.0-rc2 v0.8.0-rc1 v0.8 v0.7.5 v0.7.5-rc2 v0.7.5-rc1 v0.7.4 v0.7.4-rc2 v0.7.4-rc1 v0.7.3 v0.7.2 v0.7.2-rc1 v0.7.1 v0.7.0 v0.7 v0.6.2 v0.6.1 v0.6.0 v0.6 v0.5.4 v0.5.3 v0.5.2 v0.5.1 v0.5.0 v0.4.5 v0.4.4
No related merge requests found
Showing with 461 additions and 30 deletions
+461 -30
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { PayloadProps } from 'types/api/settings/getRetention';
const getRetention = async (): Promise<
SuccessResponse<PayloadProps> | ErrorResponse
> => {
try {
const response = await axios.get<PayloadProps>(`/settings/ttl`);
return {
statusCode: 200,
error: null,
message: 'Success',
payload: response.data,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
export default getRetention;
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { PayloadProps, Props } from 'types/api/settings/setRetention';
const setRetention = async (
props: Props,
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
try {
const response = await axios.post<PayloadProps>(
`/settings/ttl?duration=${props.duration}&type=${props.type}`,
);
return {
statusCode: 200,
error: null,
message: 'Success',
payload: response.data,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
export default setRetention;
import { DownOutlined } from '@ant-design/icons';
import { Button, Menu } from 'antd';
import { MenuInfo } from 'rc-menu/lib/interface';
import React from 'react';
import { SettingPeroid } from '.';
import {
Dropdown,
Input,
RetentionContainer,
TextContainer,
Typography,
} from './styles';
const Retention = ({
retentionValue,
setRentionValue,
selectedRetentionPeroid,
setSelectedRetentionPeroid,
text,
}: RetentionProps): JSX.Element => {
const options: Option[] = [
{
key: 'hr',
value: 'Hrs',
},
{
key: 'day',
value: 'Days',
},
{
key: 'month',
value: 'Months',
},
];
const onClickHandler = (
e: MenuInfo,
func: React.Dispatch<React.SetStateAction<SettingPeroid>>,
): void => {
const selected = e.key as SettingPeroid;
func(selected);
};
const menu = (
<Menu onClick={(e): void => onClickHandler(e, setSelectedRetentionPeroid)}>
{options.map((option) => (
<Menu.Item key={option.key}>{option.value}</Menu.Item>
))}
</Menu>
);
const currentSelectedOption = (option: SettingPeroid): string | undefined => {
return options.find((e) => e.key === option)?.value;
};
const onChangeHandler = (
e: React.ChangeEvent<HTMLInputElement>,
func: React.Dispatch<React.SetStateAction<number>>,
): void => {
const value = e.target.value;
if (value.length > 0) {
const parsedValue = Math.abs(parseInt(value, 10));
func(parsedValue);
}
if (value.length === 0) {
func(0);
}
};
return (
<RetentionContainer>
<TextContainer>
<Typography>{text}</Typography>
</TextContainer>
<Input
value={retentionValue}
onChange={(e): void => onChangeHandler(e, setRentionValue)}
/>
<Dropdown overlay={menu}>
<Button>
{currentSelectedOption(selectedRetentionPeroid)} <DownOutlined />
</Button>
</Dropdown>
</RetentionContainer>
);
};
interface Option {
key: SettingPeroid;
value: string;
}
interface RetentionProps {
retentionValue: number;
text: string;
setRentionValue: React.Dispatch<React.SetStateAction<number>>;
selectedRetentionPeroid: SettingPeroid;
setSelectedRetentionPeroid: React.Dispatch<
React.SetStateAction<SettingPeroid>
>;
}
export default Retention;
import { Button, Modal, notification, Typography } from 'antd';
import getRetentionperoidApi from 'api/settings/getRetention';
import setRetentionApi from 'api/settings/setRetention';
import Spinner from 'components/Spinner';
import useFetch from 'hooks/useFetch';
import convertIntoHr from 'lib/convertIntoHr';
import getSettingsPeroid from 'lib/getSettingsPeroid';
import React, { useCallback, useEffect, useState } from 'react';
import { PayloadProps } from 'types/api/settings/getRetention';
import Retention from './Retention';
import { ButtonContainer, Container } from './styles';
const GeneralSettings = (): JSX.Element => {
const [
selectedMetricsPeroid,
setSelectedMetricsPeroid,
] = useState<SettingPeroid>('month');
const [notifications, Element] = notification.useNotification();
const [retentionPeroidMetrics, setRetentionPeroidMetrics] = useState<number>(
0,
);
const [modal, setModal] = useState<boolean>(false);
const [postApiLoading, setPostApiLoading] = useState<boolean>(false);
const [selectedTracePeroid, setSelectedTracePeroid] = useState<SettingPeroid>(
'hr',
);
const [retentionPeroidTrace, setRetentionPeroidTrace] = useState<number>(0);
const onClickSaveHandler = useCallback(() => {
onModalToggleHandler();
}, []);
const { payload, loading, error, errorMessage } = useFetch<
PayloadProps,
undefined
>(getRetentionperoidApi, undefined);
const onModalToggleHandler = (): void => {
setModal((modal) => !modal);
};
useEffect(() => {
if (!loading && payload !== undefined) {
const { metrics_ttl_duration_hrs, traces_ttl_duration_hrs } = payload;
const traceValue = getSettingsPeroid(traces_ttl_duration_hrs);
const metricsValue = getSettingsPeroid(metrics_ttl_duration_hrs);
setRetentionPeroidTrace(traceValue.value);
setSelectedTracePeroid(traceValue.peroid);
setRetentionPeroidMetrics(metricsValue.value);
setSelectedMetricsPeroid(metricsValue.peroid);
}
}, [setSelectedMetricsPeroid, loading, payload]);
const onOkHandler = async (): Promise<void> => {
try {
setPostApiLoading(true);
const [tracesResponse, metricsResponse] = await Promise.all([
setRetentionApi({
duration: `${convertIntoHr(retentionPeroidTrace, selectedTracePeroid)}h`,
type: 'traces',
}),
setRetentionApi({
duration: `${convertIntoHr(
retentionPeroidMetrics,
selectedMetricsPeroid,
)}h`,
type: 'metrics',
}),
]);
if (
tracesResponse.statusCode === 200 &&
metricsResponse.statusCode === 200
) {
notifications.success({
message: 'Success!',
placement: 'topRight',
description: 'Congrats. The retention periods were updated correctly.',
});
onModalToggleHandler();
} else {
notifications.error({
message: 'Error',
description:
'There was an issue in changing the retention period. Please try again or reach out to support@signoz.io',
placement: 'topRight',
});
}
setPostApiLoading(false);
} catch (error) {
notifications.error({
message: 'Error',
description:
'There was an issue in changing the retention period. Please try again or reach out to support@signoz.io',
placement: 'topRight',
});
}
};
if (error) {
return <Typography>{errorMessage}</Typography>;
}
if (loading || payload === undefined) {
return <Spinner tip="Loading.." height="70vh" />;
}
return (
<Container>
{Element}
<Retention
text={'Retention Period for Metrics'}
selectedRetentionPeroid={selectedMetricsPeroid}
setRentionValue={setRetentionPeroidMetrics}
retentionValue={retentionPeroidMetrics}
setSelectedRetentionPeroid={setSelectedMetricsPeroid}
/>
<Retention
text={'Retention Period for Traces'}
selectedRetentionPeroid={selectedTracePeroid}
setRentionValue={setRetentionPeroidTrace}
retentionValue={retentionPeroidTrace}
setSelectedRetentionPeroid={setSelectedTracePeroid}
/>
<Modal
title="Are you sure you want to change the retention period?"
focusTriggerAfterClose
forceRender
destroyOnClose
closable
onCancel={onModalToggleHandler}
onOk={onOkHandler}
centered
visible={modal}
confirmLoading={postApiLoading}
>
<Typography>
This will change the amount of storage needed for saving metrics & traces.
</Typography>
</Modal>
<ButtonContainer>
<Button onClick={onClickSaveHandler} type="primary">
Save
</Button>
</ButtonContainer>
</Container>
);
};
export type SettingPeroid = 'hr' | 'day' | 'month';
export default GeneralSettings;
import {
Dropdown as DropDownComponent,
Input as InputComponent,
Typography as TypographyComponent,
} from 'antd';
import styled from 'styled-components';
export const RetentionContainer = styled.div`
width: 50%;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
`;
export const Input = styled(InputComponent)`
&&& {
height: 2rem;
max-width: 150px;
}
`;
export const Typography = styled(TypographyComponent)`
&&& {
display: flex;
align-items: center;
}
`;
export const ButtonContainer = styled.div`
&&& {
display: flex;
justify-content: flex-end;
width: 50%;
align-items: center;
margin-top: 3rem;
}
`;
export const Container = styled.div`
&&& {
display: flex;
flex-direction: column;
}
`;
export const Dropdown = styled(DropDownComponent)`
&&& {
display: flex;
justify-content: center;
align-items: center;
max-width: 150px;
min-width: 150px;
}
`;
export const TextContainer = styled.div`
&&& {
min-width: 100px;
}
`;
import { SettingPeroid } from 'container/GeneralSettings';
const converIntoHr = (value: number, peroid: SettingPeroid): number => {
if (peroid === 'day') {
return value * 24;
}
if (peroid === 'hr') {
return value;
}
return value * 720;
};
export default converIntoHr;
import { SettingPeroid } from 'container/GeneralSettings';
const getSettingsPeroid = (hr: number): PayloadProps => {
if (hr <= 0) {
return {
peroid: 'hr',
value: 0,
};
}
if (hr < 24) {
return {
peroid: 'hr',
value: hr,
};
}
if (hr < 720) {
return {
peroid: 'day',
value: hr / 24,
};
}
return {
peroid: 'month',
value: hr / 720,
};
};
interface PayloadProps {
value: number;
peroid: SettingPeroid;
}
export default getSettingsPeroid;
import { Form, Input, Space } from 'antd';
import { Alert } from 'antd';
import React, { useEffect } from 'react';
import { Tabs } from 'antd';
import React from 'react';
const SettingsPage = (): JSX.Element => {
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue({
retention_period: '3 days',
});
}, [form]);
const { TabPane } = Tabs;
import GeneralSettings from 'container/GeneralSettings';
const SettingsPage = (): JSX.Element => {
return (
<>
<Form name="basic" initialValues={{ remember: true }} form={form}>
<Form.Item
label="Retention Period"
name="retention_period"
rules={[{ required: false }]}
style={{ maxWidth: '40%' }}
>
<Input disabled={true} />
</Form.Item>
</Form>
<Space>
<Alert
message="Mail us at support@signoz.io to get instructions on how to change your retention period"
type="info"
/>
</Space>
</>
<Tabs defaultActiveKey="1">
<TabPane tab="General" key="1">
<GeneralSettings />
</TabPane>
{/* <TabPane tab="Alert Channels" key="2">
Alerts
</TabPane>
<TabPane tab="Users" key="3">
Users
</TabPane> */}
</Tabs>
);
};
......
export interface PayloadProps {
metrics_ttl_duration_hrs: number;
traces_ttl_duration_hrs: number;
}
export interface Props {
type: 'metrics' | 'traces';
duration: string;
}
export interface PayloadProps {
success: 'message';
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment