2019-11-25 17:33:58 -05:00
|
|
|
package log
|
2019-06-20 18:36:40 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
2021-09-17 19:00:59 -05:00
|
|
|
"runtime"
|
|
|
|
"strconv"
|
2021-05-25 03:38:21 -05:00
|
|
|
"strings"
|
2022-09-26 10:18:28 -05:00
|
|
|
"sync"
|
2019-06-20 18:36:40 -05:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/rs/zerolog"
|
|
|
|
)
|
|
|
|
|
2021-12-13 14:23:31 -05:00
|
|
|
const defaultPerms = 0o0600
|
|
|
|
|
2022-10-05 05:21:14 -05:00
|
|
|
//nolint:gochecknoglobals
|
2022-09-26 10:18:28 -05:00
|
|
|
var loggerSetTimeFormat sync.Once
|
|
|
|
|
2020-05-11 17:13:24 -05:00
|
|
|
// Logger extends zerolog's Logger.
|
2019-11-25 17:33:58 -05:00
|
|
|
type Logger struct {
|
|
|
|
zerolog.Logger
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l Logger) Println(v ...interface{}) {
|
2023-12-08 03:05:02 -05:00
|
|
|
l.Logger.Error().Msg("panic recovered") //nolint: check-logs
|
2019-11-25 17:33:58 -05:00
|
|
|
}
|
|
|
|
|
2022-03-21 12:37:23 -05:00
|
|
|
func NewLogger(level, output string) Logger {
|
2022-09-26 10:18:28 -05:00
|
|
|
loggerSetTimeFormat.Do(func() {
|
|
|
|
zerolog.TimeFieldFormat = time.RFC3339Nano
|
|
|
|
})
|
2019-12-13 00:53:18 -05:00
|
|
|
|
2021-12-13 14:23:31 -05:00
|
|
|
lvl, err := zerolog.ParseLevel(level)
|
2019-06-20 18:36:40 -05:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2019-12-13 00:53:18 -05:00
|
|
|
|
2019-06-20 18:36:40 -05:00
|
|
|
zerolog.SetGlobalLevel(lvl)
|
2019-12-13 00:53:18 -05:00
|
|
|
|
2019-06-20 18:36:40 -05:00
|
|
|
var log zerolog.Logger
|
2019-12-13 00:53:18 -05:00
|
|
|
|
2019-11-25 17:33:58 -05:00
|
|
|
if output == "" {
|
2019-06-20 18:36:40 -05:00
|
|
|
log = zerolog.New(os.Stdout)
|
|
|
|
} else {
|
2021-12-13 14:23:31 -05:00
|
|
|
file, err := os.OpenFile(output, os.O_APPEND|os.O_WRONLY|os.O_CREATE, defaultPerms)
|
2019-06-20 18:36:40 -05:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2024-07-29 12:32:51 -05:00
|
|
|
|
2019-06-20 18:36:40 -05:00
|
|
|
log = zerolog.New(file)
|
|
|
|
}
|
2019-12-13 00:53:18 -05:00
|
|
|
|
2021-09-17 19:00:59 -05:00
|
|
|
return Logger{Logger: log.Hook(goroutineHook{}).With().Caller().Timestamp().Logger()}
|
2019-06-20 18:36:40 -05:00
|
|
|
}
|
|
|
|
|
2023-11-01 11:16:18 -05:00
|
|
|
func NewAuditLogger(level, output string) *Logger {
|
2022-09-26 10:18:28 -05:00
|
|
|
loggerSetTimeFormat.Do(func() {
|
|
|
|
zerolog.TimeFieldFormat = time.RFC3339Nano
|
|
|
|
})
|
2021-05-25 03:38:21 -05:00
|
|
|
|
2021-12-13 14:23:31 -05:00
|
|
|
lvl, err := zerolog.ParseLevel(level)
|
2021-05-25 03:38:21 -05:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
zerolog.SetGlobalLevel(lvl)
|
|
|
|
|
|
|
|
var auditLog zerolog.Logger
|
|
|
|
|
2023-11-01 11:16:18 -05:00
|
|
|
if output == "" {
|
|
|
|
auditLog = zerolog.New(os.Stdout)
|
|
|
|
} else {
|
|
|
|
auditFile, err := os.OpenFile(output, os.O_APPEND|os.O_WRONLY|os.O_CREATE, defaultPerms)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2021-05-25 03:38:21 -05:00
|
|
|
|
2023-11-01 11:16:18 -05:00
|
|
|
auditLog = zerolog.New(auditFile)
|
|
|
|
}
|
2021-05-25 03:38:21 -05:00
|
|
|
|
|
|
|
return &Logger{Logger: auditLog.With().Timestamp().Logger()}
|
|
|
|
}
|
|
|
|
|
2022-01-20 23:11:44 -05:00
|
|
|
// GoroutineID adds goroutine-id to logs to help debug concurrency issues.
|
|
|
|
func GoroutineID() int {
|
2021-09-17 19:00:59 -05:00
|
|
|
var buf [64]byte
|
|
|
|
n := runtime.Stack(buf[:], false)
|
|
|
|
idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
|
|
|
|
|
|
|
|
id, err := strconv.Atoi(idField)
|
|
|
|
if err != nil {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
|
|
|
type goroutineHook struct{}
|
|
|
|
|
2023-05-10 12:15:33 -05:00
|
|
|
func (h goroutineHook) Run(e *zerolog.Event, level zerolog.Level, _ string) {
|
2021-09-17 19:00:59 -05:00
|
|
|
if level != zerolog.NoLevel {
|
2022-01-20 23:11:44 -05:00
|
|
|
e.Int("goroutine", GoroutineID())
|
2021-09-17 19:00:59 -05:00
|
|
|
}
|
|
|
|
}
|