1. Add eslint plugin spellcheck to check word spell 2. Fix word spell Change-Id: I73d39cf797ef5bdf993b0154816134a1e93f2ed4
394 lines
9.0 KiB
JavaScript
394 lines
9.0 KiB
JavaScript
// Copyright 2021 99cloud
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import {
|
|
isEmpty,
|
|
isArray,
|
|
isNaN,
|
|
isUndefined,
|
|
isNumber,
|
|
isString,
|
|
get,
|
|
set,
|
|
last,
|
|
flatten,
|
|
min,
|
|
max,
|
|
} from 'lodash';
|
|
import { COLORS_MAP, MILLISECOND_IN_TIME_UNIT } from 'utils/constants';
|
|
import { getLocalTimeStr, getStrFromTimestamp } from 'utils/time';
|
|
|
|
const UnitTypes = {
|
|
second: {
|
|
conditions: [0.01, 0],
|
|
units: ['s', 'ms'],
|
|
},
|
|
cpu: {
|
|
conditions: [0.1, 0],
|
|
units: ['core', 'm'],
|
|
},
|
|
memory: {
|
|
conditions: [1024 ** 4, 1024 ** 3, 1024 ** 2, 1024, 0],
|
|
units: ['TiB', 'GiB', 'MiB', 'KiB', 'Bytes'],
|
|
},
|
|
disk: {
|
|
conditions: [1000 ** 4, 1000 ** 3, 1000 ** 2, 1000, 0],
|
|
units: ['TB', 'GB', 'MB', 'KB', 'Bytes'],
|
|
},
|
|
throughput: {
|
|
conditions: [1000 ** 4, 1000 ** 3, 1000 ** 2, 1000, 0],
|
|
units: ['TB/s', 'GB/s', 'MB/s', 'KB/s', 'B/s'],
|
|
},
|
|
traffic: {
|
|
conditions: [1000 ** 4, 1000 ** 3, 1000 ** 2, 1000, 0],
|
|
units: ['TB/s', 'GB/s', 'MB/s', 'KB/s', 'B/s'],
|
|
},
|
|
bandwidth: {
|
|
conditions: [1024 ** 2 / 8, 1024 / 8, 0],
|
|
units: ['Mbps', 'Kbps', 'bps'],
|
|
},
|
|
};
|
|
|
|
export const getSuitableUnit = (value, unitType) => {
|
|
const config = UnitTypes[unitType];
|
|
|
|
if (isEmpty(config)) return '';
|
|
|
|
// value can be an array or a single value
|
|
const values = isArray(value) ? value : [[0, Number(value)]];
|
|
let result = last(config.units);
|
|
config.conditions.some((condition, index) => {
|
|
const triggered = values.some(
|
|
(_value) =>
|
|
((isArray(_value) ? get(_value, '[1]') : Number(_value)) || 0) >=
|
|
condition
|
|
);
|
|
|
|
if (triggered) {
|
|
result = config.units[index];
|
|
}
|
|
return triggered;
|
|
});
|
|
return result;
|
|
};
|
|
|
|
export const getSuitableValue = (
|
|
value,
|
|
unitType = 'default',
|
|
defaultValue = 0
|
|
) => {
|
|
if ((!isNumber(value) && !isString(value)) || isNaN(Number(value))) {
|
|
return defaultValue;
|
|
}
|
|
const unit = getSuitableUnit(value, unitType);
|
|
const unitText = unit ? ` ${t(unit)}` : '';
|
|
const count = getValueByUnit(value, unit || unitType);
|
|
return `${count}${unitText}`;
|
|
};
|
|
|
|
export const getValueByUnit = (num, unit) => {
|
|
let value = parseFloat(num);
|
|
|
|
switch (unit) {
|
|
default:
|
|
break;
|
|
case '':
|
|
case 'default':
|
|
return value;
|
|
case 'iops':
|
|
return Math.round(value);
|
|
case '%':
|
|
value *= 100;
|
|
break;
|
|
case 'm':
|
|
value *= 1000;
|
|
if (value < 1) return 0;
|
|
break;
|
|
case 'KiB':
|
|
value /= 1024;
|
|
break;
|
|
case 'MiB':
|
|
value /= 1024 ** 2;
|
|
break;
|
|
case 'GiB':
|
|
value /= 1024 ** 3;
|
|
break;
|
|
case 'TiB':
|
|
value /= 1024 ** 4;
|
|
break;
|
|
case 'Bytes':
|
|
case 'B':
|
|
case 'B/s':
|
|
break;
|
|
case 'KB':
|
|
case 'KB/s':
|
|
value /= 1000;
|
|
break;
|
|
case 'MB':
|
|
case 'MB/s':
|
|
value /= 1000 ** 2;
|
|
break;
|
|
case 'GB':
|
|
case 'GB/s':
|
|
value /= 1000 ** 3;
|
|
break;
|
|
case 'TB':
|
|
case 'TB/s':
|
|
value /= 1000 ** 4;
|
|
break;
|
|
case 'bps':
|
|
value *= 8;
|
|
break;
|
|
case 'Kbps':
|
|
value = (value * 8) / 1024;
|
|
break;
|
|
case 'Mbps':
|
|
value = (value * 8) / 1024 / 1024;
|
|
break;
|
|
case 'ms':
|
|
value *= 1000;
|
|
break;
|
|
}
|
|
|
|
return Number(value) === 0 ? 0 : Number(value.toFixed(2));
|
|
};
|
|
|
|
export const getFormatTime = (ms) =>
|
|
getStrFromTimestamp(ms).replace(/:00$/g, '');
|
|
|
|
export const getChartData = ({
|
|
type,
|
|
unit,
|
|
xKey = 'time',
|
|
legend = [],
|
|
valuesData = [],
|
|
xFormatter,
|
|
}) => {
|
|
/*
|
|
build a value map => { 1566289260: {...} }
|
|
e.g. { 1566289260: { 'utilisation': 30.2 } }
|
|
*/
|
|
const valueMap = {};
|
|
valuesData.forEach((values, index) => {
|
|
values.forEach((item) => {
|
|
const time = parseInt(get(item, [0], 0), 10);
|
|
const value = get(item, [1]);
|
|
const key = get(legend, [index]);
|
|
|
|
if (time && !valueMap[time]) {
|
|
valueMap[time] = legend.reduce((obj, xAxisKey) => {
|
|
if (!obj[xAxisKey]) obj[xAxisKey] = null;
|
|
return obj;
|
|
}, {});
|
|
}
|
|
|
|
if (key && valueMap[time]) {
|
|
valueMap[time][key] =
|
|
value === '-1'
|
|
? null
|
|
: getValueByUnit(value, isUndefined(unit) ? type : unit);
|
|
}
|
|
});
|
|
});
|
|
|
|
const formatter = (key) => (xKey === 'time' ? getFormatTime(key) : key);
|
|
|
|
// generate the chart data
|
|
const chartData = Object.entries(valueMap).map(([key, value]) => ({
|
|
[xKey]: (xFormatter || formatter)(key),
|
|
...value,
|
|
}));
|
|
|
|
return chartData;
|
|
};
|
|
|
|
export const getAreaChartOps = ({
|
|
type,
|
|
title,
|
|
unitType,
|
|
xKey = 'time',
|
|
legend = [],
|
|
data = [],
|
|
xFormatter,
|
|
...rest
|
|
}) => {
|
|
const seriesData = isArray(data) ? data : [];
|
|
const valuesData = seriesData.map((result) => get(result, 'values') || []);
|
|
const unit = unitType
|
|
? getSuitableUnit(flatten(valuesData), unitType)
|
|
: rest.unit;
|
|
|
|
const chartData = getChartData({
|
|
type,
|
|
unit,
|
|
xKey,
|
|
legend,
|
|
valuesData,
|
|
xFormatter,
|
|
});
|
|
|
|
const xAxisTickFormatter =
|
|
xKey === 'time' ? getXAxisTickFormatter(chartData) : (value) => value;
|
|
|
|
return {
|
|
...rest,
|
|
title,
|
|
unit,
|
|
xAxisTickFormatter,
|
|
data: chartData,
|
|
};
|
|
};
|
|
|
|
export const getXAxisTickFormatter = (chartValues = []) => {
|
|
const timeList = chartValues.map(({ time }) => +new Date(time));
|
|
const minTime = min(timeList);
|
|
const maxTime = max(timeList);
|
|
|
|
if (maxTime - minTime > 8640000) {
|
|
return (time) => getLocalTimeStr(time, t('Do HH:mm'));
|
|
}
|
|
|
|
return (time) => getLocalTimeStr(time, 'HH:mm:ss');
|
|
};
|
|
|
|
export const getLastMonitoringData = (data) => {
|
|
const result = {};
|
|
|
|
Object.entries(data).forEach(([key, value]) => {
|
|
const values = get(value, 'data.result[0].values', []) || [];
|
|
const _value = isEmpty(values)
|
|
? get(value, 'data.result[0].value', []) || []
|
|
: last(values);
|
|
set(result, `[${key}].value`, _value);
|
|
});
|
|
|
|
return result;
|
|
};
|
|
|
|
export const getTimesData = (data) => {
|
|
const result = [];
|
|
|
|
data.forEach((record) => {
|
|
const values = get(record, 'values') || [];
|
|
|
|
values.forEach((value) => {
|
|
const time = get(value, '[0]', 0);
|
|
if (!result.includes(time)) {
|
|
result.push(time);
|
|
}
|
|
});
|
|
});
|
|
return result.sort();
|
|
};
|
|
|
|
export const getZeroValues = () => {
|
|
const values = [];
|
|
let time = parseInt(Date.now() / 1000, 10) - 6000;
|
|
for (let i = 0; i < 10; i++) {
|
|
values[i] = [time, 0];
|
|
time += 600;
|
|
}
|
|
return values;
|
|
};
|
|
|
|
export const getColorByName = (colorName = '#fff') =>
|
|
COLORS_MAP[colorName] || colorName;
|
|
|
|
export const startAutoRefresh = (context, options = {}) => {
|
|
const params = {
|
|
method: 'fetchData',
|
|
interval: 5000, // milliseconds
|
|
leading: true,
|
|
...options,
|
|
};
|
|
|
|
if (context && context[params.method]) {
|
|
const fetch = context[params.method];
|
|
|
|
if (params.leading) {
|
|
fetch({ autoRefresh: true });
|
|
}
|
|
|
|
context.timer = setInterval(() => {
|
|
fetch({ autoRefresh: true });
|
|
}, params.interval);
|
|
}
|
|
};
|
|
|
|
export const stopAutoRefresh = (context) => {
|
|
if (context && context.timer) {
|
|
clearInterval(context.timer);
|
|
context.timer = null;
|
|
}
|
|
};
|
|
|
|
export const isSameDay = (preTime, nextTime) =>
|
|
Math.floor(preTime / 86400000) === Math.floor(nextTime / 86400000);
|
|
|
|
export const timeAliasReg = /(\d+)(\w+)/;
|
|
|
|
export const timestampify = (timeAlias) => {
|
|
const [, count = 0, unit] = timeAlias.match(timeAliasReg) || [];
|
|
return Number(count) * (MILLISECOND_IN_TIME_UNIT[unit] || 0);
|
|
};
|
|
|
|
export const fillEmptyMetrics = (params, result) => {
|
|
if (!params.times || !params.start || !params.end) {
|
|
return result;
|
|
}
|
|
|
|
const format = (num) => String(num).replace(/\..*$/, '');
|
|
const step = Math.floor((params.end - params.start) / params.times);
|
|
const correctCount = params.times + 1;
|
|
|
|
Object.values(result).forEach((item) => {
|
|
const _result = get(item, 'data.result');
|
|
if (!isEmpty(_result)) {
|
|
_result.forEach((resultItem) => {
|
|
const curValues = resultItem.values || [];
|
|
const curValuesMap = curValues.reduce(
|
|
(prev, cur) => ({
|
|
...prev,
|
|
[format(cur[0])]: cur[1],
|
|
}),
|
|
{}
|
|
);
|
|
|
|
if (curValues.length < correctCount) {
|
|
const newValues = [];
|
|
for (let index = 0; index < correctCount; index++) {
|
|
const time = format(params.start + index * step);
|
|
newValues.push([time, curValuesMap[time] || '0']);
|
|
}
|
|
resultItem.values = newValues;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
return result;
|
|
};
|
|
|
|
export const cephStatusMap = {
|
|
0: t('Healthy'),
|
|
1: t('Warning'),
|
|
2: t('Error'),
|
|
};
|
|
|
|
export const cephStatusColorMap = {
|
|
0: '#379738',
|
|
1: '#FAAD14',
|
|
2: '#D93126',
|
|
};
|