golang日志

日志

package logger

// ==========================
// Admin Vvooooooooooo
// Time  2020/1/7
// Explain log
// ==========================

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"strconv"
	"sync"
	"time"
)

const (
	_VER string = "1.0.0"
)

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 logObject 				*_FILE

const  DATEFORMAT  = "2020-1-7"

type UNIT int64

const  (
	_       = iota
	KB UNIT = 1 <<  (iota*10)
	MB
	GB
	TB
)

const (
	ALL LEVEL = iota
	DEBUG
	INFO
	WARN
	ERROR
	FATAL
	OFF
)

var(
	debug_str 			= "debug"
	info_str 			= "info"
	warn_str          	= "\033[033;1mwarn\033[033;0m"
	error_str         	= "\033[031;1merror\033[031;0m"
	fatal_str         	= "\033[031;1mfatal\033[031;0m"
//						\033[字背景颜色;1m(高亮)字符串\033[0m
)

const (
	_ = iota
	ROLLINGDAILY
	ROLLINGFILE
)

func init(){
	if runtime.GOOS == "windows"{
		warn_str          	= "warn"
		error_str         	= "error"
		fatal_str         	= "fatal"
	}
}

type _FILE struct {
	dir 		string
	filename 	string
	_suffix 	int
	isCover 	bool
	_date 		*time.Time
	mu 			*sync.RWMutex
	logfile 	*os.File
	lg 			*log.Logger
}

//主实现控制台
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("cathError ",err)
	}
}

//Debug接口

func Debug(v ...interface{})  {
	if dailyRolling {
		filecheck()
	}
	defer catchError()
	if logObject != nil{
		logObject.mu.RLock()
		defer  logObject.mu.RUnlock()
	}
	if logLevel <= DEBUG{
		if logObject !=nil{
			logObject.lg.Output(2,fmt.Sprintln(debug_str,v))
		}
		console(debug_str,v)
	}
}

//INFO接口

func Info(v ...interface{})  {
	if dailyRolling {
		filecheck()
	}
	defer catchError()
	if logObject != nil{
		logObject.mu.RLock()
		defer  logObject.mu.RUnlock()
	}
	if logLevel <= INFO{
		if logObject !=nil{
			logObject.lg.Output(2,fmt.Sprintln(info_str,v))
		}
		console(info_str,v)
	}
}

//Warn 接口
func Warn(v ...interface{}) {
	if dailyRolling {
		filecheck()
	}
	defer catchError()
	if logObject != nil {
		logObject.mu.RLock()
		defer logObject.mu.RUnlock()
	}

	if logLevel <= WARN {
		if logObject != nil {
			logObject.lg.Output(2, fmt.Sprintln(warn_str, v))
		}
		console(warn_str, v)
	}
}

//Error 接口
func Error(v ...interface{}) {
	if dailyRolling {
		filecheck()
	}
	defer catchError()
	if logObject != nil {
		logObject.mu.RLock()
		defer logObject.mu.RUnlock()
	}
	if logLevel <= ERROR {
		if logObject != nil {
			logObject.lg.Output(2, fmt.Sprintln(error_str, v))
		}
		console(error_str, v)
	}
}

//Fatal 接口
func Fatal(v ...interface{}) {
	if dailyRolling {
		filecheck()
	}
	defer catchError()
	if logObject != nil {
		logObject.mu.RLock()
		defer logObject.mu.RUnlock()
	}
	if logLevel <= FATAL {
		if logObject != nil {
			logObject.lg.Output(2, fmt.Sprintln(fatal_str, v))
		}
		console(fatal_str, v)
	}
}



//底层实现
func SetPrefix(title string){
	log.SetPrefix(title)
}

func SetConsole(isConsole bool){
	consoleAppender = isConsole
}

func SetLevel(_level LEVEL){
	logLevel = _level
}

func SetRollingFile(fileDir,filename string,maxNum int32,maxSize int64,_unit UNIT){
	maxFileCount = maxNum
	maxFileSize  = maxSize
	RollingFile = true
	dailyRolling = false
	mkdirlog(fileDir)
	logObject = &_FILE{dir:fileDir,filename:filename,isCover:false,mu:new(sync.RWMutex)}
	logObject.mu.Lock()
	defer  logObject.mu.Unlock()
	for i:=1;i<int(maxNum);i++{
		if isExist(fileDir+"/"+filename+"."+strconv.Itoa(i)){
			logObject._suffix = i
		}else{
			break
		}
	}
	if !logObject.isMustRename(){
		logObject.logfile,_ = os.OpenFile(fileDir+"/"+filename,os.O_RDWR|os.O_APPEND|os.O_CREATE,06666)
		logObject.lg = log.New(logObject.logfile,"",log.Ldate|log.Ltime|log.Lshortfile)
	}else{
		logObject.rename()
	}
	go fileMonitor()

}


func SetRollingDaily(fileDir,fileName string){
	RollingFile = false
	dailyRolling  =true
	t,_ := time.Parse(DATEFORMAT,time.Now().Format(DATEFORMAT))
	mkdirlog(fileDir)
	logObject = &_FILE{dir:fileDir,filename:fileName,_date:&t,isCover:false,mu:new(sync.RWMutex)}
	logObject.mu.Lock()
	defer  logObject.mu.Unlock()

	if !logObject.isMustRename(){
		logObject.logfile,_ = os.OpenFile(fileDir+"/"+fileName,os.O_RDWR|os.O_APPEND|os.O_CREATE,06666)
		logObject.lg = log.New(logObject.logfile,"",log.Ldate|log.Ltime|log.Lshortfile)
	}else{
		logObject.rename()
	}
}

func mkdirlog(dir string)(e error){
	_,err :=os.Stat(dir)
	b:=err ==nil || os.IsExist(err)
	if !b {
		if new_err := os.MkdirAll(dir,06666);new_err !=nil{
			if os.IsPermission(new_err){
				fmt.Println("VV create logger dir error :",new_err.Error())
				e = new_err
			}
		}
	}
	return
}

func isExist(path string) bool {
	_,err := os.Stat(path)
	return err ==nil || os.IsExist(err)
}

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 errr",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(logObject.logfile,"",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()
	}
	var path = f.dir+"/"+f.filename+"."+strconv.Itoa(int(f._suffix))
	if isExist(path){
		os.Remove(path)
	}
	os.Rename(f.dir+"/"+f.filename,path)
	f.logfile,_  =os.Create(f.dir+"/"+f.filename)
	f.lg = log.New(logObject.logfile,"",log.Ldate|log.Ltime|log.Lshortfile)
}

func fileSize(file string) int64{
	fmt.Println("VV FileSize ",file)
	f,err := os.Stat(file)
	if err!=nil{
		fmt.Println(err.Error())
		return 0
	}
	return f.Size()
}
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 logObject !=nil && logObject.isMustRename(){
		logObject.mu.Lock();
		defer logObject.mu.Unlock()
		logObject.rename()
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值