Go log library focused on humans and thread safety
MIT License
Go simple yet powerful logging library
This log library focuses on:
go get github.com/qdm12/log
The logger constructor log.New()
uses functional options.
By default the logger:
os.Stdout
INFO
levelpackage main
import "github.com/qdm12/log"
func main() {
logger := log.New()
logger.Info("my message")
// 2022-03-28T10:03:29Z INFO my message
}
Each level log method such as Warn(s string)
has a corresponding formatting method with a trailing f
such as Warnf(format string, args ...interface{})
. For example:
package main
import "github.com/qdm12/log"
func main() {
logger := log.New()
logger.Warnf("message number %d", 1)
// 2022-03-29T07:40:12Z WARN message number 1
}
You can customize the logger creation with for example:
package main
import "github.com/qdm12/log"
func main() {
logger := log.New(
log.SetLevel(log.LevelDebug),
log.SetTimeFormat(time.RFC822),
log.SetWriters(os.Stdout, os.Stderr),
log.SetComponent("module"),
log.SetCallerFile(true),
log.SetCallerFunc(true),
log.SetCallerLine(true))
logger.Info("my message")
// 29 Mar 22 07:16 UTC INFO [module] my message main.go:L19:main
// 29 Mar 22 07:16 UTC INFO [module] my message main.go:L19:main
}
This should be the preferred way to create additional loggers with different settings, since it favors dependency injection.
For example, we create logger loggerB
from loggerA
which inherits the settings from loggerA
and changes the component setting.
package main
import (
"github.com/qdm12/log"
)
func main() {
loggerA := log.New(log.SetComponent("A"))
loggerB := loggerA.New(log.SetComponent("B"))
loggerA.Info("my message")
// 2022-03-29T07:35:08Z INFO [A] my message
loggerB.Info("my message")
// 2022-03-29T07:35:08Z INFO [B] my message
}
Note this is a thread safe operation, and thread safety on the writers is also maintained.
You can create multiple loggers with the global constructor log.New()
, and writers will be thread safe to write to. For example the following won't write to the buffer at the same time:
package main
import (
"bytes"
"time"
"github.com/qdm12/log"
)
func main() {
writer := bytes.NewBuffer(nil)
timer := time.NewTimer(time.Second)
const parallelism = 2
for i := 0; i < parallelism; i++ {
go func() {
logger := log.New(log.SetWriters(writer))
for {
select {
case <-timer.C:
return
default:
logger.Info("my message")
}
}
}()
}
}
You can try it with CGO_ENABLED=1 go run -race ./examples/global
to ensure there is no data race.
The following features are available:
DEBUG
, INFO
, WARN
, ERROR
time.RFC3339
io.Writer
io.Writer
for multiple loggersDebugf
, Infof
, Warnf
, Errorf
This logging library is thread safe for each writer. To achieve, it uses a global map from writer address to mutex pointer.
⚠️ This however means that this map will not shrink at any time. If you want to use this logging library with thousands of different writers, you should not use it as it is, please create an issue.
See Contributing
This repository is under an MIT license