1 Star 0 Fork 0

webkf-net / logger-sdk-go

Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
Clone or Download
file.go 5.58 KB
Copy Edit Raw Blame History
webkf-net authored 2022-12-04 01:03 . 初始化
package logger
import (
"fmt"
"os"
"path"
"time"
)
//往文件里面写日志内容
var (
maxSize = 10000 //日志通道缓冲区大小
)
//文件日志结构体
type FileLogger struct {
Level LogLevel //日志级别
filePath string //日志文件保存的路径
fileName string //日志文件保存的文件名
fileObj *os.File //日志文件
errFileObj *os.File //err日志文件
maxFileSize int64
logChan chan *logMsg //使用指针节省内存空间
}
type logMsg struct {
level LogLevel
msg string
funcName string
fileName string
timestamp string
line int
}
//构造函数
func NewFileLogger(levelStr, fp, fn string, maxFileSize int64) *FileLogger {
logLevel, err := parseLogLevel(levelStr)
if err != nil {
panic(err)
}
fl := &FileLogger{
Level: logLevel,
filePath: fp,
fileName: fn,
maxFileSize: maxFileSize,
logChan: make(chan *logMsg, maxSize), //初始化通道
}
err = fl.initFile() //按照文件路径和文件名将文件打开
if err != nil {
panic(err)
}
return fl
}
//根据指定的日志文件路径和文件名打开日志文件
func (f *FileLogger) initFile() error {
fullFileName := path.Join(f.filePath, f.fileName)
fileObj, err := os.OpenFile(fullFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("open log file failed,err:%v\n", err)
return err
}
errFileObj, err := os.OpenFile(fullFileName+".err", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("open err file failed,err:%v\n", err)
return err
}
//日志件都已经打开了
f.fileObj = fileObj
f.errFileObj = errFileObj
//开启1个后台的goroutine去往文件里写日志
go f.writeLogBackground()
return nil
}
//判断是否需要记录该日志
func (f *FileLogger) enable(logLevel LogLevel) bool {
return logLevel >= f.Level
}
//判断文件是否需要切割
func (f *FileLogger) checkSize(file *os.File) bool {
fileInfo, err := file.Stat()
if err != nil {
fmt.Printf("get file info failed,err:%v\n", err)
return false
}
//如果当前文件大小 大于等于 日志文件的最大值 就返回true
//Size()返回的是文件的字节大小值
return fileInfo.Size() >= f.maxFileSize
}
//切割文件
func (f *FileLogger) splitFile(file *os.File) (*os.File, error) {
//需要切割旧日志文件
nowStr := time.Now().Format("20060102150405000")
fileInfo, err := file.Stat()
if err != nil {
fmt.Printf("get file info failed,err:%v\n", err)
return nil, err
}
logName := path.Join(f.filePath, fileInfo.Name()) //拿到当前的日志文件完整路径
newLogName := fmt.Sprintf("%s.bak%s", logName, nowStr) //拼接一个日志文件备份的名字
//1.关闭当前的日志文件
file.Close()
//2.备份一下rename xx.log修改成xx.log.bak202011110000
os.Rename(logName, newLogName) //修改文件名
//3.打开一个新的日志文件
fileObj, err := os.OpenFile(logName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("open new log file failed,err:%v\n", err)
return nil, err
}
//4.将打开的新日志文件对象赋值给 f.fileObj
return fileObj, nil
}
//写入日志文件
func (f *FileLogger) writeLogBackground() {
for {
if f.checkSize(f.fileObj) {
newFile, err := f.splitFile(f.fileObj) //切割普通日志文件
if err != nil {
return
}
f.fileObj = newFile
}
select {
case logTmp := <-f.logChan: //取出通道信息
//把日志拼出来
logInfo := fmt.Sprintf("[%s] [%s] [%s:%s:%d] %s\n", logTmp.timestamp, getLogString(logTmp.level), logTmp.fileName, logTmp.funcName, logTmp.line, logTmp.msg)
//写入文件内容
fmt.Fprintf(f.fileObj, logInfo)
if logTmp.level >= ERROR {
if f.checkSize(f.errFileObj) {
newFile, err := f.splitFile(f.errFileObj) //切割err日志文件
if err != nil {
return
}
f.errFileObj = newFile
}
//如果要记录的日志大于等于ERROR级别,我还要在err日志文件中再记录一遍
fmt.Fprintf(f.errFileObj, logInfo)
}
default:
time.Sleep(time.Millisecond * 500) //取不到日志时先休息500毫秒
}
}
}
//记录日志的方法
func (f *FileLogger) log(lv LogLevel, format string, a ...interface{}) {
if f.enable(lv) {
msg := fmt.Sprintf(format, a...)
now := time.Now()
funcName, fileName, lineNo := getInfo(3)
//先把日志发送到通道中
//1.造一个logMsg对象,初始化logMsg结构体
logTmp := &logMsg{
level: lv,
msg: msg,
funcName: funcName,
fileName: fileName,
timestamp: now.Format("2006-01-02 15:04:05"),
line: lineNo,
}
//给通道发送数据
select {
case f.logChan <- logTmp:
default:
//把日志丢掉保证不出现阻塞
}
}
}
//调试
func (f *FileLogger) Debug(format string, a ...interface{}) {
f.log(DEBUG, format, a...)
}
//追踪
func (f *FileLogger) Trace(format string, a ...interface{}) {
f.log(TRACE, format, a...)
}
//信息
func (f *FileLogger) Info(format string, a ...interface{}) {
f.log(INFO, format, a...)
}
//警告
func (f *FileLogger) Warning(format string, a ...interface{}) {
f.log(WARNING, format, a...)
}
//错误
func (f *FileLogger) Error(format string, a ...interface{}) {
f.log(ERROR, format, a...)
}
//致命的
func (f *FileLogger) Fatal(format string, a ...interface{}) {
f.log(FATAL, format, a...)
}
//关闭文件
func (f *FileLogger) Close() {
f.fileObj.Close()
f.errFileObj.Close()
}
Go
1
https://gitee.com/webkf-net/logger-sdk-go.git
git@gitee.com:webkf-net/logger-sdk-go.git
webkf-net
logger-sdk-go
logger-sdk-go
v1.0.0

Search