From 0142c2e08a11278d2de82899b84cb8ec93878ff0 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 24 Aug 2018 23:41:58 +0800 Subject: [PATCH] =?UTF-8?q?glog=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E7=89=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/os/glog/glog.go | 38 +++++++++++++++++---------- g/os/glog/glog_logger.go | 50 +++++++++++++++++++++++++++++++----- geg/os/glog/glog_category.go | 13 ++++++++++ geg/os/glog/glog_error.go | 2 +- 4 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 geg/os/glog/glog_category.go diff --git a/g/os/glog/glog.go b/g/os/glog/glog.go index c042c4d5b..5f7416074 100644 --- a/g/os/glog/glog.go +++ b/g/os/glog/glog.go @@ -12,28 +12,35 @@ import ( "io" "sync" "gitee.com/johng/gf/g/container/gtype" + "gitee.com/johng/gf/g/container/gmap" ) type Logger struct { - mu sync.RWMutex - io io.Writer // 日志内容写入的IO接口 - path *gtype.String // 日志写入的目录路径 - debug *gtype.Bool // 是否允许输出DEBUG信息 - btSkip *gtype.Int // 错误产生时的backtrace回调信息skip条数 - stdprint *gtype.Bool // 控制台打印开关 @author zseeker + mu sync.RWMutex + pr *Logger // 父级Logger + io io.Writer // 日志内容写入的IO接口 + path *gtype.String // 日志写入的目录路径 + debug *gtype.Bool // 是否允许输出DEBUG信息 + btSkip *gtype.Int // 错误产生时的backtrace回调信息skip条数 + stdprint *gtype.Bool // 控制台打印开关,当输出到文件时也同时打印到终端 + // @author zseeker,john } -// 默认的日志对象 -var logger = New() +var ( + // 默认的日志对象 + logger = New() + // 基于文件路径的logger对象集合,用于对象复用 + loggerMap = gmap.NewStringInterfaceMap() +) // 新建自定义的日志操作对象 func New() *Logger { return &Logger { - io : nil, - path : gtype.NewString(), - debug : gtype.NewBool(true), - btSkip : gtype.NewInt(3), - stdprint : gtype.NewBool(false), + io : nil, + path : gtype.NewString(), + debug : gtype.NewBool(true), + btSkip : gtype.NewInt(3), + stdprint : gtype.NewBool(true), } } @@ -52,6 +59,11 @@ func GetPath() string { return logger.path.Val() } +// 设置下一次输出的分类,支持多级分类设置 +func Cat(category string) *Logger { + return logger.Cat(category) +} + // 设置写日志的同时开启or关闭控制台打印,默认是关闭的 // @author zseeker // @date 2018-05-24 diff --git a/g/os/glog/glog_logger.go b/g/os/glog/glog_logger.go index 4b49549bb..fce0a3b89 100644 --- a/g/os/glog/glog_logger.go +++ b/g/os/glog/glog_logger.go @@ -18,6 +18,7 @@ import ( "gitee.com/johng/gf/g/os/gfile" "gitee.com/johng/gf/g/util/gregex" "gitee.com/johng/gf/g/os/gfilepool" + "gitee.com/johng/gf/g/container/gtype" ) const ( @@ -36,23 +37,56 @@ func init() { } } +// Logger浅拷贝,除了path,其他都是父对象属性的指针 +func (l *Logger) Clone() *Logger { + return &Logger { + pr : l, + io : l.GetIO(), + path : gtype.NewString(l.path.Val()), + debug : l.debug, + btSkip : l.btSkip, + stdprint : l.stdprint, + } +} + +// 设置下一次输出的日志分类(可以按照文件目录层级设置),在当前logpath或者当前工作目录下创建category目录, +// 这是一个链式操作,可以设置多个分类,将会创建层级的日志分类目录。 +func (l *Logger) Cat(category string) *Logger { + path := l.path.Val() + if path == "" { + path = gfile.Pwd() + } + path += gfile.Separator + category + if v := loggerMap.Get(path); v != nil { + return v.(*Logger) + } else { + logger := l.Clone() + logger.SetPath(path) + loggerMap.Set(path, logger) + return logger + } +} + // 设置BacktraceSkip func (l *Logger) SetBacktraceSkip(skip int) { l.btSkip.Set(skip) } -// 可自定义IO接口 +// 可自定义IO接口,IO可以是文件输出、标准输出、网络输出 func (l *Logger) SetIO(w io.Writer) { l.mu.Lock() l.io = w l.mu.Unlock() } -// 返回自定义IO +// 返回自定义的IO,默认为nil func (l *Logger) GetIO() io.Writer { l.mu.RLock() r := l.io l.mu.RUnlock() + if r == nil && l.pr != nil { + return l.pr.GetIO() + } return r } @@ -82,7 +116,7 @@ func (l *Logger) SetPath(path string) error { // 检测目录权限 if !gfile.Exists(path) { if err := gfile.Mkdir(path); err != nil { - fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, "glog mkdir failed: " + err.Error()) return err } } @@ -103,19 +137,21 @@ func (l *Logger) SetStdPrint(open bool) { } // 这里的写锁保证统一时刻只会写入一行日志,防止串日志的情况 -func (l *Logger) print(defaultIO io.Writer, s string) { +func (l *Logger) print(def io.Writer, s string) { + // 优先使用自定义的IO输出 writer := l.GetIO() if writer == nil { + // 如果设置的IO为空,那么其次判断是否有文件输出设置 if f := l.getFileByPool(); f != nil { writer = f - // 同时输出到文件和终端 + // 如果有文件设置那么需要判断是否同时输出到文件和终端 // @author zseeker if l.stdprint.Val() { - writer = io.MultiWriter(writer, defaultIO) + writer = io.MultiWriter(writer, def) } defer f.Close() } else { - writer = defaultIO + writer = def } } l.mu.Lock() diff --git a/geg/os/glog/glog_category.go b/geg/os/glog/glog_category.go new file mode 100644 index 000000000..a03aed097 --- /dev/null +++ b/geg/os/glog/glog_category.go @@ -0,0 +1,13 @@ +package main + +import ( + "gitee.com/johng/gf/g/os/glog" +) + +func main() { + glog.SetPath("/tmp/") + glog.Cat("test1").Cat("test2").Println("test") + glog.Println("test") +} + + diff --git a/geg/os/glog/glog_error.go b/geg/os/glog/glog_error.go index b4259b537..9f78bbb78 100644 --- a/geg/os/glog/glog_error.go +++ b/geg/os/glog/glog_error.go @@ -5,7 +5,7 @@ import ( ) func main() { - //glog.SetLogPath("/tmp/") + //glog.SetPath("/tmp/") glog.Error("This is error!") }