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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,9 @@ export interface PayloadPropsTraces {
}
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;
status: TStatus;
expected_logs_ttl_duration_hrs?: number;

View File

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