blob: a5d01e5204dde861043ea4fceb7af5a2db28fc63 [file] [log] [blame]
<!--
Copyright (c) 2020 Contributors to the Eclipse Foundation
See the NOTICE file(s) distributed with this work for additional
information regarding copyright ownership.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License 2.0 which is available at
http://www.eclipse.org/legal/epl-2.0
SPDX-License-Identifier: EPL-2.0
-->
<template>
<div style="height: 100%; position: relative">
<el-collapse v-if="useful" v-model="activeNames" style="width: 100%">
<el-collapse-item v-loading="loading" :title='$t("jifa.heap.overview")' name="0">
<div style="position: relative;">
<div style="position: absolute; top: 30px; left: 30px;" v-html="descOfSelectedSlice"></div>
<div>
<doughnut-chart :chart-data="chartData" :options="chartOptions"></doughnut-chart>
</div>
</div>
</el-collapse-item>
<el-collapse-item v-for="(record) in records" v-bind:key="record.name" :title="record.name" :name="record.name">
<el-tabs tab-position="left">
<el-tab-pane :label="$t('jifa.heap.description')">
<div v-html="record.desc"></div>
</el-tab-pane>
<el-tab-pane v-if="record.paths" :label="$t('jifa.heap.detail')">
<el-tree
:data="record.paths"
node-key="objectId"
>
<span class="custom-tree-node" style="font-size: 12px" slot-scope="{ node, data }"
@click="$emit('setSelectedObjectId', data.objectId)">
<span>
<img :src="getIcon(data.gCRoot, data.objectType)" style="margin-right: 5px"/>
{{ data.label }}
</span>
<span>
{{ data.shallowSize }} / {{ data.retainedSize }}
</span>
</span>
</el-tree>
</el-tab-pane>
</el-tabs>
</el-collapse-item>
</el-collapse>
</div>
</template>
<script>
import axios from 'axios'
import DoughnutChart from '../charts/DoughnutChart'
import {heapDumpService} from '../../util'
import {a2rgb, PIE_COLORS, REMAINDER_COLOR} from "./ColorHelper";
import {getIcon} from "./IconHealper"
export default {
props: ['file'],
components: {
DoughnutChart
},
methods: {
getIcon,
clickPie(event, elements) {
if (elements.length > 0) {
let index = elements[0]._index
this.descOfSelectedSlice = this.slices[index].desc
this.$emit("setSelectedObjectId", this.slices[index].objectId)
} else {
this.descOfSelectedSlice = null
}
},
fetchReport() {
this.loading = true
axios.get(heapDumpService(this.file, 'leak/report')).then(resp => {
this.useful = resp.data.useful
if (this.useful) {
this.slices = resp.data.slices
let labels = []
let data = []
for (let i = 0; i < this.slices.length; i++) {
labels.push(this.slices[i].label)
data.push(this.slices[i].value)
}
let color = []
let len = this.slices.length
for (let i = 0; i < len - 1; i++) {
color.push(a2rgb(PIE_COLORS[i % PIE_COLORS.length]))
}
if (this.slices[len - 1].objectId === -1
|| this.slices[len - 1].label === 'Remainder') {
color.push(a2rgb(REMAINDER_COLOR))
} else {
color.push(a2rgb((len - 1) % PIE_COLORS.length))
}
this.chartData = {
labels: labels,
datasets: [
{
backgroundColor: color,
data: data,
}
]
}
this.records = resp.data.records
this.records.forEach(
r => {
this.activeNames.push(r.name)
}
)
}
this.loading = false
})
}
},
data() {
return {
activeNames: ['0'],
loading: false,
chartData: {},
chartOptions: {
legend: false,
responsive: true,
maintainAspectRatio: false,
pieceLabel: {
mode: 'percentage',
precision: 1
},
animation: {
// animateScale: true,
// easing: 'linear'
},
onClick: this.clickPie
},
useful: true,
slices: null,
descOfSelectedSlice: null,
records: null,
}
},
created() {
this.fetchReport()
}
}
</script>
<style scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
</style>