Provide logger.SetNoLock() to remove locking during log output
Locking is enabled by default. When file is opened with appending mode,
it's safe to write concurrently to a file. In this case user can
choose to disable the lock.
diff --git a/logger.go b/logger.go
index 9052a80..f3b6438 100644
--- a/logger.go
+++ b/logger.go
@@ -26,8 +26,29 @@
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
// logged. `logrus.Debug` is useful in
Level Level
- // Used to sync writing to the log.
- mu sync.Mutex
+ // Used to sync writing to the log. Locking is enabled by Default
+ mu MutexWrap
+}
+
+type MutexWrap struct {
+ lock sync.Mutex
+ disabled bool
+}
+
+func (mw *MutexWrap) Lock() {
+ if !mw.disabled {
+ mw.lock.Lock()
+ }
+}
+
+func (mw *MutexWrap) Unlock() {
+ if !mw.disabled {
+ mw.lock.Unlock()
+ }
+}
+
+func (mw *MutexWrap) Disable() {
+ mw.disabled = true
}
// Creates a new logger. Configuration should be set by changing `Formatter`,
@@ -210,3 +231,10 @@
NewEntry(logger).Panicln(args...)
}
}
+
+//When file is opened with appending mode, it's safe to
+//write concurrently to a file (within 4k message on Linux).
+//In these cases user can choose to disable the lock.
+func (logger *Logger) SetNoLock() {
+ logger.mu.Disable()
+}
diff --git a/logger_bench_test.go b/logger_bench_test.go
index 28a1a26..dd23a35 100644
--- a/logger_bench_test.go
+++ b/logger_bench_test.go
@@ -22,6 +22,15 @@
doLoggerBenchmark(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
}
+func BenchmarkDummyLoggerNoLock(b *testing.B) {
+ nullf, err := os.OpenFile("/dev/null", os.O_WRONLY|os.O_APPEND, 0666)
+ if err != nil {
+ b.Fatalf("%v", err)
+ }
+ defer nullf.Close()
+ doLoggerBenchmarkNoLock(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
+}
+
func doLoggerBenchmark(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
logger := Logger{
Out: out,
@@ -35,3 +44,18 @@
}
})
}
+
+func doLoggerBenchmarkNoLock(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
+ logger := Logger{
+ Out: out,
+ Level: InfoLevel,
+ Formatter: formatter,
+ }
+ logger.SetNoLock()
+ entry := logger.WithFields(fields)
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ entry.Info("aaa")
+ }
+ })
+}