From 575d7eefad510cae21fac4846abf6ee34373a49c Mon Sep 17 00:00:00 2001 From: MacBookAirM2 Date: Wed, 10 May 2023 11:32:32 +0800 Subject: [PATCH] add log storage --- README-CN.md | 10 ++- README.md | 8 +- conf/zinx.json | 12 +++ examples/zinx_decoder/server.go | 1 + examples/zinx_logger/server.go | 3 +- zconf/globalobj.go | 23 ++++-- zlog/logger_core.go | 131 +++++++++----------------------- zlog/stdzlog.go | 19 ++++- zutils/witer.go | 23 +++--- 9 files changed, 110 insertions(+), 120 deletions(-) create mode 100644 conf/zinx.json diff --git a/README-CN.md b/README-CN.md index 28554cd0..ecfbdca1 100644 --- a/README-CN.md +++ b/README-CN.md @@ -264,13 +264,15 @@ recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient] ```json { "Name":"zinx v-0.10 demoApp", - "Host":"127.0.0.1", - "TCPPort":7777, + "Host":"0.0.0.0", + "TCPPort":9090, "MaxConn":3, "WorkerPoolSize":10, "LogDir": "./mylog", - "LogFile":"zinx.log", - "LogIsolationLevel": 0 + "LogFile":"app.log", + "LogSaveDays":15, + "LogCons": true, + "LogIsolationLevel":0 } ``` diff --git a/README.md b/README.md index 26c02aa7..c127e2d1 100644 --- a/README.md +++ b/README.md @@ -261,12 +261,14 @@ recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient] ```json { "Name":"zinx v-0.10 demoApp", - "Host":"127.0.0.1", - "TCPPort":7777, + "Host":"0.0.0.0", + "TCPPort":9090, "MaxConn":3, "WorkerPoolSize":10, "LogDir": "./mylog", - "LogFile":"zinx.log", + "LogFile":"app.log", + "LogSaveDays":15, + "LogCons": true, "LogIsolationLevel":0 } ``` diff --git a/conf/zinx.json b/conf/zinx.json new file mode 100644 index 00000000..ba5d9779 --- /dev/null +++ b/conf/zinx.json @@ -0,0 +1,12 @@ +{ + "Name":"zinx v-0.10 demoApp", + "Host":"0.0.0.0", + "TCPPort":9090, + "MaxConn":3, + "WorkerPoolSize":10, + "LogDir": "./mylog", + "LogFile":"app.log", + "LogSaveDays":15, + "LogCons": true, + "LogIsolationLevel":0 +} \ No newline at end of file diff --git a/examples/zinx_decoder/server.go b/examples/zinx_decoder/server.go index 19a66e77..0b0bcb59 100644 --- a/examples/zinx_decoder/server.go +++ b/examples/zinx_decoder/server.go @@ -17,6 +17,7 @@ func DoConnectionLost(conn ziface.IConnection) { } func main() { + //zlog.SetLogFile("./logs", "app.log") s := znet.NewServer() s.SetOnConnStart(DoConnectionBegin) diff --git a/examples/zinx_logger/server.go b/examples/zinx_logger/server.go index 99ff9a09..10250d71 100644 --- a/examples/zinx_logger/server.go +++ b/examples/zinx_logger/server.go @@ -3,6 +3,7 @@ package main import ( "fmt" "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/zlog" "github.com/aceld/zinx/znet" "time" ) @@ -43,6 +44,6 @@ func (t *TestRouter) PostHandle(req ziface.IRequest) { func main() { s := znet.NewServer() s.AddRouter(1, &TestRouter{}) - //zlog.SetLogger(new(MyLogger)) + zlog.SetLogger(new(MyLogger)) s.Serve() } diff --git a/zconf/globalobj.go b/zconf/globalobj.go index 09e4b8f4..8bacaba9 100644 --- a/zconf/globalobj.go +++ b/zconf/globalobj.go @@ -24,10 +24,10 @@ const ( ) /* - Store all global parameters related to the Zinx framework for use by other modules. - Some parameters can also be configured by the user based on the zinx.json file. - (存储一切有关Zinx框架的全局参数,供其他模块使用 - 一些参数也可以通过 用户根据 zinx.json来配置) + Store all global parameters related to the Zinx framework for use by other modules. + Some parameters can also be configured by the user based on the zinx.json file. + (存储一切有关Zinx框架的全局参数,供其他模块使用 + 一些参数也可以通过 用户根据 zinx.json来配置) */ type Config struct { /* @@ -66,6 +66,10 @@ type Config struct { // (日志文件名称 默认"" --如果没有设置日志文件,打印信息将打印至stderr) LogFile string + LogSaveDays int // 日志最大保留天数 + LogFileSize int64 // 日志单个日志最大容量 默认 64MB,单位:字节,记得一定要换算成MB(1024 * 1024) + LogCons bool // 日志标准输出 默认 false + // The level of log isolation. The values can be 0 (all open), 1 (debug off), 2 (debug/info off), 3 (debug/info/warn off), and so on. //日志隔离级别 -- 0:全开 1:关debug 2:关debug/info 3:关debug/info/warn ... LogIsolationLevel int @@ -85,7 +89,7 @@ type Config struct { } /* - Define a global object.(定义一个全局的对象) +Define a global object.(定义一个全局的对象) */ var GlobalObject *Config @@ -154,6 +158,13 @@ func (g *Config) HeartbeatMaxDuration() time.Duration { func (g *Config) InitLogConfig() { if g.LogFile != "" { zlog.SetLogFile(g.LogDir, g.LogFile) + zlog.SetCons(g.LogCons) + } + if g.LogSaveDays > 0 { + zlog.SetMaxAge(g.LogSaveDays) + } + if g.LogFileSize > 0 { + zlog.SetMaxSize(g.LogFileSize) } if g.LogIsolationLevel > zlog.LogDebug { zlog.SetLogLevel(g.LogIsolationLevel) @@ -161,7 +172,7 @@ func (g *Config) InitLogConfig() { } /* - init, set default value +init, set default value */ func init() { pwd, err := os.Getwd() diff --git a/zlog/logger_core.go b/zlog/logger_core.go index a326ab2d..f628af5d 100644 --- a/zlog/logger_core.go +++ b/zlog/logger_core.go @@ -18,10 +18,10 @@ package zlog import ( "bytes" "fmt" - "io" + "github.com/aceld/zinx/zutils" "os" + "path/filepath" "runtime" - "strings" "sync" "time" ) @@ -75,17 +75,9 @@ type ZinxLoggerCore struct { // log tag bit (日志标记位) flag int - // the file descriptor for log output - // (日志输出的文件描述符) - out io.Writer - // the output buffer (输出的缓冲区) buf bytes.Buffer - // the output file currently bound to the log - // (当前日志绑定的输出文件) - file *os.File - // log isolation level // (日志隔离级别) isolationLevel int @@ -94,21 +86,7 @@ type ZinxLoggerCore struct { // (获取日志文件名和代码上述的runtime.Call 的函数调用层数) calldDepth int - // log file name - // (日志文件名称) - fileName string - - // log file directory - // (日志文件目录) - fileDir string - - // last write date - // (上次写入日期) - lastWriteDate int - - // file swap lock - // (文件交换锁) - fsLock sync.Mutex + fw *zutils.Writer onLogHook func([]byte) } @@ -120,11 +98,11 @@ out: The file io for standard output prefix: The prefix of the log flag: The flag of the log header information */ -func NewZinxLog(out io.Writer, prefix string, flag int) *ZinxLoggerCore { +func NewZinxLog(prefix string, flag int) *ZinxLoggerCore { // By default, debug is turned on, the depth is 2, and the ZinxLogger object calling the log print method can call up to two levels to reach the output function // (默认 debug打开, calledDepth深度为2,ZinxLogger对象调用日志打印方法最多调用两层到达output函数) - zlog := &ZinxLoggerCore{out: out, prefix: prefix, flag: flag, file: nil, isolationLevel: 0, calldDepth: 2} + zlog := &ZinxLoggerCore{prefix: prefix, flag: flag, isolationLevel: 0, calldDepth: 2} // Set the log object's resource cleanup destructor method (this is not necessary, as go's Gc will automatically collect, but for the sake of neatness) // (设置log对象 回收资源 析构方法(不设置也可以,go的Gc会自动回收,强迫症没办法)) @@ -245,23 +223,19 @@ func (log *ZinxLoggerCore) OutPut(level int, s string) error { log.buf.WriteByte('\n') } - log.updateOutputFile() - var err error - if log.file == nil { + if log.fw == nil { // if log file is not set, output to console _, _ = os.Stderr.Write(log.buf.Bytes()) } else { // write the filled buffer to IO output - _, err = log.out.Write(log.buf.Bytes()) + _, err = log.fw.Write(log.buf.Bytes()) } if log.onLogHook != nil { log.onLogHook(log.buf.Bytes()) } - return err - } func (log *ZinxLoggerCore) verifyLogIsolation(logLevel int) bool { @@ -407,66 +381,48 @@ func (log *ZinxLoggerCore) SetPrefix(prefix string) { // SetLogFile sets the log file output // (设置日志文件输出) func (log *ZinxLoggerCore) SetLogFile(fileDir string, fileName string) { - log.fileDir = fileDir - log.fileName = fileName -} - -// Close the file associated with the log -// (关闭日志绑定的文件) -func (log *ZinxLoggerCore) closeFile() { - if log.file != nil { - _ = log.file.Close() - log.file = nil - log.out = os.Stderr + if log.fw != nil { + log.fw.Close() } + log.fw = zutils.New(filepath.Join(fileDir, fileName)) } -// update the output file for the log -// (更新文件输出) -func (log *ZinxLoggerCore) updateOutputFile() { - - var file *os.File - - yearDay := time.Now().YearDay() - - if log.lastWriteDate == yearDay && log.file != nil { +// SetMaxAge 最大保留天数 +func (log *ZinxLoggerCore) SetMaxAge(ma int) { + if log.fw == nil { return } + log.mu.Lock() + defer log.mu.Unlock() + log.fw.SetMaxAge(ma) +} - log.fsLock.Lock() - defer log.fsLock.Unlock() - - if log.lastWriteDate == yearDay && log.file != nil { +// SetMaxSize 单个日志最大容量 单位:字节 +func (log *ZinxLoggerCore) SetMaxSize(ms int64) { + if log.fw == nil { return } + log.mu.Lock() + defer log.mu.Unlock() + log.fw.SetMaxSize(ms) +} - log.lastWriteDate = yearDay - - // create the log directory - _ = mkdirLog(log.fileDir) - - // define the log file name = log file name . date suffix . log - // supported file name formats: - // 1. "zinx.log" - // 2. "zinx" - // 3. "zinx.zinx.zinx.log" - realFileNameSlice := strings.Split(log.fileName, ".log") - realFileName := realFileNameSlice[0] - newDailyFile := log.fileDir + "/" + realFileName + "." + time.Now().Format("20060102") + ".log" - - if log.checkFileExist(newDailyFile) { - file, _ = os.OpenFile(newDailyFile, os.O_APPEND|os.O_RDWR, 0644) // rw-r--r-- - } else { - file, _ = os.OpenFile(newDailyFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644) +// SetCons 同时输出控制台 +func (log *ZinxLoggerCore) SetCons(b bool) { + if log.fw == nil { + return } + log.mu.Lock() + defer log.mu.Unlock() + log.fw.SetCons(b) +} - if log.file != nil { - log.closeFile() +// Close the file associated with the log +// (关闭日志绑定的文件) +func (log *ZinxLoggerCore) closeFile() { + if log.fw != nil { + log.fw.Close() } - - log.file = file - log.out = file - } func (log *ZinxLoggerCore) SetLogLevel(logLevel int) { @@ -481,19 +437,6 @@ func (log *ZinxLoggerCore) checkFileExist(filename string) bool { return exist } -func mkdirLog(dir string) (e error) { - _, er := os.Stat(dir) - b := er == nil || os.IsExist(er) - if !b { - if err := os.MkdirAll(dir, 0775); err != nil { - if os.IsPermission(err) { - e = err - } - } - } - return -} - // Convert an integer to a fixed-length string, where the width of the string should be greater than 0 // Ensure that the buffer has sufficient capacity // (将一个整形转换成一个固定长度的字符串,字符串宽度应该是大于0的 diff --git a/zlog/stdzlog.go b/zlog/stdzlog.go index e16da980..df74ee2d 100644 --- a/zlog/stdzlog.go +++ b/zlog/stdzlog.go @@ -21,10 +21,8 @@ package zlog zlog.Ins().InfoF()等方法 */ -import "os" - // StdZinxLog creates a global log -var StdZinxLog = NewZinxLog(os.Stderr, "", BitDefault) +var StdZinxLog = NewZinxLog("", BitDefault) // Flags gets the flags of StdZinxLog func Flags() int { @@ -51,6 +49,21 @@ func SetLogFile(fileDir string, fileName string) { StdZinxLog.SetLogFile(fileDir, fileName) } +// SetMaxAge 最大保留天数 +func SetMaxAge(ma int) { + StdZinxLog.SetMaxAge(ma) +} + +// SetMaxSize 单个日志最大容量 单位:字节 +func SetMaxSize(ms int64) { + StdZinxLog.SetMaxSize(ms) +} + +// SetCons 同时输出控制台 +func SetCons(b bool) { + StdZinxLog.SetCons(b) +} + // SetLogLevel sets the log level of StdZinxLog func SetLogLevel(logLevel int) { StdZinxLog.SetLogLevel(logLevel) diff --git a/zutils/witer.go b/zutils/witer.go index e5f64dd6..6a83bb7c 100644 --- a/zutils/witer.go +++ b/zutils/witer.go @@ -11,6 +11,10 @@ import ( "time" ) +/* +add by uuxia +代码出处:https://github.com/zxysilent/logs +*/ const ( sizeMiB = 1024 * 1024 defMaxAge = 31 @@ -52,10 +56,10 @@ func New(path string) *Writer { go w.daemon() return w } -func (w *Writer) daemon() { - for range time.NewTicker(time.Second * 5).C { - w.flush() - } + +func (w *Writer) Close() error { + w.flush() + return w.close() } // SetMaxAge 最大保留天数 @@ -186,11 +190,6 @@ func (w *Writer) time2name(t time.Time) string { return t.Format(".2006-01-02-150405") } -func (w *Writer) Close() error { - w.flush() - return w.close() -} - // close closes the file if it is open. func (w *Writer) close() error { w.mu.Lock() @@ -264,3 +263,9 @@ func appendInt(b []byte, x int, width int) []byte { b[i] = utod(u) return b } + +func (w *Writer) daemon() { + for range time.NewTicker(time.Second * 5).C { + w.flush() + } +}