123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- package Logger
- import (
- "fmt"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
- "gopkg.in/natefinch/lumberjack.v2"
- "log"
- "os"
- "runtime"
- "strconv"
- "sync"
- "time"
- )
- var Logger *zap.Logger
- func InitLogger(logpath string, loglevel string) {
- // 日志分割
- hook := lumberjack.Logger{
- Filename: logpath, // 日志文件路径,默认 os.TempDir()
- MaxSize: 5, // 每个日志文件保存10M,默认 100M
- MaxBackups: 20, // 保留30个备份,默认不限
- MaxAge: 15, // 保留7天,默认不限
- Compress: false, // 是否压缩,默认不压缩
- }
- write := zapcore.AddSync(&hook)
- // 设置日志级别
- // debug 可以打印出 info debug warn
- // info 级别可以打印 warn info
- // warn 只能打印 warn
- // debug->info->warn->error
- var level zapcore.Level
- switch loglevel {
- case "debug":
- level = zap.DebugLevel
- case "info":
- level = zap.InfoLevel
- case "error":
- level = zap.ErrorLevel
- default:
- level = zap.InfoLevel
- }
- encoderConfig := zapcore.EncoderConfig{
- TimeKey: "time",
- LevelKey: "level",
- NameKey: "logger",
- CallerKey: "caller",
- MessageKey: "msg",
- StacktraceKey: "stacktrace",
- LineEnding: zapcore.DefaultLineEnding,
- EncodeLevel: zapcore.LowercaseLevelEncoder, // 小写编码器
- EncodeTime: formatEncodeTime,
- EncodeDuration: zapcore.SecondsDurationEncoder, //
- EncodeCaller: zapcore.ShortCallerEncoder, // 全路径编码器
- //EncodeName: zapcore.FullNameEncoder,
- }
- // 设置日志级别
- atomicLevel := zap.NewAtomicLevel()
- atomicLevel.SetLevel(level)
- core := zapcore.NewCore(
- // zapcore.NewConsoleEncoder(encoderConfig),
- zapcore.NewJSONEncoder(encoderConfig),
- //zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)),
- //zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(write)), // 打印到控制台和文件
- write, //文件
- level,
- )
- // 开启开发模式,堆栈跟踪
- caller := zap.AddCaller()
- // 开启文件及行号
- development := zap.Development()
- // 设置初始化字段,如:添加一个服务器名称
- //filed := zap.Fields(zap.String("serviceName", "serviceName"))
- // 构造日志
- Logger = zap.New(core, caller, development)
- Logger.Info("DefaultLogger init success")
- }
- func formatEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
- enc.AppendString(fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()))
- }
- func Field(key string, val interface{}) zap.Field {
- return zap.Any(key, val)
- }
- const (
- _VER string = "1.0.2"
- )
- type LEVEL int32
- var logLevel LEVEL = 1
- var maxFileSize int64
- var maxFileCount int32
- var dailyRolling bool = true
- var consoleAppender bool = true
- var RollingFile bool = false
- var logObj *_FILE
- const DATEFORMAT = "2006-01-02"
- type UNIT int64
- const (
- _ = iota
- KB UNIT = 1 << (iota * 10)
- MB
- GB
- TB
- )
- const (
- ALL LEVEL = iota
- DEBUG
- INFO
- WARN
- ERROR
- FATAL
- OFF
- )
- type _FILE struct {
- dir string
- filename string
- _suffix int
- isCover bool
- _date *time.Time
- mu *sync.RWMutex
- logfile *os.File
- lg *log.Logger
- }
- func SetConsole(isConsole bool) {
- consoleAppender = isConsole
- }
- func SetLevel(_level LEVEL) {
- logLevel = _level
- }
- func SetRollingFile(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
- maxFileCount = maxNumber
- maxFileSize = maxSize * int64(_unit)
- RollingFile = true
- dailyRolling = false
- mkdirlog(fileDir)
- logObj = &_FILE{dir: fileDir, filename: fileName, isCover: false, mu: new(sync.RWMutex)}
- logObj.mu.Lock()
- defer logObj.mu.Unlock()
- for i := 1; i <= int(maxNumber); i++ {
- if isExist(fileDir + "/" + fileName + "." + strconv.Itoa(i)) {
- logObj._suffix = i
- } else {
- break
- }
- }
- if !logObj.isMustRename() {
- logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
- logObj.lg = log.New(logObj.logfile, "", log.Ldate|log.Ltime|log.Lshortfile)
- } else {
- logObj.rename()
- }
- go fileMonitor()
- }
- func SetRollingDaily(fileDir, fileName string) {
- RollingFile = false
- dailyRolling = true
- t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
- mkdirlog(fileDir)
- logObj = &_FILE{dir: fileDir, filename: fileName, _date: &t, isCover: false, mu: new(sync.RWMutex)}
- logObj.mu.Lock()
- defer logObj.mu.Unlock()
- if !logObj.isMustRename() {
- logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
- logObj.lg = log.New(logObj.logfile, "", log.Ldate|log.Ltime|log.Lshortfile)
- } else {
- logObj.rename()
- }
- }
- func mkdirlog(dir string) (e error) {
- _, er := os.Stat(dir)
- b := er == nil || os.IsExist(er)
- if !b {
- if err := os.MkdirAll(dir, 0666); err != nil {
- if os.IsPermission(err) {
- fmt.Println("create dir error:", err.Error())
- e = err
- }
- }
- }
- return
- }
- func console(s ...interface{}) {
- if consoleAppender {
- _, file, line, _ := runtime.Caller(2)
- short := file
- for i := len(file) - 1; i > 0; i-- {
- if file[i] == '/' {
- short = file[i+1:]
- break
- }
- }
- file = short
- log.Println(file, strconv.Itoa(line), s)
- }
- }
- func catchError() {
- if err := recover(); err != nil {
- log.Println("err", err)
- }
- }
- func Debug(v ...interface{}) {
- if dailyRolling {
- fileCheck()
- }
- defer catchError()
- if logObj != nil {
- logObj.mu.RLock()
- defer logObj.mu.RUnlock()
- }
- if logLevel <= DEBUG {
- if logObj != nil {
- logObj.lg.Output(2, fmt.Sprintln("debug", v))
- }
- console("debug", v)
- }
- }
- func Info(v ...interface{}) {
- if dailyRolling {
- fileCheck()
- }
- defer catchError()
- if logObj != nil {
- logObj.mu.RLock()
- defer logObj.mu.RUnlock()
- }
- if logLevel <= INFO {
- if logObj != nil {
- logObj.lg.Output(2, fmt.Sprintln("info", v))
- }
- console("info", v)
- }
- }
- func Warn(v ...interface{}) {
- if dailyRolling {
- fileCheck()
- }
- defer catchError()
- if logObj != nil {
- logObj.mu.RLock()
- defer logObj.mu.RUnlock()
- }
- if logLevel <= WARN {
- if logObj != nil {
- logObj.lg.Output(2, fmt.Sprintln("warn", v))
- }
- console("warn", v)
- }
- }
- func Error(v ...interface{}) {
- if dailyRolling {
- fileCheck()
- }
- defer catchError()
- if logObj != nil {
- logObj.mu.RLock()
- defer logObj.mu.RUnlock()
- }
- if logLevel <= ERROR {
- if logObj != nil {
- logObj.lg.Output(2, fmt.Sprintln("error", v))
- }
- console("error", v)
- }
- }
- func Fatal(v ...interface{}) {
- if dailyRolling {
- fileCheck()
- }
- defer catchError()
- if logObj != nil {
- logObj.mu.RLock()
- defer logObj.mu.RUnlock()
- }
- if logLevel <= FATAL {
- if logObj != nil {
- logObj.lg.Output(2, fmt.Sprintln("fatal", v))
- }
- console("fatal", v)
- }
- }
- func (f *_FILE) isMustRename() bool {
- if dailyRolling {
- t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
- if t.After(*f._date) {
- return true
- }
- } else {
- if maxFileCount > 1 {
- if fileSize(f.dir+"/"+f.filename) >= maxFileSize {
- return true
- }
- }
- }
- return false
- }
- func (f *_FILE) rename() {
- if dailyRolling {
- fn := f.dir + "/" + f.filename + "." + f._date.Format(DATEFORMAT)
- if !isExist(fn) && f.isMustRename() {
- if f.logfile != nil {
- f.logfile.Close()
- }
- err := os.Rename(f.dir+"/"+f.filename, fn)
- if err != nil {
- f.lg.Println("rename err", err.Error())
- }
- t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
- f._date = &t
- f.logfile, _ = os.Create(f.dir + "/" + f.filename)
- f.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)
- }
- } else {
- f.coverNextOne()
- }
- }
- func (f *_FILE) nextSuffix() int {
- return int(f._suffix%int(maxFileCount) + 1)
- }
- func (f *_FILE) coverNextOne() {
- f._suffix = f.nextSuffix()
- if f.logfile != nil {
- f.logfile.Close()
- }
- if isExist(f.dir + "/" + f.filename + "." + strconv.Itoa(int(f._suffix))) {
- os.Remove(f.dir + "/" + f.filename + "." + strconv.Itoa(int(f._suffix)))
- }
- os.Rename(f.dir+"/"+f.filename, f.dir+"/"+f.filename+"."+strconv.Itoa(int(f._suffix)))
- f.logfile, _ = os.Create(f.dir + "/" + f.filename)
- f.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)
- }
- func fileSize(file string) int64 {
- fmt.Println("fileSize", file)
- f, e := os.Stat(file)
- if e != nil {
- fmt.Println(e.Error())
- return 0
- }
- return f.Size()
- }
- func isExist(path string) bool {
- _, err := os.Stat(path)
- return err == nil || os.IsExist(err)
- }
- func fileMonitor() {
- timer := time.NewTicker(1 * time.Second)
- for {
- select {
- case <-timer.C:
- fileCheck()
- }
- }
- }
- func fileCheck() {
- defer func() {
- if err := recover(); err != nil {
- log.Println(err)
- }
- }()
- if logObj != nil && logObj.isMustRename() {
- logObj.mu.Lock()
- defer logObj.mu.Unlock()
- logObj.rename()
- }
- }
|