目录结构
| - myLog
| - mylog.go
| - file_log.go
| - 项目目录
| - main.go
"""
使用:
设置日志路径, 日志名, 日志切割大小, 日志记录等级
实例化后, 即可使用
"""
调用文件
package main
import (
"xx/xx/mylogger"
)
const (
filePath string = "./"
srvName string = "hellen"
fileLevel string = "Warning"
consoleLevel string = "Debug"
maxSize int64 = 1 << 10
)
var logger mylogger.Logger
func main() {
logger = mylogger.NewLogSet(filePath, srvName, fileLevel, consoleLevel, maxSize)
defer logger.Close()
logger.Debug("用户 ss 尝试登录 %d 次", 1)
logger.Info("用户 ss 尝试登录 %d 次", 2)
logger.Warning("用户 ss 尝试登录 %d 次", 3)
logger.Error("用户 ss 尝试登录 %d 次", 4)
logger.Fatal("用户 ss 尝试登录 %d 次", 5)
}
日志库文件
package mylogger
type Level uint16
const (
Debug Level = iota
Info
Warning
Error
Fatal
)
type Logger interface {
Debug(format string, args ...interface{})
Info(format string, args ...interface{})
Warning(format string, args ...interface{})
Error(format string, args ...interface{})
Fatal(format string, args ...interface{})
Close()
}
package mylogger
import (
"fmt"
"os"
"path"
"time"
)
type LogSet struct {
fileLevel Level
conLevel Level
filePath string
srvName string
accFile *os.File
errFile *os.File
maxSize int64
}
func NewLogSet(filepath, srvName, fileLevelStr, conLevelStr string, maxSize int64) *LogSet {
fileLevel := strToLevel(fileLevelStr)
conLevel := strToLevel(conLevelStr)
l := &LogSet{
fileLevel: fileLevel,
conLevel: conLevel,
filePath: filepath,
srvName: srvName,
maxSize: maxSize,
}
l.accFile, l.errFile = l.initFile()
return l
}
func (l *LogSet) initFile() (*os.File, *os.File) {
accLogName := fmt.Sprintf("%s/%s_acc.log", l.filePath, l.srvName)
f1, err1 := os.OpenFile(accLogName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err1 != nil {
panic(fmt.Errorf("open file %s failed, %v", accLogName, err1))
}
errLogName := fmt.Sprintf("%s/%s_err.log", l.filePath, l.srvName)
f2, err2 := os.OpenFile(errLogName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err2 != nil {
panic(fmt.Errorf("open file %s failed, %v", errLogName, err2))
}
return f1, f2
}
func (l *LogSet) checkLogSize(f *os.File, mod string) {
LogInfo, err := f.Stat()
if err != nil {
return
}
now := time.Now().Format("20060102150405")
LogSize := LogInfo.Size()
if LogSize > l.maxSize {
f.Close()
a := path.Join(l.filePath, l.srvName)
oldName := fmt.Sprintf("%s_%s.log", a, mod)
newName := fmt.Sprintf("%s_%s.%s.log", a, mod, now)
os.Rename(oldName, newName)
f, err := os.OpenFile(oldName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
panic(fmt.Errorf("open file %s failed, %v", oldName, err))
}
switch mod {
case "acc":
l.accFile = f
case "err":
l.errFile = f
}
}
}
func (l *LogSet) logFormat(level Level, format string, args ...interface{}) {
now := time.Now().Format("2006-01-02 15:04:05.000")
fileName, funcName, line := getCallerInfo(3)
levelStr := getLevelStr(level)
logMsg := fmt.Sprintf("[%s][%s:%d][%s][%v] %s\n", now, fileName, line, funcName, levelStr, format)
if l.conLevel <= level {
fmt.Fprintf(os.Stdout, logMsg, args...)
}
if l.fileLevel <= level {
l.checkLogSize(l.accFile, "acc")
fmt.Fprintf(l.accFile, logMsg, args...)
l.checkLogSize(l.errFile, "err")
if level > Warning {
fmt.Fprintf(l.errFile, logMsg, args...)
}
}
}
func (l *LogSet) Debug(format string, args ...interface{}) {
l.logFormat(Debug, format, args...)
}
func (l *LogSet) Info(format string, args ...interface{}) {
l.logFormat(Info, format, args...)
}
func (l *LogSet) Warning(format string, args ...interface{}) {
l.logFormat(Warning, format, args...)
}
func (l *LogSet) Error(format string, args ...interface{}) {
l.logFormat(Error, format, args...)
}
func (l *LogSet) Fatal(format string, args ...interface{}) {
l.logFormat(Fatal, format, args...)
}
func (l *LogSet) Close() {
l.accFile.Close()
l.errFile.Close()
}
package mylogger
import (
"path"
"runtime"
"strings"
)
func getCallerInfo(skip int) (fileName, funcName string, line int) {
pc, file, line, ok := runtime.Caller(skip)
if !ok {
return
}
fileName = path.Base(file)
funcName = runtime.FuncForPC(pc).Name()
return fileName, funcName, line
}
func getLevelStr(level Level) string {
switch level {
case Debug:
return "Debug"
case Info:
return "Info"
case Warning:
return "Warning"
case Error:
return "Error"
case Fatal:
return "Fatal"
default:
return "Info"
}
}
func strToLevel(levelStr string) Level {
levelStr = strings.ToLower(levelStr)
switch levelStr {
case "debug":
return Debug
case "info":
return Info
case "warning":
return Warning
case "error":
return Error
case "fatal":
return Fatal
default:
return Info
}
}