plugin architecture and flexible log system for golang
go get github.com/xfxdev/xlog import ( "github.com/xfxdev/xlog" ) strLogLevel := "INFO" // also maybe read from config. logLevel, suc := xlog.ParseLevel(strLogLevel) if suc == false{// failed to parse log level, will use the default level[INFO] instead." } xlog.SetLevel(logLevel) // write log to file. w2f, err := xlog.NewW2FileListener("") if err != nil{xlog.Fatal(err) } else{xlog.AddListener(w2f) } xlog.Info("server start...") xlog.Debugf("ip : %v", "127.0.0.1") ###Level logging
// xlog provide 6 logging levels. const ( PanicLevel Level = iota FatalLevel ErrorLevel WarnLevel InfoLevel DebugLevel ) you can call 'SetLevel' to change the log level. All the logs which level <= your set will be output. for example:
// all logs will be output because DEBUG is the max level. xlog.SetLevel(xlog.DebugLevel) // only Panic/Fatal/Error logs will be output because WARN/INFO/DEBUG > ERROR. xlog.SetLevel(xlog.ErrorLevel) ###Custom Log Layout xlog provide a flexible log layout system to custom the style of log output. What you need to do is just set the layout flags.
xlog.SetLayout('layout flags...') xlog provide some builtin layout:
// %y : year // %M : month // %d : day // %h : hour // %m : min // %s : second // %l : log msg // %L : log level // %F : file eg: /a/b/c/d.go // %f : short file eg: d.go // %i : line // %D : %y/%M/%d // %T : %h:%m:%s You can use a combination of them, for example:
// this mean every log message will have a '[level] year/month/day hour:min:sec' perfix, eg: xlog.SetLayout("%L %D %T %l") // outputs: [INFO] 2016/01/01 13:27:07 net start... [WARN] 2016/01/01 13:28:00 ... [DEBUG] 2016/01/01 13:28:00 accept... // add filename and line to log message. xlog.SetLayout("%L %D %T [%f(%i)] %l") // outputs: [INFO] 2016/01/01 13:27:07 [test.go:(72)] net start... [WARN] 2016/01/01 13:28:00 [test.go:(100)] ... [DEBUG] 2016/01/01 13:28:00 [test.go:(128)] accept... You can use any form of combination, even meaningless thing, such as more spaces, arbitrary symbols:
xlog.SetLayout("hahaha%L | %D %T [ABC] %l [i'm after hahaha]") // outputs: // notice the prefix 'hahaha', the spaces in the middle, and the suffix '[i'm after hahaha]' hahaha[INFO] | 2017/01/07 14:09:47 [ABC] net start... [i'm after hahaha] hahaha[WARN] | 2017/01/07 14:09:47 [ABC] ... [i'm after hahaha] hahaha[DEBUG] | 2017/01/07 14:09:47 [ABC] accept... [i'm after hahaha] NOTICE: If you doesn't call 'SetLayout', xlog will use '%L %D %T %l' by default.
###Output a log to different targets xlog use listener system to output the log message.
// A Listener simple typed of io.Writer type Listener io.Writer A logger can have multiple listeners, xlog have 2 builtin listener, which are os.Stderr and W2FileListener. xlog will output log to os.Stderr by default, but you can add W2FileListener to output the log to file.
w2f, err := xlog.NewW2FileListener("logfilePath...") if err != nil{xlog.Fatal(err) } else{xlog.AddListener(w2f) } In 'NewW2FileListener' function, xlog will use the 'logfilePath' to create log file, so please makesure your path is correct.
os.MkdirAll(filepath.Dir(logfilePath), os.ModePerm) Also, you can give a empty path to NewW2FileListener(""), this will create log file by simple rule. for example: If your app current path is 'a/b/c', and your app name is 'testapp' Then the log file will be 'a/b/c/log/testapp_2016_01_01.log'
w2f, err := xlog.NewW2FileListener("") // create log file at : 'a/b/c/log/test_2016_01_01.log' if err != nil{xlog.Fatal(err) } xlog.AddListener(w2f) You can create new listener according you need, just implement the io.Writer interface.
type Writer interface{Write(p []byte) (n int, err error) } ###Thread safety By default xlog is protected by mutex, so you can output logs in multiple goroutines.