feat: s3 ttl validation

This commit is contained in:
Pranshu Chittora 2022-04-04 19:38:23 +05:30
parent 5be1eb58b2
commit 24d6a1e7b2
No known key found for this signature in database
GPG Key ID: 3A9E57A016CC0626
4 changed files with 195 additions and 117 deletions

View File

@ -8,7 +8,13 @@ const setRetention = async (
props: Props,
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
try {
const response = await axios.post<PayloadProps>(`/settings/ttl`, props);
const response = await axios.post<PayloadProps>(
`/settings/ttl?duration=${props.totalDuration}&type=${props.type}${
props.coldStorage
? `&coldStorage=${props.coldStorage};toColdDuration=${props.toColdDuration}`
: ''
}`,
);
return {
statusCode: 200,

View File

@ -24,9 +24,17 @@ function Retention({
timeUnitValue: initialTimeUnitValue,
} = convertHoursValueToRelevantUnit(retentionValue);
const [selectedTimeUnit, setSelectTimeUnit] = useState(initialTimeUnitValue);
const [selectedValue, setSelectedValue] = useState<number | null>(
initialValue,
);
const [selectedValue, setSelectedValue] = useState<number | null>(null);
useEffect(() => {
setSelectedValue(initialValue);
}, [initialValue]);
useEffect(() => {
setSelectTimeUnit(initialTimeUnitValue);
}, [initialTimeUnitValue]);
const menuItems = TimeUnits.map((option) => (
<Option key={option.value} value={option.value}>
@ -44,6 +52,7 @@ function Retention({
TimeUnits,
(timeUnit) => timeUnit.value === selectedTimeUnit,
)?.multiplier;
if (!selectedValue) setRetentionValue(null);
if (selectedValue && inverseMultiplier) {
setRetentionValue(selectedValue * (1 / inverseMultiplier));
}
@ -89,7 +98,7 @@ function Retention({
style={{ width: 75 }}
/>
<Select
defaultValue={selectedTimeUnit}
value={selectedTimeUnit}
onChange={currentSelectedOption}
style={{ width: 100 }}
>
@ -103,7 +112,7 @@ function Retention({
}
interface RetentionProps {
retentionValue: number;
retentionValue: number | null;
text: string;
setRetentionValue: React.Dispatch<React.SetStateAction<number | null>>;
hide: boolean;

View File

@ -36,26 +36,35 @@ function GeneralSettings(): JSX.Element {
const [availableDisks, setAvailableDisks] = useState<IDiskType | null>(null);
useEffect(() => {
getDisks().then((response) => setAvailableDisks(response));
getDisks().then((response) => setAvailableDisks(response.payload));
}, []);
const { payload: currentTTLValues, loading, error, errorMessage } = useFetch<
PayloadProps,
undefined
>(getRetentionPeriodApi, undefined);
const [metricsTotalRetentionPeriod, setMetricsTotalRetentionPeriod] = useState<
number | null
>(currentTTLValues?.metrics_ttl_duration_hrs);
>(null);
const [metricsS3RetentionPeriod, setMetricsS3RetentionPeriod] = useState<
number | null
>(currentTTLValues?.metrics_move_ttl_duration_hrs);
>(null);
const [tracesTotalRetentionPeriod, setTracesTotalRetentionPeriod] = useState<
number | null
>(currentTTLValues?.traces_ttl_duration_hrs);
>(null);
const [tracesS3RetentionPeriod, setTracesS3RetentionPeriod] = useState<
number | null
>(currentTTLValues?.traces_move_ttl_duration_hrs);
>(null);
useEffect(() => {
if (currentTTLValues) {
setMetricsTotalRetentionPeriod(currentTTLValues.metrics_ttl_duration_hrs);
setMetricsS3RetentionPeriod(currentTTLValues.metrics_move_ttl_duration_hrs);
setTracesTotalRetentionPeriod(currentTTLValues.traces_ttl_duration_hrs);
setTracesS3RetentionPeriod(currentTTLValues.traces_move_ttl_duration_hrs);
console.log({ currentTTLValues });
}
}, [currentTTLValues]);
const onModalToggleHandler = (): void => {
setModal((modal) => !modal);
@ -79,12 +88,12 @@ function GeneralSettings(): JSX.Element {
}
};
// const retentionRenderConfig = () => { };
const renderConfig = useMemo(() => {
const s3Enabled = !!find(
availableDisks,
(disks: IDiskType) => disks?.type === 's3',
const s3Enabled = useMemo(
() => !!find(availableDisks, (disks: IDiskType) => disks?.type === 's3'),
[availableDisks],
);
return [
const renderConfig = [
{
name: 'Metrics',
retentionFields: [
@ -117,14 +126,29 @@ function GeneralSettings(): JSX.Element {
},
],
},
];
}, [
availableDisks,
metricsS3RetentionPeriod,
metricsTotalRetentionPeriod,
tracesS3RetentionPeriod,
tracesTotalRetentionPeriod,
]);
].map((category): JSX.Element | null => {
if (
Array.isArray(category.retentionFields) &&
category.retentionFields.length > 0
) {
return (
<Col flex="40%" style={{ minWidth: 475 }} key={category.name}>
<Typography.Title level={3}>{category.name}</Typography.Title>
{category.retentionFields.map((retentionField) => (
<Retention
key={retentionField.name}
text={retentionField.name}
retentionValue={retentionField.value}
setRetentionValue={retentionField.setValue}
hide={!!retentionField.hide}
/>
))}
</Col>
);
}
return null;
});
const onOkHandler = async (): Promise<void> => {
try {
@ -138,28 +162,46 @@ function GeneralSettings(): JSX.Element {
// (payload?.metrics_ttl_duration_hrs || 0) < 0
// ? payload?.metrics_ttl_duration_hrs || 0
// : parseInt(retentionPeroidMetrics, 10);
const apiResponse = await setRetentionApi({
metrics_ttl_duration_hrs: metricsTotalRetentionPeriod || -1,
metrics_move_ttl_duration_hrs: metricsS3RetentionPeriod || -1,
traces_move_ttl_duration_hrs: tracesS3RetentionPeriod || -1,
traces_ttl_duration_hrs: tracesTotalRetentionPeriod || -1,
});
const [metricsTTLApiResponse, tracesTTLApiResponse] = await Promise.all([
setRetentionApi({
type: 'metrics',
totalDuration: `${metricsTotalRetentionPeriod || -1}h`,
coldStorage: s3Enabled ? 's3' : null,
toColdDuration: `${metricsS3RetentionPeriod || -1}h`,
}),
setRetentionApi({
type: 'traces',
totalDuration: `${tracesTotalRetentionPeriod || -1}h`,
coldStorage: s3Enabled ? 's3' : null,
toColdDuration: `${tracesS3RetentionPeriod || -1}h`,
}),
]);
[
{
apiResponse: metricsTTLApiResponse,
name: 'metrics',
},
{
apiResponse: tracesTTLApiResponse,
name: 'traces',
},
].forEach(({ apiResponse, name }) => {
if (apiResponse.statusCode === 200) {
notifications.success({
message: 'Success!',
placement: 'topRight',
description: 'Congrats. The retention periods were updated correctly.',
description: `Congrats. The retention periods for ${name} has been updated successfully.`,
});
// checkMetricTraceDefault(retentionTraceValue, retentionMetricsValue);
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',
description: `There was an issue in changing the retention period for ${name}. Please try again or reach out to support@signoz.io`,
placement: 'topRight',
});
}
});
setPostApiLoading(false);
} catch (error) {
notifications.error({
@ -169,8 +211,57 @@ function GeneralSettings(): JSX.Element {
placement: 'topRight',
});
}
setModal(false);
};
const [isDisabled, errorText] = useMemo(() => {
// Various methods to return dynamic error message text.
const messages = {
compareError: (value: string | number): string =>
`Total retention period for ${value} cant be lower than period after which data is moved to s3`,
nullValueError: (value: string | number): string =>
`Retention Peroid for ${value} is not set yet. Please set by choosing below`,
};
// Defaults to button not disabled and empty error message text.
let isDisabled = false;
let errorText = '';
if (s3Enabled) {
if (
(metricsTotalRetentionPeriod || metricsS3RetentionPeriod) &&
Number(metricsTotalRetentionPeriod) < Number(metricsS3RetentionPeriod)
) {
isDisabled = true;
errorText = messages.compareError('metrics');
} else if (
(tracesTotalRetentionPeriod || tracesS3RetentionPeriod) &&
Number(tracesTotalRetentionPeriod) < Number(tracesS3RetentionPeriod)
) {
isDisabled = true;
errorText = messages.compareError('traces');
}
}
if (!metricsTotalRetentionPeriod || !tracesTotalRetentionPeriod) {
isDisabled = true;
if (!metricsTotalRetentionPeriod && !tracesTotalRetentionPeriod) {
errorText = messages.nullValueError('metrics and traces');
} else if (!metricsTotalRetentionPeriod) {
errorText = messages.nullValueError('metrics');
} else if (!tracesTotalRetentionPeriod) {
errorText = messages.nullValueError('traces');
}
}
return [isDisabled, errorText];
}, [
metricsS3RetentionPeriod,
metricsTotalRetentionPeriod,
s3Enabled,
tracesS3RetentionPeriod,
tracesTotalRetentionPeriod,
]);
if (error) {
return <Typography>{errorMessage}</Typography>;
}
@ -179,31 +270,6 @@ function GeneralSettings(): JSX.Element {
return <Spinner tip="Loading.." height="70vh" />;
}
const getErrorText = (): string => {
const getValue = (value: string): string =>
`Retention Peroid for ${value} is not set yet. Please set by choosing below`;
if (!isDefaultMetrics && !isDefaultTrace) {
return '';
}
if (isDefaultMetrics && !isDefaultTrace) {
return `${getValue('Metrics')}`;
}
if (!isDefaultMetrics && isDefaultTrace) {
return `${getValue('Trace')}`;
}
return `${getValue('Trace , Metrics')}`;
};
const isDisabledHandler = (): boolean => {
return false;
};
const errorText = getErrorText();
return (
<Col xs={24} md={22} xl={20} xxl={18} style={{ margin: 'auto' }}>
{Element}
@ -228,14 +294,14 @@ function GeneralSettings(): JSX.Element {
/>
</ToolTipContainer>
)}
<Row justify="space-around">
{renderConfig.map((category): JSX.Element | null => {
<Row justify="space-around" style={{ gap: '4%' }}>
{/* {renderConfig.map((category): JSX.Element | null => {
if (
Array.isArray(category.retentionFields) &&
category.retentionFields.length > 0
) {
return (
<Col flex="48%" style={{ minWidth: 500 }} key={category.name}>
<Col flex="40%" style={{ minWidth: 475 }} key={category.name}>
<Typography.Title level={3}>{category.name}</Typography.Title>
{category.retentionFields.map((retentionField) => (
@ -251,7 +317,8 @@ function GeneralSettings(): JSX.Element {
);
}
return null;
})}
})} */}
{renderConfig}
</Row>
<Modal
@ -272,11 +339,7 @@ function GeneralSettings(): JSX.Element {
</Modal>
<ButtonContainer>
<Button
onClick={onClickSaveHandler}
disabled={isDisabledHandler()}
type="primary"
>
<Button onClick={onClickSaveHandler} disabled={isDisabled} type="primary">
Save
</Button>
</ButtonContainer>

View File

@ -1,8 +1,8 @@
export interface Props {
metrics_ttl_duration_hrs: number;
metrics_move_ttl_duration_hrs: number;
traces_ttl_duration_hrs: number;
traces_move_ttl_duration_hrs: number;
type: 'metrics' | 'traces';
totalDuration: string;
coldStorage?: 's3' | null;
toColdDuration?: string;
}
export interface PayloadProps {