You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
8.0 KiB
Go

package icslog
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime/debug"
"strconv"
"strings"
"sync"
"time"
"gitlab.com/ics_cinnamon/voiceStatistics/icsconf"
"gitlab.com/ics_cinnamon/voiceStatistics/icserror"
"gitlab.com/ics_cinnamon/voiceStatistics/icsutil"
)
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.CurrentDate = time.Now()
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 := time.Now().Hour(), time.Now().Minute()
gIcsLog.LogFileName = fmt.Sprintf("%s/LGT.%03d.%d%02d%02d%02d%02d.log", gIcsLog.Path, icsconf.GetIcsConfig().InfoConfig.ServerID, yyyy, mm, dd, hh, mi)
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 {
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, 0666)
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, 0666)
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 {
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, 0666)
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() {
//var derr *icserror.IcsError = nil
delLogCount := 0
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 logYYYY, logMM, logDD string
for _, file := range files {
/*
TODO
1. 로그 파일을 시간으로 변환
2. 현재 시간 - 삭제기간
3. 둘 시간 차이가 0 이상 나면 삭제대상
*/
logTime := strings.SplitN(file.Name(), "-", -1)[1]
logYYYY, logMM, logDD = logTime[:4], logTime[4:6], logTime[6:8]
chgLogTime, perr := time.Parse("2006-01-02", fmt.Sprintf("%s-%s-%s", logYYYY, logMM, logDD))
if perr != nil {
s.Printf(LOG_LEVEL_ERROR, -1, " Log Time Parse error - %s \n", perr)
fmt.Printf("Log Time Parse error - %s", perr)
} else {
diff := delTime.Sub(chgLogTime)
// diff > 0 => delete log
if diff > 0 {
delResult := icsutil.DeleteFile(s.Path, file.Name())
if delResult != "" {
s.Printf(LOG_LEVEL_ERROR, -1, " Delete File error - %s \n", delResult)
} else {
s.Printf(LOG_LEVEL_INFO, -1, " Delete %s!!!!\n", file.Name())
fmt.Printf("Delete %s!!!!\n", file.Name())
delLogCount += 1
}
}
}
}
}
s.Printf(LOG_LEVEL_INFO, -1, " Delete File Count - %d \n", delLogCount)
fmt.Printf("Log Delete Count : %d", delLogCount)
}