├── README.md ├── logger.go ├── default.go └── log.go /README.md: -------------------------------------------------------------------------------- 1 | # log 2 | 3 | a logger extend standard log package for baa. 4 | 5 | * more log level, Info/Warn/Error/Debug 6 | * more log method 7 | * optimize log write 8 | * used for configless 9 | 10 | ## Install 11 | 12 | * dependent [setting](github.com/go-baa/setting) package 13 | * optional config file: `conf/app.ini` 14 | 15 | ``` 16 | go get -u github.com/go-baa/setting 17 | go get -u github.com/go-baa/log 18 | ``` 19 | 20 | ## Usage 21 | 22 | ``` 23 | package main 24 | 25 | import ( 26 | "github.com/go-baa/log" 27 | ) 28 | 29 | func main() { 30 | log.Println("xx") 31 | log.Debugln("xx") 32 | } 33 | ``` 34 | 35 | ## Config 36 | 37 | config depend config file of `setting` ,you need add follow lines to config file: 38 | 39 | ``` 40 | // conf/app.ini 41 | [default] 42 | # output log to os.Stderr or filepath 43 | log.file = os.Stderr 44 | # 0 off, 1 fatal, 2 panic, 5 error, 6 warn, 10 info, 11 debug 45 | log.level = 11 46 | ``` 47 | 48 | `log.file` setting log to file, it is be a file path, also can be `os.Stderr` or `os.Stdout`. 49 | `log.level` setting log level, default is `5`, The greater the level of output error the more detailed. 50 | -------------------------------------------------------------------------------- /logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | // LogLevel 日志级别 4 | type LogLevel int 5 | 6 | const ( 7 | // !nashtsai! following level also match syslog.Priority value 8 | LOG_UNKNOWN LogLevel = iota - 2 // -2 9 | LOG_OFF LogLevel = iota - 1 // -1 10 | LOG_PRINT // 0 11 | LOG_FATAL // 1 12 | LOG_PANIC // 2 13 | LOG_ERROR LogLevel = iota + 1 // 5 14 | LOG_WARN // 6 15 | LOG_INFO LogLevel = iota + 4 // 11 16 | LOG_DEBUG // 12 17 | ) 18 | 19 | var levelNames = map[LogLevel]string{ 20 | LOG_UNKNOWN: "UNKNOWN", 21 | LOG_PRINT: "PRINT", 22 | LOG_FATAL: "FATAL", 23 | LOG_PANIC: "PANIC", 24 | LOG_ERROR: "ERROR", 25 | LOG_WARN: "WARN", 26 | LOG_INFO: "INFO", 27 | LOG_DEBUG: "DEBUG", 28 | } 29 | 30 | // Logger interface 31 | type Logger interface { 32 | Level() LogLevel 33 | SetLevel(l LogLevel) 34 | SetCopy(ch chan string) 35 | Flush() 36 | Print(v ...interface{}) 37 | Printf(format string, v ...interface{}) 38 | Println(v ...interface{}) 39 | Fatal(v ...interface{}) 40 | Fatalf(format string, v ...interface{}) 41 | Fatalln(v ...interface{}) 42 | Panic(v ...interface{}) 43 | Panicf(format string, v ...interface{}) 44 | Panicln(v ...interface{}) 45 | Error(v ...interface{}) 46 | Errorf(format string, v ...interface{}) 47 | Errorln(v ...interface{}) 48 | Warn(v ...interface{}) 49 | Warnf(format string, v ...interface{}) 50 | Warnln(v ...interface{}) 51 | Info(v ...interface{}) 52 | Infof(format string, v ...interface{}) 53 | Infoln(v ...interface{}) 54 | Debug(v ...interface{}) 55 | Debugf(format string, v ...interface{}) 56 | Debugln(v ...interface{}) 57 | Output(calldepth int, s string) error 58 | } 59 | -------------------------------------------------------------------------------- /default.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/go-baa/setting" 8 | ) 9 | 10 | // _defaultLogger 日志接口 11 | var _defaultLogger Logger 12 | 13 | // Default 返回默认日志器 14 | func Default() Logger { 15 | return _defaultLogger 16 | } 17 | 18 | func Level() LogLevel { 19 | return _defaultLogger.Level() 20 | } 21 | 22 | func SetLevel(l LogLevel) { 23 | _defaultLogger.SetLevel(l) 24 | } 25 | 26 | func SetCopy(ch chan string) { 27 | _defaultLogger.SetCopy(ch) 28 | } 29 | 30 | func Flush() { 31 | _defaultLogger.Flush() 32 | } 33 | 34 | func Print(v ...interface{}) { 35 | _defaultLogger.Print(v...) 36 | } 37 | 38 | func Printf(format string, v ...interface{}) { 39 | _defaultLogger.Printf(format, v...) 40 | } 41 | 42 | func Println(v ...interface{}) { 43 | _defaultLogger.Println(v...) 44 | } 45 | 46 | func Fatal(v ...interface{}) { 47 | _defaultLogger.Fatal(v...) 48 | } 49 | 50 | func Fatalf(format string, v ...interface{}) { 51 | _defaultLogger.Fatalf(format, v...) 52 | } 53 | 54 | func Fatalln(v ...interface{}) { 55 | _defaultLogger.Fatalln(v...) 56 | } 57 | 58 | func Panic(v ...interface{}) { 59 | _defaultLogger.Panic(v...) 60 | } 61 | 62 | func Panicf(format string, v ...interface{}) { 63 | _defaultLogger.Panicf(format, v...) 64 | } 65 | 66 | func Panicln(v ...interface{}) { 67 | _defaultLogger.Panicln(v...) 68 | } 69 | 70 | func Error(v ...interface{}) { 71 | _defaultLogger.Error(v...) 72 | } 73 | 74 | func Errorf(format string, v ...interface{}) { 75 | _defaultLogger.Errorf(format, v...) 76 | } 77 | 78 | func Errorln(v ...interface{}) { 79 | _defaultLogger.Errorln(v...) 80 | } 81 | 82 | func Warn(v ...interface{}) { 83 | _defaultLogger.Warn(v...) 84 | } 85 | 86 | func Warnf(format string, v ...interface{}) { 87 | _defaultLogger.Warnf(format, v...) 88 | } 89 | 90 | func Warnln(v ...interface{}) { 91 | _defaultLogger.Warnln(v...) 92 | } 93 | 94 | func Info(v ...interface{}) { 95 | _defaultLogger.Info(v...) 96 | } 97 | 98 | func Infof(format string, v ...interface{}) { 99 | _defaultLogger.Infof(format, v...) 100 | } 101 | 102 | func Infoln(v ...interface{}) { 103 | _defaultLogger.Infoln(v...) 104 | } 105 | 106 | func Debug(v ...interface{}) { 107 | _defaultLogger.Debug(v...) 108 | } 109 | 110 | func Debugf(format string, v ...interface{}) { 111 | _defaultLogger.Debugf(format, v...) 112 | } 113 | 114 | func Debugln(v ...interface{}) { 115 | _defaultLogger.Debugln(v...) 116 | } 117 | 118 | func Output(calldepth int, s string) error { 119 | _defaultLogger.(*tLogger).SetCallerLevel(calldepth) 120 | _defaultLogger.Println(s) 121 | return nil 122 | } 123 | 124 | func init() { 125 | var f *os.File 126 | file := setting.Config.MustString("log.file", "") 127 | if file == "" || file == "os.Stderr" { 128 | f = os.Stderr 129 | } else if file == "os.Stdout" { 130 | f = os.Stdout 131 | } else { 132 | var err error 133 | f, err = os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) 134 | if err != nil { 135 | log.Fatalf("error opening logfile: %v\n", err) 136 | } 137 | // 不能关闭文件 138 | //defer f.Close() 139 | } 140 | _defaultLogger = New(f, "["+setting.AppName+"] ", log.LstdFlags) 141 | _defaultLogger.SetLevel(LogLevel(setting.Config.MustInt("log.level", int(LOG_WARN)))) 142 | _defaultLogger.(*tLogger).SetCallerLevel(3) 143 | } 144 | -------------------------------------------------------------------------------- /log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "os" 8 | "runtime" 9 | "strings" 10 | "sync" 11 | ) 12 | 13 | const ( 14 | Ldate = log.Ldate // the date in the local time zone: 2009/01/23 15 | Ltime = log.Ltime // the time in the local time zone: 01:23:23 16 | Lmicroseconds = log.Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. 17 | Llongfile = log.Llongfile // full file name and line number: /a/b/c/d.go:23 18 | Lshortfile = log.Lshortfile // final file name element and line number: d.go:23. overrides Llongfile 19 | LUTC = log.LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone 20 | LstdFlags = log.LstdFlags // initial values for the standard logger 21 | ) 22 | 23 | type tLogger struct { 24 | logger *log.Logger 25 | level LogLevel 26 | callerLevel int 27 | flag int 28 | buf chan string 29 | copy chan string 30 | copyEnabled bool 31 | close chan struct{} 32 | mu sync.Mutex 33 | } 34 | 35 | // New 创建一个新的日志记录器 36 | func New(out io.Writer, prefix string, flag int) Logger { 37 | l := new(tLogger) 38 | l.logger = log.New(out, prefix, flag) 39 | l.level = LOG_DEBUG 40 | l.flag = flag 41 | l.callerLevel = 2 42 | 43 | // buffer flush 44 | l.buf = make(chan string, 128) 45 | l.close = make(chan struct{}) 46 | go func(l *tLogger) { 47 | for s := range l.buf { 48 | l.logger.Print(s) 49 | } 50 | l.close <- struct{}{} 51 | }(l) 52 | 53 | return l 54 | } 55 | 56 | // Flags returns the standard flags. 57 | func Flags() int { 58 | return LstdFlags 59 | } 60 | 61 | func (t *tLogger) Level() LogLevel { 62 | t.mu.Lock() 63 | defer t.mu.Unlock() 64 | return t.level 65 | } 66 | 67 | func (t *tLogger) SetLevel(level LogLevel) { 68 | t.mu.Lock() 69 | defer t.mu.Unlock() 70 | t.level = level 71 | } 72 | 73 | func (t *tLogger) SetCopy(ch chan string) { 74 | t.mu.Lock() 75 | defer t.mu.Unlock() 76 | t.copy = ch 77 | if ch == nil { 78 | t.copyEnabled = false 79 | } else { 80 | t.copyEnabled = true 81 | } 82 | } 83 | 84 | func (t *tLogger) LevelName(level LogLevel) string { 85 | if n, ok := levelNames[level]; ok { 86 | return n 87 | } 88 | return "^?^" 89 | } 90 | 91 | func (t *tLogger) SetCallerLevel(v int) { 92 | t.callerLevel = v 93 | } 94 | 95 | func (t *tLogger) Flush() { 96 | close(t.buf) 97 | <-t.close 98 | } 99 | 100 | func (t *tLogger) Print(v ...interface{}) { 101 | t.output(LOG_PRINT, "", false, v...) 102 | } 103 | 104 | func (t *tLogger) Printf(format string, v ...interface{}) { 105 | t.output(LOG_PRINT, format, false, v...) 106 | } 107 | 108 | func (t *tLogger) Println(v ...interface{}) { 109 | t.output(LOG_PRINT, "", true, v...) 110 | } 111 | 112 | func (t *tLogger) Fatal(v ...interface{}) { 113 | t.output(LOG_FATAL, "", false, v...) 114 | os.Exit(1) 115 | } 116 | 117 | func (t *tLogger) Fatalf(format string, v ...interface{}) { 118 | t.output(LOG_FATAL, format, false, v...) 119 | os.Exit(1) 120 | } 121 | 122 | func (t *tLogger) Fatalln(v ...interface{}) { 123 | t.output(LOG_FATAL, "", true, v...) 124 | os.Exit(1) 125 | } 126 | 127 | func (t *tLogger) Panic(v ...interface{}) { 128 | s := fmt.Sprint(v...) 129 | t.output(LOG_PANIC, "", false, s) 130 | panic(s) 131 | } 132 | 133 | func (t *tLogger) Panicf(format string, v ...interface{}) { 134 | s := fmt.Sprintf(format, v...) 135 | t.output(LOG_PANIC, "", false, s) 136 | panic(s) 137 | } 138 | 139 | func (t *tLogger) Panicln(v ...interface{}) { 140 | s := fmt.Sprintln(v...) 141 | t.output(LOG_PANIC, "", false, s) 142 | panic(s) 143 | } 144 | 145 | func (t *tLogger) Error(v ...interface{}) { 146 | t.output(LOG_ERROR, "", false, v...) 147 | } 148 | 149 | func (t *tLogger) Errorf(format string, v ...interface{}) { 150 | t.output(LOG_ERROR, format, false, v...) 151 | } 152 | 153 | func (t *tLogger) Errorln(v ...interface{}) { 154 | t.output(LOG_ERROR, "", true, v...) 155 | } 156 | 157 | func (t *tLogger) Warn(v ...interface{}) { 158 | t.output(LOG_WARN, "", false, v...) 159 | } 160 | 161 | func (t *tLogger) Warnf(format string, v ...interface{}) { 162 | t.output(LOG_WARN, format, false, v...) 163 | } 164 | 165 | func (t *tLogger) Warnln(v ...interface{}) { 166 | t.output(LOG_WARN, "", true, v...) 167 | } 168 | 169 | func (t *tLogger) Info(v ...interface{}) { 170 | t.output(LOG_INFO, "", false, v...) 171 | } 172 | 173 | func (t *tLogger) Infof(format string, v ...interface{}) { 174 | t.output(LOG_INFO, format, false, v...) 175 | } 176 | 177 | func (t *tLogger) Infoln(v ...interface{}) { 178 | t.output(LOG_INFO, "", true, v...) 179 | } 180 | 181 | func (t *tLogger) Debug(v ...interface{}) { 182 | t.output(LOG_DEBUG, "", false, v...) 183 | } 184 | 185 | func (t *tLogger) Debugf(format string, v ...interface{}) { 186 | t.output(LOG_DEBUG, format, false, v...) 187 | } 188 | 189 | func (t *tLogger) Debugln(v ...interface{}) { 190 | t.output(LOG_DEBUG, "", true, v...) 191 | } 192 | 193 | func (t *tLogger) Output(calldepth int, s string) error { 194 | t.SetCallerLevel(calldepth) 195 | t.Println(s) 196 | return nil 197 | } 198 | 199 | func (t *tLogger) output(level LogLevel, format string, newline bool, v ...interface{}) { 200 | if t.level == LOG_OFF { 201 | return 202 | } 203 | if t.level < level { 204 | return 205 | } 206 | 207 | // 记录调用者位置 208 | var s string 209 | _, file, line, ok := runtime.Caller(t.callerLevel) 210 | if !ok { 211 | file = "???" 212 | line = 0 213 | } 214 | if t.flag&(Lshortfile|Llongfile) != 0 { 215 | if t.flag&Lshortfile != 0 { 216 | pos := strings.LastIndex(file, "/") + 1 217 | file = string(file[pos:]) 218 | } 219 | s = fmt.Sprintf("%s:%d ", file, line) 220 | } 221 | 222 | // log level 223 | // don't output `print` level name 224 | if level != LOG_PRINT { 225 | s += fmt.Sprintf("[%s] ", t.LevelName(level)) 226 | } 227 | 228 | var formatText string 229 | if format == "" { 230 | var buf []string 231 | for i := range v { 232 | buf = append(buf, fmt.Sprintf("%v", v[i])) 233 | } 234 | formatText = strings.Join(buf, " ") 235 | } else { 236 | formatText = fmt.Sprintf(format, v...) 237 | } 238 | 239 | s += formatText 240 | 241 | if newline { 242 | s += "\n" 243 | } 244 | 245 | // PANIC, FATAL immediately output 246 | if level <= LOG_PANIC { 247 | t.logger.Print(s) 248 | } else { 249 | // in buffer 250 | t.buf <- s 251 | } 252 | 253 | // copy log stream 254 | if t.copyEnabled { 255 | go func() { 256 | t.copy <- s 257 | }() 258 | } 259 | } 260 | --------------------------------------------------------------------------------