|
@@ -4,13 +4,14 @@
|
|
|
|
|
|
<script>
|
|
|
import resize from '@/components/Charts/mixins/resize'
|
|
|
-// import chartResdata from './data.js'
|
|
|
-import { getFlameData } from '@/api/trace'
|
|
|
+// import { getFlameData } from '@/api/trace'
|
|
|
export default {
|
|
|
mixins: [resize],
|
|
|
data() {
|
|
|
return {
|
|
|
- chart: null
|
|
|
+ chart: null,
|
|
|
+ apis:require("../../../assets/apis.jpg"),
|
|
|
+ apm:require("../../../assets/apm.jpg"),
|
|
|
}
|
|
|
},
|
|
|
props: ['tractID'],
|
|
@@ -31,55 +32,7 @@ export default {
|
|
|
this.chart = this.$echarts5.init(document.getElementById('flameGraphContent'))
|
|
|
|
|
|
var option;
|
|
|
- const renderItem = (params, api) => {
|
|
|
- const level = api.value(0);
|
|
|
- const start = api.coord([api.value(1), level]);
|
|
|
- const end = api.coord([api.value(2), level]);
|
|
|
- const height = ((api.size && api.size([0, 1])) || [0, 20])[1];
|
|
|
- const width = end[0] - start[0];
|
|
|
- const ProcessName = '进程名称'
|
|
|
- const CollectionEquipment = '采集设备'
|
|
|
- const CollectionName = ` ${api.value(6) == 'syscall' ? ProcessName+':'+api.value(5)|| '':(api.value(6) == 'network'?CollectionEquipment+':'+api.value(5)|| '' : '')}`
|
|
|
- return {
|
|
|
- type: 'rect',
|
|
|
- transition: ['shape'],
|
|
|
- shape: {
|
|
|
- x: start[0],
|
|
|
- y: start[1] - height / 2,
|
|
|
- width,
|
|
|
- height: height - 2 /* itemGap */,
|
|
|
- r: 2
|
|
|
- },
|
|
|
- style: {
|
|
|
- fill: api.visual('color')
|
|
|
- },
|
|
|
- emphasis: {
|
|
|
- style: {
|
|
|
- stroke: '#000'
|
|
|
- }
|
|
|
- },
|
|
|
- textConfig: {
|
|
|
- position: 'insideLeft'
|
|
|
- },
|
|
|
- textContent: {
|
|
|
- style: {
|
|
|
- text: `${api.value(3)} 耗时:${api.value(7)}ms${CollectionName}`,
|
|
|
- fontFamily: 'Verdana',
|
|
|
- fill: '#000',
|
|
|
- width: width - 4,
|
|
|
- overflow: 'truncate',
|
|
|
- ellipsis: '..',
|
|
|
- truncateMinChar: 1
|
|
|
- },
|
|
|
- emphasis: {
|
|
|
- style: {
|
|
|
- stroke: '#000',
|
|
|
- lineWidth: 0.5
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- };
|
|
|
+
|
|
|
this.chart.showLoading();
|
|
|
let para = {
|
|
|
'trace_id': this.tractID
|
|
@@ -93,8 +46,8 @@ export default {
|
|
|
if (res && res.status == 200) {
|
|
|
this.chart.hideLoading();
|
|
|
const chartResdata = res.data.OPT_STATUS // OPT_STATUS这个对象就是根节点
|
|
|
-
|
|
|
const levelOfOriginalJson = this.heightOfJson(chartResdata);
|
|
|
+ let seriesData = this.setSeries(this.recursionJson(chartResdata))
|
|
|
option = {
|
|
|
backgroundColor: {
|
|
|
type: 'linear',
|
|
@@ -114,29 +67,18 @@ export default {
|
|
|
]
|
|
|
},
|
|
|
tooltip: {
|
|
|
+ className: 'custom-tooltip-box',
|
|
|
formatter: (params) => {
|
|
|
- const samples = params.value[2] - params.value[1];
|
|
|
let res = `${params.marker} ${
|
|
|
params.value[3]
|
|
|
}<br/>${params.marker} 耗时: ${params.value[7]}<br/>${params.marker} 比例: ${+params.value[4].toFixed(2)}%<br/>`
|
|
|
for (const key in params.data.detail) {
|
|
|
res+=`${params.marker} ${key}: ${params.data.detail[key] || '--'}<br/>`
|
|
|
}
|
|
|
+ res+=`<div style='position:absolute;bottom:10px;right:10px;width:80px;height:80px;z-index: -1;backdrop-filter: blur(10px);background-image:url("${params.value[6] =='apm'?this.apm:this.apis}");background-size:cover;background-repeat:no-repeat;background-position: center;'></div>`
|
|
|
return res;
|
|
|
}
|
|
|
},
|
|
|
- title: [
|
|
|
- // {
|
|
|
- // text: 'Flame Graph',
|
|
|
- // left: 'center',
|
|
|
- // top: 10,
|
|
|
- // textStyle: {
|
|
|
- // fontFamily: 'Verdana',
|
|
|
- // fontWeight: 'normal',
|
|
|
- // fontSize: 20
|
|
|
- // }
|
|
|
- // }
|
|
|
- ],
|
|
|
toolbox: {
|
|
|
feature: {
|
|
|
restore: {}
|
|
@@ -152,32 +94,15 @@ export default {
|
|
|
max: levelOfOriginalJson
|
|
|
},
|
|
|
series: [
|
|
|
- {
|
|
|
- type: 'custom',
|
|
|
- // name: this.formatCategoryData(chartResdata),
|
|
|
- renderItem,
|
|
|
- encode: {
|
|
|
- x: [0, 1, 2],
|
|
|
- y: 0
|
|
|
- },
|
|
|
- data: this.recursionJson(chartResdata)
|
|
|
- }
|
|
|
- // ...dataList.map(function (data, index) {
|
|
|
- // return {
|
|
|
- // type: 'bar',
|
|
|
- // animation: false,
|
|
|
- // name: legendData[index + 1],
|
|
|
- // itemStyle: {
|
|
|
- // opacity: 0.5
|
|
|
- // },
|
|
|
- // data: data
|
|
|
- // };
|
|
|
- // })
|
|
|
- ]
|
|
|
- // legend: {
|
|
|
- // show:true,
|
|
|
- // data: this.formatCategoryData(chartResdata)
|
|
|
- // }
|
|
|
+ ...seriesData
|
|
|
+ ],
|
|
|
+ color: ['#f2d643', '#eb8146', '#ffb248', '#d95850'], // 图例的颜色
|
|
|
+ legend: {
|
|
|
+ show:true,
|
|
|
+ // data: this.formatCategoryData(chartResdata),
|
|
|
+ data: ['apm', 'syscall', 'network', 'unknown']
|
|
|
+ }
|
|
|
+
|
|
|
};
|
|
|
this.chart.setOption(option);
|
|
|
this.chart.on('click', (params) => {
|
|
@@ -192,6 +117,75 @@ export default {
|
|
|
})
|
|
|
|
|
|
},
|
|
|
+ setSeries(chartResdata){
|
|
|
+ const renderItem = (params, api) => {
|
|
|
+ const level = api.value(0);
|
|
|
+ const start = api.coord([api.value(1), level]);
|
|
|
+ const end = api.coord([api.value(2), level]);
|
|
|
+ const height = ((api.size && api.size([0, 1])) || [0, 20])[1];
|
|
|
+ const width = end[0] - start[0];
|
|
|
+ const ProcessName = '进程名称'
|
|
|
+ const CollectionEquipment = '采集设备'
|
|
|
+ const CollectionName = ` ${api.value(6) == 'syscall' ? ProcessName+':'+api.value(5)|| '':(api.value(6) == 'network'?CollectionEquipment+':'+api.value(5)|| '' : '')}`
|
|
|
+ return {
|
|
|
+ type: 'rect',
|
|
|
+ transition: ['shape'],
|
|
|
+ shape: {
|
|
|
+ x: start[0],
|
|
|
+ y: start[1] - height / 2,
|
|
|
+ width,
|
|
|
+ height: height - 2 /* itemGap */,
|
|
|
+ r: 2
|
|
|
+ },
|
|
|
+ style: {
|
|
|
+ fill: api.visual('color')
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ style: {
|
|
|
+ stroke: '#000'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ textConfig: {
|
|
|
+ position: 'insideLeft'
|
|
|
+ },
|
|
|
+ textContent: {
|
|
|
+ style: {
|
|
|
+ text: `${api.value(3)} 耗时:${api.value(7)}ms${CollectionName}`,
|
|
|
+ fontFamily: 'Verdana',
|
|
|
+ fill: '#000',
|
|
|
+ width: width - 4,
|
|
|
+ overflow: 'truncate',
|
|
|
+ ellipsis: '..',
|
|
|
+ truncateMinChar: 1
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ style: {
|
|
|
+ stroke: '#000',
|
|
|
+ lineWidth: 0.5
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ };
|
|
|
+ let res = []
|
|
|
+ chartResdata.forEach(item=>{
|
|
|
+ if (item){
|
|
|
+ let obj = {
|
|
|
+ type: 'custom',
|
|
|
+ name:item?.value[6] || '',
|
|
|
+ renderItem,
|
|
|
+ encode: {
|
|
|
+ x: [0, 1, 2],
|
|
|
+ y: 0
|
|
|
+ },
|
|
|
+ data: [item]
|
|
|
+ }
|
|
|
+ res.push(obj)
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ return res
|
|
|
+ },
|
|
|
filterJson(json, id) {
|
|
|
if (id == null) {
|
|
|
return json;
|
|
@@ -201,12 +195,15 @@ export default {
|
|
|
return item;
|
|
|
}
|
|
|
for (const child of item.children || []) {
|
|
|
- const temp = recur(child, id);
|
|
|
- if (temp) {
|
|
|
- item.children = [temp];
|
|
|
- item.value = temp.duration; // change the parents' values
|
|
|
- return item;
|
|
|
+ if (item.children.length > 0){
|
|
|
+ const temp = recur(child, id);
|
|
|
+ if (temp) {
|
|
|
+ item.children = [temp];
|
|
|
+ item.value = temp.duration; // change the parents' values
|
|
|
+ return item;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
};
|
|
|
return recur(json, id) || json;
|
|
@@ -215,7 +212,7 @@ export default {
|
|
|
const data = [];
|
|
|
const ColorTypes = {
|
|
|
root:'#8fd3e8',
|
|
|
- apm: '#b5c334',
|
|
|
+ apm: '#f2d643',
|
|
|
syscall: '#eb8146',
|
|
|
network: '#ffb248',
|
|
|
unknown:'#d95850'
|
|
@@ -228,7 +225,7 @@ export default {
|
|
|
const CollectionEquipment = '采集设备'
|
|
|
const collectionName = `${item.span_category == 'syscall' ? item.detail[ProcessName]|| '': (item.span_category == 'network'?item.detail[CollectionEquipment] || '' : '')}`
|
|
|
const temp = {
|
|
|
- name: item.id,
|
|
|
+ name: item?.id,
|
|
|
value: [
|
|
|
level,
|
|
|
start,
|
|
@@ -262,12 +259,14 @@ export default {
|
|
|
const data = [];
|
|
|
const filteredJson = this.filterJson(structuredClone(jsonObj), id);
|
|
|
const recur = (item) => {
|
|
|
- if(item){
|
|
|
- data.push(item.span_category);
|
|
|
- }
|
|
|
- if(item) {
|
|
|
+ // console.log('item-=======23421342342====', item, data)
|
|
|
+ if(item !== null && item !== undefined && Object.keys(item).length > 0){
|
|
|
+ // console.log('data----', item)
|
|
|
+ data.push(item?.span_category);
|
|
|
for (const child of item.children || []) {
|
|
|
- recur(child);
|
|
|
+ if(item.children.length > 0){
|
|
|
+ recur(child);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -288,9 +287,7 @@ export default {
|
|
|
return maxLevel;
|
|
|
};
|
|
|
return recur(json);
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
@@ -299,4 +296,8 @@ export default {
|
|
|
width: 100%;
|
|
|
height: calc(100vh - 200px);
|
|
|
}
|
|
|
+::v-deep .custom-tooltip-box{
|
|
|
+ background-color: rgba(0, 0, 0, 0.6) !important;
|
|
|
+ color:white !important;
|
|
|
+}
|
|
|
</style>
|