2022-09-10 23:13:42 +08:00
|
|
|
|
<template>
|
2022-09-15 15:51:00 +08:00
|
|
|
|
<div class="link-direction-grid">
|
2022-09-28 15:35:03 +08:00
|
|
|
|
<!--左侧链路出入口-->
|
2023-08-29 16:24:02 +08:00
|
|
|
|
<popover-content :title="$t('linkMonitor.outLink') + ' & ' + $t('linkMonitor.inLink')" :isNoData="isLinkNoData" :gridData="linkGridData" :showError="isLinkShowError" :content="linkErrorMsg" style="width: 900px;"/>
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
|
|
|
|
|
<!--右侧链路下一跳-->
|
2023-03-16 19:07:37 +08:00
|
|
|
|
<popover-content :title="$t('linkMonitor.nextHopInternetOfGrid')" :isNoData="isNextNoData" :gridData="nextGridData" :showError="isNextShowError" :content="nextErrorMsg" />
|
2022-09-15 15:51:00 +08:00
|
|
|
|
</div>
|
2022-09-10 23:13:42 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import chartMixin from '@/views/charts2/chart-mixin'
|
2022-09-15 15:51:00 +08:00
|
|
|
|
import { getSecond } from '@/utils/date-util'
|
|
|
|
|
|
import { api } from '@/utils/api'
|
2022-09-28 15:35:03 +08:00
|
|
|
|
import { storageKey } from '@/utils/constants'
|
|
|
|
|
|
import PopoverContent from './LinkDirectionGrid/PopoverContent'
|
|
|
|
|
|
import { computeScore } from '@/utils/tools'
|
2023-02-03 15:57:43 +08:00
|
|
|
|
import axios from 'axios'
|
2022-09-10 23:13:42 +08:00
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: 'LinkDirectionGrid',
|
2022-09-15 15:51:00 +08:00
|
|
|
|
mixins: [chartMixin],
|
|
|
|
|
|
data () {
|
|
|
|
|
|
return {
|
2022-11-21 17:31:30 +08:00
|
|
|
|
linkGridData: [],
|
|
|
|
|
|
nextGridData: [],
|
|
|
|
|
|
isLinkNoData: false,
|
|
|
|
|
|
isNextNoData: false,
|
|
|
|
|
|
isLinkShowError: false, // 显示左侧链路报错标识
|
|
|
|
|
|
linkErrorMsg: '', // 左侧链路的报错信息
|
|
|
|
|
|
isNextShowError: false, // 显示右侧下一跳报错标识
|
|
|
|
|
|
nextErrorMsg: '' // 右侧下一跳的报错信息
|
2022-09-15 15:51:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2022-09-28 15:35:03 +08:00
|
|
|
|
components: {
|
|
|
|
|
|
PopoverContent
|
|
|
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
|
|
|
timeFilter: {
|
2022-11-21 17:31:30 +08:00
|
|
|
|
handler () {
|
2022-09-28 15:35:03 +08:00
|
|
|
|
this.init()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
mounted () {
|
|
|
|
|
|
this.init()
|
|
|
|
|
|
},
|
2022-09-15 15:51:00 +08:00
|
|
|
|
methods: {
|
|
|
|
|
|
init () {
|
2022-09-28 15:35:03 +08:00
|
|
|
|
// 链路基本信息
|
|
|
|
|
|
let linkInfo = localStorage.getItem(storageKey.linkInfo)
|
|
|
|
|
|
linkInfo = JSON.parse(linkInfo)
|
|
|
|
|
|
|
2022-09-15 15:51:00 +08:00
|
|
|
|
const params = {
|
|
|
|
|
|
startTime: getSecond(this.timeFilter.startTime),
|
|
|
|
|
|
endTime: getSecond(this.timeFilter.endTime)
|
|
|
|
|
|
}
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
const dataRequest = axios.get(api.linkMonitor.bigramAnalysis, { params: params }).catch(e => {
|
|
|
|
|
|
this.isLinkShowError = true
|
|
|
|
|
|
this.isLinkNoData = false
|
|
|
|
|
|
this.linkErrorMsg = this.errorMsgHandler(e)
|
|
|
|
|
|
})
|
|
|
|
|
|
const nextHopRequest = axios.get(api.linkMonitor.bigramNextHopAnalysis, { params: params }).catch(e => {
|
|
|
|
|
|
this.isNextShowError = true
|
|
|
|
|
|
this.isNextNoData = false
|
|
|
|
|
|
this.nextErrorMsg = this.errorMsgHandler(e)
|
|
|
|
|
|
})
|
2022-10-13 16:36:14 +08:00
|
|
|
|
this.toggleLoading(true)
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-03-16 19:14:53 +08:00
|
|
|
|
Promise.all([dataRequest, nextHopRequest]).then(response => {
|
2023-08-25 16:23:18 +08:00
|
|
|
|
if (response[0].status === 200 && response[1].status === 200) {
|
2023-03-16 19:07:37 +08:00
|
|
|
|
const res = []
|
|
|
|
|
|
res[0] = response[0].data
|
|
|
|
|
|
res[1] = response[1].data
|
2023-08-25 16:23:18 +08:00
|
|
|
|
if (response[0].status === 200) {
|
2023-03-16 19:07:37 +08:00
|
|
|
|
this.isLinkShowError = false
|
2022-11-29 14:54:37 +08:00
|
|
|
|
// 链路流量数据
|
2023-03-16 19:07:37 +08:00
|
|
|
|
const linkData = res[0].data.result
|
2023-08-29 16:24:02 +08:00
|
|
|
|
// 接口数据乱序,根据入链路id(inLinkId)大小排序之后,
|
|
|
|
|
|
// 再根据同inLinkId下的outLinkId进行排序
|
2023-03-16 19:07:37 +08:00
|
|
|
|
linkData.sort((a, b) => {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
if (a.inLinkId !== b.inLinkId) {
|
|
|
|
|
|
return a.inLinkId - b.inLinkId
|
2023-03-16 19:07:37 +08:00
|
|
|
|
}
|
2023-08-29 16:24:02 +08:00
|
|
|
|
return a.outLinkId - b.outLinkId
|
2023-03-16 19:07:37 +08:00
|
|
|
|
})
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
this.isLinkNoData = linkData.length === 0
|
|
|
|
|
|
if (!this.isLinkNoData) {
|
|
|
|
|
|
// 链路流量数据
|
|
|
|
|
|
const linkGridData = []
|
|
|
|
|
|
linkData.forEach(d => {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
const inLink = linkInfo.find(l => l.originalLinkId === d.inLinkId)
|
|
|
|
|
|
const outLink = linkInfo.find(l => l.originalLinkId === d.outLinkId)
|
|
|
|
|
|
if (inLink && outLink) {
|
|
|
|
|
|
const data = linkGridData.find(g => g.linkId === inLink.linkId)
|
2022-11-21 17:31:30 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 上行使用情况计算
|
2023-08-29 16:24:02 +08:00
|
|
|
|
const outUsage = this.computeUsage(d.outBitsRate, outLink.bandwidth)
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 下行使用情况计算
|
2023-08-29 16:24:02 +08:00
|
|
|
|
const inUsage = this.computeUsage(d.inBitsRate, inLink.bandwidth)
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 宽带使用超过90%,赋红点
|
2022-11-21 17:31:30 +08:00
|
|
|
|
|
2023-08-29 16:24:02 +08:00
|
|
|
|
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 计算npm分数
|
|
|
|
|
|
// 分数低于3分,赋红点
|
|
|
|
|
|
d.score = this.localComputeScore(d)
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
d.scoreLow3 = d.score < 3 || d.score === '-'
|
|
|
|
|
|
|
|
|
|
|
|
if (data) {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
const existedEgressLink = data.out.find(e => e.linkId === outLink.linkId)
|
2023-03-16 19:07:37 +08:00
|
|
|
|
if (!existedEgressLink) {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
data.out.push({
|
|
|
|
|
|
linkId: outLink.linkId,
|
|
|
|
|
|
outUsage: outUsage,
|
|
|
|
|
|
inUsage: inUsage,
|
|
|
|
|
|
popoverWidth: this.computeWidth(outUsage, inUsage, 'popover'),
|
|
|
|
|
|
valueWidth: this.computeWidth(outUsage, inUsage, 'value'),
|
2023-03-16 19:07:37 +08:00
|
|
|
|
totalBitsRate: d.totalBitsRate,
|
|
|
|
|
|
...d
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
linkGridData.push({
|
2023-08-29 16:24:02 +08:00
|
|
|
|
linkId: inLink.linkId,
|
|
|
|
|
|
out: [{
|
|
|
|
|
|
linkId: outLink.linkId,
|
|
|
|
|
|
outUsage: outUsage,
|
|
|
|
|
|
inUsage: inUsage,
|
|
|
|
|
|
popoverWidth: this.computeWidth(outUsage, inUsage, 'popover'),
|
|
|
|
|
|
valueWidth: this.computeWidth(outUsage, inUsage, 'value'),
|
2023-03-16 19:07:37 +08:00
|
|
|
|
totalBitsRate: d.totalBitsRate,
|
|
|
|
|
|
...d
|
|
|
|
|
|
}]
|
2022-11-29 14:54:37 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
2022-09-15 15:51:00 +08:00
|
|
|
|
}
|
2023-03-16 19:07:37 +08:00
|
|
|
|
})
|
2023-06-25 15:07:24 +08:00
|
|
|
|
this.isLinkNoData = linkGridData.length === 0
|
2023-03-16 19:07:37 +08:00
|
|
|
|
this.linkGridData = linkGridData
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2023-06-25 15:07:24 +08:00
|
|
|
|
this.isLinkNoData = true
|
2023-03-16 19:07:37 +08:00
|
|
|
|
this.isLinkShowError = true
|
2023-03-22 10:20:22 +08:00
|
|
|
|
this.linkErrorMsg = this.errorMsgHandler(res[0])
|
2022-11-29 14:54:37 +08:00
|
|
|
|
}
|
2022-11-21 17:31:30 +08:00
|
|
|
|
|
2023-08-25 16:23:18 +08:00
|
|
|
|
if (response[1].status === 200) {
|
2023-03-16 19:07:37 +08:00
|
|
|
|
this.isNextShowError = false
|
2022-11-21 17:31:30 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 链路下一跳信息
|
|
|
|
|
|
const nextLinkData = res[1].data.result
|
|
|
|
|
|
// 接口数据乱序,根据入方向排序,再根据同个入方向下的出方向进行排序
|
|
|
|
|
|
nextLinkData.sort((a, b) => {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
if (a.inLinkDirection !== b.inLinkDirection) {
|
|
|
|
|
|
return a.inLinkDirection.localeCompare(b.inLinkDirection, 'zh')
|
2023-03-16 19:07:37 +08:00
|
|
|
|
}
|
2023-08-29 16:24:02 +08:00
|
|
|
|
return a.outLinkDirection.localeCompare(b.outLinkDirection, 'zh')
|
2023-03-16 19:07:37 +08:00
|
|
|
|
})
|
2022-11-21 17:31:30 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
this.isNextNoData = nextLinkData.length === 0
|
|
|
|
|
|
if (!this.isNextNoData) {
|
|
|
|
|
|
// 链路下一跳数据
|
|
|
|
|
|
const nextGridData = []
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
nextLinkData.forEach(d => {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
const inLink = linkInfo.find(l => l.nextHop === d.inLinkDirection && l.direction === 'in')
|
|
|
|
|
|
const outLink = linkInfo.find(l => l.nextHop === d.outLinkDirection && l.direction === 'out')
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-08-29 16:24:02 +08:00
|
|
|
|
if (inLink && outLink) {
|
|
|
|
|
|
const data = nextGridData.find(g => g.linkId === inLink.linkId)
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-08-29 16:24:02 +08:00
|
|
|
|
let outBandwidth = 0
|
|
|
|
|
|
let inBandwidth = 0
|
2023-03-16 19:07:37 +08:00
|
|
|
|
linkInfo.forEach((item) => {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
if (item.nextHop === d.outLinkDirection && item.direction === 'out') {
|
|
|
|
|
|
outBandwidth += item.bandwidth
|
2023-03-16 19:07:37 +08:00
|
|
|
|
}
|
2023-08-29 16:24:02 +08:00
|
|
|
|
if (item.nextHop === d.inLinkDirection && item.direction === 'in') {
|
|
|
|
|
|
inBandwidth += item.bandwidth
|
2023-03-16 19:07:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 上行使用情况计算
|
2023-08-29 16:24:02 +08:00
|
|
|
|
const outUsage = this.computeUsage(d.outBitsRate, outBandwidth)
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 下行使用情况计算
|
2023-08-29 16:24:02 +08:00
|
|
|
|
const inUsage = this.computeUsage(d.inBitsRate, inBandwidth)
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 宽带使用超过90%,赋红点
|
2022-11-21 17:31:30 +08:00
|
|
|
|
|
2023-08-29 16:24:02 +08:00
|
|
|
|
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
|
2023-03-16 19:07:37 +08:00
|
|
|
|
// 计算npm分数
|
|
|
|
|
|
// 分数低于3分,赋红点
|
|
|
|
|
|
d.score = this.localComputeScore(d)
|
2022-11-21 17:31:30 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
d.scoreLow3 = d.score < 3 || d.score === '-'
|
2022-09-28 15:35:03 +08:00
|
|
|
|
|
2023-03-16 19:07:37 +08:00
|
|
|
|
if (data) {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
const existedEgressLink = data.out.find(e => e.linkId === outLink.linkId)
|
2023-03-16 19:07:37 +08:00
|
|
|
|
if (!existedEgressLink) {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
data.out.push({
|
|
|
|
|
|
linkId: outLink.linkId,
|
|
|
|
|
|
nextHop: outLink.nextHop,
|
|
|
|
|
|
outUsage: outUsage,
|
|
|
|
|
|
inUsage: inUsage,
|
|
|
|
|
|
popoverWidth: this.computeWidth(outUsage, inUsage, 'popover'),
|
|
|
|
|
|
valueWidth: this.computeWidth(outUsage, inUsage, 'value'),
|
2023-03-16 19:07:37 +08:00
|
|
|
|
totalBitsRate: d.totalBitsRate,
|
|
|
|
|
|
...d
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
nextGridData.push({
|
2023-08-29 16:24:02 +08:00
|
|
|
|
linkId: inLink.linkId,
|
|
|
|
|
|
nextHop: inLink.nextHop,
|
|
|
|
|
|
out: [{
|
|
|
|
|
|
linkId: outLink.linkId,
|
|
|
|
|
|
nextHop: inLink.nextHop,
|
|
|
|
|
|
outUsage: outUsage,
|
|
|
|
|
|
inUsage: inUsage,
|
|
|
|
|
|
popoverWidth: this.computeWidth(outUsage, inUsage, 'popover'),
|
|
|
|
|
|
valueWidth: this.computeWidth(outUsage, inUsage, 'value'),
|
2023-03-16 19:07:37 +08:00
|
|
|
|
totalBitsRate: d.totalBitsRate,
|
|
|
|
|
|
...d
|
|
|
|
|
|
}]
|
2022-11-29 14:54:37 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
2022-09-28 15:35:03 +08:00
|
|
|
|
}
|
2023-03-16 19:07:37 +08:00
|
|
|
|
})
|
2023-06-25 15:07:24 +08:00
|
|
|
|
this.isNextNoData = nextGridData.length === 0
|
2023-03-16 19:07:37 +08:00
|
|
|
|
this.nextGridData = nextGridData
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2023-06-25 15:07:24 +08:00
|
|
|
|
this.isNextNoData = true
|
2023-03-16 19:07:37 +08:00
|
|
|
|
this.isNextShowError = true
|
2023-03-22 10:20:22 +08:00
|
|
|
|
this.nextErrorMsg = this.errorMsgHandler(res[1])
|
2022-11-29 14:54:37 +08:00
|
|
|
|
}
|
2022-09-15 15:51:00 +08:00
|
|
|
|
}
|
2022-10-13 16:36:14 +08:00
|
|
|
|
}).finally(() => {
|
|
|
|
|
|
this.toggleLoading(false)
|
2022-09-15 15:51:00 +08:00
|
|
|
|
})
|
2022-09-28 15:35:03 +08:00
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 计算上下行使用占比
|
|
|
|
|
|
*/
|
|
|
|
|
|
computeUsage (e, bandwidth) {
|
2022-09-29 16:36:30 +08:00
|
|
|
|
let usage = e / bandwidth
|
|
|
|
|
|
if (usage >= 1) {
|
|
|
|
|
|
usage = 1
|
|
|
|
|
|
}
|
|
|
|
|
|
return usage
|
2022-09-28 15:35:03 +08:00
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 本地计算npm分数
|
|
|
|
|
|
*/
|
2022-11-21 17:31:30 +08:00
|
|
|
|
localComputeScore (data) {
|
2022-09-28 15:35:03 +08:00
|
|
|
|
let score = 0
|
2022-11-01 14:13:47 +08:00
|
|
|
|
const dataScore = {
|
|
|
|
|
|
establishLatencyMs: data.establishLatencyMs || null,
|
|
|
|
|
|
httpResponseLatency: data.httpResponseLatency || null,
|
|
|
|
|
|
sslConLatency: data.sslConLatency || null,
|
|
|
|
|
|
tcpLostlenPercent: data.tcpLostlenPercent || null,
|
|
|
|
|
|
pktRetransPercent: data.pktRetransPercent || null
|
2022-09-28 15:35:03 +08:00
|
|
|
|
}
|
2022-11-01 14:13:47 +08:00
|
|
|
|
score = computeScore(dataScore)
|
|
|
|
|
|
return score
|
2022-10-14 14:50:46 +08:00
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 计算popover弹窗和右侧数据模块的宽度
|
|
|
|
|
|
* 弹窗最小宽度为360px,右侧数据最小宽度为75px,右侧数据每大一位,popover弹窗宽度增加7px
|
|
|
|
|
|
*/
|
2023-08-29 16:24:02 +08:00
|
|
|
|
computeWidth (out, _in, flag) {
|
2022-10-14 14:50:46 +08:00
|
|
|
|
let width = 0
|
|
|
|
|
|
let length = 0
|
|
|
|
|
|
|
2023-08-29 16:24:02 +08:00
|
|
|
|
let outUsage = ''
|
|
|
|
|
|
let inUsage = ''
|
2022-10-14 18:04:13 +08:00
|
|
|
|
|
2023-08-29 16:24:02 +08:00
|
|
|
|
if (out < 0.0001 && out !== 0) {
|
|
|
|
|
|
outUsage = '<0.01%'
|
2022-10-14 18:04:13 +08:00
|
|
|
|
} else {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
outUsage = JSON.stringify(parseFloat((out * 100).toFixed(2)))
|
2022-10-14 18:04:13 +08:00
|
|
|
|
}
|
2023-08-29 16:24:02 +08:00
|
|
|
|
if (_in < 0.0001 && _in !== 0) {
|
|
|
|
|
|
inUsage = '<0.01%'
|
2022-10-14 18:04:13 +08:00
|
|
|
|
} else {
|
2023-08-29 16:24:02 +08:00
|
|
|
|
inUsage = JSON.stringify(parseFloat((_in * 100).toFixed(2)))
|
2022-10-14 18:04:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-29 16:24:02 +08:00
|
|
|
|
length = outUsage.length + inUsage.length - 1
|
2022-10-14 14:50:46 +08:00
|
|
|
|
|
|
|
|
|
|
if (flag === 'popover') {
|
|
|
|
|
|
width = 360 + length * 7
|
|
|
|
|
|
} else {
|
|
|
|
|
|
width = 75 + length * 7
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return width
|
2022-09-15 15:51:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-09-10 23:13:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
</script>
|