Skip to content

Commit

Permalink
[Index Management] Fix globalMaxRetention display error in data reten…
Browse files Browse the repository at this point in the history
  • Loading branch information
viajes7 and elasticmachine authored Oct 31, 2024
1 parent 424233e commit 1e7bb1e
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { getLifecycleValue } from './data_streams';
import { deserializeGlobalMaxRetention, getLifecycleValue } from './data_streams';

describe('Data stream helpers', () => {
describe('getLifecycleValue', () => {
Expand Down Expand Up @@ -45,4 +45,36 @@ describe('Data stream helpers', () => {
).toBe('5 days');
});
});

describe('deserializeGlobalMaxRetention', () => {
it('if globalMaxRetention is undefined', () => {
expect(deserializeGlobalMaxRetention(undefined)).toEqual({});
});

it('split globalMaxRetention size and units', () => {
expect(deserializeGlobalMaxRetention('1000h')).toEqual({
size: '1000',
unit: 'h',
unitText: 'hours',
});
});

it('support all of the units that are accepted by es', () => {
expect(deserializeGlobalMaxRetention('1000ms')).toEqual({
size: '1000',
unit: 'ms',
unitText: 'milliseconds',
});
expect(deserializeGlobalMaxRetention('1000micros')).toEqual({
size: '1000',
unit: 'micros',
unitText: 'microseconds',
});
expect(deserializeGlobalMaxRetention('1000nanos')).toEqual({
size: '1000',
unit: 'nanos',
unitText: 'nanoseconds',
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,19 @@ export const isDSLWithILMIndices = (dataStream?: DataStream | null) => {

return;
};

export const deserializeGlobalMaxRetention = (globalMaxRetention?: string) => {
if (!globalMaxRetention) {
return {};
}

const { size, unit } = splitSizeAndUnits(globalMaxRetention);
const availableTimeUnits = [...timeUnits, ...extraTimeUnits];
const match = availableTimeUnits.find((timeUnit) => timeUnit.value === unit);

return {
size,
unit,
unitText: match?.text ?? unit,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { getIndexListUri } from '../../../../services/routing';
import { documentationService } from '../../../../services/documentation';
import { splitSizeAndUnits, DataStream } from '../../../../../../common';
import { timeUnits } from '../../../../constants/time_units';
import { isDSLWithILMIndices } from '../../../../lib/data_streams';
import { deserializeGlobalMaxRetention, isDSLWithILMIndices } from '../../../../lib/data_streams';
import { useAppContext } from '../../../../app_context';
import { UnitField } from '../../../../components/shared';
import { updateDataRetention } from '../../../../services/api';
Expand Down Expand Up @@ -214,6 +214,7 @@ export const EditDataRetentionModal: React.FunctionComponent<Props> = ({
const { history } = useAppContext();
const dslWithIlmIndices = isDSLWithILMIndices(dataStream);
const { size, unit } = splitSizeAndUnits(lifecycle?.data_retention as string);
const globalMaxRetention = deserializeGlobalMaxRetention(lifecycle?.globalMaxRetention);
const {
services: { notificationService },
config: { enableTogglingDataRetention, enableProjectLevelRetentionChecks },
Expand Down Expand Up @@ -331,8 +332,11 @@ export const EditDataRetentionModal: React.FunctionComponent<Props> = ({
<>
<FormattedMessage
id="xpack.idxMgmt.dataStreamsDetailsPanel.editDataRetentionModal.modalTitleText"
defaultMessage="Maximum data retention period is {maxRetention} days"
values={{ maxRetention: lifecycle?.globalMaxRetention.slice(0, -1) }}
defaultMessage="Maximum data retention period is {maxRetention} {unitText}"
values={{
maxRetention: globalMaxRetention.size,
unitText: globalMaxRetention.unitText,
}}
/>
<EuiSpacer />
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,26 @@ describe('isBiggerThanGlobalMaxRetention', () => {
});
});

it('should correctly compare retention in all of the units that are accepted by es', () => {
// 1000 milliseconds = 1 seconds
expect(isBiggerThanGlobalMaxRetention(1, 's', '1000ms')).toBeUndefined();
expect(isBiggerThanGlobalMaxRetention(2, 's', '1000ms')).toEqual({
message: 'Maximum data retention period on this project is 1000 milliseconds.',
});

// 1000000 microseconds = 1 seconds
expect(isBiggerThanGlobalMaxRetention(1, 's', '1000000micros')).toBeUndefined();
expect(isBiggerThanGlobalMaxRetention(2, 'm', '1000000micros')).toEqual({
message: 'Maximum data retention period on this project is 1000000 microseconds.',
});

// 1000000000 microseconds = 1 seconds
expect(isBiggerThanGlobalMaxRetention(2, 's', '1000000000nanos'));
expect(isBiggerThanGlobalMaxRetention(2, 'h', '1000000000nanos')).toEqual({
message: 'Maximum data retention period on this project is 1000000000 nanoseconds.',
});
});

it('should throw an error for unknown time units', () => {
expect(() => isBiggerThanGlobalMaxRetention(10, 'x', '30d')).toThrow('Unknown unit: x');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,44 @@

import { i18n } from '@kbn/i18n';
import { splitSizeAndUnits } from '../../../../../../common';
import { deserializeGlobalMaxRetention } from '../../../../lib/data_streams';

const convertToMinutes = (value: string) => {
const convertToSeconds = (value: string) => {
const { size, unit } = splitSizeAndUnits(value);
const sizeNum = parseInt(size, 10);

switch (unit) {
case 'd':
// days to minutes
return sizeNum * 24 * 60;
// days to seconds
return sizeNum * 24 * 60 * 60;
case 'h':
// hours to minutes
return sizeNum * 60;
// hours to seconds
return sizeNum * 60 * 60;
case 'm':
// minutes to minutes
return sizeNum;
// minutes to seconds
return sizeNum * 60;
case 's':
// seconds to minutes (round up if any remainder)
return Math.ceil(sizeNum / 60);
// seconds to seconds
return sizeNum;
case 'ms':
// milliseconds to seconds
return sizeNum / 1000;
case 'micros':
// microseconds to seconds
return sizeNum / 1000 / 1000;
case 'nanos':
// nanoseconds to seconds
return sizeNum / 1000 / 1000 / 1000;
default:
throw new Error(`Unknown unit: ${unit}`);
}
};

const isRetentionBiggerThan = (valueA: string, valueB: string) => {
const minutesA = convertToMinutes(valueA);
const minutesB = convertToMinutes(valueB);
const secondsA = convertToSeconds(valueA);
const secondsB = convertToSeconds(valueB);

return minutesA > minutesB;
return secondsA > secondsB;
};

export const isBiggerThanGlobalMaxRetention = (
Expand All @@ -46,14 +56,19 @@ export const isBiggerThanGlobalMaxRetention = (
return undefined;
}

const { size, unitText } = deserializeGlobalMaxRetention(globalMaxRetention);
return isRetentionBiggerThan(`${retentionValue}${retentionTimeUnit}`, globalMaxRetention)
? {
message: i18n.translate(
'xpack.idxMgmt.dataStreamsDetailsPanel.editDataRetentionModal.dataRetentionFieldMaxError',
{
defaultMessage: 'Maximum data retention period on this project is {maxRetention} days.',
defaultMessage:
'Maximum data retention period on this project is {maxRetention} {unitText}.',
// Remove the unit from the globalMaxRetention value
values: { maxRetention: globalMaxRetention.slice(0, -1) },
values: {
maxRetention: size,
unitText,
},
}
),
}
Expand Down

0 comments on commit 1e7bb1e

Please sign in to comment.