CN-1223 fix: score改版

This commit is contained in:
chenjinsong
2023-10-22 20:21:32 +08:00
parent 40d43acb6c
commit c5c7b58720
24 changed files with 617 additions and 123 deletions

View File

@@ -128,7 +128,7 @@ $blue: #046ECA;
}
}
}
.link-statistical-dimension {
.row-dot {
margin-top: 5px;
margin-right: 5px;
@@ -147,6 +147,7 @@ $blue: #046ECA;
border-radius: 50%;
background: #E26154;
}
}
.item-popover-up, .item-popover-down {
font-size: 17px;

View File

@@ -349,6 +349,24 @@
.data-score-green {
background: #749F4D;
}
.score-dot {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: #CBCBCB;
margin-right: 4px;
&.score-dot--red {
background-color: #E26154;
}
&.score-dot--yellow {
background-color: #E5A219;
}
&.score-dot--green {
background-color: #749F4D;
}
}
height:24px;
font-size: 14px;
color: #046ECA;

View File

@@ -174,6 +174,25 @@
font-size: 14px;
color: #353636;
font-weight: 400;
.score-dot {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: #CBCBCB;
margin-right: 4px;
&.score-dot--red {
background-color: #E26154;
}
&.score-dot--yellow {
background-color: #E5A219;
}
&.score-dot--green {
background-color: #749F4D;
}
}
}
}
}

View File

@@ -257,8 +257,6 @@ export default {
},
methods: {
fileChange (file, fileList) {
console.info(!_.endsWith(file.name, '.csv'))
console.info(file.size > this.uploadFileSizeLimit)
// 判断后缀,仅支持.csv
if (!_.endsWith(file.name, '.csv')) {
this.fileList = []

View File

@@ -96,5 +96,41 @@ export default {
this.relationshipShowMoreTwo = false
this.relationshipShowMoreOne = false
}
},
computed: {
scoreDot () {
const dots = []
if (this.score === '-') {
for (let i = 0; i < 6; i++) {
dots.push({
class: 'score-dot'
})
}
} else {
for (let i = 0; i < 6; i++) {
if (i < this.score) {
dots.push({
class: `score-dot ${handleClass(this.score)}`
})
} else {
dots.push({
class: 'score-dot'
})
}
}
}
return dots
function handleClass (score) {
if (score <= 2) {
return 'score-dot--red'
} else if (score <= 4) {
return 'score-dot--yellow'
} else if (score <= 6) {
return 'score-dot--green'
}
return ''
}
}
}
}

View File

@@ -60,6 +60,29 @@ const panel = {
routerHistoryList: [], // 路由跳转记录列表
dnsQtypeMapData: [],
dnsRcodeMapData: [],
scoreBase: {
isReady: false,
establishLatencyMs: {
p10: null,
p90: null
},
httpResponseLatency: {
p10: null,
p90: null
},
sslConLatency: {
p10: null,
p90: null
},
tcpLostlenPercent: {
p10: null,
p90: null
},
pktRetransPercent: {
p10: null,
p90: null
}
},
chartTabList: null // chartTabs组件的tab状态点击列表初始化为null方便原有逻辑计算
},
mutations: {
@@ -153,6 +176,56 @@ const panel = {
setRouterHistoryList (state, list) {
state.routerHistoryList = list
},
resetScoreBase (state) {
state.scoreBase = {
isReady: false,
establishLatencyMs: {
p10: null,
p90: null
},
httpResponseLatency: {
p10: null,
p90: null
},
sslConLatency: {
p10: null,
p90: null
},
tcpLostlenPercent: {
p10: null,
p90: null
},
pktRetransPercent: {
p10: null,
p90: null
}
}
},
setScoreBase (state, scoreBase) {
state.scoreBase = {
isReady: true,
establishLatencyMs: {
p10: scoreBase.establishLatencyMsP10,
p90: scoreBase.establishLatencyMsP90
},
httpResponseLatency: {
p10: scoreBase.httpResponseLatencyP10,
p90: scoreBase.httpResponseLatencyP90
},
sslConLatency: {
p10: scoreBase.sslConLatencyP10,
p90: scoreBase.sslConLatencyP90
},
tcpLostlenPercent: {
p10: scoreBase.tcpLostlenPercentP10,
p90: scoreBase.tcpLostlenPercentP90
},
pktRetransPercent: {
p10: scoreBase.pktRetransPercentP10,
p90: scoreBase.pktRetransPercentP90
}
}
},
setChartTabList (state, list) {
state.chartTabList = list
}
@@ -232,6 +305,12 @@ const panel = {
},
getChartTabList (state) {
return state.chartTabList
},
scoreBaseReady (state) {
return state.scoreBase.isReady
},
getScoreBase (state) {
return state.scoreBase
}
},
actions: {

View File

@@ -784,12 +784,13 @@ export function getChainRatio (current, prev) {
}
}
export function computeScore (data) {
export function computeScore (data, scoreBase) {
let score = 0
let k = 0
let totalScore = 0
const scoreArr = []
let num = 0
console.info(data, scoreBase)
Object.keys(data).forEach(t => {
if (!data[t] && data[t] !== 0) {
num += 1
@@ -799,26 +800,14 @@ export function computeScore (data) {
} else if (t === 'httpResponseLatency' || t === 'sslConLatency') {
k = 0.05
}
if (t === 'establishLatencyMs' || t === 'httpResponseLatency' || t === 'sslConLatency') {
if (!data[t] && data[t] !== 0) {
score = 1
} else if (data[t] <= 50) {
} else if (data[t] <= scoreBase[t].p10) {
score = 1
} else if (data[t] > 200) {
} else if (data[t] >= scoreBase[t].p90) {
score = 0
} else {
score = (data[t] - 200) / (50 - 200)
}
} else if (t === 'tcpLostlenPercent' || t === 'pktRetransPercent') {
if (!data[t] && data[t] !== 0) {
score = 1
} else if (data[t] <= 0.01) {
score = 1
} else if (data[t] > 0.05) {
score = 0
} else {
score = (data[t] - 0.05) / (0.01 - 0.05)
}
score = (data[t] - scoreBase[t].p90) / (scoreBase[t].p10 - scoreBase[t].p90)
}
scoreArr.push(score * k)
})
@@ -1319,9 +1308,9 @@ export function numberWithCommas (num) {
*/
export function switchStatus (status) {
switch (status) {
case 0:
case '0':
return 'detection.create.disabled'
case 1:
case '1':
return 'detection.create.enabled'
}
}

View File

@@ -104,7 +104,9 @@ export default {
dnsRcodeMapData: [],
dnsQtypeMapData: [],
score: null,
curTabState: curTabState
curTabState: curTabState,
performanceData: {},
scoreDataState: false // 评分数据是否加载完成
}
},
computed: {
@@ -114,24 +116,34 @@ export default {
// 显示顶部的Metric单位选项标识
showMetric () {
return this.panelType === panelTypeAndRouteMapping.networkOverview || this.panelType === panelTypeAndRouteMapping.networkOverviewDrillDown
},
scoreBaseState () {
return this.$store.getters.scoreBaseReady
}
},
watch: {
// npmThirdLevelMenuScore: {
// deep: true,
// immediate: true,
// handler (n) {
// this.score = n
// }
// }
timeFilter: {
handler () {
if (this.$route.path === '/panel/networkAppPerformance' && (this.lineQueryCondition || this.networkOverviewBeforeTab)) {
if (this.$route.path === '/panel/networkAppPerformance') {
this.$store.commit('resetScoreBase')
this.queryScoreBase()
if (this.lineQueryCondition || this.networkOverviewBeforeTab) {
this.scoreCalculation()
}
}
}
},
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData()
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData()
}
}
},
async mounted () {
// this.panelName = this.$store.getters.getPanelName
const pName = this.$route.query.panelName ? this.$t(this.$route.query.panelName) : ''
@@ -212,9 +224,15 @@ export default {
return chart
})
})
if (this.$route.path === '/panel/networkAppPerformance' && (this.lineQueryCondition || this.networkOverviewBeforeTab)) {
if (this.$route.path === '/panel/networkAppPerformance') {
if (this.lineQueryCondition || this.networkOverviewBeforeTab) {
this.scoreCalculation()
}
}
if (this.$route.path === '/panel/networkAppPerformance' || this.$route.path === '/panel/linkMonitor') {
this.$store.commit('resetScoreBase')
this.queryScoreBase()
}
},
setup (props) {
// router引入store会报错故在panel里调用
@@ -396,6 +414,44 @@ export default {
})
overwriteUrl(newUrl)
},
// 动态查询评分基准
queryScoreBase () {
const params = {
startTime: this.timeFilter.startTime,
endTime: this.timeFilter.endTime
}
const tcp = axios.get(api.npm.overview.tcpSessionDelay, { params: params })
const http = axios.get(api.npm.overview.httpResponseDelay, { params: params })
const ssl = axios.get(api.npm.overview.sslConDelay, { params: params })
const tcpPercent = axios.get(api.npm.overview.tcpLostlenPercent, { params: params })
const packetPercent = axios.get(api.npm.overview.packetRetransPercent, { params: params })
Promise.all([tcp, http, ssl, tcpPercent, packetPercent]).then(res => {
const scoreBase = {}
res.forEach((t, i) => {
if (t.status === 200) {
if (i === 0) {
scoreBase.establishLatencyMsP10 = _.get(t.data, 'data.result.establishLatencyMsP10', null)
scoreBase.establishLatencyMsP90 = _.get(t.data, 'data.result.establishLatencyMsP90', null)
} else if (i === 1) {
scoreBase.httpResponseLatencyP10 = _.get(t.data, 'data.result.httpResponseLatencyP10', null)
scoreBase.httpResponseLatencyP90 = _.get(t.data, 'data.result.httpResponseLatencyP90', null)
} else if (i === 2) {
scoreBase.sslConLatencyP10 = _.get(t.data, 'data.result.sslConLatencyP10', null)
scoreBase.sslConLatencyP90 = _.get(t.data, 'data.result.sslConLatencyP90', null)
} else if (i === 3) {
scoreBase.tcpLostlenPercentP10 = _.get(t.data, 'data.result.tcpLostlenPercentP10', null)
scoreBase.tcpLostlenPercentP90 = _.get(t.data, 'data.result.tcpLostlenPercentP90', null)
} else if (i === 4) {
scoreBase.pktRetransPercentP10 = _.get(t.data, 'data.result.pktRetransPercentP10', null)
scoreBase.pktRetransPercentP90 = _.get(t.data, 'data.result.pktRetransPercentP90', null)
}
}
})
this.$store.commit('setScoreBase', scoreBase)
}).catch((e) => {
}).finally(() => {
})
},
scoreCalculation () {
let condition = ''
let url = ''
@@ -443,18 +499,21 @@ export default {
url = api.npm.overview.networkAnalysis
}
if ((type && condition) || type) {
this.scoreDataState = false
this.performanceData = {}
params.type = params.type || type
axios.get(url, { params }).then(res => {
if (res.status === 200) {
const data = {
this.performanceData = {
establishLatencyMs: _.get(res, 'data.data.result.establishLatencyMsAvg', null),
httpResponseLatency: _.get(res, 'data.data.result.httpResponseLatencyAvg', null),
sslConLatency: _.get(res, 'data.data.result.sslConLatencyAvg', null),
tcpLostlenPercent: _.get(res, 'data.data.result.tcpLostlenPercentAvg', null),
pktRetransPercent: _.get(res, 'data.data.result.pktRetransPercentAvg', null)
}
this.score = computeScore(data)
}
}).finally(() => {
this.scoreDataState = true
})
}
},
@@ -467,6 +526,9 @@ export default {
}
})
window.open(href, '_blank')
},
handleScoreData () {
this.score = computeScore(this.performanceData, this.$store.getters.getScoreBase)
}
},
/**

View File

@@ -30,7 +30,8 @@ export default {
isLinkShowError: false, // 显示左侧链路报错标识
linkErrorMsg: '', // 左侧链路的报错信息
isNextShowError: false, // 显示右侧下一跳报错标识
nextErrorMsg: '' // 右侧下一跳的报错信息
nextErrorMsg: '', // 右侧下一跳的报错信息
scoreDataState: false // 评分数据是否加载完成
}
},
components: {
@@ -41,6 +42,23 @@ export default {
handler () {
this.init()
}
},
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData(this.linkGridData)
this.handleScoreData(this.nextGridData)
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData(this.linkGridData)
this.handleScoreData(this.nextGridData)
}
}
},
computed: {
scoreBaseState () {
return this.$store.getters.scoreBaseReady
}
},
mounted () {
@@ -48,6 +66,7 @@ export default {
},
methods: {
init () {
this.scoreDataState = false
// 链路基本信息
let linkInfo = localStorage.getItem(storageKey.linkInfo)
linkInfo = JSON.parse(linkInfo)
@@ -117,9 +136,9 @@ export default {
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
// 计算npm分数
// 分数低于3分赋红点
d.score = this.localComputeScore(d)
// d.score = this.localComputeScore(d)
d.scoreLow3 = d.score < 3 || d.score === '-'
// d.scoreLow3 = d.score < 3 || d.score === '-'
const xAxis = inLink.linkId.split('Hundredgige').pop() - 1
const yAxis = outLink.linkId.split('Hundredgige').pop() - 1
@@ -210,9 +229,9 @@ export default {
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
// 计算npm分数
// 分数低于3分赋红点
d.score = this.localComputeScore(d)
// d.score = this.localComputeScore(d)
d.scoreLow3 = d.score < 3 || d.score === '-'
// d.scoreLow3 = d.score < 3 || d.score === '-'
const xAxis = inLink.linkId
const yAxis = outLink.linkId
@@ -254,6 +273,7 @@ export default {
}
}
}).finally(() => {
this.scoreDataState = true
this.toggleLoading(false)
})
},
@@ -282,6 +302,23 @@ export default {
score = computeScore(dataScore)
return score
},
handleScoreData (data) {
data.forEach(d => {
if (d.out) {
d.out.forEach(t => {
const data = {
establishLatencyMs: t.establishLatencyMs,
httpResponseLatency: t.httpResponseLatency,
sslConLatency: t.sslConLatency,
tcpLostlenPercent: t.tcpLostlenPercent,
pktRetransPercent: t.pktRetransPercent
}
t.score = computeScore(data, this.$store.getters.getScoreBase)
t.scoreLow3 = t.score < 3 || t.score === '-'
})
}
})
},
/**
* 计算popover弹窗和右侧数据模块的宽度
* 弹窗最小宽度为360px右侧数据最小宽度为75px右侧数据每大一位popover弹窗宽度增加7px

View File

@@ -87,7 +87,14 @@ export default {
bandWidth: 0,
loading: false,
showError: false,
errorMsg: ''
errorMsg: '',
scoreDataState: false,
performanceData: {}
}
},
computed: {
scoreBaseState () {
return this.$store.getters.scoreBaseReady
}
},
watch: {
@@ -95,6 +102,16 @@ export default {
handler (n) {
this.linkTrafficData()
}
},
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData()
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData()
}
}
},
methods: {
@@ -103,6 +120,9 @@ export default {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime)
}
this.loading = true
this.performanceData = {}
this.scoreDataState = false
if (this.queryCondition) {
const condition = this.queryCondition.split(' or ')
if (condition.length > 1) {
@@ -142,7 +162,6 @@ export default {
this.bandWidth = bandwidthAll
}
}
this.loading = true
axios.get(api.linkMonitor.networkAnalysis, { params: params }).then(response => {
const res = response.data
if (response.status === 200) {
@@ -152,7 +171,7 @@ export default {
this.linkTrafficListData = {}
this.linkTrafficListData.npmScore = '-'
} else {
const data = {
this.performanceData = {
establishLatencyMs: _.get(res.data.result[0], 'establishLatencyMs', null),
httpResponseLatency: _.get(res.data.result[0], 'httpResponseLatency', null),
sslConLatency: _.get(res.data.result[0], 'sslConLatency', null),
@@ -160,19 +179,24 @@ export default {
pktRetransPercent: _.get(res.data.result[0], 'pktRetransPercent', null)
}
this.linkTrafficListData = res.data.result[0]
this.linkTrafficListData.npmScore = computeScore(data)
// this.linkTrafficListData.npmScore = computeScore(data)
}
} else {
this.showError = true
this.errorMsg = res.message
}
}).catch(e => {
console.error(e)
this.showError = true
this.errorMsg = e.message
this.isNoData = false
}).finally(() => {
this.loading = false
this.scoreDataState = true
})
},
handleScoreData () {
this.linkTrafficListData.npmScore = computeScore(this.performanceData, this.$store.getters.getScoreBase)
}
},
mounted () {

View File

@@ -379,12 +379,25 @@ export default {
timeFilter: {
handler (n) {
const queryParams = this.getQueryParams()
this.changeUrlTabState()
this.getChartData(queryParams)
this.changeUrlTabState()
}
},
metric (n) {
this.changeMetric()
},
scoreBaseState (n) {
if (n && Object.keys(_.get(this.tableData, '[0].scoreGroup', {})).length >= 5) {
this.handleScoreData()
}
},
tableData: {
deep: true,
handler (n) {
if (Object.keys(_.get(n, '[0].scoreGroup', {})).length >= 5 && this.scoreBaseState) {
this.handleScoreData()
}
}
}
},
computed: {
@@ -399,6 +412,9 @@ export default {
className = 'tab-table tab-table__no-bottom'
}
return className
},
scoreBaseState () {
return this.$store.getters.scoreBaseReady
}
},
mixins: [chartMixin],
@@ -468,8 +484,8 @@ export default {
return excludeName.indexOf(title.name) > -1 ? false : 'custom'
},
searchColumnWidth (columnType) {
let checkedGroup = this.customTableTitles.filter(item => item.checked)
let checkedNum = checkedGroup.length
const checkedGroup = this.customTableTitles.filter(item => item.checked)
const checkedNum = checkedGroup.length
if (columnType === 'dillDown') {
if (checkedNum === 1) {
return 'auto'
@@ -1038,12 +1054,12 @@ export default {
} else {
item.scoreGroup[self.columnNameGroup[tableColumn.prop]] = 0
}
if (Object.keys(item.scoreGroup).length >= 5) {
/* if (Object.keys(item.scoreGroup).length >= 5) {
item.score = computeScore(item.scoreGroup)
if (!_.isNumber(item.score)) {
item.score = '-'
}
}
} */
})
} else {
tableColumn.showError = true
@@ -2223,6 +2239,18 @@ export default {
this.orderBy = 'sessions'
this.metricUnit = 'sessions'
}
},
handleScoreData () {
this.tableData.forEach(t => {
const data = {
establishLatencyMs: t.scoreGroup ? t.scoreGroup.establishLatencyMs : null,
httpResponseLatency: t.scoreGroup ? t.scoreGroup.httpResponseLatency : null,
sslConLatency: t.scoreGroup ? t.scoreGroup.sslConLatency : null,
tcpLostlenPercent: t.scoreGroup ? t.scoreGroup.tcpLostlenPercent : null,
pktRetransPercent: t.scoreGroup ? t.scoreGroup.pktRetransPercent : null
}
t.score = computeScore(data, this.$store.getters.getScoreBase)
})
}
},
async mounted () {

View File

@@ -172,7 +172,8 @@ export default {
curTabState: curTabState,
urlChangeParams: {},
showError: false,
errorMsg: ''
errorMsg: '',
scoreDataState: false // 评分数据是否加载完成
}
},
components: {
@@ -185,6 +186,21 @@ export default {
handler () {
this.init()
}
},
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData()
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData()
}
}
},
computed: {
scoreBaseState () {
return this.$store.getters.scoreBaseReady
}
},
methods: {
@@ -197,6 +213,7 @@ export default {
const currentTrafficRequest = axios.get(api.npm.overview.appTrafficAnalysis, { params: { ...params, cycle: 0 } })
const lastCycleTrafficRequest = axios.get(api.npm.overview.appTrafficAnalysis, { params: { ...params, cycle: 1 } })
this.toggleLoading(true)
this.scoreDataState = false
Promise.all([currentTrafficRequest, lastCycleTrafficRequest]).then(res => {
if (res[0].status === 200 && res[1].status === 200) {
this.showError = false
@@ -239,6 +256,9 @@ export default {
t[keyPre[i] + 'Score'] = r.data.data.result.find(d => d.appSubcategory === t.appSubcategory)
})
} else {
tableData.forEach(t => {
t[keyPre[i] + 'Score'] = null
})
this.showError = true
msg = msg + ',' + r.data.data.message
if (msg.indexOf(',') === 0) {
@@ -250,7 +270,7 @@ export default {
this.errorMsg = msg
}
})
tableData.forEach(t => {
/* tableData.forEach(t => {
const data = {
establishLatencyMs: t.tcpScore ? t.tcpScore.establishLatencyMs : null,
httpResponseLatency: t.httpScore ? t.httpScore.httpResponseLatency : null,
@@ -259,10 +279,11 @@ export default {
pktRetransPercent: t.packetRetransScore ? t.packetRetransScore.pktRetransPercent : null
}
t.score = computeScore(data)
})
}) */
this.tableData = tableData
}).finally(() => {
this.toggleLoading(false)
this.scoreDataState = true
})
} else {
this.tableData = []
@@ -382,6 +403,18 @@ export default {
overwriteUrl(newUrl)
}
this.urlChangeParams = {}
},
handleScoreData () {
this.tableData.forEach(t => {
const data = {
establishLatencyMs: t.tcpScore ? t.tcpScore.establishLatencyMs : null,
httpResponseLatency: t.httpScore ? t.httpScore.httpResponseLatency : null,
sslConLatency: t.sslScore ? t.sslScore.sslConLatency : null,
tcpLostlenPercent: t.tcpLostScore ? t.tcpLostScore.tcpLostlenPercent : null,
pktRetransPercent: t.packetRetransScore ? t.packetRetransScore.pktRetransPercent : null
}
t.score = computeScore(data, this.$store.getters.getScoreBase)
})
}
},
mounted () {

View File

@@ -43,21 +43,38 @@ export default {
trafficDirection: 'Server',
curTabState: curTabState,
showError: false,
errorMsg: ''
errorMsg: '',
scoreDataState: false
}
},
mixins: [chartMixin],
computed: {
scoreBaseState () {
return this.$store.getters.scoreBaseReady
}
},
watch: {
timeFilter: {
handler () {
this.loadAm4ChartMap(this.polygonSeries, this.worldImageSeries)
}
},
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData()
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData()
}
}
},
methods: {
async initMap () {
// 初始化插件
this.toggleLoading(true)
this.scoreDataState = false // 重置评分数据状态
const geoData = await getGeoData(storageKey.iso36112WorldLow)
const chart = am4Core.create('npmDrillDownMap', am4Maps.MapChart)
chart.geodata = geoData
@@ -81,6 +98,7 @@ export default {
// 清除数据
// polygonSeries.data.splice(0)
this.toggleLoading(true)
this.scoreDataState = false // 重置评分数据状态
// 清除legend
this.myChart.children.each((s, i) => {
if (s && s.className !== 'Container') {
@@ -140,10 +158,11 @@ export default {
tcpLostlenPercent: valueToRangeValue(data.tcpLostlenPercent, unitTypes.percent).join(' '),
pktRetransPercent: valueToRangeValue(data.pktRetransPercent, unitTypes.percent).join(' ')
}
t.tooltip.data.score = computeScore(data)
t.performanceData = data
/* t.tooltip.data.score = computeScore(data)
if (t.tooltip.data.score === '-') {
t.tooltip.data.score = ''
}
} */
t.tooltip.data.total = valueToRangeValue(t.totalBitsRate, unitTypes.bps).join(' ')
t.tooltip.data.inbound = valueToRangeValue(t.inboundBitsRate, unitTypes.bps).join(' ')
t.tooltip.data.outbound = valueToRangeValue(t.outboundBitsRate, unitTypes.bps).join(' ')
@@ -161,6 +180,7 @@ export default {
sslConLatency: this.$t('networkAppPerformance.sslResponseLatency')
}
})
this.scoreDataState = true
this.loadMarkerData(imageSeries, mapData)
})
} else {
@@ -180,14 +200,10 @@ export default {
}
},
loadMarkerData (imageSeries, data) {
const _data = data.filter(d => d.tooltip.data.score || d.tooltip.data.score === 0)
imageSeries.data = _data.map(r => ({
imageSeries.data = data.map(r => ({
...r,
score: r.tooltip.data.score,
name: r.superAdminArea || r.countryRegion,
id: r.serverId,
color: this.scoreColor(r.tooltip.data.score),
border: this.scoreColor(r.tooltip.data.score)
id: r.serverId
}))
},
scoreColor (score) {
@@ -307,6 +323,22 @@ export default {
})
return imageSeries
},
handleScoreData () {
const imageSeries = this.location ? this.countryImageSeries : this.worldImageSeries
imageSeries.data = imageSeries.data.map(d => {
let score = computeScore(d.performanceData, this.$store.getters.getScoreBase)
if (score === '-') {
score = ''
}
d.tooltip.data.score = score
return {
...d,
score,
color: this.scoreColor(score),
border: this.scoreColor(score)
}
})
}
},
mounted () {

View File

@@ -75,14 +75,21 @@ export default {
trafficDirection: 'Server',
location: '',
showError: false,
errorMsg: ''
errorMsg: '',
scoreDataState: false
}
},
mixins: [chartMixin],
computed: {
scoreBaseState () {
return this.$store.getters.scoreBaseReady
}
},
methods: {
async initMap () {
// 初始化插件
this.toggleLoading(true)
this.scoreDataState = false // 重置评分数据状态
const geoData = await getGeoData(storageKey.iso36112WorldLow)
const chart = am4Core.create('npmMap', am4Maps.MapChart)
chart.geodata = geoData
@@ -101,14 +108,13 @@ export default {
this.worldImageSeries.mapImages.template.events.on('hit', async ev => {
this.$store.commit('setNpmLocationCountry', ev.target.dataItem.dataContext.name)
this.location = ev.target.dataItem.dataContext.name
const countryId = ev.target.dataItem.dataContext.id
ev.target.isHover = false
await this.drill(countryId)
})
},
loadAm4ChartMap (polygonSeries, imageSeries) {
try {
this.toggleLoading(true)
this.scoreDataState = false // 重置评分数据状态
// 清除legend
this.myChart.children.each((s, i) => {
if (s && s.className !== 'Container') {
@@ -172,10 +178,11 @@ export default {
tcpLostlenPercent: valueToRangeValue(data.tcpLostlenPercent, unitTypes.percent).join(' '),
pktRetransPercent: valueToRangeValue(data.pktRetransPercent, unitTypes.percent).join(' ')
}
t.tooltip.data.score = computeScore(data)
t.performanceData = data
/* t.tooltip.data.score = computeScore(data)
if (t.tooltip.data.score === '-') {
t.tooltip.data.score = ''
}
} */
t.tooltip.data.total = valueToRangeValue(t.totalBitsRate, unitTypes.bps).join(' ')
t.tooltip.data.inbound = valueToRangeValue(t.inboundBitsRate, unitTypes.bps).join(' ')
t.tooltip.data.outbound = valueToRangeValue(t.outboundBitsRate, unitTypes.bps).join(' ')
@@ -193,6 +200,7 @@ export default {
sslConLatency: this.$t('networkAppPerformance.sslResponseLatency')
}
})
this.scoreDataState = true
this.loadMarkerData(imageSeries, mapData)
}).catch(e => {
this.showError = true
@@ -219,17 +227,13 @@ export default {
}
},
loadMarkerData (imageSeries, data) {
const _data = data.filter(d => d.tooltip.data.score || d.tooltip.data.score === 0)
imageSeries.data = _data.map(r => ({
imageSeries.data = data.map(r => ({
...r,
score: r.tooltip.data.score,
name: r.superAdminArea || r.countryRegion,
id: r.serverId,
color: this.scoreColor(r.tooltip.data.score),
border: this.scoreColor(r.tooltip.data.score)
id: r.serverId
}))
if (!this.location) {
this.filterLocationOptions(_data)
this.filterLocationOptions(data)
}
},
filterLocationOptions (data) {
@@ -391,6 +395,23 @@ export default {
this.$message.warning(this.$t('tip.noDetailMap'))
}
}
},
handleScoreData () {
const imageSeries = this.location ? this.countryImageSeries : this.worldImageSeries
imageSeries.data = imageSeries.data.map(d => {
let score = computeScore(d.performanceData, this.$store.getters.getScoreBase)
if (score === '-') {
score = ''
}
d.tooltip.data.score = score
return {
...d,
score,
color: this.scoreColor(score),
border: this.scoreColor(score)
}
})
// this.myChart.invalidateData()
}
},
watch: {
@@ -430,6 +451,16 @@ export default {
this.loadAm4ChartMap(this.polygonSeries, this.worldImageSeries)
}
}
},
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData()
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData()
}
}
},
mounted () {

View File

@@ -7,7 +7,7 @@ import {
chartColorForBehaviorPattern,
unitTypes
} from '@/utils/constants'
import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
import unitConvert from '@/utils/unit-convert'
import { axisFormatter } from '@/views/charts/charts/tools'
import { xAxisTimeFormatter, xAxisTimeRich } from '@/utils/date-util'

View File

@@ -17,7 +17,7 @@
@search="search"
></explorer-search>
<!-- 内容区 -->
<div v-if="showList" style="display: flex;flex-direction: row;">
<div v-if="showList" style="display: flex;flex-direction: row;padding-bottom: 20px;">
<entity-filter
:filter-data="newFilterData"
:loading-left="loadingLeft"
@@ -689,6 +689,44 @@ export default {
} else {
this.search({ q: '', str: '', metaList: [] })
}
},
queryScoreBase () {
const { startTime, endTime } = getNowTime(60 * 24)
const params = {
startTime: getSecond(startTime),
endTime: getSecond(endTime)
}
const tcp = axios.get(api.npm.overview.tcpSessionDelay, { params: params })
const http = axios.get(api.npm.overview.httpResponseDelay, { params: params })
const ssl = axios.get(api.npm.overview.sslConDelay, { params: params })
const tcpPercent = axios.get(api.npm.overview.tcpLostlenPercent, { params: params })
const packetPercent = axios.get(api.npm.overview.packetRetransPercent, { params: params })
Promise.all([tcp, http, ssl, tcpPercent, packetPercent]).then(res => {
const scoreBase = {}
res.forEach((t, i) => {
if (t.status === 200) {
if (i === 0) {
scoreBase.establishLatencyMsP10 = _.get(t.data, 'data.result.establishLatencyMsP10', null)
scoreBase.establishLatencyMsP90 = _.get(t.data, 'data.result.establishLatencyMsP90', null)
} else if (i === 1) {
scoreBase.httpResponseLatencyP10 = _.get(t.data, 'data.result.httpResponseLatencyP10', null)
scoreBase.httpResponseLatencyP90 = _.get(t.data, 'data.result.httpResponseLatencyP90', null)
} else if (i === 2) {
scoreBase.sslConLatencyP10 = _.get(t.data, 'data.result.sslConLatencyP10', null)
scoreBase.sslConLatencyP90 = _.get(t.data, 'data.result.sslConLatencyP90', null)
} else if (i === 3) {
scoreBase.tcpLostlenPercentP10 = _.get(t.data, 'data.result.tcpLostlenPercentP10', null)
scoreBase.tcpLostlenPercentP90 = _.get(t.data, 'data.result.tcpLostlenPercentP90', null)
} else if (i === 4) {
scoreBase.pktRetransPercentP10 = _.get(t.data, 'data.result.pktRetransPercentP10', null)
scoreBase.pktRetransPercentP90 = _.get(t.data, 'data.result.pktRetransPercentP90', null)
}
}
})
this.$store.commit('setScoreBase', scoreBase)
}).catch((e) => {
}).finally(() => {
})
}
},
mounted () {
@@ -709,6 +747,9 @@ export default {
}
this.initSearch(q)
this.listMode = listMode
// 查询评分基准
this.$store.commit('resetScoreBase')
this.queryScoreBase()
}
},
watch: {

View File

@@ -39,7 +39,7 @@
</div>
<div @click="showMoreFilter(item, index)"
:class="item.showNum === item.data.length ? 'filter-no-show-more' : 'filter-show-more'">
{{ $t('entity.showMore') }}
{{ $t('overall.showMore') }}
</div>
<div class="filter-hr"></div>
</div>

View File

@@ -678,7 +678,6 @@ export default {
// 手动高亮listNode
const _listNode = _this.graph.findById(listNode.id)
_this.graph.emit('node:click', { item: _listNode, target: _listNode.getKeyShape() })
console.info(_this.stackData)
if (_this.stackData.justUndo) {
_this.stackData.justUndo = false
_this.stackData.redo = []

View File

@@ -143,7 +143,10 @@
<div class="row-item-label">
<span class="row-item-label">{{ $t('network.score') }}&nbsp;:&nbsp;&nbsp;</span>
<span class="row-item-value" style="position: relative;">
<span v-if="!loadingNetworkQuality">{{ score }}</span>
<template v-if="!loadingNetworkQuality && score !=='-'">
<span v-for="(dot, i) in scoreDot" :key="i" :class="dot.class"></span>
</template>
<template v-else-if="score ==='-'"><span>-</span></template>
<loading :loading="loadingNetworkQuality" size="small"></loading>
</span>
</div>

View File

@@ -68,12 +68,8 @@
<div class="row__label row__label--width130">{{$t('entities.networkQualityRating')}}</div>
<div style="position: relative;">
<div class="entity-score" v-if="!loadingNetworkQuality">
<div v-if="score !== '-'">
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
<div class="circle-icon" v-else-if="score <= 6" :class="{'data-score-green': score <= 6}" ></div>
</div>
{{score}}
<span v-for="(dot, i) in scoreDot" :key="i" :class="dot.class"></span>
<span style="padding-left: 4px;">{{score}}</span>
</div>
<loading :loading="loadingNetworkQuality" size="small" style="left: 1rem;width: 50%;"></loading>
</div>

View File

@@ -76,12 +76,8 @@
<div class="row__label row__label--width130">{{$t('entities.networkQualityRating')}}</div>
<div style="position: relative;">
<div class="entity-score" v-if="!loadingNetworkQuality">
<div v-if="score !== '-'">
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
<div class="circle-icon" v-else-if="score <= 6" :class="{'data-score-green': score <= 6}" ></div>
</div>
{{score}}
<span v-for="(dot, i) in scoreDot" :key="i" :class="dot.class"></span>
<span style="padding-left: 4px;">{{score}}</span>
</div>
<loading :loading="loadingNetworkQuality" size="small" style="left: 1rem;width: 50%;"></loading>
</div>

View File

@@ -107,12 +107,8 @@
<div class="row__label row__label--width130">{{$t('entities.networkQualityRating')}}</div>
<div style="position: relative;">
<div class="entity-score" v-if="!loadingNetworkQuality">
<div v-if="score !== '-'">
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
<div class="circle-icon" v-else-if="score <= 6" :class="{'data-score-green': score <= 6}" ></div>
</div>
{{score}}
<span v-for="(dot, i) in scoreDot" :key="i" :class="dot.class"></span>
<span style="padding-left: 4px;">{{score}}</span>
</div>
<loading :loading="loadingNetworkQuality" size="small" style="left: 1rem;width: 50%;"></loading>
</div>

View File

@@ -48,7 +48,9 @@ export default {
score: '-', // 网络质量评分
performanceMetricEndTimeInterval: 3600, // 服务质量事件指标的结束时间与开始时间的秒间隔
isShowMoreApp: false, // related App 展示更多时
isShowMoreDomain: false // related Domain 展示更多时
isShowMoreDomain: false, // related Domain 展示更多时
scoreDataState: false, // 性能数据加载情况true 表示加载完成
performanceScoreData: {} // 用来计算评分的性能数据
}
},
computed: {
@@ -92,6 +94,21 @@ export default {
}
return className
}
},
scoreBaseState () {
return this.$store.getters.scoreBaseReady
}
},
watch: {
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData()
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData()
}
}
},
methods: {
@@ -258,17 +275,18 @@ export default {
queryEntityDetailNetworkQuantity () {
this.loadingNetworkQuality = true
this.performanceScoreData = {}
this.scoreDataState = false
if (this.networkQuantityUrl) {
axios.get(this.networkQuantityUrl, { params: this.getQueryParams() }).then(response => {
if (response.status === 200) {
const data = {
this.performanceScoreData = {
establishLatencyMs: response.data.data.result.establishLatencyMsAvg || null,
httpResponseLatency: response.data.data.result.httpResponseLatencyAvg || null,
sslConLatency: response.data.data.result.sslConLatencyAvg || null,
tcpLostlenPercent: response.data.data.result.tcpLostlenPercentAvg || null,
pktRetransPercent: response.data.data.result.pktRetransPercentAvg || null
}
this.score = computeScore(data)
this.entityData.establishLatencyMsAvg = response.data.data.result.establishLatencyMsAvg
this.entityData.establishLatencyP50 = response.data.data.result.establishLatencyP50
this.entityData.establishLatencyP90 = response.data.data.result.establishLatencyP90
@@ -321,6 +339,8 @@ export default {
this.singleValues.chartDatas.splice(4, 1, pktRetransPercent)
}
this.loadingNetworkQuality = false
}).finally(() => {
this.scoreDataState = true
})
}
},
@@ -472,6 +492,9 @@ export default {
document.body.addEventListener('click', showBlock)
})
}
},
handleScoreData () {
this.score = computeScore(this.performanceScoreData, this.$store.getters.getScoreBase)
}
},
setup () {

View File

@@ -30,7 +30,9 @@ export default {
eventNum: 0, // 性能事件和安全事件数量之和
loadingEvent: false, // event的loading
performanceEventUrl: '', // 性能事件接口url
securityEventUrl: '' // 安全事件接口url
securityEventUrl: '', // 安全事件接口url
performanceScoreData: {},
scoreDataState: false
}
},
computed: {
@@ -77,6 +79,43 @@ export default {
resource: this.entityData.entityValue
}
return params
},
scoreBaseState () {
return this.$store.getters.scoreBaseReady
},
scoreDot () {
const dots = []
if (this.score === '-') {
for (let i = 0; i < 6; i++) {
dots.push({
class: 'score-dot'
})
}
} else {
for (let i = 0; i < 6; i++) {
if (i < this.score) {
dots.push({
class: `score-dot ${handleClass(this.score)}`
})
} else {
dots.push({
class: 'score-dot'
})
}
}
}
return dots
function handleClass (score) {
if (score <= 2) {
return 'score-dot--red'
} else if (score <= 4) {
return 'score-dot--yellow'
} else if (score <= 6) {
return 'score-dot--green'
}
return ''
}
}
},
methods: {
@@ -221,20 +260,21 @@ export default {
/** 获取网络评分 */
queryNetworkQuantity () {
this.loadingNetworkQuality = true
this.performanceScoreData = {}
this.scoreDataState = false
axios.get(this.scoreUrl, { params: this.getQueryParams() }).then(response => {
if (response.status === 200) {
const data = {
this.performanceScoreData = {
establishLatencyMs: _.get(response, 'data.data.result.establishLatencyMsAvg', null),
httpResponseLatency: _.get(response, 'data.data.result.httpResponseLatencyAvg', null),
sslConLatency: _.get(response, 'data.data.result.sslConLatencyAvg', null),
tcpLostlenPercent: _.get(response, 'data.data.result.tcpLostlenPercentAvg', null),
pktRetransPercent: _.get(response, 'data.data.result.pktRetransPercentAvg', null)
}
this.score = computeScore(data)
}
}).finally(() => {
this.loadingNetworkQuality = false
this.scoreDataState = true
})
},
/** 获取事件数量 */
@@ -251,6 +291,9 @@ export default {
}).finally(() => {
this.loadingEvent = false
})
},
handleScoreData () {
this.score = computeScore(this.performanceScoreData, this.$store.getters.getScoreBase)
}
},
watch: {
@@ -259,6 +302,16 @@ export default {
handler (n) {
this.initUrl()
}
},
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData()
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData()
}
}
},
mounted () {