需求分析
![在这里插入图片描述](https://img-blog.csdnimg.cn/e5493aa1e2b24ed2abb5b1a32bbea8b3.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Zsb3dlcnh4eHh4,size_16,color_FFFFFF,t_70)
file.go(将log写入文件内)
package mylogger
import (
"fmt"
"os"
"path"
"time"
)
type FileLogger struct {
Level LogLevel
filePath string
fileName string
fileObj *os.File
errFileObj *os.File
maxFileSize int64
}
func NewFileLogger(leverStr, fp, fn string, maxSize int64) *FileLogger {
LogLevel, err := parseLogLevel(leverStr)
if err != nil {
panic(err)
}
fl:= &FileLogger{
Level: LogLevel,
filePath: fp,
fileName: fn,
maxFileSize: 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",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",err)
return err
}
f.fileObj = fileObj
f.errFileObj = errFileObj
return nil
}
func (f *FileLogger)checkSize(file *os.File) bool{
fileInfo,err := file.Stat()
if err != nil {
fmt.Printf("get file info failed: %v\n", err)
return false
}
if fileInfo.Size() >= f.maxFileSize{
return true
}else{
return false
}
}
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: %v\n", err)
return nil,err
}
logName := path.Join(f.filePath,fileInfo.Name())
fmt.Println(logName)
newLogName := fmt.Sprintf("%s.bak%s",logName,nowStr)
fmt.Println("2")
file.Close()
os.Rename(logName,newLogName)
fmt.Println(logName)
fileObj,err := os.OpenFile(logName,os.O_APPEND|os.O_CREATE|os.O_WRONLY,0644)
fmt.Println("1")
if err != nil {
fmt.Printf("open new log file failed,err:%v",err)
return nil,err
}
return fileObj,nil
}
func (f *FileLogger) log(lv LogLevel, format string, a ...interface{}) {
if f.enable(lv){
msg := fmt.Sprintf(format, a...)
now := time.Now()
funcName, fileName, linNo := getInfo(3)
if f.checkSize(f.fileObj){
newFile ,err := f.splitFile(f.fileObj)
if err != nil {
return
}
f.fileObj = newFile
}
fmt.Fprintf(f.fileObj,"[%s][%s][%s:%s:%d] %s\n", now.Format("2006-01-02 15:04:05"), getLogString(lv), funcName, fileName, linNo, msg)
if lv >= ERROR{
if f.checkSize(f.fileObj){
newFile ,err := f.splitFile(f.errFileObj)
if err != nil {
return
}
f.errFileObj = newFile
}
fmt.Fprintf(f.errFileObj,"[%s][%s][%s:%s:%d] %s\n", now.Format("2006-01-02 15:04:05"), getLogString(lv), funcName, fileName, linNo, msg)
}
}
}
func (f *FileLogger) enable(LogLevel LogLevel) bool {
return LogLevel >= f.Level
}
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()
}
console.go(将文件显示在终端上)
package mylogger
import (
"fmt"
"time"
)
type ConsoleLogger struct {
level LogLevel
}
func NewLog(levelStr string) ConsoleLogger {
level, err := parseLogLevel(levelStr)
if err != nil {
panic(err)
}
return ConsoleLogger{
level: level,
}
}
func (c ConsoleLogger) enable(LogLevel LogLevel) bool {
return LogLevel >= c.level
}
func (c ConsoleLogger) log(lv LogLevel, format string, a ...interface{}) {
if c.enable(lv){
msg := fmt.Sprintf(format, a...)
now := time.Now()
funcName, fileName, linNo := getInfo(3)
fmt.Printf("[%s][%s][%s:%s:%d] %s\n", now.Format("2006-01-02 15:04:05"), getLogString(lv), funcName, fileName, linNo, msg)
}
}
func (c ConsoleLogger) Debug(format string, a ...interface{}) {
c.log(DEBUG, format, a...)
}
func (c ConsoleLogger) Trace(format string, a ...interface{}) {
c.log(TRACE, format, a...)
}
func (c ConsoleLogger) Info(format string, a ...interface{}) {
c.log(INFO, format, a...)
}
func (c ConsoleLogger) Warning(format string, a ...interface{}) {
c.log(WARNING, format, a...)
}
func (c ConsoleLogger) Error(format string, a ...interface{}) {
c.log(ERROR, format, a...)
}
func (c ConsoleLogger) Fatal(format string, a ...interface{}) {
c.log(FATAL, format, a...)
}
mylogger.go(部分函数)
package mylogger
import (
"errors"
"fmt"
"path"
"runtime"
"strings"
)
type LogLevel uint16
const (
UNKNOWN LogLevel = iota
DEBUG
TRACE
INFO
WARNING
ERROR
FATAL
)
type Logger interface {
Debug(fromat string,a...interface{})
Info(fromat string,a...interface{})
Warning(fromat string,a...interface{})
Error(fromat string,a...interface{})
FATAL(fromat string,a...interface{})
}
func parseLogLevel(s string) (LogLevel, error) {
s = strings.ToLower(s)
switch s {
case"debug":
return DEBUG,nil
case"trace":
return TRACE,nil
case"info":
return INFO,nil
case"warning":
return WARNING,nil
case"error":
return ERROR,nil
case"fatal":
return FATAL,nil
default:
err := errors.New("无效的日志级别")
return UNKNOWN,err
}
}
func getLogString(lv LogLevel) string {
switch lv {
case DEBUG:
return "DEBUG"
case TRACE:
return "TRACE"
case INFO:
return "INFO"
case WARNING:
return "WARNING"
case ERROR:
return "ERROR"
case FATAL:
return "FATAL"
default:
return "DEBUG"
}
}
func getInfo(skip int)(funcName ,filename string,lineNo int) {
pc,file,lineNo,ok :=runtime.Caller(skip)
if !ok {
fmt.Printf("runtime.Caller() failed")
return
}
funcName = runtime.FuncForPC(pc).Name()
filename = path.Base(file)
return
}
main.go(主函数)
package main
import (
"go_work/awesomeProject/study07/mylogger"
)
func main() {
for{
log := mylogger.NewFileLogger("Info","./","huasheng.log",10*1024)
id := 1001
name := "华生"
log.Debug("这是一条Debug日志 id:%d, name:%s", id, name)
log.Trace("这是一条Trace日志id:%d, name:%s", id, name)
log.Info("这是一条Info日志id:%d, name:%s", id, name)
log.Warning("这是一条Warning日志id:%d, name:%s", id, name)
log.Error("这是一条Error日志")
log.Info("这是一条Info日志")
log.Fatal("这是一条Fatal日志")
}
}