go get github.com/go-pkgz/lgr
l := lgr.New(lgr.Msec, lgr.Debug, lgr.CallerFile, lgr.CallerFunc) // allow debug and caller info, timestamp with milliseconds
l.Logf("INFO some important message, %v", err)
l.Logf("DEBUG some less important message, %v", err)
output looks like this:
2018/01/07 13:02:34.000 INFO {svc/handler.go:101 h.MyFunc1} some important message, can't open file myfile.xyz
2018/01/07 13:02:34.015 DEBUG {svc/handler.go:155 h.MyFunc2} some less important message, file is too small`
Without lgr.Caller*
it will drop {caller}
part
lgr
package provides a single interfacelgr.L
with a single methodLogf(format string, args ...interface{})
. Function wrapperlgr.Func
allows to makelgr.L
from a function directly.- Default logger functionality can be used without
lgr.New
(see "global logger") - Two predefined loggers available:
lgr.NoOp
(do-nothing logger) andlgr.Std
(passing directly to stdlib log)
lgr.New
call accepts functional options:
lgr.Debug
- turn debug mode on to allow messages with "DEBUG" level (filtered otherwise)lgr.Out(io.Writer)
- sets the output writer, defaultos.Stdout
lgr.Err(io.Writer)
- sets the error writer, defaultos.Stderr
lgr.CallerFile
- adds the caller file infolgr.CallerFunc
- adds the caller function infolgr.CallerPkg
- adds the caller packagelgr.LevelBraces
- wraps levels with "[" and "]"lgr.Msec
- adds milliseconds to timestamplgr.Format
- sets custom template, overwrite all other formatting modifiers.
example: l := lgr.New(lgr.Debug, lgr.Msec)
Several predefined templates provided and can be passed directly to lgr.Format
, i.e. lgr.Format(lgr.WithMsec)
Short = `{{.DT.Format "2006/01/02 15:04:05"}} {{.Level}} {{.Message}}`
WithMsec = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} {{.Message}}`
WithPkg = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerPkg}}) {{.Message}}`
ShortDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}}) {{.Message}}`
FuncDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFunc}}) {{.Message}}`
FullDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}} {{.CallerFunc}}) {{.Message}}`
User can make a custom template and pass it directly to lgr.Format
. For example:
lgr.Format(`{{.Level}} - {{.DT.Format "2006-01-02T15:04:05Z07:00"}} - {{.CallerPkg}} - {{.Message}}`)
Note: formatter (predefined or custom) adds measurable overhead - the cost will depend on the version of Go, but is between 30
and 50% in recent tests with 1.12. You can validate this in your environment via benchmarks: go test -bench=. -run=Bench
lgr.Logf
recognizes prefixes like "INFO" or "[INFO]" as levels. The full list of supported levels - "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "PANIC" and "FATAL"
TRACE
will be filtered unlesslgr.Trace
option definedDEBUG
will be filtered unlesslgr.Debug
orlgr.Trace
options definedINFO
andWARN
don't have any special behavior attachedERROR
sends messages to both out and err writersFATAL
and send messages to both out and err writers and exit(1)PANIC
does the same asFATAL
but in addition sends dump of callers and runtime info to err.
lgr
logger can be converted to io.Writer
or *log.Logger
lgr.ToWriter(l lgr.L, level string) io.Writer
- makes io.Writer forwarding write ops to underlyinglgr.L
lgr.ToStdLogger(l lgr.L, level string) *log.Logger
- makes standard logger on top oflgr.L
level
parameter is optional, if defined (non-empty) will enforce the level.
Users should avoid global logger and pass the concrete logger as a dependency. However, in some cases a global logger may be needed, for example migration from stdlib log
to lgr
. For such cases log "github.com/go-pkgz/lgr"
can be imported instead of log
package.
Global logger provides lgr.Printf
, lgr.Print
and lgr.Fatalf
functions. User can customize the logger by calling lgr.Setup(options ...)
. The instance of this logger can be retrieved with lgr.Default()