1 Star 0 Fork 0

hz2769514387 / gpc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
LogTools.go 8.79 KB
一键复制 编辑 原始数据 按行查看 历史
hz2769514387 提交于 2022-04-21 21:11 . 时间简化
package gpc
import (
"bufio"
"fmt"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"sync"
"time"
"gitee.com/hz2769514387/gpc/system"
"github.com/go-ini/ini"
)
//日志级别
type LOGLEVEL int8
const (
LevelDebug LOGLEVEL = iota
LevelInfo
LevelWarning
LevelError
LevelClose
)
//日志对象
type LogTools struct {
mutex sync.Mutex
year int
month time.Month
day int
logFile *os.File
logWritter *bufio.Writer
exited bool
LogLevel LOGLEVEL
LogFileDirctory string
LogFileName string
StdOut int
}
var LogToolsDefault = new(LogTools)
//实现io.Writer
func (l *LogTools) Write(b []byte) (n int, err error) {
return LogBytes(LevelInfo, b)
}
/*
InitLogger 初始化 log,返回关闭log的函数
调用示例:defer myutil.InitLogTools("xxx.ini")()
配置文件示例:
[Log]
LogFileDirctory=C:\LOG\LogDir
LogLevel=DEBUG
StdOut=1
*/
func InitLogTools(logconfigFile string) func() {
//读取配置
var cfg *ini.File
var err error
if filepath.IsAbs(logconfigFile) {
cfg, err = ini.Load(logconfigFile)
} else {
cfg, err = ini.Load(path.Join(GetSelfFileDir(), logconfigFile))
}
if err != nil {
fmt.Fprintln(os.Stdout, "ini.Load failed, err:", err)
LogToolsDefault.LogFileDirctory = GetSelfFileDir()
LogToolsDefault.LogLevel = LevelInfo
LogToolsDefault.StdOut = 0
} else {
LogToolsDefault.LogFileDirctory = cfg.Section("Log").Key("LogFileDirctory").MustString(GetSelfFileDir())
LogToolsDefault.StdOut = cfg.Section("Log").Key("StdOut").MustInt(0)
LogLevel := cfg.Section("Log").Key("LogLevel").MustString("INFO")
switch LogLevel[0] {
case 'D', 'd':
LogToolsDefault.LogLevel = LevelDebug
case 'I', 'i':
LogToolsDefault.LogLevel = LevelInfo
case 'W', 'w':
LogToolsDefault.LogLevel = LevelWarning
case 'E', 'e':
LogToolsDefault.LogLevel = LevelError
case 'C', 'c':
LogToolsDefault.LogLevel = LevelClose
default:
LogToolsDefault.LogLevel = LevelInfo
}
}
LogToolsDefault.LogFileName = GetSelfFileName()
//打开文件
t := time.Now()
reopenFile(&t)
//hook panic
err = system.StdErrorToFile(LogToolsDefault.logFile)
//进程出入口日志
Warningf("==========[start:%s]==================", GetSelfFileName())
if err != nil {
Warning("WARN:StdErrorToFile Fail:", err)
}
//定时flush
LogToolsDefault.exited = false
go func() {
for {
time.Sleep(1 * time.Second)
LogToolsDefault.mutex.Lock()
flushLog()
if LogToolsDefault.exited {
LogToolsDefault.mutex.Unlock()
break
}
LogToolsDefault.mutex.Unlock()
}
}()
return closeLogTools
}
// Debug
func Debugf(format string, v ...interface{}) {
if LogToolsDefault.LogLevel > LevelDebug {
return
}
LogString(LevelDebug, fmt.Sprintf(format, v...))
}
// Debug
func Debug(v ...interface{}) {
if LogToolsDefault.LogLevel > LevelDebug {
return
}
LogString(LevelDebug, fmt.Sprintln(v...))
}
// Infor
func Inforf(format string, v ...interface{}) {
if LogToolsDefault.LogLevel > LevelInfo {
return
}
LogString(LevelInfo, fmt.Sprintf(format, v...))
}
// Infor
func Infor(v ...interface{}) {
if LogToolsDefault.LogLevel > LevelInfo {
return
}
LogString(LevelInfo, fmt.Sprintln(v...))
}
// Warning
func Warningf(format string, v ...interface{}) {
if LogToolsDefault.LogLevel > LevelWarning {
return
}
LogString(LevelWarning, fmt.Sprintf(format, v...))
}
// Warning
func Warning(v ...interface{}) {
if LogToolsDefault.LogLevel > LevelWarning {
return
}
LogString(LevelWarning, fmt.Sprintln(v...))
}
// Error
func Errorf(format string, v ...interface{}) {
if LogToolsDefault.LogLevel > LevelError {
return
}
LogString(LevelError, fmt.Sprintf(format, v...))
}
// Error
func Error(v ...interface{}) {
if LogToolsDefault.LogLevel > LevelError {
return
}
LogString(LevelError, fmt.Sprintln(v...))
}
// Panic
func Panic(v ...interface{}) {
logstr := fmt.Sprintln(v...)
if LogToolsDefault.LogLevel != LevelClose {
LogString(LevelError, logstr)
}
closeLogTools()
panic(logstr)
}
//写入字符串
func LogString(writelevel LOGLEVEL, s string) {
//写入前缀
t := time.Now()
var buff = logPrefixToBuf(writelevel, &t)
//写入内容
nonewline := (s[len(s)-1] != '\n')
*buff = append(*buff, s...)
if nonewline {
*buff = append(*buff, '\n')
}
//实际执行写入
LogToolsDefault.mutex.Lock()
reopenFile(&t)
if LogToolsDefault.logWritter != nil {
LogToolsDefault.logWritter.Write(*buff)
}
LogToolsDefault.mutex.Unlock()
if LogToolsDefault.StdOut != 0 {
if nonewline {
fmt.Fprintln(os.Stdout, s)
} else {
fmt.Fprint(os.Stdout, s)
}
}
}
//写入字节数组
func LogBytes(writelevel LOGLEVEL, b []byte) (n int, err error) {
//写入前缀
t := time.Now()
var buff = logPrefixToBuf(writelevel, &t)
//写入内容
nonewline := (b[len(b)-1] != '\n')
*buff = append(*buff, b...)
if nonewline {
*buff = append(*buff, '\n')
}
//实际执行写入
LogToolsDefault.mutex.Lock()
reopenFile(&t)
if LogToolsDefault.logWritter != nil {
n, err = LogToolsDefault.logWritter.Write(*buff)
}
LogToolsDefault.mutex.Unlock()
if LogToolsDefault.StdOut != 0 {
if nonewline {
fmt.Fprintln(os.Stdout, string(b))
} else {
fmt.Fprint(os.Stdout, string(b))
}
}
return n, err
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//重新打开文件
func reopenFile(pNowTime *time.Time) {
tY, tM, tD := pNowTime.Date()
if LogToolsDefault.logFile != nil &&
LogToolsDefault.logWritter != nil &&
tD == LogToolsDefault.day &&
tM == LogToolsDefault.month &&
tY == LogToolsDefault.year {
LogToolsDefault.year, LogToolsDefault.month, LogToolsDefault.day = tY, tM, tD
return
}
LogToolsDefault.year, LogToolsDefault.month, LogToolsDefault.day = tY, tM, tD
//需要重新打开文件
if LogToolsDefault.logFile != nil || LogToolsDefault.logWritter != nil {
LogToolsDefault.logWritter.Flush()
LogToolsDefault.logFile.Close()
}
// 判断是否有Director文件夹
logFullPath := path.Join(LogToolsDefault.LogFileDirctory, pNowTime.Format("2006-01"), pNowTime.Format("2006-01-02")) + "/"
if !IsExist(logFullPath) {
os.MkdirAll(logFullPath, os.ModePerm)
}
logFullPath = path.Join(logFullPath, LogToolsDefault.LogFileName+"_"+pNowTime.Format("2006-01-02")+".log")
var err error
LogToolsDefault.logFile, err = os.OpenFile(logFullPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("open log file failed, err:", err)
return
}
if LogToolsDefault.logWritter == nil {
LogToolsDefault.logWritter = bufio.NewWriterSize(LogToolsDefault.logFile, 1024*100)
} else {
LogToolsDefault.logWritter.Reset(LogToolsDefault.logFile)
}
}
//Flush
func flushLog() {
if LogToolsDefault.logWritter == nil {
return
}
bufCnt := LogToolsDefault.logWritter.Buffered()
if bufCnt == 0 {
return
}
LogToolsDefault.logWritter.Flush()
}
// ExitLogger 退出log
func closeLogTools() {
LogToolsDefault.mutex.Lock()
if LogToolsDefault.exited {
LogToolsDefault.mutex.Unlock()
return
}
if LogToolsDefault.logWritter != nil {
LogToolsDefault.mutex.Unlock()
Warning("==========[ end ]==================")
LogToolsDefault.mutex.Lock()
}
flushLog()
LogToolsDefault.logWritter = nil
LogToolsDefault.logFile = nil
LogToolsDefault.exited = true
LogToolsDefault.mutex.Unlock()
}
//写入前缀到buf
func logPrefixToBuf(writelevel LOGLEVEL, pNowTime *time.Time) *[]byte {
//写入级别
var buff []byte
switch writelevel {
case LevelDebug:
buff = append(buff, 'D')
case LevelInfo:
buff = append(buff, 'I')
case LevelWarning:
buff = append(buff, 'W')
case LevelError:
buff = append(buff, 'E')
default:
buff = append(buff, '?')
}
buff = append(buff, ' ')
//写入时间
hour, min, sec := pNowTime.Clock()
itoa(&buff, hour, 2)
buff = append(buff, ':')
itoa(&buff, min, 2)
buff = append(buff, ':')
itoa(&buff, sec, 2)
buff = append(buff, '.')
itoa(&buff, pNowTime.Nanosecond()/1e3, 6)
buff = append(buff, ' ')
//写入文件名和行号
var file string
var line int
var ok bool
_, file, line, ok = runtime.Caller(3)
if !ok {
file = "???"
line = 0
}
for i := len(file) - 1; i > 0; i-- {
if file[i] == '/' {
file = file[i+1:]
break
}
}
buff = append(buff, file...)
buff = append(buff, ':')
itoa(&buff, line, 4)
//文件名长度不够,补齐空格
appendspace := 25 - len(file)
if appendspace > 0 {
appendstr := strings.Repeat(" ", appendspace)
buff = append(buff, appendstr...)
}
buff = append(buff, ' ')
return &buff
}
// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
func itoa(buf *[]byte, i int, wid int) {
// Assemble decimal in reverse order.
var b [20]byte
bp := len(b) - 1
for i >= 10 || wid > 1 {
wid--
q := i / 10
b[bp] = byte('0' + i - q*10)
bp--
i = q
}
// i < 10
b[bp] = byte('0' + i)
*buf = append(*buf, b[bp:]...)
}
Go
1
https://gitee.com/hz2769514387/gpc.git
git@gitee.com:hz2769514387/gpc.git
hz2769514387
gpc
gpc
master

搜索帮助