Finish the dashboard summary things.
This commit is contained in:
parent
439d23df2d
commit
2d1a95594f
@ -46,17 +46,17 @@ func (this *Context) Init() {
|
||||
this.Router = NewRouter()
|
||||
}
|
||||
|
||||
|
||||
func (this *Context) OpenDb() {
|
||||
|
||||
var err error = nil
|
||||
this.DB, err = gorm.Open("mysql", CONFIG.MysqlUrl)
|
||||
|
||||
//是否打开sql日志
|
||||
this.DB.LogMode(false)
|
||||
if err != nil {
|
||||
panic("failed to connect mysql database")
|
||||
LOGGER.Panic("failed to connect mysql database")
|
||||
}
|
||||
|
||||
//是否打开sql日志(在调试阶段可以打开,以方便查看执行的SQL)
|
||||
this.DB.LogMode(false)
|
||||
}
|
||||
|
||||
func (this *Context) CloseDb() {
|
||||
@ -91,8 +91,7 @@ func (this *Context) registerBean(bean IBean) {
|
||||
}
|
||||
|
||||
} else {
|
||||
err := fmt.Sprintf("注册的【%s】不是Bean类型。", typeName)
|
||||
panic(err)
|
||||
LOGGER.Panic("注册的【%s】不是Bean类型。", typeName)
|
||||
}
|
||||
|
||||
}
|
||||
@ -154,8 +153,8 @@ func (this *Context) GetBean(bean IBean) IBean {
|
||||
if val, ok := this.BeanMap[typeName]; ok {
|
||||
return val
|
||||
} else {
|
||||
err := fmt.Sprintf("【%s】没有注册。", typeName)
|
||||
panic(err)
|
||||
LOGGER.Panic("【%s】没有注册。", typeName)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,6 @@ func (this *DashboardController) RegisterRoutes() map[string]func(writer http.Re
|
||||
//过去七天分时调用量
|
||||
func (this *DashboardController) InvokeList(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
return this.Success(this.dashboardDao.InvokeList())
|
||||
return this.Success("")
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package rest
|
||||
|
||||
import (
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"github.com/nu7hatch/gouuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -9,47 +10,46 @@ type DashboardDao struct {
|
||||
BaseDao
|
||||
}
|
||||
|
||||
//过去七天调用量
|
||||
func (this *DashboardDao) InvokeList() []*DashboardInvoke {
|
||||
//创建
|
||||
func (this *DashboardDao) Create(dashboard *Dashboard) *Dashboard {
|
||||
|
||||
//过去几天
|
||||
var dayNum = 15;
|
||||
var tableName = Footprint{}.TableName()
|
||||
now := time.Now()
|
||||
startDate := now.AddDate(0, 0, 1-dayNum)
|
||||
rows, err := CONTEXT.DB.Raw("SELECT COUNT(uuid) AS invoke_num,COUNT(DISTINCT(ip)) AS uv,dt FROM "+tableName+" WHERE dt>= ? AND dt <= ? GROUP BY dt",
|
||||
ConvertTimeToDateString(startDate),
|
||||
ConvertTimeToDateString(now)).Rows()
|
||||
this.PanicError(err)
|
||||
defer rows.Close()
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
dashboard.Uuid = string(timeUUID.String())
|
||||
dashboard.CreateTime = time.Now()
|
||||
dashboard.UpdateTime = time.Now()
|
||||
db := CONTEXT.DB.Create(dashboard)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
var invokeMap = make(map[string]*DashboardInvoke)
|
||||
var dashboardInvokes []*DashboardInvoke
|
||||
for rows.Next() {
|
||||
var invokeNum int64 = 0;
|
||||
var uv int64 = 0;
|
||||
var dt string;
|
||||
rows.Scan(&invokeNum, &uv, &dt)
|
||||
invokeMap[dt] = &DashboardInvoke{
|
||||
InvokeNum: invokeNum,
|
||||
Uv: uv,
|
||||
Dt: dt,
|
||||
}
|
||||
}
|
||||
for i := 1 - dayNum; i <= 0; i++ {
|
||||
date := now.AddDate(0, 0, i)
|
||||
dt := ConvertTimeToDateString(date)
|
||||
v, ok := invokeMap[dt]
|
||||
if ok {
|
||||
dashboardInvokes = append(dashboardInvokes, v)
|
||||
} else {
|
||||
dashboardInvokes = append(dashboardInvokes, &DashboardInvoke{
|
||||
InvokeNum: 0,
|
||||
Uv: 0,
|
||||
Dt: dt,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return dashboardInvokes
|
||||
return dashboard
|
||||
}
|
||||
|
||||
//修改一条记录
|
||||
func (this *DashboardDao) Save(dashboard *Dashboard) *Dashboard {
|
||||
|
||||
dashboard.UpdateTime = time.Now()
|
||||
db := CONTEXT.DB.Save(dashboard)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return dashboard
|
||||
}
|
||||
|
||||
|
||||
//删除一条记录
|
||||
func (this *DashboardDao) Delete(dashboard *Dashboard) {
|
||||
|
||||
db := CONTEXT.DB.Delete(&dashboard)
|
||||
this.PanicError(db.Error)
|
||||
}
|
||||
|
||||
|
||||
//按照dt查询
|
||||
func (this *DashboardDao) FindByDt(dt string) *Dashboard {
|
||||
|
||||
// Read
|
||||
var dashboard Dashboard
|
||||
db := CONTEXT.DB.Where(&Dashboard{Dt: dt}).First(&dashboard)
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return &dashboard
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ package rest
|
||||
*/
|
||||
type Dashboard struct {
|
||||
Base
|
||||
VisitNum int64 `json:"visitNum"`
|
||||
TotalVisitNum int64 `json:"totalVisitNum"`
|
||||
InvokeNum int64 `json:"invokeNum"`
|
||||
TotalInvokeNum int64 `json:"totalInvokeNum"`
|
||||
Uv int64 `json:"uv"`
|
||||
TotalUv int64 `json:"totalUv"`
|
||||
MatterNum int64 `json:"matterNum"`
|
||||
|
@ -1,13 +1,21 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//@Service
|
||||
type DashboardService struct {
|
||||
Bean
|
||||
dashboardDao *DashboardDao
|
||||
footprintDao *FootprintDao
|
||||
matterDao *MatterDao
|
||||
imageCacheDao *ImageCacheDao
|
||||
userDao *UserDao
|
||||
//每天凌晨定时整理器
|
||||
maintainTimer *time.Timer
|
||||
}
|
||||
|
||||
|
||||
//初始化方法
|
||||
func (this *DashboardService) Init() {
|
||||
this.Bean.Init()
|
||||
@ -18,9 +26,103 @@ func (this *DashboardService) Init() {
|
||||
this.dashboardDao = b
|
||||
}
|
||||
|
||||
b = CONTEXT.GetBean(this.footprintDao)
|
||||
if b, ok := b.(*FootprintDao); ok {
|
||||
this.footprintDao = b
|
||||
}
|
||||
|
||||
b = CONTEXT.GetBean(this.matterDao)
|
||||
if b, ok := b.(*MatterDao); ok {
|
||||
this.matterDao = b
|
||||
}
|
||||
|
||||
b = CONTEXT.GetBean(this.imageCacheDao)
|
||||
if b, ok := b.(*ImageCacheDao); ok {
|
||||
this.imageCacheDao = b
|
||||
}
|
||||
|
||||
b = CONTEXT.GetBean(this.userDao)
|
||||
if b, ok := b.(*UserDao); ok {
|
||||
this.userDao = b
|
||||
}
|
||||
|
||||
//立即执行数据清洗任务
|
||||
go this.maintain()
|
||||
}
|
||||
|
||||
//每日清洗离线数据表。
|
||||
func (this *DashboardService) maintain() {
|
||||
|
||||
//准备好下次维护日志的时间。
|
||||
now := time.Now()
|
||||
nextTime := FirstMinuteOfDay(Tomorrow())
|
||||
duration := nextTime.Sub(now)
|
||||
this.logger.Info("每日数据汇总,下次时间:%s ", ConvertTimeToDateTimeString(nextTime))
|
||||
this.maintainTimer = time.AfterFunc(duration, func() {
|
||||
go this.maintain()
|
||||
})
|
||||
|
||||
//准备日期开始结尾
|
||||
startTime := FirstSecondOfDay(Yesterday())
|
||||
endTime := LastSecondOfDay(Yesterday())
|
||||
dt := ConvertTimeToDateString(startTime)
|
||||
longTimeAgo := time.Now()
|
||||
longTimeAgo = longTimeAgo.AddDate(-20, 0, 0)
|
||||
|
||||
this.logger.Info("统计汇总表 %s -> %s", ConvertTimeToDateTimeString(startTime), ConvertTimeToDateTimeString(endTime))
|
||||
|
||||
//判断昨天的记录是否已经生成,如果生成了就直接删除掉
|
||||
dbDashboard := this.dashboardDao.FindByDt(dt)
|
||||
if dbDashboard != nil {
|
||||
this.logger.Info(" %s 的汇总已经存在了,删除以进行更新", dt)
|
||||
this.dashboardDao.Delete(dbDashboard)
|
||||
}
|
||||
|
||||
invokeNum := this.footprintDao.CountBetweenTime(startTime, endTime)
|
||||
this.logger.Info("调用数:%d", invokeNum)
|
||||
|
||||
totalInvokeNum := this.footprintDao.CountBetweenTime(longTimeAgo, endTime)
|
||||
this.logger.Info("历史总调用数:%d", totalInvokeNum)
|
||||
|
||||
uv := this.footprintDao.UvBetweenTime(startTime, endTime)
|
||||
this.logger.Info("UV:%d", uv)
|
||||
|
||||
totalUv := this.footprintDao.UvBetweenTime(longTimeAgo, endTime)
|
||||
this.logger.Info("历史总UV:%d", totalUv)
|
||||
|
||||
matterNum := this.matterDao.CountBetweenTime(startTime, endTime)
|
||||
this.logger.Info("文件数量数:%d", matterNum)
|
||||
|
||||
totalMatterNum := this.matterDao.CountBetweenTime(longTimeAgo, endTime)
|
||||
this.logger.Info("历史文件总数:%d", totalMatterNum)
|
||||
|
||||
matterSize := this.matterDao.SizeBetweenTime(startTime, endTime)
|
||||
this.logger.Info("文件大小:%d", matterSize)
|
||||
|
||||
totalMatterSize := this.matterDao.SizeBetweenTime(longTimeAgo, endTime)
|
||||
this.logger.Info("历史文件总大小:%d", totalMatterSize)
|
||||
|
||||
cacheSize := this.imageCacheDao.SizeBetweenTime(startTime, endTime)
|
||||
this.logger.Info("缓存大小:%d", cacheSize)
|
||||
|
||||
totalCacheSize := this.imageCacheDao.SizeBetweenTime(longTimeAgo, endTime)
|
||||
this.logger.Info("历史缓存总大小:%d", totalCacheSize)
|
||||
|
||||
avgCost := this.footprintDao.AvgCostBetweenTime(startTime, endTime)
|
||||
this.logger.Info("平均耗时:%d ms", avgCost)
|
||||
|
||||
dashboard := &Dashboard{
|
||||
InvokeNum: invokeNum,
|
||||
TotalInvokeNum: totalInvokeNum,
|
||||
Uv: uv,
|
||||
TotalUv: totalUv,
|
||||
MatterNum: matterNum,
|
||||
TotalMatterNum: totalMatterNum,
|
||||
FileSize: matterSize + cacheSize,
|
||||
TotalFileSize: totalMatterSize + totalCacheSize,
|
||||
AvgCost: avgCost,
|
||||
Dt: dt,
|
||||
}
|
||||
|
||||
this.dashboardDao.Create(dashboard)
|
||||
}
|
||||
|
@ -88,3 +88,31 @@ func (this *FootprintDao) Delete(footprint *Footprint) {
|
||||
db := CONTEXT.DB.Delete(&footprint)
|
||||
this.PanicError(db.Error)
|
||||
}
|
||||
|
||||
//获取一段时间中,总的数量
|
||||
func (this *FootprintDao) CountBetweenTime(startTime time.Time, endTime time.Time) int64 {
|
||||
var count int64
|
||||
db := CONTEXT.DB.Model(&Footprint{}).Where("create_time >= ? AND create_time <= ?", startTime, endTime).Count(&count)
|
||||
this.PanicError(db.Error)
|
||||
return count
|
||||
}
|
||||
|
||||
//获取一段时间中UV的数量
|
||||
func (this *FootprintDao) UvBetweenTime(startTime time.Time, endTime time.Time) int64 {
|
||||
var count int64
|
||||
db := CONTEXT.DB.Model(&Footprint{}).Where("create_time >= ? AND create_time <= ?", startTime, endTime).Select("COUNT(DISTINCT(ip))")
|
||||
this.PanicError(db.Error)
|
||||
row := db.Row()
|
||||
row.Scan(&count)
|
||||
return count
|
||||
}
|
||||
|
||||
//获取一段时间中平均耗时
|
||||
func (this *FootprintDao) AvgCostBetweenTime(startTime time.Time, endTime time.Time) int64 {
|
||||
var cost float64
|
||||
db := CONTEXT.DB.Model(&Footprint{}).Where("create_time >= ? AND create_time <= ?", startTime, endTime).Select("AVG(cost)")
|
||||
this.PanicError(db.Error)
|
||||
row := db.Row()
|
||||
row.Scan(&cost)
|
||||
return int64(cost)
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ type Footprint struct {
|
||||
Params string `json:"params"`
|
||||
Cost int64 `json:"cost"`
|
||||
Success bool `json:"success"`
|
||||
Dt string `json:"dt"`
|
||||
}
|
||||
|
||||
// set File's table name to be `profiles`
|
||||
|
@ -76,7 +76,6 @@ func (this *FootprintService) Trace(writer http.ResponseWriter, request *http.Re
|
||||
Params: paramsString,
|
||||
Cost: int64(duration / time.Millisecond),
|
||||
Success: success,
|
||||
Dt: ConvertTimeToDateString(time.Now()),
|
||||
}
|
||||
|
||||
footprint = this.footprintDao.Create(footprint)
|
||||
|
@ -192,3 +192,13 @@ func (this *ImageCacheDao) DeleteByMatterUuid(matterUuid string) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//获取一段时间中文件总大小
|
||||
func (this *ImageCacheDao) SizeBetweenTime(startTime time.Time, endTime time.Time) int64 {
|
||||
var size int64
|
||||
db := CONTEXT.DB.Model(&ImageCache{}).Where("create_time >= ? AND create_time <= ?", startTime, endTime).Select("SUM(size)")
|
||||
this.PanicError(db.Error)
|
||||
row := db.Row()
|
||||
row.Scan(&size)
|
||||
return size
|
||||
}
|
||||
|
@ -32,10 +32,13 @@ func (this *Logger) log(prefix string, format string, v ...interface{}) {
|
||||
defer this.Unlock()
|
||||
|
||||
//控制台中打印日志
|
||||
fmt.Printf(format+"\r\n", v...)
|
||||
var consoleFormat = fmt.Sprintf("%s%s %s\r\n", prefix, ConvertTimeToTimeString(time.Now()), format)
|
||||
fmt.Printf(consoleFormat, v...)
|
||||
|
||||
this.goLogger.SetPrefix(prefix)
|
||||
this.goLogger.Printf(format, v...)
|
||||
//每一行我们加上换行符
|
||||
var fileFormat = fmt.Sprintf("%s\r\n", format)
|
||||
this.goLogger.Printf(fileFormat, v...)
|
||||
}
|
||||
|
||||
//处理日志的统一方法。
|
||||
@ -101,7 +104,7 @@ func (this *Logger) maintain() {
|
||||
now := time.Now()
|
||||
nextTime := FirstSecondOfDay(Tomorrow())
|
||||
duration := nextTime.Sub(now)
|
||||
go this.Info("%vs后将进行下一次日志维护 下次时间维护时间:%v ", int64(duration/time.Second), nextTime)
|
||||
go this.Info("%vs 后将进行下一次日志维护 下次时间维护时间:%v ", int64(duration/time.Second), nextTime)
|
||||
this.maintainTimer = time.AfterFunc(duration, func() {
|
||||
go this.maintain()
|
||||
})
|
||||
@ -133,7 +136,6 @@ func (this *Logger) closeFile() {
|
||||
panic("尝试关闭日志时出错: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (this *Logger) Destroy() {
|
||||
|
@ -264,3 +264,21 @@ func (this *MatterDao) Delete(matter *Matter) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//获取一段时间中,总的数量
|
||||
func (this *MatterDao) CountBetweenTime(startTime time.Time, endTime time.Time) int64 {
|
||||
var count int64
|
||||
db := CONTEXT.DB.Model(&Matter{}).Where("create_time >= ? AND create_time <= ?", startTime, endTime).Count(&count)
|
||||
this.PanicError(db.Error)
|
||||
return count
|
||||
}
|
||||
|
||||
//获取一段时间中文件总大小
|
||||
func (this *MatterDao) SizeBetweenTime(startTime time.Time, endTime time.Time) int64 {
|
||||
var size int64
|
||||
db := CONTEXT.DB.Model(&Matter{}).Where("create_time >= ? AND create_time <= ?", startTime, endTime).Select("SUM(size)")
|
||||
this.PanicError(db.Error)
|
||||
row := db.Row()
|
||||
row.Scan(&size)
|
||||
return size
|
||||
}
|
@ -20,6 +20,11 @@ func ConvertTimeToDateTimeString(time time.Time) string {
|
||||
return time.Local().Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
//将一个时间字符串转换成日期时间对象(yyyy-MM-dd HH:mm:ss)
|
||||
func ConvertTimeToTimeString(time time.Time) string {
|
||||
return time.Local().Format("15:04:05")
|
||||
}
|
||||
|
||||
//将一个时间字符串转换成日期对象(yyyy-MM-dd)
|
||||
func ConvertTimeToDateString(time time.Time) string {
|
||||
return time.Local().Format("2006-01-02")
|
||||
@ -37,6 +42,12 @@ func FirstSecondOfDay(day time.Time) time.Time {
|
||||
return time.Date(day.Year(), day.Month(), day.Day(), 0, 0, 0, 0, local)
|
||||
}
|
||||
|
||||
//一天中的第一分钟
|
||||
func FirstMinuteOfDay(day time.Time) time.Time {
|
||||
local, _ := time.LoadLocation("Local")
|
||||
return time.Date(day.Year(), day.Month(), day.Day(), 0, 1, 0, 0, local)
|
||||
}
|
||||
|
||||
//明天此刻的时间
|
||||
func Tomorrow() time.Time {
|
||||
tomorrow := time.Now()
|
||||
|
Loading…
Reference in New Issue
Block a user