logger.go 2.6 KB
Newer Older
W
wangzelin.wzl 已提交
1 2 3 4 5
package log

import (
	"fmt"
	"io"
O
ob-robot 已提交
6
	"os"
W
wangzelin.wzl 已提交
7 8
	"runtime"
	"strings"
O
ob-robot 已提交
9
	"sync"
W
wangzelin.wzl 已提交
10 11 12 13 14

	"github.com/sirupsen/logrus"
	"gopkg.in/natefinch/lumberjack.v2"
)

O
ob-robot 已提交
15 16 17 18
const (
	StartTimeKey = "startTime"
)

W
wangzelin.wzl 已提交
19 20 21
const defaultTimestampFormat = "2006-01-02T15:04:05.99999-07:00"

var textFormatter = &TextFormatter{
O
ob-robot 已提交
22
	TimestampFormat:        defaultTimestampFormat, // log timestamp format
W
wangzelin.wzl 已提交
23 24 25 26 27 28 29
	FullTimestamp:          true,
	DisableLevelTruncation: true,
	FieldMap: map[string]string{
		"WARNING": "WARN", // log level string, use WARN
	},
	// log caller, filename:line callFunction
	CallerPrettyfier: func(frame *runtime.Frame) (string, string) {
O
ob-robot 已提交
30
		filename := getPackage(frame.File)
W
wangzelin.wzl 已提交
31 32 33 34 35 36
		name := frame.Function
		idx := strings.LastIndex(name, ".")
		return name[idx+1:], fmt.Sprintf("%s:%d", filename, frame.Line)
	},
}

O
ob-robot 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
/**
 * wrap a writer to ignore error to avoid bad write cause logrus logger always print error messages.
 */
type noErrWriter struct {
	o sync.Once
	w io.WriteCloser
}

func (w *noErrWriter) Write(p []byte) (n int, err error) {
	n, err = w.w.Write(p)
	if err != nil {
		w.o.Do(func() {
			// only print error message once
			_, _ = fmt.Fprintf(os.Stderr, "write log failed %v\n", err)
		})
		return len(p), nil
	}
	return
}

func (w *noErrWriter) Close() error {
	return w.w.Close()
}

W
wangzelin.wzl 已提交
61 62 63 64 65 66 67 68 69 70 71 72
type LoggerConfig struct {
	Level      string `yaml:"level"`
	Filename   string `yaml:"filename"`
	MaxSize    int    `yaml:"maxsize"`
	MaxAge     int    `yaml:"maxage"`
	MaxBackups int    `yaml:"maxbackups"`
	LocalTime  bool   `yaml:"localtime"`
	Compress   bool   `yaml:"compress"`
}

func InitLogger(config LoggerConfig) *logrus.Logger {
	logger := logrus.StandardLogger()
O
ob-robot 已提交
73 74 75 76 77 78 79 80 81 82 83
	if curOut, ok := logger.Out.(*noErrWriter); ok {
		if l, ok := curOut.w.(*lumberjack.Logger); ok {
			l.Filename = config.Filename
			l.MaxSize = config.MaxSize
			l.MaxBackups = config.MaxBackups
			l.MaxAge = config.MaxAge
			l.Compress = config.Compress
			_ = l.Close()
		}
	} else {
		writer := &lumberjack.Logger{
W
wangzelin.wzl 已提交
84 85 86 87 88
			Filename:   config.Filename,
			MaxSize:    config.MaxSize,
			MaxBackups: config.MaxBackups,
			MaxAge:     config.MaxAge,
			Compress:   config.Compress,
O
ob-robot 已提交
89 90 91 92 93 94 95 96
			LocalTime:  true,
		}
		logger.SetOutput(&noErrWriter{w: writer})
		// log format
		logger.SetFormatter(textFormatter)

		// use CallerHook, not ReportCaller
		logger.SetReportCaller(false)
W
wangzelin.wzl 已提交
97

O
ob-robot 已提交
98 99 100 101 102 103
		// log hook
		// cost duration hook
		logger.AddHook(new(CostDurationHook))
		// caller hook
		logger.AddHook(new(CallerHook))
	}
W
wangzelin.wzl 已提交
104 105 106 107 108 109 110 111
	// log level
	level, err := logrus.ParseLevel(config.Level)
	if err != nil {
		panic(fmt.Sprintf("parse log level: %+v", err))
	}
	logger.SetLevel(level)
	return logger
}