758 lines
25 KiB
Vue
758 lines
25 KiB
Vue
<script>
|
||
import "~/assets/styles/InstanceMonitor.B0X15iQt.css";
|
||
import { toDisplayString } from "vue";
|
||
import { renderList } from "vue";
|
||
import { onMounted } from "vue";
|
||
import { onBeforeUnmount } from "vue";
|
||
import { watch } from "vue";
|
||
import { defineAsyncComponent } from "vue";
|
||
import { createBlock } from "vue";
|
||
import { ref } from "vue";
|
||
import { withCtx } from "vue";
|
||
import { createCommentVNode } from "vue";
|
||
import { computed } from "vue";
|
||
import { createElementBlock } from "vue";
|
||
import { Fragment } from "vue";
|
||
import { createElementVNode } from "vue";
|
||
import { createTextVNode } from "vue";
|
||
import { unref } from "vue";
|
||
import { defineComponent } from "vue";
|
||
import { createVNode } from "vue";
|
||
import { openBlock } from "vue";
|
||
import { loadModule } from "~/utils/load-module.js";
|
||
import { useApi } from "~/lib/auth.js";
|
||
import button from "primevue/button";
|
||
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
|
||
import { t as useTheme_t } from "~/lib/useTheme.js";
|
||
import message from "primevue/message";
|
||
import ListSegments from "~/components/ListSegments.vue";
|
||
import skeleton from "primevue/skeleton";
|
||
import { n as finance_resource_chart_n } from "~/lib/finance-resource-chart.js";
|
||
import { t as finance_resource_chart_t } from "~/lib/finance-resource-chart.js";
|
||
var O = defineAsyncComponent(() =>
|
||
loadModule(
|
||
() => import("~/components/ChartBox.vue").then((e) => e.default || e),
|
||
[],
|
||
import.meta.url,
|
||
),
|
||
),
|
||
k = {
|
||
class: `mon`,
|
||
},
|
||
A = {
|
||
class: `range-row`,
|
||
},
|
||
j = {
|
||
class: `hint`,
|
||
},
|
||
M = {
|
||
key: 1,
|
||
class: `charts`,
|
||
},
|
||
N = {
|
||
class: `chart-title`,
|
||
},
|
||
P = {
|
||
class: `chart-viewport`,
|
||
},
|
||
F = {
|
||
key: 2,
|
||
class: `charts`,
|
||
},
|
||
I = {
|
||
class: `chart-title`,
|
||
},
|
||
L = {
|
||
key: 0,
|
||
class: `chart-unit`,
|
||
},
|
||
R = {
|
||
class: `chart-viewport`,
|
||
},
|
||
z = {
|
||
key: 0,
|
||
class: `chart-error`,
|
||
},
|
||
B = {
|
||
key: 2,
|
||
class: `chart-empty`,
|
||
},
|
||
V = {
|
||
class: `refresh-row`,
|
||
},
|
||
H = `#f59e0b`,
|
||
U = Object.assign(
|
||
_plugin_vue_export_helper_t(
|
||
defineComponent({
|
||
__name: `InstanceMonitor`,
|
||
props: {
|
||
hostId: {},
|
||
module: {},
|
||
},
|
||
setup(a) {
|
||
let g = a,
|
||
y = useApi(),
|
||
S = useTheme_t(),
|
||
U = computed(() => (S.isDark.value ? `#38bdf8` : `#0ea5e9`)),
|
||
W = ref([]),
|
||
G = ref(!1),
|
||
K = ref(``),
|
||
q = 0,
|
||
J = !1,
|
||
Y = ``,
|
||
X = [
|
||
{
|
||
label: `1小时`,
|
||
value: 3600,
|
||
},
|
||
{
|
||
label: `24小时`,
|
||
value: 86400,
|
||
},
|
||
{
|
||
label: `7天`,
|
||
value: 604800,
|
||
},
|
||
{
|
||
label: `1个月`,
|
||
value: 2592e3,
|
||
},
|
||
{
|
||
label: `1年`,
|
||
value: 31536e3,
|
||
},
|
||
],
|
||
Z = ref(86400),
|
||
Q = (e) => {
|
||
let t = new Date(e * 1e3);
|
||
return `${String(t.getHours()).padStart(2, `0`)}:${String(t.getMinutes()).padStart(2, `0`)}`;
|
||
};
|
||
async function te(e, t, n = `mf_cloud`) {
|
||
let r = [
|
||
{
|
||
type: `cpu`,
|
||
title: `CPU 使用率`,
|
||
max: 100,
|
||
pick: [
|
||
{
|
||
name: `CPU`,
|
||
fn: (e) => e.value,
|
||
color: U.value,
|
||
unit: `%`,
|
||
},
|
||
],
|
||
},
|
||
{
|
||
type: `memory`,
|
||
title: `内存使用率`,
|
||
max: 100,
|
||
pick: [
|
||
{
|
||
name: `内存`,
|
||
fn: (e) =>
|
||
e.total
|
||
? (Number(e.used ?? 0) / Number(e.total)) * 100
|
||
: void 0,
|
||
color: U.value,
|
||
unit: `%`,
|
||
},
|
||
],
|
||
},
|
||
{
|
||
type: `bw`,
|
||
title: `带宽(入 / 出)`,
|
||
pick: [
|
||
{
|
||
name: `入`,
|
||
fn: (e) => e.in_bw,
|
||
color: U.value,
|
||
},
|
||
{
|
||
name: `出`,
|
||
fn: (e) => e.out_bw,
|
||
color: H,
|
||
},
|
||
],
|
||
scale: `bits`,
|
||
},
|
||
{
|
||
type: `disk_io`,
|
||
title: `硬盘 IO(读 / 写)`,
|
||
pick: [
|
||
{
|
||
name: `读`,
|
||
fn: (e) => e.read_bytes,
|
||
color: U.value,
|
||
unit: `B/s`,
|
||
},
|
||
{
|
||
name: `写`,
|
||
fn: (e) => e.write_bytes,
|
||
color: H,
|
||
unit: `B/s`,
|
||
},
|
||
],
|
||
},
|
||
];
|
||
function i(e) {
|
||
let t = e > 0 ? Math.max(0, Math.floor(Math.log2(e) / 10)) : 0,
|
||
n = [`bps`, `Kbps`, `Mbps`, `Gbps`, `Tbps`];
|
||
return {
|
||
divisor: 1024 ** t,
|
||
unit: n[Math.min(t, n.length - 1)],
|
||
};
|
||
}
|
||
let a = n === `jy_dcim` ? r.filter((e) => e.type === `bw`) : r,
|
||
o = await Promise.allSettled(
|
||
a.map((r) =>
|
||
y.get(`/${n}/${e}/chart`, {
|
||
type: r.type,
|
||
start_time: t,
|
||
}),
|
||
),
|
||
);
|
||
return a.map((e, t) => {
|
||
let n = o[t];
|
||
if (n.status === `rejected`)
|
||
return {
|
||
key: e.type,
|
||
title: e.title,
|
||
labels: [],
|
||
series: [],
|
||
error:
|
||
n.reason instanceof Error
|
||
? n.reason.message
|
||
: `监控数据加载失败,请重试`,
|
||
};
|
||
let r = n.value.list ?? [],
|
||
a = e.pick.map((e) =>
|
||
r.map((t) => {
|
||
let n = e.fn(t);
|
||
return n === void 0 || Number.isNaN(n) ? null : Number(n);
|
||
}),
|
||
),
|
||
s =
|
||
e.scale === `bits`
|
||
? i(Math.max(0, ...a.flat().filter((e) => e !== null)))
|
||
: null;
|
||
return {
|
||
key: e.type,
|
||
title: e.title,
|
||
max: e.max,
|
||
labels: r.map((e) => Q(e.time)),
|
||
series: e.pick.map((e, t) => ({
|
||
name: e.name,
|
||
unit: s ? s.unit : e.unit,
|
||
color: e.color,
|
||
data: a[t].map((e) =>
|
||
e === null
|
||
? null
|
||
: Number((e / (s?.divisor ?? 1)).toFixed(2)),
|
||
),
|
||
})),
|
||
};
|
||
});
|
||
}
|
||
async function ne(e, t, n) {
|
||
let r = [
|
||
{
|
||
type: `cpu`,
|
||
title: `CPU 使用率`,
|
||
max: 100,
|
||
},
|
||
{
|
||
type: `memory`,
|
||
title: `内存使用率`,
|
||
max: 100,
|
||
},
|
||
{
|
||
type: `flow`,
|
||
title: `带宽(进 / 出)`,
|
||
},
|
||
{
|
||
type: `disk`,
|
||
title: `硬盘 IO(读 / 写)`,
|
||
},
|
||
],
|
||
i = await Promise.allSettled(
|
||
r.map((r) =>
|
||
y.get(`/remf_finance/${e}/chart`, {
|
||
type: r.type,
|
||
start: t,
|
||
end: n,
|
||
}),
|
||
),
|
||
);
|
||
return r.map((e, t) => {
|
||
let n = i[t];
|
||
if (n.status === `rejected`)
|
||
return {
|
||
key: e.type,
|
||
title: e.title,
|
||
labels: [],
|
||
series: [],
|
||
error:
|
||
n.reason instanceof Error
|
||
? n.reason.message
|
||
: `监控数据加载失败,请重试`,
|
||
};
|
||
let r = n.value ?? {};
|
||
if (e.type === `cpu` || e.type === `memory`) {
|
||
let t = finance_resource_chart_n(r, e.type);
|
||
return {
|
||
key: e.type,
|
||
title: e.title,
|
||
max: 100,
|
||
labels: t.labels,
|
||
series: [
|
||
{
|
||
name: e.type === `cpu` ? `CPU` : `内存`,
|
||
unit: `%`,
|
||
color: U.value,
|
||
data: t.data,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
let a = (r.list?.[0] ?? []).map((e) =>
|
||
String(e.time ?? ``).slice(11, 16),
|
||
),
|
||
o = (r.list ?? []).map((e, t) => ({
|
||
name: String(r.label?.[t] ?? `系列 ${t + 1}`).replace(
|
||
/\(.*\)$/,
|
||
``,
|
||
),
|
||
unit: r.unit,
|
||
color: t === 0 ? U.value : H,
|
||
data: e.map((e) => finance_resource_chart_t(e.value)),
|
||
}));
|
||
return {
|
||
key: e.type,
|
||
title: e.title,
|
||
max: e.max,
|
||
labels: a,
|
||
series: o,
|
||
};
|
||
});
|
||
}
|
||
async function re(e) {
|
||
let t = await y.get(`/kky_ecs/monitor/${e}`),
|
||
n = (t.sample_info ?? []).map((e) =>
|
||
String(e.timestamp ?? ``).slice(11, 16),
|
||
),
|
||
r = (e, t, r, i, a, o = 1) => ({
|
||
key: e,
|
||
title: t,
|
||
labels: n,
|
||
series: (r ?? []).map((e, t) => ({
|
||
name: e.title,
|
||
unit: a,
|
||
color: i[t % i.length],
|
||
data: (e.value ?? []).map((e) =>
|
||
typeof e == `number` ? Number((e / o).toFixed(2)) : null,
|
||
),
|
||
})),
|
||
});
|
||
return [
|
||
r(`cpu`, `CPU 使用率`, t.cpu, [U.value], `%`),
|
||
r(`memory`, `内存`, t.memory, [U.value, H], `KB`),
|
||
r(`bandwidth`, `带宽`, t.bandwidth, [U.value, H], `Mbps`, 1e3),
|
||
r(`disk`, `硬盘 IO`, t.disk, [U.value, H], `KB/s`),
|
||
];
|
||
}
|
||
async function $() {
|
||
if (J) return;
|
||
let e = ++q,
|
||
t = g.hostId,
|
||
n = g.module,
|
||
r = Z.value,
|
||
i = `${n}:${t}:${n === `kky_ecs` ? `` : r}`,
|
||
a = () =>
|
||
!J &&
|
||
e === q &&
|
||
t === g.hostId &&
|
||
n === g.module &&
|
||
(n === `kky_ecs` || r === Z.value);
|
||
((G.value = !0), (K.value = ``), Y !== i && (W.value = []));
|
||
try {
|
||
let e = Date.now(),
|
||
o =
|
||
n === `mf_cloud` ||
|
||
n === `remf_cloud` ||
|
||
n === `jy_cloud` ||
|
||
n === `jy_dcim`
|
||
? await te(t, Math.floor(e / 1e3) - r, n)
|
||
: n === `remf_finance`
|
||
? await ne(t, e - r * 1e3, e)
|
||
: await re(t);
|
||
a() && ((W.value = o), (Y = i));
|
||
} catch (e) {
|
||
if (!a()) return;
|
||
((K.value = e instanceof Error ? e.message : `加载监控数据失败`),
|
||
(W.value = []));
|
||
} finally {
|
||
a() && (G.value = !1);
|
||
}
|
||
}
|
||
function ie(e) {
|
||
if (g.module === `kky_ecs` || e === void 0) return;
|
||
let t = Number(e);
|
||
if (X.some((e) => e.value === t)) return ((Z.value = t), $());
|
||
}
|
||
let ae = (e) => e.series.some((e) => e.data.some((e) => e !== null));
|
||
function oe(e) {
|
||
let t = S.isDark.value ? `#a1a1aa` : `#94a3b8`,
|
||
n = S.isDark.value ? `rgba(255,255,255,.08)` : `rgba(0,0,0,.06)`;
|
||
return {
|
||
grid: {
|
||
left: 6,
|
||
right: 10,
|
||
top: 26,
|
||
bottom: 4,
|
||
outerBoundsMode: `same`,
|
||
outerBoundsContain: `axisLabel`,
|
||
},
|
||
tooltip: {
|
||
trigger: `axis`,
|
||
},
|
||
legend:
|
||
e.series.length > 1
|
||
? {
|
||
top: 0,
|
||
right: 0,
|
||
itemWidth: 10,
|
||
itemHeight: 2,
|
||
textStyle: {
|
||
fontSize: 11,
|
||
},
|
||
}
|
||
: void 0,
|
||
xAxis: {
|
||
type: `category`,
|
||
data: e.labels,
|
||
boundaryGap: !1,
|
||
axisTick: {
|
||
show: !1,
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: n,
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: t,
|
||
fontSize: 11,
|
||
},
|
||
},
|
||
yAxis: {
|
||
type: `value`,
|
||
max: e.max,
|
||
axisLine: {
|
||
show: !1,
|
||
},
|
||
axisTick: {
|
||
show: !1,
|
||
},
|
||
axisLabel: {
|
||
color: t,
|
||
fontSize: 11,
|
||
formatter: e.series.every((e) => e.unit === `%`)
|
||
? (e) => `${e}%`
|
||
: void 0,
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
color: n,
|
||
},
|
||
},
|
||
},
|
||
series: e.series.map((t) => ({
|
||
name: t.name,
|
||
type: `line`,
|
||
smooth: !0,
|
||
showSymbol: !1,
|
||
connectNulls: !1,
|
||
areaStyle:
|
||
e.series.length === 1
|
||
? {
|
||
opacity: 0.12,
|
||
}
|
||
: void 0,
|
||
lineStyle: {
|
||
width: 1.6,
|
||
color: t.color,
|
||
},
|
||
itemStyle: {
|
||
color: t.color,
|
||
},
|
||
data: t.data,
|
||
tooltip: {
|
||
valueFormatter: (e) =>
|
||
e == null
|
||
? `暂无数据`
|
||
: t.unit === `%`
|
||
? `${e}%`
|
||
: t.unit
|
||
? `${e} ${t.unit}`
|
||
: String(e),
|
||
},
|
||
})),
|
||
};
|
||
}
|
||
return (
|
||
onMounted($),
|
||
watch(() => [g.hostId, g.module], $),
|
||
onBeforeUnmount(() => {
|
||
((J = !0), (q += 1));
|
||
}),
|
||
(n, r) => {
|
||
let i = ListSegments,
|
||
s = button,
|
||
u = message,
|
||
g = skeleton,
|
||
y = O;
|
||
return (
|
||
openBlock(),
|
||
createElementBlock(`div`, k, [
|
||
createElementVNode(`div`, A, [
|
||
a.module === `kky_ecs`
|
||
? createCommentVNode(``, !0)
|
||
: (openBlock(),
|
||
createBlock(
|
||
i,
|
||
{
|
||
key: 0,
|
||
"aria-label": `监控时间范围`,
|
||
"model-value": unref(Z),
|
||
options: X,
|
||
"onUpdate:modelValue": ie,
|
||
},
|
||
null,
|
||
8,
|
||
[`model-value`],
|
||
)),
|
||
createElementVNode(`span`, j, [
|
||
a.module === `kky_ecs`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 1,
|
||
},
|
||
[
|
||
createTextVNode(
|
||
`数据由平台采集,可查询的时间范围固定。`,
|
||
),
|
||
],
|
||
64,
|
||
))
|
||
: (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 0,
|
||
},
|
||
[
|
||
createTextVNode(
|
||
`数据由平台采集,实例未运行时可能为空。`,
|
||
),
|
||
],
|
||
64,
|
||
)),
|
||
]),
|
||
]),
|
||
unref(K)
|
||
? (openBlock(),
|
||
createBlock(
|
||
u,
|
||
{
|
||
key: 0,
|
||
severity: `error`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(unref(K)) + ` `, 1),
|
||
createVNode(
|
||
s,
|
||
{
|
||
label: `重试`,
|
||
size: `small`,
|
||
severity: `secondary`,
|
||
text: ``,
|
||
loading: unref(G),
|
||
onClick: $,
|
||
},
|
||
null,
|
||
8,
|
||
[`loading`],
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(G) && !unref(W).length
|
||
? (openBlock(),
|
||
createElementBlock(`div`, M, [
|
||
(openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
null,
|
||
renderList(4, (e) =>
|
||
createElementVNode(
|
||
`div`,
|
||
{
|
||
key: e,
|
||
class: `chart-card`,
|
||
},
|
||
[
|
||
createElementVNode(`div`, N, [
|
||
createVNode(g, {
|
||
width: `35%`,
|
||
height: `24px`,
|
||
}),
|
||
]),
|
||
createElementVNode(`div`, P, [
|
||
createVNode(g, {
|
||
height: `280px`,
|
||
}),
|
||
]),
|
||
],
|
||
),
|
||
),
|
||
64,
|
||
)),
|
||
]))
|
||
: (openBlock(),
|
||
createElementBlock(`div`, F, [
|
||
(openBlock(!0),
|
||
createElementBlock(
|
||
Fragment,
|
||
null,
|
||
renderList(
|
||
unref(W),
|
||
(t) => (
|
||
openBlock(),
|
||
createElementBlock(
|
||
`div`,
|
||
{
|
||
key: t.key,
|
||
class: `chart-card`,
|
||
},
|
||
[
|
||
createElementVNode(`div`, I, [
|
||
createTextVNode(
|
||
toDisplayString(t.title),
|
||
1,
|
||
),
|
||
t.series[0]?.unit
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`span`,
|
||
L,
|
||
`(` +
|
||
toDisplayString(t.series[0].unit) +
|
||
`)`,
|
||
1,
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
]),
|
||
createElementVNode(`div`, R, [
|
||
t.error
|
||
? (openBlock(),
|
||
createElementBlock(`div`, z, [
|
||
createVNode(
|
||
u,
|
||
{
|
||
severity: `error`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(
|
||
toDisplayString(t.error) +
|
||
` `,
|
||
1,
|
||
),
|
||
createVNode(
|
||
s,
|
||
{
|
||
label: `重试`,
|
||
size: `small`,
|
||
severity: `secondary`,
|
||
text: ``,
|
||
loading: unref(G),
|
||
onClick: $,
|
||
},
|
||
null,
|
||
8,
|
||
[`loading`],
|
||
),
|
||
]),
|
||
_: 2,
|
||
},
|
||
1024,
|
||
),
|
||
]))
|
||
: ae(t)
|
||
? (openBlock(),
|
||
createBlock(
|
||
y,
|
||
{
|
||
key: 1,
|
||
option: oe(t),
|
||
height: 280,
|
||
loading: unref(G),
|
||
},
|
||
null,
|
||
8,
|
||
[`option`, `loading`],
|
||
))
|
||
: (openBlock(),
|
||
createElementBlock(
|
||
`p`,
|
||
B,
|
||
`暂无监控数据`,
|
||
)),
|
||
]),
|
||
],
|
||
)
|
||
),
|
||
),
|
||
128,
|
||
)),
|
||
])),
|
||
createElementVNode(`div`, V, [
|
||
createVNode(
|
||
s,
|
||
{
|
||
label: `刷新`,
|
||
icon: `pi pi-refresh`,
|
||
size: `small`,
|
||
severity: `secondary`,
|
||
text: ``,
|
||
loading: unref(G),
|
||
onClick: $,
|
||
},
|
||
null,
|
||
8,
|
||
[`loading`],
|
||
),
|
||
]),
|
||
])
|
||
);
|
||
}
|
||
);
|
||
},
|
||
}),
|
||
[[`__scopeId`, `data-v-6a900feb`]],
|
||
),
|
||
{
|
||
__name: `InstanceMonitor`,
|
||
},
|
||
);
|
||
export {};
|
||
export default U;
|
||
</script>
|