chore: added api chagnes for logs retenetion v2 api (#8649)

* chore: added api chagnes for logs retenetion v2 api

* chore: added pr review fixes

* chore: minor fix

* feat: added api changes for setting retention period

* chore: pr review fixes

* chore: removed return statement

* fix: pr reviews

* fix: pr review
This commit is contained in:
Abhi kumar 2025-08-29 15:10:15 +05:30 committed by GitHub
parent 1a193fb1a9
commit c838d7e2d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 166 additions and 38 deletions

View File

@ -0,0 +1,25 @@
import { ApiV2Instance } from 'api';
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps } from 'types/api/settings/getRetention';
// Only works for logs
const getRetentionV2 = async (): Promise<
SuccessResponseV2<PayloadProps<'logs'>>
> => {
try {
const response = await ApiV2Instance.get<PayloadProps<'logs'>>(
`/settings/ttl`,
);
return {
httpStatusCode: response.status,
data: response.data,
};
} catch (error) {
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
}
};
export default getRetentionV2;

View File

@ -1,14 +1,14 @@
import axios from 'api'; import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/settings/setRetention'; import { PayloadPropsV2, Props } from 'types/api/settings/setRetention';
const setRetention = async ( const setRetention = async (
props: Props, props: Props,
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => { ): Promise<SuccessResponseV2<PayloadPropsV2>> => {
try { try {
const response = await axios.post<PayloadProps>( const response = await axios.post<PayloadPropsV2>(
`/settings/ttl?duration=${props.totalDuration}&type=${props.type}${ `/settings/ttl?duration=${props.totalDuration}&type=${props.type}${
props.coldStorage props.coldStorage
? `&coldStorage=${props.coldStorage}&toColdDuration=${props.toColdDuration}` ? `&coldStorage=${props.coldStorage}&toColdDuration=${props.toColdDuration}`
@ -17,13 +17,11 @@ const setRetention = async (
); );
return { return {
statusCode: 200, httpStatusCode: response.status,
error: null, data: response.data,
message: 'Success',
payload: response.data,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
} }
}; };

View File

@ -0,0 +1,32 @@
import { ApiV2Instance } from 'api';
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadPropsV2, PropsV2 } from 'types/api/settings/setRetention';
const setRetentionV2 = async ({
type,
defaultTTLDays,
coldStorageVolume,
coldStorageDuration,
ttlConditions,
}: PropsV2): Promise<SuccessResponseV2<PayloadPropsV2>> => {
try {
const response = await ApiV2Instance.post<PayloadPropsV2>(`/settings/ttl`, {
type,
defaultTTLDays,
coldStorageVolume,
coldStorageDuration,
ttlConditions,
});
return {
httpStatusCode: response.status,
data: response.data,
};
} catch (error) {
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
}
};
export default setRetentionV2;

View File

@ -2,22 +2,30 @@
import { LoadingOutlined } from '@ant-design/icons'; import { LoadingOutlined } from '@ant-design/icons';
import { Button, Card, Col, Divider, Modal, Row, Spin, Typography } from 'antd'; import { Button, Card, Col, Divider, Modal, Row, Spin, Typography } from 'antd';
import setRetentionApi from 'api/settings/setRetention'; import setRetentionApi from 'api/settings/setRetention';
import setRetentionApiV2 from 'api/settings/setRetentionV2';
import TextToolTip from 'components/TextToolTip'; import TextToolTip from 'components/TextToolTip';
import GeneralSettingsCloud from 'container/GeneralSettingsCloud'; import GeneralSettingsCloud from 'container/GeneralSettingsCloud';
import useComponentPermission from 'hooks/useComponentPermission'; import useComponentPermission from 'hooks/useComponentPermission';
import { useGetTenantLicense } from 'hooks/useGetTenantLicense'; import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import { StatusCodes } from 'http-status-codes';
import find from 'lodash-es/find'; import find from 'lodash-es/find';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; import { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { UseQueryResult } from 'react-query'; import { UseQueryResult } from 'react-query';
import { useInterval } from 'react-use'; import { useInterval } from 'react-use';
import { ErrorResponse, SuccessResponse } from 'types/api'; import {
ErrorResponse,
ErrorResponseV2,
SuccessResponse,
SuccessResponseV2,
} from 'types/api';
import { import {
IDiskType, IDiskType,
PayloadProps as GetDisksPayload, PayloadProps as GetDisksPayload,
} from 'types/api/disks/getDisks'; } from 'types/api/disks/getDisks';
import APIError from 'types/api/error';
import { TTTLType } from 'types/api/settings/common'; import { TTTLType } from 'types/api/settings/common';
import { import {
PayloadPropsLogs as GetRetentionPeriodLogsPayload, PayloadPropsLogs as GetRetentionPeriodLogsPayload,
@ -127,7 +135,7 @@ function GeneralSettings({
useEffect(() => { useEffect(() => {
if (logsCurrentTTLValues) { if (logsCurrentTTLValues) {
setLogsTotalRetentionPeriod(logsCurrentTTLValues.logs_ttl_duration_hrs); setLogsTotalRetentionPeriod(logsCurrentTTLValues.default_ttl_days * 24);
setLogsS3RetentionPeriod( setLogsS3RetentionPeriod(
logsCurrentTTLValues.logs_move_ttl_duration_hrs logsCurrentTTLValues.logs_move_ttl_duration_hrs
? logsCurrentTTLValues.logs_move_ttl_duration_hrs ? logsCurrentTTLValues.logs_move_ttl_duration_hrs
@ -336,20 +344,40 @@ function GeneralSettings({
} }
try { try {
onPostApiLoadingHandler(type); onPostApiLoadingHandler(type);
const setTTLResponse = await setRetentionApi({
type,
totalDuration: `${apiCallTotalRetention || -1}h`,
coldStorage: s3Enabled ? 's3' : null,
toColdDuration: `${apiCallS3Retention || -1}h`,
});
let hasSetTTLFailed = false; let hasSetTTLFailed = false;
if (setTTLResponse.statusCode === 409) {
try {
if (type === 'logs') {
await setRetentionApiV2({
type,
defaultTTLDays: apiCallTotalRetention ? apiCallTotalRetention / 24 : -1, // convert Hours to days
coldStorageVolume: '',
coldStorageDuration: 0,
ttlConditions: [],
});
} else {
await setRetentionApi({
type,
totalDuration: `${apiCallTotalRetention || -1}h`,
coldStorage: s3Enabled ? 's3' : null,
toColdDuration: `${apiCallS3Retention || -1}h`,
});
}
} catch (error) {
hasSetTTLFailed = true; hasSetTTLFailed = true;
notifications.error({ if ((error as APIError).getHttpStatusCode() === StatusCodes.CONFLICT) {
message: 'Error', notifications.error({
description: t('retention_request_race_condition'), message: 'Error',
placement: 'topRight', description: t('retention_request_race_condition'),
}); placement: 'topRight',
});
} else {
notifications.error({
message: 'Error',
description: (error as APIError).getErrorMessage(),
placement: 'topRight',
});
}
} }
if (type === 'metrics') { if (type === 'metrics') {
@ -376,11 +404,14 @@ function GeneralSettings({
logsTtlValuesRefetch(); logsTtlValuesRefetch();
if (!hasSetTTLFailed) if (!hasSetTTLFailed)
// Updates the currentTTL Values in order to avoid pushing the same values. // Updates the currentTTL Values in order to avoid pushing the same values.
setLogsCurrentTTLValues({ setLogsCurrentTTLValues((prev) => ({
...prev,
logs_ttl_duration_hrs: logsTotalRetentionPeriod || -1, logs_ttl_duration_hrs: logsTotalRetentionPeriod || -1,
logs_move_ttl_duration_hrs: logsS3RetentionPeriod || -1, logs_move_ttl_duration_hrs: logsS3RetentionPeriod || -1,
status: '', default_ttl_days: logsTotalRetentionPeriod
}); ? logsTotalRetentionPeriod / 24 // convert Hours to days
: -1,
}));
} }
} catch (error) { } catch (error) {
notifications.error({ notifications.error({
@ -399,6 +430,7 @@ function GeneralSettings({
const renderConfig = [ const renderConfig = [
{ {
name: 'Metrics', name: 'Metrics',
type: 'metrics',
retentionFields: [ retentionFields: [
{ {
name: t('total_retention_period'), name: t('total_retention_period'),
@ -440,6 +472,7 @@ function GeneralSettings({
}, },
{ {
name: 'Traces', name: 'Traces',
type: 'traces',
retentionFields: [ retentionFields: [
{ {
name: t('total_retention_period'), name: t('total_retention_period'),
@ -479,6 +512,7 @@ function GeneralSettings({
}, },
{ {
name: 'Logs', name: 'Logs',
type: 'logs',
retentionFields: [ retentionFields: [
{ {
name: t('total_retention_period'), name: t('total_retention_period'),
@ -537,6 +571,7 @@ function GeneralSettings({
/> />
{category.retentionFields.map((retentionField) => ( {category.retentionFields.map((retentionField) => (
<Retention <Retention
type={category.type as TTTLType}
key={retentionField.name} key={retentionField.name}
text={retentionField.name} text={retentionField.name}
retentionValue={retentionField.value} retentionValue={retentionField.value}
@ -625,7 +660,7 @@ interface GeneralSettingsProps {
ErrorResponse | SuccessResponse<GetRetentionPeriodTracesPayload> ErrorResponse | SuccessResponse<GetRetentionPeriodTracesPayload>
>['refetch']; >['refetch'];
logsTtlValuesRefetch: UseQueryResult< logsTtlValuesRefetch: UseQueryResult<
ErrorResponse | SuccessResponse<GetRetentionPeriodLogsPayload> ErrorResponseV2 | SuccessResponseV2<GetRetentionPeriodLogsPayload>
>['refetch']; >['refetch'];
} }

View File

@ -9,6 +9,7 @@ import {
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
import { TTTLType } from 'types/api/settings/common';
import { import {
Input, Input,
@ -20,11 +21,13 @@ import {
convertHoursValueToRelevantUnit, convertHoursValueToRelevantUnit,
SettingPeriod, SettingPeriod,
TimeUnits, TimeUnits,
TimeUnitsValues,
} from './utils'; } from './utils';
const { Option } = Select; const { Option } = Select;
function Retention({ function Retention({
type,
retentionValue, retentionValue,
setRetentionValue, setRetentionValue,
text, text,
@ -50,7 +53,9 @@ function Retention({
if (!interacted.current) setSelectTimeUnit(initialTimeUnitValue); if (!interacted.current) setSelectTimeUnit(initialTimeUnitValue);
}, [initialTimeUnitValue]); }, [initialTimeUnitValue]);
const menuItems = TimeUnits.map((option) => ( const menuItems = TimeUnits.filter((option) =>
type === 'logs' ? option.value !== TimeUnitsValues.hr : true,
).map((option) => (
<Option key={option.value} value={option.value}> <Option key={option.value} value={option.value}>
{option.key} {option.key}
</Option> </Option>
@ -124,6 +129,7 @@ function Retention({
} }
interface RetentionProps { interface RetentionProps {
type: TTTLType;
retentionValue: number | null; retentionValue: number | null;
text: string; text: string;
setRetentionValue: Dispatch<SetStateAction<number | null>>; setRetentionValue: Dispatch<SetStateAction<number | null>>;

View File

@ -1,11 +1,13 @@
import { Typography } from 'antd'; import { Typography } from 'antd';
import getDisks from 'api/disks/getDisks'; import getDisks from 'api/disks/getDisks';
import getRetentionPeriodApi from 'api/settings/getRetention'; import getRetentionPeriodApi from 'api/settings/getRetention';
import getRetentionPeriodApiV2 from 'api/settings/getRetentionV2';
import Spinner from 'components/Spinner'; import Spinner from 'components/Spinner';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQueries } from 'react-query'; import { useQueries } from 'react-query';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse, SuccessResponseV2 } from 'types/api';
import APIError from 'types/api/error';
import { TTTLType } from 'types/api/settings/common'; import { TTTLType } from 'types/api/settings/common';
import { PayloadProps as GetRetentionPeriodAPIPayloadProps } from 'types/api/settings/getRetention'; import { PayloadProps as GetRetentionPeriodAPIPayloadProps } from 'types/api/settings/getRetention';
@ -15,6 +17,10 @@ type TRetentionAPIReturn<T extends TTTLType> = Promise<
SuccessResponse<GetRetentionPeriodAPIPayloadProps<T>> | ErrorResponse SuccessResponse<GetRetentionPeriodAPIPayloadProps<T>> | ErrorResponse
>; >;
type TRetentionAPIReturnV2<T extends TTTLType> = Promise<
SuccessResponseV2<GetRetentionPeriodAPIPayloadProps<T>>
>;
function GeneralSettings(): JSX.Element { function GeneralSettings(): JSX.Element {
const { t } = useTranslation('common'); const { t } = useTranslation('common');
const { user } = useAppContext(); const { user } = useAppContext();
@ -36,7 +42,7 @@ function GeneralSettings(): JSX.Element {
queryKey: ['getRetentionPeriodApiTraces', user?.accessJwt], queryKey: ['getRetentionPeriodApiTraces', user?.accessJwt],
}, },
{ {
queryFn: (): TRetentionAPIReturn<'logs'> => getRetentionPeriodApi('logs'), queryFn: (): TRetentionAPIReturnV2<'logs'> => getRetentionPeriodApiV2(), // Only works for logs
queryKey: ['getRetentionPeriodApiLogs', user?.accessJwt], queryKey: ['getRetentionPeriodApiLogs', user?.accessJwt],
}, },
{ {
@ -70,7 +76,7 @@ function GeneralSettings(): JSX.Element {
if (getRetentionPeriodLogsApiResponse.isError || getDisksResponse.isError) { if (getRetentionPeriodLogsApiResponse.isError || getDisksResponse.isError) {
return ( return (
<Typography> <Typography>
{getRetentionPeriodLogsApiResponse.data?.error || {(getRetentionPeriodLogsApiResponse.error as APIError).getErrorMessage() ||
getDisksResponse.data?.error || getDisksResponse.data?.error ||
t('something_went_wrong')} t('something_went_wrong')}
</Typography> </Typography>
@ -86,7 +92,7 @@ function GeneralSettings(): JSX.Element {
getRetentionPeriodTracesApiResponse.isLoading || getRetentionPeriodTracesApiResponse.isLoading ||
!getRetentionPeriodTracesApiResponse.data?.payload || !getRetentionPeriodTracesApiResponse.data?.payload ||
getRetentionPeriodLogsApiResponse.isLoading || getRetentionPeriodLogsApiResponse.isLoading ||
!getRetentionPeriodLogsApiResponse.data?.payload !getRetentionPeriodLogsApiResponse.data?.data
) { ) {
return <Spinner tip="Loading.." height="70vh" />; return <Spinner tip="Loading.." height="70vh" />;
} }
@ -99,7 +105,7 @@ function GeneralSettings(): JSX.Element {
metricsTtlValuesRefetch: getRetentionPeriodMetricsApiResponse.refetch, metricsTtlValuesRefetch: getRetentionPeriodMetricsApiResponse.refetch,
tracesTtlValuesPayload: getRetentionPeriodTracesApiResponse.data?.payload, tracesTtlValuesPayload: getRetentionPeriodTracesApiResponse.data?.payload,
tracesTtlValuesRefetch: getRetentionPeriodTracesApiResponse.refetch, tracesTtlValuesRefetch: getRetentionPeriodTracesApiResponse.refetch,
logsTtlValuesPayload: getRetentionPeriodLogsApiResponse.data?.payload, logsTtlValuesPayload: getRetentionPeriodLogsApiResponse.data?.data,
logsTtlValuesRefetch: getRetentionPeriodLogsApiResponse.refetch, logsTtlValuesRefetch: getRetentionPeriodLogsApiResponse.refetch,
}} }}
/> />

View File

@ -5,19 +5,26 @@ export interface ITimeUnit {
key: string; key: string;
multiplier: number; multiplier: number;
} }
export enum TimeUnitsValues {
hr = 'hr',
day = 'day',
month = 'month',
}
export const TimeUnits: ITimeUnit[] = [ export const TimeUnits: ITimeUnit[] = [
{ {
value: 'hr', value: TimeUnitsValues.hr,
key: 'Hours', key: 'Hours',
multiplier: 1, multiplier: 1,
}, },
{ {
value: 'day', value: TimeUnitsValues.day,
key: 'Days', key: 'Days',
multiplier: 1 / 24, multiplier: 1 / 24,
}, },
{ {
value: 'month', value: TimeUnitsValues.month,
key: 'Months', key: 'Months',
multiplier: 1 / (24 * 30), multiplier: 1 / (24 * 30),
}, },

View File

@ -17,7 +17,9 @@ export interface PayloadPropsTraces {
} }
export interface PayloadPropsLogs { export interface PayloadPropsLogs {
logs_ttl_duration_hrs: number; version: 'v1' | 'v2';
default_ttl_days: number;
logs_ttl_duration_hrs?: number;
logs_move_ttl_duration_hrs?: number; logs_move_ttl_duration_hrs?: number;
status: TStatus; status: TStatus;
expected_logs_ttl_duration_hrs?: number; expected_logs_ttl_duration_hrs?: number;

View File

@ -7,6 +7,23 @@ export interface Props {
toColdDuration?: string; toColdDuration?: string;
} }
export interface PropsV2 {
type: TTTLType;
defaultTTLDays: number;
coldStorageVolume: string;
coldStorageDuration: number;
ttlConditions: {
conditions: {
key: string;
values: string[];
}[];
ttlDays: number;
}[];
}
export interface PayloadProps { export interface PayloadProps {
success: 'message'; success: 'message';
} }
export interface PayloadPropsV2 {
message: string;
}