mirror of https://github.com/shunfei/cronsun
Add line chart in Dash page to display job executeds in past 7 days
parent
ed8ec6093e
commit
4e6e5a191e
25
job_log.go
25
job_log.go
|
@ -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
|
||||
}
|
||||
|
|
39
web/info.go
39
web/info.go
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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': '多个名称用英文逗号分隔',
|
||||
|
|
Loading…
Reference in New Issue