package icslog import ( "bytes" "fmt" "io/ioutil" "log" "os" "path/filepath" "strconv" "strings" "sync" "time" "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" "gitlab.com/ics_cinnamon/voiceStatistics/icserror" ) type IcsLog struct { logger *log.Logger Output int Level int Path string LogFileName string LogFile *os.File DiskLimit int DelDay int DelHour int isRotate bool logSize int rotateNum int buf bytes.Buffer CurrentDate time.Time conf *icsconf.LogConfig //conf *icsconf.IcsConfig IsDiskFull bool M *sync.Mutex } //default max log size 30 megabytes const DEFAULT_LOG_MAX_SIZE = 30 //default log rotate num const DEFAULT_LOG_ROTATE_NUM = 10 //max log rotate num const MAX_LOG_ROTATE_NUM = 99 const ( LOG_LEVEL_DEBUG2 = iota LOG_LEVEL_DEBUG1 LOG_LEVEL_DEBUG LOG_LEVEL_STATIS LOG_LEVEL_INFO LOG_LEVEL_WARN LOG_LEVEL_ERROR LOG_LEVEL_FATAL LOG_LEVEL_MAX ) //log output const ( LOG_OUTPUT_FILE = 1 << (32 - 1 - iota) LOG_OUTPUT_STDOUT ) var IcsLogLevelStr [LOG_LEVEL_MAX]string var gIcsLog *IcsLog var onceLog sync.Once func init() { IcsLogLevelStr[LOG_LEVEL_DEBUG2] = "DEBUG2" IcsLogLevelStr[LOG_LEVEL_DEBUG1] = "DEBUG1" IcsLogLevelStr[LOG_LEVEL_DEBUG] = "DEBUG" IcsLogLevelStr[LOG_LEVEL_STATIS] = "STATISTICS" IcsLogLevelStr[LOG_LEVEL_INFO] = "INFO" IcsLogLevelStr[LOG_LEVEL_WARN] = "WARN" IcsLogLevelStr[LOG_LEVEL_ERROR] = "ERROR" IcsLogLevelStr[LOG_LEVEL_FATAL] = "FATAL" } //if fail, return icserror func NewIcsLog(conf *icsconf.LogConfig, level int, output int, path string, disklimit int) (*IcsLog, *icserror.IcsError) { //func NewIcsLog(conf *icsconf.IcsConfig, level int, output int, path string, disklimit int) (*IcsLog, *icserror.IcsError) { //func NewIcsLog(conf *icsconf.IcsConfig, level interface{}, output interface{}, path string, disklimit int) (*IcsLog, *icserror.IcsError) { var reterr *icserror.IcsError = nil //singleton onceLog.Do(func() { gIcsLog = &IcsLog{ conf: conf, Level: level, Output: output, Path: path, DiskLimit: disklimit, IsDiskFull: false, // logSize: DEFAULT_LOG_MAX_SIZE, rotateNum: DEFAULT_LOG_ROTATE_NUM, } gIcsLog.M = &sync.Mutex{} gIcsLog.isRotate = strings.Compare("YES", strings.ToUpper(gIcsLog.conf.RotateConfig.YesNo)) == 0 //gIcsLog.isRotate = strings.Compare("YES", strings.ToUpper(gIcsLog.conf.LogConfig.RotateConfig.YesNo)) == 0 var serr error // gIcsLog.logSize, serr = strconv.Atoi(gIcsLog.conf.RotateConfig.Size) // //gIcsLog.logSize, serr = strconv.Atoi(gIcsLog.conf.LogConfig.RotateConfig.Size) // if serr != nil { // gIcsLog.logSize = DEFAULT_LOG_MAX_SIZE // } gIcsLog.rotateNum, serr = strconv.Atoi(gIcsLog.conf.RotateConfig.Num) //gIcsLog.rotateNum, serr = strconv.Atoi(gIcsLog.conf.LogConfig.RotateConfig.Num) if serr != nil { gIcsLog.rotateNum = DEFAULT_LOG_ROTATE_NUM } if gIcsLog.rotateNum > MAX_LOG_ROTATE_NUM { gIcsLog.rotateNum = MAX_LOG_ROTATE_NUM } // gIcsLog.logger = log.New(&gIcsLog.buf, "", log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile) gIcsLog.logger = log.New(&gIcsLog.buf, "", 0) // 5분 연산 now := time.Now() nowMin := now.Minute() nowMinRem := nowMin % 5 nowMinS := fmt.Sprintf("%02dm", nowMinRem) convMinutes, _ := time.ParseDuration(nowMinS) diffMinutes := now.Add(-convMinutes) fmt.Println("diffMinutes ", diffMinutes) gIcsLog.CurrentDate = diffMinutes gIcsLog.DelDay = conf.DelConfig.DelDay gIcsLog.DelHour = conf.DelConfig.DelHour // make log file - LGT.001.20220715.log // log dir - /logs/voiceGW/tlo/{YYYYMMDD} yyyy, mm, dd := gIcsLog.CurrentDate.Date() hh, mi := diffMinutes.Hour(), diffMinutes.Minute() gIcsLog.LogFileName = fmt.Sprintf("%s/%d%02d%02d/LGT.%03d.%d%02d%02d%02d%02d.log", gIcsLog.Path, yyyy, mm, dd, icsconf.GetIcsConfig().InfoConfig.ServerID, yyyy, mm, dd, hh, mi) fmt.Println("logfileName ", gIcsLog.LogFileName) stat, err := os.Stat(gIcsLog.LogFileName) if err == nil { if gIcsLog.checkLogRotate() && stat.Size()/ONEMB >= int64(gIcsLog.logSize) { rotateNum := gIcsLog.getTodayLogFileNum() //fmt.Println("rotate num:", rotateNum) if rotateNum > 0 && rotateNum < gIcsLog.rotateNum { gIcsLog.shiftLogFiles(rotateNum) var oerr error oerr = os.MkdirAll(filepath.Dir(gIcsLog.LogFileName), 0777) if oerr != nil { fmt.Println("mkdir err : ", oerr) icserror.ICSERRMakeDir.SetError(oerr) icserror.ICSERRMakeDir.PrintWithCaller(0) return } fmt.Println("mkdir success") gIcsLog.LogFile, oerr = os.OpenFile(gIcsLog.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777) if oerr != nil { //fmt.Println(gIcsLog.LogFileName) icserror.ICSERRFileOpen.SetError(oerr) reterr = icserror.ICSERRFileOpen reterr.PrintWithCaller(0) return } } } else if stat.Size()/ONEMB < int64(gIcsLog.logSize) { var oerr error oerr = os.MkdirAll(filepath.Dir(gIcsLog.LogFileName), 0777) if oerr != nil { icserror.ICSERRMakeDir.SetError(oerr) icserror.ICSERRMakeDir.PrintWithCaller(0) return } gIcsLog.LogFile, oerr = os.OpenFile(gIcsLog.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777) if oerr != nil { //fmt.Println(gIcsLog.LogFileName) icserror.ICSERRFileOpen.SetError(oerr) reterr = icserror.ICSERRFileOpen reterr.PrintWithCaller(0) return } } } else { var oerr error oerr = os.MkdirAll(filepath.Dir(gIcsLog.LogFileName), 0777) if oerr != nil { fmt.Println("mkdir err : ", oerr) icserror.ICSERRMakeDir.SetError(oerr) icserror.ICSERRMakeDir.PrintWithCaller(0) return } fmt.Println("mkdir success") gIcsLog.LogFile, oerr = os.OpenFile(gIcsLog.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777) if oerr != nil { //fmt.Println(gIcsLog.LogFileName) icserror.ICSERRFileOpen.SetError(oerr) reterr = icserror.ICSERRFileOpen reterr.PrintWithCaller(0) return } } }) return gIcsLog, reterr } func GetIcsLog() *IcsLog { return gIcsLog } func GetLogLevelID(str string) int { switch str { case "DEBUG2": return LOG_LEVEL_DEBUG2 case "DEBUG1": return LOG_LEVEL_DEBUG1 case "DEBUG": return LOG_LEVEL_DEBUG case "STATISTICS": return LOG_LEVEL_STATIS case "INFO": return LOG_LEVEL_INFO case "WARN": return LOG_LEVEL_WARN case "ERROR": return LOG_LEVEL_ERROR case "FATAL": return LOG_LEVEL_FATAL default: return -1 } } func GetLogOutputID(str string) int { switch str { case "FILE": return LOG_OUTPUT_FILE default: return LOG_OUTPUT_STDOUT } } func (s *IcsLog) DelLog() { conf := icsconf.GetIcsConfig() if !conf.LogConfig.DelConfig.Value { return } //var derr *icserror.IcsError = nil defer func() { if err := recover(); err != nil { switch v := err.(type) { case error: icserror.ICSERRFileOpen.SetError(v) // s.Printf(LOG_LEVEL_WARN, -1, "PANIC! %s\n%s", icserror.ICSERRFileOpen.GetError().Error(), string(debug.Stack())) default: // s.Print(LOG_LEVEL_WARN, -1, icserror.ICSERRFileOpen.GetError().Error()) } } //derr = icserror.ICSERRFileOpen }() // 1. Get Log Del Time yyyy, mm, dd := s.CurrentDate.Date() curTime, _ := time.Parse("2006-01-02", fmt.Sprintf("%d-%02d-%02d", yyyy, mm, dd)) delTime := curTime.AddDate(0, 0, -s.DelDay) files, rderr := ioutil.ReadDir(s.Path) if rderr != nil { // s.Printf(LOG_LEVEL_ERROR, -1, " Read Log Dir error - %s \n", rderr) // fmt.Printf("Read Log Dir error - %s", rderr) } else { var YYYY, MM, DD string for _, file := range files { _, cerr := strconv.Atoi(file.Name()) if cerr != nil { // s.Printf(LOG_LEVEL_ERROR, -1, "Voice Date Parse Error- %s \n", file.Name()) continue } YYYY, MM, DD = file.Name()[:4], file.Name()[4:6], file.Name()[6:8] chgVTime, perr := time.Parse("2006-01-02", fmt.Sprintf("%s%s%s", YYYY, MM, DD)) if perr != nil { // s.Printf(LOG_LEVEL_ERROR, -1, " Voice Time Parse error - %s \n", perr) // fmt.Printf("Voice Time Parse error - %s\n", perr) } else { diff := delTime.Sub(chgVTime) if diff > 0 { delResult := os.RemoveAll(fmt.Sprintf("%s/%s", s.Path, file.Name())) if delResult != nil { // s.Printf(LOG_LEVEL_ERROR, -1, " Delete File error - %s \n", delResult) // fmt.Printf("Delete File error [%s] - %s \n", file.Name(), delResult.Error()) } else { // s.Printf(LOG_LEVEL_INFO, -1, " Delete %s \n", file.Name()) // fmt.Printf("Delete %s \n", file.Name()) } } } } } // s.Printf(LOG_LEVEL_INFO, -1, " Delete File Count - %d \n", delLogCount) // fmt.Printf("Log Delete Count : %d", delLogCount) }