mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-26 17:49:15 +01:00
added spider stats
This commit is contained in:
@@ -74,4 +74,8 @@ export default {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.el-table {
|
||||
min-height: 360px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -87,23 +87,9 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getIcon (type) {
|
||||
if (type === 1) {
|
||||
return 'fa-file-o'
|
||||
} else if (type === 2) {
|
||||
return 'fa-folder'
|
||||
}
|
||||
},
|
||||
onEdit () {
|
||||
this.isEdit = true
|
||||
},
|
||||
onChange (path) {
|
||||
this.$store.commit('file/SET_CURRENT_PATH', path)
|
||||
},
|
||||
onChangeSubmit () {
|
||||
this.isEdit = false
|
||||
this.$store.dispatch('file/getFileList', { path: this.currentPath })
|
||||
},
|
||||
onItemClick (item) {
|
||||
if (item.is_dir) {
|
||||
// 目录
|
||||
|
||||
@@ -13,24 +13,33 @@
|
||||
<status-tag :status="taskForm.status"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Log File Path')">
|
||||
<el-input v-model="taskForm.log_stdout_path" placeholder="Log File Path" disabled></el-input>
|
||||
<el-input v-model="taskForm.log_path" placeholder="Log File Path" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Create Timestamp')">
|
||||
<el-input v-model="taskForm.create_ts" placeholder="Create Timestamp" disabled></el-input>
|
||||
<el-form-item :label="$t('Create Time')">
|
||||
<el-input :value="getTime(taskForm.create_ts)" placeholder="Create Time" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Finish Timestamp')">
|
||||
<el-input v-model="taskForm.finish_ts" placeholder="Finish Timestamp" disabled></el-input>
|
||||
<el-form-item :label="$t('Start Time')">
|
||||
<el-input :value="getTime(taskForm.start_ts)" placeholder="Start Time" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Duration (sec)')">
|
||||
<el-input v-model="taskForm.duration" placeholder="Duration" disabled></el-input>
|
||||
<el-form-item :label="$t('Finish Time')">
|
||||
<el-input :value="getTime(taskForm.finish_ts)" placeholder="Finish Time" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Wait Duration (sec)')">
|
||||
<el-input :value="getWaitDuration(taskForm)" placeholder="Wait Duration" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Runtime Duration (sec)')">
|
||||
<el-input :value="getRuntimeDuration(taskForm)" placeholder="Runtime Duration" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Total Duration (sec)')">
|
||||
<el-input :value="getTotalDuration(taskForm)" placeholder="Runtime Duration" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Results Count')">
|
||||
<el-input v-model="taskForm.num_results" placeholder="Results Count" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Average Results Count per Second')">
|
||||
<el-input v-model="taskForm.avg_num_results" placeholder="Average Results Count per Second" disabled>
|
||||
</el-input>
|
||||
<el-input v-model="taskForm.result_count" placeholder="Results Count" disabled></el-input>
|
||||
</el-form-item>
|
||||
<!--<el-form-item :label="$t('Average Results Count per Second')">-->
|
||||
<!--<el-input v-model="taskForm.avg_num_results" placeholder="Average Results Count per Second" disabled>-->
|
||||
<!--</el-input>-->
|
||||
<!--</el-form-item>-->
|
||||
<el-form-item :label="$t('Error Message')" v-if="taskForm.status === 'error'">
|
||||
<div class="error-message">
|
||||
{{ taskForm.error }}
|
||||
@@ -50,6 +59,7 @@ import {
|
||||
mapState
|
||||
} from 'vuex'
|
||||
import StatusTag from '../Status/StatusTag'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
export default {
|
||||
name: 'NodeInfoView',
|
||||
@@ -70,6 +80,22 @@ export default {
|
||||
.then(() => {
|
||||
this.$message.success(`Task "${this.$route.params.id}" has been sent signal to stop`)
|
||||
})
|
||||
},
|
||||
getTime (str) {
|
||||
if (!str || str.match('^0001')) return 'NA'
|
||||
return dayjs(str).format('YYYY-MM-DD HH:mm:ss')
|
||||
},
|
||||
getWaitDuration (row) {
|
||||
if (row.start_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.start_ts).diff(row.create_ts, 'second')
|
||||
},
|
||||
getRuntimeDuration (row) {
|
||||
if (row.finish_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.finish_ts).diff(row.start_ts, 'second')
|
||||
},
|
||||
getTotalDuration (row) {
|
||||
if (row.finish_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.finish_ts).diff(row.create_ts, 'second')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,14 +100,14 @@ export default {
|
||||
if (this.masterNode.id === this.nodes[i].id) continue
|
||||
|
||||
// master
|
||||
links.push({
|
||||
source: this.masterNode.id,
|
||||
target: this.nodes[i].id,
|
||||
value: 0.5,
|
||||
lineStyle: {
|
||||
color: '#409EFF'
|
||||
}
|
||||
})
|
||||
// links.push({
|
||||
// source: this.masterNode.id,
|
||||
// target: this.nodes[i].id,
|
||||
// value: 0.5,
|
||||
// lineStyle: {
|
||||
// color: '#409EFF'
|
||||
// }
|
||||
// })
|
||||
}
|
||||
return links
|
||||
}
|
||||
@@ -120,6 +120,7 @@ export default {
|
||||
},
|
||||
tooltip: {
|
||||
formatter: params => {
|
||||
if (!params.data.name) return
|
||||
let str = '<span style="margin-right:5px;display:inline-block;height:12px;width:12px;border-radius:6px;background:' + params.color + '"></span>'
|
||||
if (params.data.name) str += '<span>' + params.data.name + '</span><br>'
|
||||
if (params.data.ip) str += '<span>IP: ' + params.data.ip + '</span><br>'
|
||||
|
||||
@@ -27,7 +27,6 @@ export default {
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
|
||||
@@ -17,20 +17,14 @@
|
||||
type="success"/>
|
||||
<metric-card :label="$t('Avg Duration (sec)')"
|
||||
icon="fa fa-hourglass"
|
||||
:value="getDecimal(overviewStats.avg_duration)"
|
||||
:value="getDecimal(overviewStats.avg_runtime_duration)"
|
||||
type="warning"/>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--./overall stats-->
|
||||
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-card class="chart-wrapper" style="margin-right: 20px;">
|
||||
<h4>{{$t('Tasks by Status')}}</h4>
|
||||
<div id="task-pie-status" class="chart"></div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<el-col :span="24">
|
||||
<el-card class="chart-wrapper">
|
||||
<h4>{{$t('Daily Tasks')}}</h4>
|
||||
<div id="task-line" class="chart"></div>
|
||||
@@ -39,13 +33,7 @@
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-card class="chart-wrapper" style="margin-right: 20px;">
|
||||
<h4>{{$t('Tasks by Node')}}</h4>
|
||||
<div id="task-pie-node" class="chart"></div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<el-col :span="24">
|
||||
<el-card class="chart-wrapper">
|
||||
<h4>{{$t('Daily Avg Duration (sec)')}}</h4>
|
||||
<div id="duration-line" class="chart"></div>
|
||||
@@ -71,64 +59,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
renderTaskPieStatus () {
|
||||
const chart = echarts.init(this.$el.querySelector('#task-pie-status'))
|
||||
const option = {
|
||||
tooltip: {
|
||||
show: true
|
||||
},
|
||||
series: [{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
// radius: ['50%', '70%'],
|
||||
data: this.statusStats.map(d => {
|
||||
let color
|
||||
if (d.name === 'SUCCESS') {
|
||||
color = '#67c23a'
|
||||
} else if (d.name === 'STARTED') {
|
||||
color = '#e6a23c'
|
||||
} else if (d.name === 'FAILURE') {
|
||||
color = '#f56c6c'
|
||||
} else {
|
||||
color = 'grey'
|
||||
}
|
||||
return {
|
||||
name: this.$t(d.name),
|
||||
value: d.value,
|
||||
itemStyle: {
|
||||
color
|
||||
}
|
||||
}
|
||||
})
|
||||
}]
|
||||
}
|
||||
chart.setOption(option)
|
||||
},
|
||||
|
||||
renderTaskPieNode () {
|
||||
const chart = echarts.init(this.$el.querySelector('#task-pie-node'))
|
||||
const option = {
|
||||
tooltip: {
|
||||
show: true
|
||||
},
|
||||
series: [{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
// radius: ['50%', '70%'],
|
||||
data: this.nodeStats.map(d => {
|
||||
return {
|
||||
name: d.name,
|
||||
value: d.value
|
||||
// itemStyle: {
|
||||
// color
|
||||
// }
|
||||
}
|
||||
})
|
||||
}]
|
||||
}
|
||||
chart.setOption(option)
|
||||
},
|
||||
|
||||
renderTaskLine () {
|
||||
const chart = echarts.init(this.$el.querySelector('#task-line'))
|
||||
const option = {
|
||||
@@ -145,7 +75,7 @@ export default {
|
||||
},
|
||||
series: [{
|
||||
type: 'line',
|
||||
data: this.dailyStats.map(d => d.count),
|
||||
data: this.dailyStats.map(d => d.task_count),
|
||||
areaStyle: {},
|
||||
smooth: true
|
||||
}],
|
||||
@@ -173,7 +103,7 @@ export default {
|
||||
},
|
||||
series: [{
|
||||
type: 'line',
|
||||
data: this.dailyStats.map(d => d.duration),
|
||||
data: this.dailyStats.map(d => d.avg_runtime_duration),
|
||||
areaStyle: {},
|
||||
smooth: true
|
||||
}],
|
||||
@@ -186,9 +116,7 @@ export default {
|
||||
},
|
||||
|
||||
render () {
|
||||
this.renderTaskPieStatus()
|
||||
this.renderTaskLine()
|
||||
this.renderTaskPieNode()
|
||||
this.renderDurationLine()
|
||||
},
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<h5 class="title">{{title}}</h5>
|
||||
<el-button type="success" plain class="small-btn" size="mini" icon="fa fa-refresh" @click="onRefresh"></el-button>
|
||||
</el-row>
|
||||
<el-table border height="480px" :data="taskList">
|
||||
<el-table border height="480px" :data="taskList" @row-click="onClickTask">
|
||||
<el-table-column property="node" :label="$t('Node')" width="120" align="left">
|
||||
<template slot-scope="scope">
|
||||
<a class="a-tag" @click="onClickNode(scope.row)">{{scope.row.node_name}}</a>
|
||||
@@ -15,6 +15,11 @@
|
||||
<a class="a-tag" @click="onClickSpider(scope.row)">{{scope.row.spider_name}}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column property="result_count" :label="$t('Results Count')" width="60" align="right">
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.result_count}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Status')"
|
||||
align="left"
|
||||
width="100">
|
||||
@@ -23,7 +28,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--<el-table-column property="create_ts" label="Create Time" width="auto" align="center"></el-table-column>-->
|
||||
<el-table-column property="create_ts" :label="$t('Create Time')" width="auto" align="left">
|
||||
<el-table-column property="create_ts" :label="$t('Create Time')" width="150" align="left">
|
||||
<template slot-scope="scope">
|
||||
<a href="javascript:" class="a-tag" @click="onClickTask(scope.row)">
|
||||
{{getTime(scope.row.create_ts).format('YYYY-MM-DD HH:mm:ss')}}
|
||||
@@ -48,7 +53,9 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
// setInterval handle
|
||||
handle: undefined
|
||||
handle: undefined,
|
||||
// 防抖
|
||||
clicked: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@@ -64,13 +71,21 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onClickSpider (row) {
|
||||
this.clicked = true
|
||||
setTimeout(() => {
|
||||
this.clicked = false
|
||||
}, 100)
|
||||
this.$router.push(`/spiders/${row.spider_id}`)
|
||||
},
|
||||
onClickNode (row) {
|
||||
this.clicked = true
|
||||
setTimeout(() => {
|
||||
this.clicked = false
|
||||
}, 100)
|
||||
this.$router.push(`/nodes/${row.node_id}`)
|
||||
},
|
||||
onClickTask (row) {
|
||||
this.$router.push(`/tasks/${row._id}`)
|
||||
if (!this.clicked) this.$router.push(`/tasks/${row._id}`)
|
||||
},
|
||||
onRefresh () {
|
||||
if (this.$route.path.split('/')[1] === 'spiders') {
|
||||
@@ -114,4 +129,8 @@ export default {
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.el-table >>> tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user