added dashboard

pull/1/head
Doflatango 8 years ago committed by miraclesu
parent 0aa957715f
commit f33843e0ff

@ -12,6 +12,7 @@ import (
const (
Coll_JobLog = "job_log"
Coll_JobLatestLog = "job_latest_log"
Coll_Stat = "stat"
)
// 任务执行记录
@ -108,4 +109,36 @@ func CreateJobLog(j *Job, t time.Time, rs string, success bool) {
if err := mgoDB.Upsert(Coll_JobLatestLog, bson.M{"node": jl.Node, "jobId": jl.JobId, "jobGroup": jl.JobGroup}, latestLog); err != nil {
log.Error(err.Error())
}
var inc = bson.M{"total": 1}
if jl.Success {
inc["successed"] = 1
} else {
inc["failed"] = 1
}
err := mgoDB.Upsert(Coll_Stat, bson.M{"name": "job-day", "date": time.Now().Format("2006-01-02")}, bson.M{"$inc": inc})
if err != nil {
log.Error("increase stat.job ", err.Error())
}
err = mgoDB.Upsert(Coll_Stat, bson.M{"name": "job"}, bson.M{"$inc": inc})
if err != nil {
log.Error("increase stat.job ", err.Error())
}
}
type StatExecuted struct {
Total int64 `bson:"total" json:"total"`
Successed int64 `bson:"successed" json:"successed"`
Failed int64 `bson:"failed" json:"failed"`
}
func JobLogStat() (s *StatExecuted, err error) {
err = mgoDB.One(Coll_Stat, bson.M{"name": "job"}, &s)
return
}
func JobLogDayStat(day time.Time) (s *StatExecuted, err error) {
err = mgoDB.One(Coll_Stat, bson.M{"name": "job-day", "date": day.Format("2006-01-02")}, &s)
return
}

@ -0,0 +1,31 @@
package web
import (
"net/http"
"time"
v3 "github.com/coreos/etcd/clientv3"
"sunteng/cronsun/conf"
"sunteng/cronsun/models"
)
type Info struct{}
func (inf *Info) Overview(w http.ResponseWriter, r *http.Request) {
var overview = struct {
TotalJobs int64 `json:"totalJobs"`
JobExecuted *models.StatExecuted `json:"jobExecuted"`
JobExecutedDaily *models.StatExecuted `json:"jobExecutedDaily"`
}{}
overview.JobExecuted, _ = models.JobLogStat()
overview.JobExecutedDaily, _ = models.JobLogDayStat(time.Now())
gresp, err := models.DefalutClient.Get(conf.Config.Cmd, v3.WithPrefix(), v3.WithCountOnly())
if err == nil {
overview.TotalJobs = gresp.Count
}
outJSON(w, overview)
}

@ -13,6 +13,7 @@ func InitRouters() (s *http.Server, err error) {
jobHandler := &Job{}
nodeHandler := &Node{}
jobLogHandler := &JobLog{}
infoHandler := &Info{}
r := mux.NewRouter()
subrouter := r.PathPrefix("/v1").Subrouter()
@ -58,6 +59,9 @@ func InitRouters() (s *http.Server, err error) {
h = BaseHandler{Handle: nodeHandler.DeleteGroup}
subrouter.Handle("/node/group/{id}", h).Methods("DELETE")
h = BaseHandler{Handle: infoHandler.Overview}
subrouter.Handle("/info/overview", h).Methods("GET")
uidir := conf.Config.Web.UIDir
if len(uidir) == 0 {
uidir = path.Join("web", "ui", "dist")

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -10,6 +10,7 @@
"private": true,
"author": "heshitan@sunteng.com",
"dependencies": {
"chart.js": "^2.5.0",
"jquery": "^3.1.1",
"semantic-ui": "^2.2.7",
"vue": "^2.1.0",

@ -1,9 +1,146 @@
<style scope>
#numbers {padding-bottom: 30px;}
#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>dash</div>
<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">{{totalJobs}}</div>
<div class="header title">任务总数</div>
</div>
</div>
</div>
<div class="column">
<div class="ui fluid card">
<div class="content">
<div class="header number">{{totalExecuted}}</div>
<div class="header title">执行任务总次数</div>
</div>
</div>
</div>
<div class="column">
<div class="ui fluid card">
<div class="content">
<div class="header number">{{todayExecuted}}</div>
<div class="header title">今日执行任务次数</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">节点总数</div>
</div>
</div>
</div>
</div>
</div>
<div id="charts">
<div class="ui card">
<div class="content">
<h4 class="header">当前节点状态</h4>
<div class="description">
<canvas ref="node"></canvas>
</div>
</div>
</div>
<div class="ui card">
<div class="content">
<h4 class="header">今日任务概况</h4>
<div class="description">
<canvas ref="job"></canvas>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Chart from 'charts';
export default {
name: 'dash'
name: 'dash',
data(){
return {
totalJobs: 0,
totalExecuted: 0,
todayExecuted: 0,
totalNodes: 0
}
},
mounted(){
var vm = this;
var renderJobInfo = function(resp){
vm.totalJobs = resp.totalJobs;
vm.totalExecuted = resp.jobExecuted.total;
vm.todayExecuted = resp.jobExecutedDaily.total;
new Chart($(vm.$refs.job), {
type: 'pie',
data: {
labels: ["成功", "失败"],
datasets: [{
data: [resp.jobExecuted.successed, resp.jobExecuted.failed],
backgroundColor: ["#21BA45", "#333", "#DB2828"],
hoverBackgroundColor: ["#39DE60", "#555", "#D64848"]
}]
}
});
}
var renderNodeInfo = function(resp){
vm.totalNodes = resp.length;
var online = 0;
var offline = 0;
var damaged = 0;
for (var i in resp) {
if (resp[i].alived && resp[i].connected) {
online++;
} else if (resp[i].alived && !resp[i].connected) {
damaged++;
} else if(!resp[i].alived) {
offline++;
}
}
new Chart($(vm.$refs.node), {
type: 'pie',
data: {
labels: ["在线", "离线", "故障"],
datasets: [{
data: [online, offline, damaged],
backgroundColor: ["#21BA45", "#333", "#DB2828"],
hoverBackgroundColor: ["#39DE60", "#555", "#D64848"]
}]
}
});
}
this.$rest.GET('/info/overview').onsucceed(200, renderJobInfo).do();
this.$rest.GET('nodes').onsucceed(200, renderNodeInfo).do();
}
}
</script>

@ -25,7 +25,7 @@
<input type="date" v-model="end">
</div>
</div>
<div class="fields">
<div class="two fields">
<div class="filed">
<div ref="latest" class="ui checkbox">
<input type="checkbox" class="hidden" v-model="latest">

@ -48,7 +48,8 @@ module.exports = {
alias: {
'vue$': 'vue/dist/vue.common.js',
'semantic$': 'semantic-ui/dist/semantic.min.js',
'semanticcss$': 'semantic-ui/dist/semantic.min.css'
'semanticcss$': 'semantic-ui/dist/semantic.min.css',
'charts$': 'chart.js/dist/Chart.min.js'
}
},
devServer: {

Loading…
Cancel
Save