Add line chart in Dash page to display job executeds in past 7 days

pull/49/head
Doflatango 2017-12-12 15:38:34 +08:00
parent ed8ec6093e
commit 4e6e5a191e
5 changed files with 131 additions and 97 deletions

View File

@ -146,9 +146,10 @@ func CreateJobLog(j *Job, t time.Time, rs string, success bool) {
}
type StatExecuted struct {
Total int64 `bson:"total" json:"total"`
Successed int64 `bson:"successed" json:"successed"`
Failed int64 `bson:"failed" json:"failed"`
Total int64 `bson:"total" json:"total"`
Successed int64 `bson:"successed" json:"successed"`
Failed int64 `bson:"failed" json:"failed"`
Date string `bson:"date" json:"date"`
}
func JobLogStat() (s *StatExecuted, err error) {
@ -156,7 +157,21 @@ func JobLogStat() (s *StatExecuted, err error) {
return
}
func JobLogDayStat(day time.Time) (s *StatExecuted, err error) {
err = mgoDB.FindOne(Coll_Stat, bson.M{"name": "job-day", "date": day.Format("2006-01-02")}, &s)
func JobLogDailyStat(begin, end time.Time) (ls []*StatExecuted, err error) {
const oneDay = time.Hour * 24
err = mgoDB.WithC(Coll_Stat, func(c *mgo.Collection) error {
dateList := make([]string, 0, 8)
cur := begin
for {
dateList = append(dateList, cur.Format("2006-01-02"))
cur = cur.Add(oneDay)
if cur.After(end) {
break
}
}
return c.Find(bson.M{"name": "job-day", "date": bson.M{"$in": dateList}}).Sort("date").All(&ls)
})
return
}

View File

@ -13,14 +13,43 @@ type Info struct{}
func (inf *Info) Overview(ctx *Context) {
var overview = struct {
TotalJobs int64 `json:"totalJobs"`
JobExecuted *cronsun.StatExecuted `json:"jobExecuted"`
JobExecutedDaily *cronsun.StatExecuted `json:"jobExecutedDaily"`
TotalJobs int64 `json:"totalJobs"`
JobExecuted *cronsun.StatExecuted `json:"jobExecuted"`
JobExecutedDaily []*cronsun.StatExecuted `json:"jobExecutedDaily"`
}{}
overview.JobExecuted, _ = cronsun.JobLogStat()
overview.JobExecutedDaily, _ = cronsun.JobLogDayStat(time.Now())
const day = 24 * time.Hour
days := 7
overview.JobExecuted, _ = cronsun.JobLogStat()
end := time.Now()
begin := end.Add(time.Duration(1-days) * day)
statList, _ := cronsun.JobLogDailyStat(begin, end)
list := make([]*cronsun.StatExecuted, days)
cur := begin
for i := 0; i < days; i++ {
date := cur.Format("2006-01-02")
var se *cronsun.StatExecuted
for j := range statList {
if statList[j].Date == date {
se = statList[j]
statList = statList[1:]
break
}
}
if se != nil {
list[i] = se
} else {
list[i] = &cronsun.StatExecuted{Date: date}
}
cur = cur.Add(day)
}
overview.JobExecutedDaily = list
gresp, err := cronsun.DefalutClient.Get(conf.Config.Cmd, v3.WithPrefix(), v3.WithCountOnly())
if err == nil {
overview.TotalJobs = gresp.Count

View File

@ -3,21 +3,24 @@
#numbers .card .header {text-align: center;}
#numbers .card .number {font-size: 2em;}
#numbers .card .title {font-size: 1em;}
#charts>div {
width: 300px;
display: inline-block;
margin: 0 1em;
border: none;
box-shadow: none;
}
#charts .header {text-align: center;}
</style>
<template>
<div>
<div id="numbers" class="ui three column grid">
<div class="row">
<div class="column">
<div class="ui fluid card">
<div class="content">
<div class="header number">
<span style="color:green;">{{totalOnlineNodes}}</span>/
<span>{{totalOfflineNodes}}</span>/
<span style="color:red;">{{totalDamagedNodes}}</span>
</div>
<div class="header title">{{$L('total number of nodes')}}</div>
</div>
</div>
</div>
<div class="column">
<div class="ui fluid card">
<div class="content">
@ -34,45 +37,11 @@
</div>
</div>
</div>
<div class="column">
<div class="ui fluid card">
<div class="content">
<div class="header number">{{todayExecuted}}</div>
<div class="header title">{{$L('total number of executeds(today)')}}</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui fluid card">
<div class="content">
<div class="header number">{{totalNodes}}</div>
<div class="header title">{{$L('total number of nodes')}}</div>
</div>
</div>
</div>
</div>
</div>
<div id="charts">
<div class="ui card">
<div class="content">
<h4 class="header"><router-link to="node">{{$L('node stat')}}</router-link></h4>
<div class="description">
<canvas ref="node"></canvas>
</div>
</div>
</div>
<div class="ui card">
<div class="content">
<h4 class="header"><router-link :to="'log?begin='+today+'&end='+today">{{$L('executed stat(today)')}}</router-link></h4>
<div class="description">
<canvas ref="job"></canvas>
</div>
</div>
</div>
<canvas ref="daily" height="80"></canvas>
</div>
</div>
</template>
@ -87,8 +56,9 @@ export default {
return {
totalJobs: 0,
totalExecuted: 0,
todayExecuted: 0,
totalNodes: 0,
totalOnlineNodes: 0,
totalOfflineNodes: 0,
totalDamagedNodes: 0,
today: ''
}
@ -102,20 +72,62 @@ export default {
var renderJobInfo = function(resp){
vm.totalJobs = resp.totalJobs;
vm.totalExecuted = resp.jobExecuted ? resp.jobExecuted.total : 0;
vm.todayExecuted = resp.jobExecutedDaily ? resp.jobExecutedDaily.total : 0;
var dailySuccessed = resp.jobExecutedDaily ? resp.jobExecutedDaily.successed : 0;
var dailytotal = resp.jobExecutedDaily ? resp.jobExecutedDaily.total : 0;
new Chart($(vm.$refs.job), {
type: 'pie',
data: {
labels: [vm.$L("{n} successed", dailySuccessed), vm.$L("{n} failed", dailytotal-dailySuccessed)],
datasets: [{
data: [dailySuccessed, dailytotal - dailySuccessed],
backgroundColor: ["#21BA45", "#DB2828"],
hoverBackgroundColor: ["#39DE60", "#D64848"]
}]
var data = {
labels: [],
datasets: [{
label: vm.$L('successed'),
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgb(75, 192, 192)',
fill: false,
yAxisID: 'yAxisSuccessed',
data: []
}, {
label: vm.$L('failed'),
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgb(255, 99, 132)',
fill: false,
yAxisID: 'yAxisFailed',
data: []
}]
};
for (var i in resp.jobExecutedDaily) {
var info = resp.jobExecutedDaily[i];
data.labels.push(info.date),
data.datasets[0].data.push(info.successed);
data.datasets[1].data.push(info.failed);
}
var ctx = vm.$refs.daily.getContext('2d');
var chart = Chart.Line(ctx, {
data: data,
options: {
responsive: true,
hoverMode: 'index',
stacked: false,
title:{
display: true,
text: vm.$L('job executed in past 7 days')
},
scales: {
yAxes: [{
type: 'linear',
display: true,
position: 'left',
id: 'yAxisSuccessed'
}, {
type: 'linear',
display: true,
position: 'right',
id: 'yAxisFailed',
gridLines: {
drawOnChartArea: false
}
}],
}
}
});
chart.update();
}
var renderNodeInfo = function(resp){
@ -132,22 +144,14 @@ export default {
offline++;
}
}
new Chart($(vm.$refs.node), {
type: 'pie',
data: {
labels: [vm.$L("{n} online", online), vm.$L("{n} offline", offline), vm.$L("{n} damaged", damaged)],
datasets: [{
data: [online, offline, damaged],
backgroundColor: ["#21BA45", "#333", "#DB2828"],
hoverBackgroundColor: ["#39DE60", "#555", "#D64848"]
}]
}
});
vm.totalOnlineNodes = online;
vm.totalOfflineNodes = offline;
vm.totalDamagedNodes = damaged;
}
this.$rest.GET('/info/overview').onsucceed(200, renderJobInfo).do();
this.$rest.GET('nodes').onsucceed(200, renderNodeInfo).do();
}
}
</script>
</script>

View File

@ -22,15 +22,8 @@ var language = {
'account': 'Account',
'total number of jobs': 'Total jobs',
'total number of executeds': 'Total executeds',
'total number of executeds(today)': 'Total executeds(today)',
'total number of nodes': 'Total nodes',
'{n} online': '{0} online',
'{n} offline': '{0} offline',
'{n} damaged': '{0} damaged',
'{n} successed': '{0} successed',
'{n} failed': '{0} failed',
'node stat': 'Node Stat',
'executed stat(today)': 'Executed Stat(today)',
'job executed in past 7 days': 'Job executed in past 7 days',
'job name': 'Job name',
'multiple names can separated by commas': 'Multiple names can separated by commas',

View File

@ -22,15 +22,8 @@ var language = {
'account': '账号',
'total number of jobs': '任务总数',
'total number of executeds': '执行任务总次数',
'total number of executeds(today)': '执行任务总次数(今天)',
'total number of nodes': '节点总数',
'{n} online': '在线 {0}',
'{n} offline': '离线 {0}',
'{n} damaged': '故障 {0}',
'{n} successed': '成功 {0}',
'{n} failed': '失败 {0}',
'node stat': '节点概况',
'executed stat(today)': '执行概况(今天)',
'job executed in past 7 days': '过去 7 天任务统计',
'job name': '任务名称',
'multiple names can separated by commas': '多个名称用英文逗号分隔',