包含日志输出文件记录功能,终端打印功能,文件大小超限备份功能
github下载
main.go
package apelog
// DEBUG TRACE INFO WARN ERROR CRITICAL
type level uint16
const (
DEBUG level= iota
TRACE
INFO
WARN
ERROR
CRITICAL
// 限制记录日志级别
LEVEL_CONF = 0
// 限制终端打印级别
CSL_LEVEL = 0
// 日志文件大小限制,超过限制进行切分
MAXSIZE = 10 * 1024 * 1024
)
// level:0->DEBUG;1->TRACE... also: e.g:apelog.DEBUG...
func Apelog(level level, logFilePath string, logFileName string, msg string) {
fileLogger := newFileLogger(level, logFilePath, logFileName)
consoleLogger := newConsoleLogger(level)
consoleLogger.console_info(level,msg)
fileLogger.record_info(level, msg)
}
}
file_log.go
package apelog
import (
"fmt"
"os"
"time"
)
// FileLogger往文件中记录日志的结构体
type fileLogger struct {
level level
logFilePath string
logFileName string
logFile *os.File
}
// NewFileLogger 生成文件日志结构体示例的构造函数
func newFileLogger(level level, logFilePath string, logFileName string) *fileLogger {
flobj := &fileLogger{
level: level,
logFilePath: logFilePath,
logFileName: logFileName,
}
flobj.initFileLogger()
return flobj
}
// 初始化文件日志的文件句柄
func (f *fileLogger) initFileLogger() {
filepath := fmt.Sprintf("%s%s", f.logFilePath, f.logFileName)
file, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
//defer file.Close()
if err != nil {
panic(fmt.Sprintf("open file:%s failed", filepath))
}
f.logFile = file
}
// 检查是否需要切分
func (f *fileLogger) checkSplit(file *os.File) bool {
fileinfo, _ := file.Stat()
filesize := fileinfo.Size()
return filesize >= MAXSIZE
}
// 进行切分
func (f *fileLogger) splitLog(file *os.File) *os.File{
filename := file.Name()
now := time.Now()
backupname := fmt.Sprintf("%s_%d_%s_%d.back", filename, now.Year(),now.Month(),now.Day())
// 关闭原文件
file.Close()
// 备份
os.Rename(filename, backupname)
// 新建
fileobj, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
panic(fmt.Sprintf("open file:%s failed", filename))
}
return fileobj
}
// 拼接日志信息并记录
func (f *fileLogger) record_info(level level, msg string) {
if level < LEVEL_CONF {
return
}
rec_time := time.Now().Format(" [2006-01-02 15:04:05] ")
fileName, line, funcName := getCallerInfo(3)
inf := fmt.Sprintf("%s [file:%s] [function:%s] [line:%d] %s", rec_time, fileName, funcName, line, msg)
level_str := get_level_str(level)
inf = fmt.Sprintf("[%s]%s", level_str, inf)
if f.checkSplit(f.logFile){
f.logFile = f.splitLog(f.logFile)
}
fmt.Fprintln(f.logFile, inf)
}
console.go
package apelog
// 往终端打印
import (
"fmt"
"os"
"time"
)
type consoleLogger struct {
level level
}
func newConsoleLogger(level level) *consoleLogger {
cl := &consoleLogger{
level: level,
}
return cl
}
// 拼接日志信息并记录
func (c *consoleLogger) console_info(level level, msg string) {
if level < CSL_LEVEL {
return
}
rec_time := time.Now().Format(" [2006-01-02 15:04:05] ")
fileName, line, funcName := getCallerInfo(3)
inf := fmt.Sprintf("%s [file:%s] [function:%s] [line:%d] %s", rec_time, fileName, funcName, line, msg)
level_str := get_level_str(level)
inf = fmt.Sprintf("[%s]%s",level_str, inf)
fmt.Fprintln(os.Stdout, inf)
}
utils.go
package apelog
import (
"fmt"
"path"
"runtime"
)
// 公用工具函数
func getCallerInfo(skip int) (fileName string, line int, funcName string) {
pc, file, line, ok := runtime.Caller(skip)
if !ok {
return
}
// 从file中剥离出文件名
fileName = path.Base(file)
//根据pc拿到函数名
funcName = path.Base(runtime.FuncForPC(pc).Name())
return fileName, line, funcName
}
//获取日志等级字符串
func get_level_str(level level) string {
switch level {
case DEBUG:
return "DEBUG"
case TRACE:
return "TRACE"
case INFO:
return "INFO"
case WARN:
return "WARN"
case ERROR:
return "ERROR"
case CRITICAL:
return "CRITICAL"
default:
panic(fmt.Sprintf("logtype error:wrong num, required 1~5 but given %d", level))
}
}
调用测试
package main
import (
"fmt"
"mylog2/apelog"
)
func main() {
//for {
userid:=1
msg := fmt.Sprintf("id为%d的用户登录频繁",userid)
apelog.Apelog(apelog.INFO,"./test1/","test.log",msg)
//}
}
}