logging: add logger system with levels

The built-in logging system is rather basic. Implement a multi-level
logger to ease interpreting the logs. Configure the loggers with
prefixes and microsecond precision for timestamps.

Also, prefix the messages with the source file name and line number.
Because of this, enabling the logs has a performance cost. They will
only be enabled when redirecting aerc stdout to a file.

Here is an example output:

DEBUG 2022/07/20 12:52:34.536190 worker.go:45: PostAction *types.FetchDirectoryContents
DEBUG 2022/07/20 12:52:34.536329 worker.go:92: ProcessAction *types.FetchDirectoryContents(2417)
DEBUG 2022/07/20 12:52:34.536407 idler.go:159: idler (0xc00017c000) [idle:false,wait:false] =>(idle) [debounce]
INFO  2022/07/20 12:52:34.536432 threadbuilder.go:59: 130 threads created in 220.796µs
DEBUG 2022/07/20 12:52:34.536449 worker.go:75: ProcessMessage *types.DirectoryInfo(2416)
DEBUG 2022/07/20 12:52:34.536453 idler.go:159: idler (0xc00017c000) [idle:false,wait:false] <=(idle)
DEBUG 2022/07/20 12:52:34.536459 worker.go:45: PostAction *types.FetchDirectoryContents
INFO  2022/07/20 12:52:34.536470 open.go:30: Fetching UID list
INFO  2022/07/20 12:52:34.536689 threadbuilder.go:59: 130 threads created in 201.635µs

Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Moritz Poldrack <moritz@poldrack.dev>
This commit is contained in:
Robin Jarry 2022-07-19 22:31:25 +02:00
parent b188f19131
commit a1f779ccc9

70
logging/logger.go Normal file
View file

@ -0,0 +1,70 @@
package logging
import (
"fmt"
"io/ioutil"
"log"
"os"
)
var (
dbg *log.Logger
info *log.Logger
warn *log.Logger
err *log.Logger
)
func Init() {
flags := log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile | log.LUTC
dbg = log.New(os.Stdout, "DEBUG ", flags)
info = log.New(os.Stdout, "INFO ", flags)
warn = log.New(os.Stdout, "WARN ", flags)
err = log.New(os.Stdout, "ERROR ", flags)
}
func ErrorLogger() *log.Logger {
if err == nil {
return log.New(ioutil.Discard, "", log.LstdFlags)
}
return err
}
func Debugf(message string, args ...interface{}) {
if dbg == nil {
return
}
if len(args) > 0 {
message = fmt.Sprintf(message, args...)
}
dbg.Output(2, message)
}
func Infof(message string, args ...interface{}) {
if info == nil {
return
}
if len(args) > 0 {
message = fmt.Sprintf(message, args...)
}
info.Output(2, message)
}
func Warnf(message string, args ...interface{}) {
if warn == nil {
return
}
if len(args) > 0 {
message = fmt.Sprintf(message, args...)
}
warn.Output(2, message)
}
func Errorf(message string, args ...interface{}) {
if err == nil {
return
}
if len(args) > 0 {
message = fmt.Sprintf(message, args...)
}
err.Output(2, message)
}