You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gol/logger.go

141 lines
3.3 KiB

package logger
import (
"fmt"
"log"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/getsentry/raven-go"
"github.com/tchap/zapext/zapsentry"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
)
var zapLogger *zap.Logger
func Named(name string) *zap.Logger {
return zapLogger.Named(name)
}
func With(fields ...zap.Field) *zap.Logger {
return zapLogger.With(fields...)
}
func LogPanic(msg string) {
if r := recover(); r != nil {
buf := make([]byte, 10240)
n := runtime.Stack(buf, false)
err := fmt.Sprintf("%v\n\n%s", r, buf[:n])
Error(msg, zap.String("error", err))
time.Sleep(5 * time.Second) // wait to write logs and sent to sentry
}
}
func Fatal(msg string, fields ...zap.Field) {
zapLogger.Fatal(msg, fields...)
}
func Error(msg string, fields ...zap.Field) {
zapLogger.Error(msg, fields...)
}
func Warn(msg string, fields ...zap.Field) {
zapLogger.Warn(msg, fields...)
}
func Info(msg string, fields ...zap.Field) {
zapLogger.Info(msg, fields...)
}
func Debug(msg string, fields ...zap.Field) {
zapLogger.Debug(msg, fields...)
}
func Sync() error {
return zapLogger.Sync()
}
func buildErrorsFilename(logFileName string) string {
ext := path.Ext(logFileName)
errFileName := strings.TrimSuffix(path.Base(logFileName), ext)
errFileName += "-errors" + ext
return filepath.Join(path.Dir(logFileName), errFileName)
}
func Init(conf *Configuration) {
cfg := zap.NewProductionEncoderConfig()
cfg.EncodeTime = zapcore.RFC3339NanoTimeEncoder
cores := []zapcore.Core{
zapcore.NewCore(zapcore.NewJSONEncoder(cfg), zapcore.Lock(os.Stdout), loggingLevelGTE(conf.Stdout.Level)),
}
// file logger
if conf.File.Enabled {
loggerConf := conf.File
fileLevelEnabler := loggingLevelGTE(loggerConf.Level)
writer := zapcore.AddSync(
&lumberjack.Logger{
Filename: loggerConf.Filename,
LocalTime: loggerConf.LocalTime,
MaxSize: loggerConf.MaxSize,
MaxBackups: loggerConf.MaxBackups,
},
)
cores = append(cores, zapcore.NewCore(zapcore.NewJSONEncoder(cfg), writer, fileLevelEnabler))
redirectStderrToFile(conf)
}
// sentry
if conf.Sentry.DSN != "" {
loggerConf := conf.Sentry
tags := map[string]string{
"env": os.Getenv("ENVIRONMENT"),
}
client, err := raven.NewWithTags(loggerConf.DSN, tags)
if err != nil {
log.Fatal("failed to get a Sentry client", err)
}
sentryLevelEnabler := loggingLevelGTE(loggerConf.Level)
cores = append(cores, zapsentry.NewCore(sentryLevelEnabler, client))
}
core := zapcore.NewTee(cores...)
logger := zap.New(core)
defer func() {
_ = logger.Sync()
}()
SetLogger(logger)
}
type levelComparator func(msgLevel zapcore.Level, loggingLevel zapcore.Level) bool
func loggingLevelGTE(level string) zap.LevelEnablerFunc {
return loggingLevelEnabledFunc(
level, func(msgLevel zapcore.Level, loggingLevel zapcore.Level) bool {
return msgLevel >= loggingLevel
},
)
}
func loggingLevelEnabledFunc(level string, comparator levelComparator) zap.LevelEnablerFunc {
var loggingLevel zapcore.Level
if err := loggingLevel.UnmarshalText([]byte(level)); err != nil {
log.Fatal("Fail parse console log level", err)
}
return func(msgLevel zapcore.Level) bool {
return comparator(msgLevel, loggingLevel)
}
}
func SetLogger(logger *zap.Logger) {
zapLogger = logger
}