kos/pkg/log/file.go

252 lines
4.9 KiB
Go
Raw Permalink Normal View History

2023-04-23 17:57:36 +08:00
package log
import (
"fmt"
"os"
"strconv"
"sync"
"time"
)
type File struct {
Filename string `json:"filename"`
MaxSize int64 `json:"max_size"`
MaxLogFiles int `json:"max_log_files"`
Format string `json:"format"`
Level int `json:"level"`
mutex sync.RWMutex
buf []byte
fp *os.File
prefix string
size int64
}
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:]...)
}
func (lg *File) SetLevel(lv int) {
lg.Level = lv
}
func (lg *File) Prefix(s string) {
lg.prefix = s
}
func (lg *File) Print(i ...interface{}) {
lg.write(TraceLevel, fmt.Sprint(i...))
}
func (lg *File) Printf(format string, args ...interface{}) {
lg.write(TraceLevel, fmt.Sprintf(format, args...))
}
func (lg *File) Debug(i ...interface{}) {
lg.write(DebugLevel, fmt.Sprint(i...))
}
func (lg *File) Debugf(format string, args ...interface{}) {
lg.write(DebugLevel, fmt.Sprintf(format, args...))
}
func (lg *File) Info(i ...interface{}) {
lg.write(InfoLevel, fmt.Sprint(i...))
}
func (lg *File) Infof(format string, args ...interface{}) {
lg.write(InfoLevel, fmt.Sprintf(format, args...))
}
func (lg *File) Warn(i ...interface{}) {
lg.write(WarnLevel, fmt.Sprint(i...))
}
func (lg *File) Warnf(format string, args ...interface{}) {
lg.write(WarnLevel, fmt.Sprintf(format, args...))
}
func (lg *File) Error(i ...interface{}) {
lg.write(ErrorLevel, fmt.Sprint(i...))
}
func (lg *File) Errorf(format string, args ...interface{}) {
lg.write(ErrorLevel, fmt.Sprintf(format, args...))
}
func (lg *File) Fatal(i ...interface{}) {
lg.write(FatalLevel, fmt.Sprint(i...))
}
func (lg *File) Fatalf(format string, args ...interface{}) {
lg.write(FatalLevel, fmt.Sprintf(format, args...))
}
func (lg *File) Panic(i ...interface{}) {
lg.write(PanicLevel, fmt.Sprint(i...))
}
func (lg *File) Panicf(format string, args ...interface{}) {
lg.write(PanicLevel, fmt.Sprintf(format, args...))
}
func (lg *File) format(buf *[]byte, level int, s string) (err error) {
t := time.Now()
year, month, day := t.Date()
itoa(buf, year, 4)
*buf = append(*buf, '-')
itoa(buf, int(month), 2)
*buf = append(*buf, '-')
itoa(buf, day, 2)
*buf = append(*buf, ' ')
hour, min, sec := t.Clock()
itoa(buf, hour, 2)
*buf = append(*buf, ':')
itoa(buf, min, 2)
*buf = append(*buf, ':')
itoa(buf, sec, 2)
*buf = append(*buf, ' ')
*buf = append(*buf, '[')
*buf = append(*buf, getLevelText(level)...)
*buf = append(*buf, ']')
*buf = append(*buf, ' ')
*buf = append(*buf, s...)
return
}
// Write 实现标准的写入行数
func (lg *File) Write(p []byte) (n int, err error) {
lg.mutex.Lock()
defer lg.mutex.Unlock()
if n, err = lg.fp.Write(p); err != nil {
return
}
lg.size += int64(n)
if lg.MaxSize > 0 && lg.size >= lg.MaxSize {
if err = lg.rotate(); err != nil {
return
}
lg.size = 0
}
return
}
func (lg *File) write(level int, s string) {
var (
n int
err error
)
if lg.Level > level {
return
}
lg.mutex.Lock()
defer lg.mutex.Unlock()
lg.buf = lg.buf[:0]
if err = lg.format(&lg.buf, level, s); err != nil {
return
}
lg.buf = append(lg.buf, '\n')
if n, err = lg.fp.Write(lg.buf); err != nil {
return
}
lg.size += int64(n)
if lg.MaxSize > 0 && lg.size >= lg.MaxSize {
if err = lg.rotate(); err != nil {
return
}
lg.size = 0
}
}
func (lg *File) isExists(filename string) bool {
if _, err := os.Stat(filename); err == nil {
return true
} else {
return false
}
}
// rotate 实现日志滚动处理
func (lg *File) rotate() (err error) {
if err = lg.close(); err != nil {
return
}
for i := lg.MaxLogFiles; i >= 0; i-- {
filename := lg.Filename
if i > 0 {
filename += "." + strconv.Itoa(i)
}
if i == lg.MaxLogFiles {
if lg.isExists(filename) {
if err = os.Remove(filename); err != nil {
return
}
}
} else {
if lg.isExists(filename) {
if err = os.Rename(filename, lg.Filename+"."+strconv.Itoa(i+1)); err != nil {
return
}
}
}
}
err = lg.open()
return
}
func (lg *File) Reload() (err error) {
lg.mutex.Lock()
defer lg.mutex.Unlock()
_ = lg.close()
err = lg.open()
return
}
func (lg *File) open() (err error) {
if lg.fp, err = os.OpenFile(lg.Filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600); err != nil {
return
}
return
}
func (lg *File) Open() (err error) {
var (
info os.FileInfo
)
if err = lg.open(); err != nil {
return
}
if info, err = os.Stat(lg.Filename); err == nil {
lg.size = info.Size()
}
return
}
func (lg *File) close() (err error) {
if lg.fp != nil {
err = lg.fp.Close()
}
return
}
func (lg *File) Close() (err error) {
err = lg.close()
return
}
func NewFileLogger(filename string) *File {
lg := &File{Filename: filename, buf: make([]byte, 1024)}
return lg
}