package zciyon import ( "bufio" "fmt" "net" "os" "runtime" "strings" "time" ) type ciyLogMsg struct { tim int level int fnname string msg string track string } type CiyLog struct { Filename string tkver string tkname string chfile chan ciyLogMsg wrfile *bufio.Writer lvfile int bfile bool chtcp chan ciyLogMsg socktcp net.Conn lvtcp int //btcp bool } func NewCiyLog(maxchan int) *CiyLog { log := &CiyLog{} log.Filename = "" log.chfile = make(chan ciyLogMsg, maxchan) log.chtcp = make(chan ciyLogMsg, maxchan) return log } func (thos *CiyLog) InitFile(files string, level int) { //打开文件句柄,每隔2秒写一次磁盘 thos.lvfile = level thos.Filename = files f, err := os.OpenFile(files, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640) if err != nil { Clog("OpenFile err:", err) return } thos.wrfile = bufio.NewWriter(f) thos.bfile = false go func() { defer func() { if conv := recover(); conv != nil { Clog("Log File fatal:", conv) } }() for { msg := <-thos.chfile _, err := thos.wrfile.WriteString(fmt.Sprintf("%v;;%v;;%v;;%v;;%v\n", msg.level, Todate(msg.tim, "Y-m-d H:i:s"), msg.fnname, msg.msg, msg.track)) if err != nil { Clog("Log File Write err:", err) } thos.bfile = true } }() go func() { defer func() { if conv := recover(); conv != nil { Clog("Log File fatal:", conv) } }() for { if thos.bfile { err := thos.wrfile.Flush() if err != nil { Clog("Log File Flush err:", err) } thos.bfile = false } time.Sleep(2 * time.Second) } }() } func (thos *CiyLog) InitTCP(ipport string, level int) { //打开TCP客户端,自动重连 thos.lvtcp = level thos.socktcp, _ = net.Dial("tcp", "log.ciy.cn:4005") go func() { for { select { case msg := <-thos.chtcp: Clog("tcp go", msg) //写文件 default: time.Sleep(2 * time.Second) } } }() } func (thos *CiyLog) SupportStack(ver string) { // vernums := strings.Split(ver, ".") // thos.tkver = "V" + vernums[len(vernums)-1] thos.tkver = "V" + ver thos.tkname = "/" + CiyWebDir[strings.LastIndex(CiyWebDir, "/")+1:] + "/" } func (thos *CiyLog) Debug(fnname, msg string) { Clog("LOG Debug", fnname, msg) if thos == nil { return } thos.setlog(1, fnname, msg) } func (thos *CiyLog) Info(fnname, msg string) { Clog("LOG Info", fnname, msg) if thos == nil { return } thos.setlog(2, fnname, msg) } func (thos *CiyLog) Warn(fnname, msg string) { Clog("LOG Warn", fnname, msg) if thos == nil { return } thos.setlog(3, fnname, msg) } func (thos *CiyLog) Error(fnname, msg string) { Clog("LOG Error", fnname, msg) if thos == nil { return } thos.setlog(4, fnname, msg) } func (thos *CiyLog) Fatal(fnname, msg string) { Clog("LOG Fatal", fnname, msg) if thos == nil { return } thos.setlog(5, fnname, msg) } func (thos *CiyLog) setlog(level int, fnname, msg string) { track := "" if thos.tkname != "" { track += thos.tkver systrack := 3 //记录框架及系统调用深度 for i := 2; i < 20; i++ { _, file, line, ok := runtime.Caller(i) if !ok { break } if ind := strings.Index(file, thos.tkname); ind > -1 { if strings.Contains(file, "zciyon") { systrack-- if systrack == 0 { break } } else { systrack = 3 } track += fmt.Sprintf("~%v:%v", file[ind+len(thos.tkname):], line) } else { systrack-- if systrack == 0 { break } ind := strings.LastIndex(file, "/") if ind > -1 { ind2 := strings.LastIndex(file[:ind], "/") if ind2 > -1 { ind = ind2 } track += fmt.Sprintf("~%v:%v", file[ind:], line) } else { track += fmt.Sprintf("~%v:%v", file, line) } } } } if thos.wrfile != nil && thos.lvfile <= level { thos.chfile <- ciyLogMsg{tim: Tostamp(), level: level, fnname: fnname, msg: msg, track: track} } if thos.socktcp != nil && thos.lvtcp <= level { thos.chtcp <- ciyLogMsg{tim: Tostamp(), level: level, fnname: fnname, msg: msg, track: track} } }