From 1bdfb4996e324ca31a241d2f3d2b7bb8a3d65a41 Mon Sep 17 00:00:00 2001 From: zicla Date: Fri, 30 Nov 2018 22:01:31 +0800 Subject: [PATCH] Finish the logger maintain things. --- rest/alien_service.go | 5 ++- rest/logger.go | 91 +++++++++++++++++++++++++++++++++++++---- rest/matter_dao.go | 8 +++- rest/matter_model.go | 2 +- rest/router.go | 3 ++ rest/user_controller.go | 1 - rest/user_service.go | 1 - rest/util_time.go | 42 +++++++++++++++++++ 8 files changed, 138 insertions(+), 15 deletions(-) create mode 100644 rest/util_time.go diff --git a/rest/alien_service.go b/rest/alien_service.go index b558d3e..81bff0d 100644 --- a/rest/alien_service.go +++ b/rest/alien_service.go @@ -68,8 +68,6 @@ func (this *AlienService) PreviewOrDownload( operator *User, withContentDisposition bool) { - this.logger.Info("预览或下载文件 " + uuid + " " + filename) - matter := this.matterDao.CheckByUuid(uuid) //判断是否是文件夹 @@ -133,4 +131,7 @@ func (this *AlienService) PreviewOrDownload( this.matterService.DownloadFile(writer, request, CONFIG.MatterPath+matter.Path, matter.Name, withContentDisposition) } + //文件下载次数加一,为了加快访问速度,异步进行 + go this.matterDao.TimesIncrement(uuid) + } diff --git a/rest/logger.go b/rest/logger.go index c0ec792..3128761 100644 --- a/rest/logger.go +++ b/rest/logger.go @@ -4,6 +4,8 @@ import ( "fmt" "log" "os" + "sync" + "time" ) //日志系统必须高保 @@ -12,14 +14,24 @@ var LOGGER *Logger = &Logger{} //在Logger的基础上包装一个全新的Logger. type Logger struct { + //加锁,在维护日志期间,禁止写入日志。 + sync.RWMutex + //继承logger goLogger *log.Logger //日志记录所在的文件 file *os.File + //每天凌晨定时整理器 + maintainTimer *time.Timer } //处理日志的统一方法。 func (this *Logger) log(prefix string, format string, v ...interface{}) { + + this.Lock() + defer this.Unlock() + + //控制台中打印日志 fmt.Printf(format+"\r\n", v...) this.goLogger.SetPrefix(prefix) @@ -28,32 +40,82 @@ func (this *Logger) log(prefix string, format string, v ...interface{}) { //处理日志的统一方法。 func (this *Logger) Debug(format string, v ...interface{}) { - this.log("[debug]", format, v...) + this.log("[DEBUG]", format, v...) } func (this *Logger) Info(format string, v ...interface{}) { - this.log("[info ]", format, v...) + this.log("[INFO ]", format, v...) } func (this *Logger) Warn(format string, v ...interface{}) { - this.log("[warn ]", format, v...) + this.log("[WARN ]", format, v...) } func (this *Logger) Error(format string, v ...interface{}) { - this.log("[error]", format, v...) + this.log("[ERROR]", format, v...) } func (this *Logger) Panic(format string, v ...interface{}) { - this.log("[panic]", format, v...) + this.log("[PANIC]", format, v...) panic(fmt.Sprintf(format, v...)) } func (this *Logger) Init() { + this.openFile() + + //日志需要自我备份,自我维护。明天第一秒触发 + nextTime := FirstSecondOfDay(Tomorrow()) + duration := nextTime.Sub(time.Now()) + this.maintainTimer = time.AfterFunc(duration, func() { + go this.maintain() + }) + +} + +//将日志写入到今天的日期中(该方法内必须使用异步方法记录日志,否则会引发死锁) +func (this *Logger) maintain() { + + this.Lock() + defer this.Unlock() + + go this.Info("每日维护日志") + + //首先关闭文件。 + this.closeFile() + + //日志归类到昨天 + destPath := GetLogPath() + "/tank-" + Yesterday().Local().Format("2006-01-02") + ".log" + + //直接重命名文件 + err := os.Rename(this.fileName(), destPath) + if err != nil { + go this.Error("重命名文件出错", err.Error()) + } + + //再次打开文件 + this.openFile() + + //准备好下次维护日志的时间。 + now := time.Now() + nextTime := FirstSecondOfDay(Tomorrow()) + duration := nextTime.Sub(now) + this.maintainTimer = time.AfterFunc(duration, func() { + go this.maintain() + }) +} + + +//日志名称 +func (this *Logger) fileName() string { + return GetLogPath() + "/tank.log" +} + +//打开日志文件 +func (this *Logger) openFile() { //日志输出到文件中 文件打开后暂时不关闭 - filePath := GetLogPath() + "/tank.log" - fmt.Printf("使用日志文件 %s\r\n", filePath) - f, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + fmt.Printf("使用日志文件 %s\r\n", this.fileName()) + f, err := os.OpenFile(this.fileName(), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { panic("日志文件无法正常打开: " + err.Error()) } @@ -62,7 +124,8 @@ func (this *Logger) Init() { this.file = f } -func (this *Logger) Destroy() { +//关闭日志文件 +func (this *Logger) closeFile() { if this.file != nil { err := this.file.Close() if err != nil { @@ -71,3 +134,13 @@ func (this *Logger) Destroy() { } } + +func (this *Logger) Destroy() { + + this.closeFile() + + if this.maintainTimer != nil { + this.maintainTimer.Stop() + } + +} diff --git a/rest/matter_dao.go b/rest/matter_dao.go index 7721638..93292b6 100644 --- a/rest/matter_dao.go +++ b/rest/matter_dao.go @@ -6,8 +6,8 @@ import ( _ "github.com/jinzhu/gorm/dialects/mysql" "github.com/nu7hatch/gouuid" "os" - "time" "strings" + "time" ) type MatterDao struct { @@ -216,6 +216,12 @@ func (this *MatterDao) Save(matter *Matter) *Matter { return matter } +//计数器加一 +func (this *MatterDao) TimesIncrement(matterUuid string) { + db := CONTEXT.DB.Model(&Matter{}).Where("uuid = ?", matterUuid).Update("times", gorm.Expr("times + 1")) + this.PanicError(db.Error) +} + //删除一个文件,数据库中删除,物理磁盘上删除。 func (this *MatterDao) Delete(matter *Matter) { diff --git a/rest/matter_model.go b/rest/matter_model.go index f6aeea8..bcb2edb 100644 --- a/rest/matter_model.go +++ b/rest/matter_model.go @@ -1,6 +1,5 @@ package rest - /** * 文件。alien表示是否是应用内使用的文件,比如说蓝眼云盘的头像,alien = true 这种文件在上传时不需要指定存放目录,会统一放在同一个文件夹下。 */ @@ -15,6 +14,7 @@ type Matter struct { Size int64 `json:"size"` Privacy bool `json:"privacy"` Path string `json:"path"` + Times int64 `json:"times"` Parent *Matter `gorm:"-" json:"parent"` } diff --git a/rest/router.go b/rest/router.go index 24ac292..10dda03 100644 --- a/rest/router.go +++ b/rest/router.go @@ -59,6 +59,9 @@ func (this *Router) GlobalPanicHandler(writer http.ResponseWriter, request *http } else if value, ok := err.(*WebResult); ok { //一个WebResult对象 webResult = value + } else if value, ok := err.(*CodeWrapper); ok { + //一个WebResult对象 + webResult = ConstWebResult(value) } else if value, ok := err.(error); ok { //一个普通的错误对象 webResult = CustomWebResult(CODE_WRAPPER_UNKNOWN, value.Error()) diff --git a/rest/user_controller.go b/rest/user_controller.go index bbcf28d..7604691 100644 --- a/rest/user_controller.go +++ b/rest/user_controller.go @@ -215,7 +215,6 @@ func (this *UserController) Logout(writer http.ResponseWriter, request *http.Req //session置为过期 sessionCookie, err := request.Cookie(COOKIE_AUTH_KEY) if err != nil { - this.logger.Error("找不到任何登录信息") return this.Success("已经退出登录了!") } sessionId := sessionCookie.Value diff --git a/rest/user_service.go b/rest/user_service.go index 76fb72c..008f7fe 100644 --- a/rest/user_service.go +++ b/rest/user_service.go @@ -38,7 +38,6 @@ func (this *UserService) bootstrap(writer http.ResponseWriter, request *http.Req //验证用户是否已经登录。 sessionCookie, err := request.Cookie(COOKIE_AUTH_KEY) if err != nil { - this.logger.Error("找不到任何登录信息") return } diff --git a/rest/util_time.go b/rest/util_time.go new file mode 100644 index 0000000..6b137f9 --- /dev/null +++ b/rest/util_time.go @@ -0,0 +1,42 @@ +package rest + +import ( + "fmt" + "time" +) + +//将一个时间字符串转换成时间对象(yyyy-MM-dd HH:mm:ss) +func ConvertToTime(timeString string) time.Time { + local, _ := time.LoadLocation("Local") + t, err := time.ParseInLocation("2006-01-02 15:04:05", timeString, local) + if err != nil { + panic(fmt.Sprintf("不能将%s转为时间类型", timeString)) + } + return t +} + +//一天中的最后一秒钟 +func LastSecondOfDay(day time.Time) time.Time { + local, _ := time.LoadLocation("Local") + return time.Date(day.Year(), day.Month(), day.Day(), 23, 59, 59, 0, local) +} + +//一天中的第一秒钟 +func FirstSecondOfDay(day time.Time) time.Time { + local, _ := time.LoadLocation("Local") + return time.Date(day.Year(), day.Month(), day.Day(), 0, 0, 0, 0, local) +} + +//明天此刻的时间 +func Tomorrow() time.Time { + tomorrow := time.Now() + tomorrow.AddDate(0, 0, 1) + return tomorrow +} + +//昨天此刻的时间 +func Yesterday() time.Time { + tomorrow := time.Now() + tomorrow.AddDate(0, 0, -1) + return tomorrow +}