Skip to content

Commit

Permalink
fix(PDiskSpaceDistribution): update slots severity calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
artemmufazalov committed Feb 4, 2025
1 parent 286d493 commit b3c29d5
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 25 deletions.
10 changes: 5 additions & 5 deletions src/containers/PDiskPage/PDiskPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ import './PDiskPage.scss';
const pdiskPageCn = cn('ydb-pdisk-page');

const PDISK_TABS_IDS = {
diskDistribution: 'diskDistribution',
spaceDistribution: 'spaceDistribution',
storage: 'storage',
} as const;

const PDISK_PAGE_TABS = [
{
id: PDISK_TABS_IDS.diskDistribution,
id: PDISK_TABS_IDS.spaceDistribution,
get title() {
return pDiskPageKeyset('disk-distribution');
return pDiskPageKeyset('space-distribution');
},
},
{
Expand All @@ -56,7 +56,7 @@ const PDISK_PAGE_TABS = [
},
];

const pDiskTabSchema = z.nativeEnum(PDISK_TABS_IDS).catch(PDISK_TABS_IDS.diskDistribution);
const pDiskTabSchema = z.nativeEnum(PDISK_TABS_IDS).catch(PDISK_TABS_IDS.spaceDistribution);

export function PDiskPage() {
const dispatch = useTypedDispatch();
Expand Down Expand Up @@ -237,7 +237,7 @@ export function PDiskPage() {

const renderTabsContent = () => {
switch (pDiskTab) {
case 'diskDistribution': {
case 'spaceDistribution': {
return pDiskData ? (
<div className={pdiskPageCn('disk-distribution')}>
<PDiskSpaceDistribution data={pDiskData} />
Expand Down
2 changes: 1 addition & 1 deletion src/containers/PDiskPage/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"node": "Node",

"storage": "Storage",
"disk-distribution": "Disk distribution",
"space-distribution": "Space distribution",

"empty-slot": "Empty slot",
"log": "Log",
Expand Down
227 changes: 227 additions & 0 deletions src/store/reducers/pdisk/__tests__/preparePDiskDataResponse.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import type {TPDiskInfoResponse} from '../../../../types/api/pdisk';
import {preparePDiskDataResponse} from '../utils';

describe('preparePDiskDataResponse', () => {
const rawData = {
Whiteboard: {
PDisk: {
PDiskId: 1,
ChangeTime: '1738670321505',
Path: '/ydb_data/pdisk1tmbtrl7c.data',
Guid: '1',
Category: '0',
AvailableSize: '66454552576',
TotalSize: '100000000000',
State: 'Normal',
Device: 'Green',
Realtime: 'Green',
SerialNumber: '',
SystemSize: '2000000000',
LogUsedSize: '2000000000',
LogTotalSize: '60000000000',
EnforcedDynamicSlotSize: '20000000000',
NumActiveSlots: 1,
},
VDisks: [
{
VDiskId: {
GroupID: 2181038081,
GroupGeneration: 1,
Ring: 0,
Domain: 0,
VDisk: 0,
},
ChangeTime: '1738672482849',
PDiskId: 1,
VDiskSlotId: 1001,
Guid: '1',
Kind: '0',
VDiskState: 'OK',
DiskSpace: 'Green',
SatisfactionRank: {
FreshRank: {
Flag: 'Green',
},
LevelRank: {
Flag: 'Green',
},
},
Replicated: true,
ReplicationProgress: 1,
ReplicationSecondsRemaining: 0,
AllocatedSize: '5000000000',
AvailableSize: '20000000000',
HasUnreadableBlobs: false,
IncarnationGuid: '13331041715376219418',
InstanceGuid: '18177015420302975983',
FrontQueues: 'Green',
StoragePoolName: 'dynamic_storage_pool:1',
ReadThroughput: '0',
WriteThroughput: '0',
},
],
},
BSC: {
PDisk: {
Type: 'ROT',
Kind: '0',
Path: '/ydb_data/pdisk1tmbtrl7c.data',
Guid: '1',
BoxId: '1',
SharedWithOs: false,
ReadCentric: false,
AvailableSize: '66454552576',
TotalSize: '68719476736',
StatusV2: 'ACTIVE',
StatusChangeTimestamp: '1737458853219782',
EnforcedDynamicSlotSize: '20000000000',
ExpectedSlotCount: 16,
NumActiveSlots: 1,
Category: '0',
DecommitStatus: 'DECOMMIT_NONE',
State: 'Normal',
},
VDisks: [
{
Key: {
NodeId: 1,
PDiskId: 1,
VSlotId: 0,
},
Info: {
GroupId: 0,
GroupGeneration: 1,
FailRealm: 0,
FailDomain: 0,
VDisk: 0,
AllocatedSize: '1000000000',
AvailableSize: '20000000000',
StatusV2: 'READY',
Kind: 'Default',
DiskSpace: 'Green',
Replicated: true,
State: 'OK',
},
},
],
},
} as unknown as TPDiskInfoResponse;

it('Should correctly retrieve slots', () => {
const preparedData = preparePDiskDataResponse([rawData, {}]);

expect(preparedData.SlotItems?.length).toEqual(17);
expect(preparedData.SlotItems?.filter((slot) => slot.SlotType === 'log').length).toEqual(1);
expect(preparedData.SlotItems?.filter((slot) => slot.SlotType === 'vDisk').length).toEqual(
1,
);
expect(preparedData.SlotItems?.filter((slot) => slot.SlotType === 'empty').length).toEqual(
15,
);
});
it('Should correctly calculate empty slots size if EnforcedDynamicSlotSize is provided', () => {
const preparedData = preparePDiskDataResponse([rawData, {}]);

expect(preparedData.SlotItems?.find((slot) => slot.SlotType === 'empty')?.Total).toEqual(
20_000_000_000,
);
});
it('Should correctly calculate empty slots size if EnforcedDynamicSlotSize is undefined', () => {
const data: TPDiskInfoResponse = {
...rawData,
Whiteboard: {
...rawData.Whiteboard,
PDisk: {
...rawData.Whiteboard?.PDisk,
EnforcedDynamicSlotSize: undefined,
},
},
BSC: {
...rawData.BSC,
PDisk: {
...rawData.BSC?.PDisk,
EnforcedDynamicSlotSize: undefined,
},
},
};
const preparedData = preparePDiskDataResponse([data, {}]);

expect(preparedData.SlotItems?.find((slot) => slot.SlotType === 'empty')?.Total).toEqual(
1_000_000_000,
);
});
it('Should return yellow or red severity for log if its size exceeds thresholds', () => {
const dataWarning: TPDiskInfoResponse = {
...rawData,
Whiteboard: {
...rawData.Whiteboard,
PDisk: {
...rawData.Whiteboard?.PDisk,
LogUsedSize: '90',
LogTotalSize: '100',
},
},
};
const preparedDataWarning = preparePDiskDataResponse([dataWarning, {}]);

expect(
preparedDataWarning.SlotItems?.find((slot) => slot.SlotType === 'log')?.Severity,
).toEqual(3);

const dataDanger: TPDiskInfoResponse = {
...rawData,
Whiteboard: {
...rawData.Whiteboard,
PDisk: {
...rawData.Whiteboard?.PDisk,
LogUsedSize: '99',
LogTotalSize: '100',
},
},
};
const preparedDataDanger = preparePDiskDataResponse([dataDanger, {}]);

expect(
preparedDataDanger.SlotItems?.find((slot) => slot.SlotType === 'log')?.Severity,
).toEqual(5);
});
it('Should return yellow or red severity for vdisk if its size exceeds thresholds', () => {
const dataWarning: TPDiskInfoResponse = {
...rawData,
Whiteboard: {
...rawData.Whiteboard,
VDisks: [
{
...rawData.Whiteboard?.VDisks?.[0],
AllocatedSize: '90',
AvailableSize: '10',
},
],
},
};
const preparedDataWarning = preparePDiskDataResponse([dataWarning, {}]);

expect(
preparedDataWarning.SlotItems?.find((slot) => slot.SlotType === 'vDisk')?.Severity,
).toEqual(3);

const dataDanger: TPDiskInfoResponse = {
...rawData,
Whiteboard: {
...rawData.Whiteboard,
VDisks: [
{
...rawData.Whiteboard?.VDisks?.[0],
AllocatedSize: '99',
AvailableSize: '1',
},
],
},
};
const preparedDataDanger = preparePDiskDataResponse([dataDanger, {}]);

expect(
preparedDataDanger.SlotItems?.find((slot) => slot.SlotType === 'vDisk')?.Severity,
).toEqual(5);
});
});
21 changes: 16 additions & 5 deletions src/store/reducers/pdisk/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {TPDiskInfoResponse} from '../../../types/api/pdisk';
import type {TEvSystemStateResponse} from '../../../types/api/systemState';
import {getArray, valueIsDefined} from '../../../utils';
import {getSpaceSeverity} from '../../../utils/disks/helpers';
import {
prepareWhiteboardPDiskData,
prepareWhiteboardVDiskData,
Expand Down Expand Up @@ -34,18 +35,20 @@ export function preparePDiskDataResponse([pdiskResponse = {}, nodeResponse]: [
TotalSize: PDiskTotalSize,
SystemSize,
ExpectedSlotCount,
EnforcedDynamicSlotSize,
SlotSize,
} = preparedPDisk;

let logSlot: SlotItem<'log'> | undefined;

if (valueIsDefined(LogTotalSize)) {
const usagePercent = (Number(LogUsedSize) * 100) / Number(LogTotalSize);

logSlot = {
SlotType: 'log',
Used: Number(LogUsedSize),
Total: Number(LogTotalSize),
UsagePercent: (Number(LogUsedSize) * 100) / Number(LogTotalSize),
Severity: 1,
UsagePercent: usagePercent,
Severity: getSpaceSeverity(usagePercent),
SlotData: {
LogUsedSize,
LogTotalSize,
Expand All @@ -60,11 +63,19 @@ export function preparePDiskDataResponse([pdiskResponse = {}, nodeResponse]: [
preparedVDisks.sort((disk1, disk2) => Number(disk2.VDiskSlotId) - Number(disk1.VDiskSlotId));

const vdisksSlots: SlotItem<'vDisk'>[] = preparedVDisks.map((preparedVDisk) => {
// VDisks do not have strict limits and can be bigger than they should
// In most storage views we don't colorize them depending on space usage
// Colorize them inside PDiskSpaceDistribution so overused slots will be visible
const slotSeverity = Math.max(
getSpaceSeverity(preparedVDisk.AllocatedPercent),
preparedVDisk.Severity || 0,
);

return {
SlotType: 'vDisk',
Id: preparedVDisk.VDiskId?.GroupID,
Title: preparedVDisk.StoragePoolName,
Severity: preparedVDisk.Severity,
Severity: slotSeverity,
Used: Number(preparedVDisk.AllocatedSize),
Total: Number(preparedVDisk.TotalSize),
UsagePercent: preparedVDisk.AllocatedPercent,
Expand All @@ -78,7 +89,7 @@ export function preparePDiskDataResponse([pdiskResponse = {}, nodeResponse]: [
if (ExpectedSlotCount && ExpectedSlotCount > vdisksSlots.length) {
const emptySlotsCount = ExpectedSlotCount - vdisksSlots.length;

let emptySlotSize = Number(EnforcedDynamicSlotSize);
let emptySlotSize = Number(SlotSize);

if (isNaN(emptySlotSize)) {
const vDisksTotalSize = vdisksSlots.reduce((sum, item) => {
Expand Down
17 changes: 5 additions & 12 deletions src/utils/disks/calculatePDiskSeverity.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import {EFlag} from '../../types/api/enums';
import type {TPDiskState} from '../../types/api/pdisk';
import {generateEvaluator} from '../generateEvaluator';

import {
DISK_COLOR_STATE_TO_NUMERIC_SEVERITY,
NOT_AVAILABLE_SEVERITY,
PDISK_STATE_SEVERITY,
} from './constants';

const getUsageSeverityForPDisk = generateEvaluator([EFlag.Green, EFlag.Yellow, EFlag.Red]);
import {NOT_AVAILABLE_SEVERITY, PDISK_STATE_SEVERITY} from './constants';
import {getSpaceSeverity} from './helpers';

export function calculatePDiskSeverity<
T extends {
Expand All @@ -17,13 +10,13 @@ export function calculatePDiskSeverity<
},
>(pDisk: T) {
const stateSeverity = getStateSeverity(pDisk.State);
const spaceSeverityFlag = getUsageSeverityForPDisk(pDisk.AllocatedPercent || 0);
const spaceSeverity = getSpaceSeverity(pDisk.AllocatedPercent);

if (stateSeverity === NOT_AVAILABLE_SEVERITY || !spaceSeverityFlag) {
if (stateSeverity === NOT_AVAILABLE_SEVERITY || !spaceSeverity) {
return stateSeverity;
}

return Math.max(stateSeverity, DISK_COLOR_STATE_TO_NUMERIC_SEVERITY[spaceSeverityFlag]);
return Math.max(stateSeverity, spaceSeverity);
}

function getStateSeverity(pDiskState?: TPDiskState) {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/disks/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const DISK_COLOR_STATE_TO_NUMERIC_SEVERITY: Record<EFlag, number> = {
Yellow: 3,
Orange: 4,
Red: 5,
};
} as const;

type SeverityToColor = Record<number, keyof typeof DISK_COLOR_STATE_TO_NUMERIC_SEVERITY>;

Expand Down
Loading

0 comments on commit b3c29d5

Please sign in to comment.