Skip to content

Commit

Permalink
Merge pull request #2 from liasece/jansen
Browse files Browse the repository at this point in the history
refactoring log rotate logic
  • Loading branch information
liasece authored Jul 2, 2020
2 parents 2198b70 + e9d16bf commit 992e196
Show file tree
Hide file tree
Showing 8 changed files with 278 additions and 384 deletions.
156 changes: 38 additions & 118 deletions log/file_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package log

import (
"bufio"
"bytes"
"errors"
"fmt"
syslog "log"
Expand All @@ -11,70 +10,30 @@ import (
"time"
)

var pathVariableTable map[byte]func(*time.Time) int

// fileWriter 文件输出器,将日志记录输出到文件中
type fileWriter struct {
filebasename string
pathFmt string
file *os.File
fileBufWriter *bufio.Writer
actions []func(*time.Time) int
variables []interface{}
RedirectError bool // 是否重定向错误信息到日志文件
filePath string
lastRoateTail string
rotateTimeLayout string
file *os.File
fileBufWriter *bufio.Writer
variables []interface{}
redirectError bool // 是否重定向错误信息到日志文件
}

// newFileWriter 构造一个文件输出器
func newFileWriter() *fileWriter {
return &fileWriter{}
func newFileWriter(filePath string, rotateTimeLayout string) *fileWriter {
return &fileWriter{
filePath: filePath,
rotateTimeLayout: rotateTimeLayout,
}
}

// Init 初始化文件输出器
func (w *fileWriter) Init() error {
return w.Rotate()
}

// SetPathPattern 设置文件路径
func (w *fileWriter) SetPathPattern(filebasename string, pattern string) error {
n := 0
for _, c := range pattern {
if c == '%' {
n++
}
}

if n == 0 {
w.filebasename = filebasename
w.pathFmt = pattern
return nil
}

w.actions = make([]func(*time.Time) int, 0, n)
w.variables = make([]interface{}, n)
tmp := []byte(pattern)

variable := 0
for _, c := range tmp {
if variable == 1 {
act, ok := pathVariableTable[c]
if !ok {
return errors.New("Invalid rotate pattern (" + pattern + ")")
}
w.actions = append(w.actions, act)
variable = 0
continue
}
if c == '%' {
variable = 1
}
}

w.filebasename = filebasename
w.pathFmt = convertPatternToFmt(tmp)

return nil
}

// Write 写入一条日志记录
func (w *fileWriter) Write(r *Record) error {
if w.fileBufWriter == nil {
Expand All @@ -99,22 +58,13 @@ func (w *fileWriter) RotateByTime(t *time.Time) error {

// doRotate 尝试转储文件,如果不需要进行转储,返回 nil
func (w *fileWriter) doRotate(t *time.Time) error {
v := 0
rotate := false

for i, act := range w.actions {
v = act(t)
if v != w.variables[i] {
w.variables[i] = v
rotate = true
}
if w.rotateTimeLayout == "" {
return w.initFile(w.filePath)
}
// fmt.Printf("start rotate file,actions:%d,%d,%d,%d,%d\n", len(w.actions), w.variables[0], w.variables[1], w.variables[2], w.variables[3])

if !rotate {
newRotateTail := t.Format(w.rotateTimeLayout)
if newRotateTail == w.lastRoateTail {
return nil
}
// fmt.Printf("start rotate file,actions:%d,%d,%d,%d,%d\n", len(w.actions), w.variables[0], w.variables[1], w.variables[2], w.variables[3])

if w.fileBufWriter != nil {
if err := w.fileBufWriter.Flush(); err != nil {
Expand All @@ -128,8 +78,16 @@ func (w *fileWriter) doRotate(t *time.Time) error {
}
}

filePath := fmt.Sprintf(w.pathFmt, w.variables...)
filePath := fmt.Sprint(w.filePath, ".", newRotateTail)
if err := w.initFile(filePath); err != nil {
syslog.Println(err)
return err
}
w.lastRoateTail = newRotateTail
return nil
}

func (w *fileWriter) initFile(filePath string) error {
if err := os.MkdirAll(path.Dir(filePath), 0755); err != nil {
if !os.IsExist(err) {
return err
Expand All @@ -139,11 +97,12 @@ func (w *fileWriter) doRotate(t *time.Time) error {
// 这是真正的日志文件
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
syslog.Println(filePath, err)
return err
}
w.file = file

if w.RedirectError {
if w.redirectError {
// 把错误重定向到日志文件来
sysDup(int(w.file.Fd()))
}
Expand All @@ -153,66 +112,27 @@ func (w *fileWriter) doRotate(t *time.Time) error {
}

// 创建一个软链接
// 检查文件是存在
_, fileerr := os.Stat(w.filebasename)
if fileerr == nil { // 文件存在
os.Remove(w.filebasename)
}
// Create a symlink
{
err := os.Symlink(path.Base(filePath), w.filebasename)
if filePath != w.filePath {
// 检查文件是存在
_, fileerr := os.Stat(w.filePath)
if fileerr == nil {
// this file already exist
os.Remove(w.filePath)
}
// Create a symlink
err := os.Symlink(path.Base(filePath), w.filePath)
if err != nil {
syslog.Println(err.Error())
syslog.Println("os.Symlink error:", err.Error())
// return err
}
}

return nil
}

// Flush 将文件缓冲区中的内容 Flush
// Flush 将文件缓冲区中的内容
func (w *fileWriter) Flush() error {
if w.fileBufWriter != nil {
return w.fileBufWriter.Flush()
}
return nil
}

func getYear(now *time.Time) int {
return now.Year() % 100
}

func getMonth(now *time.Time) int {
return int(now.Month())
}

func getDay(now *time.Time) int {
return now.Day()
}

func getHour(now *time.Time) int {
return now.Hour()
}

func getMin(now *time.Time) int {
return now.Minute()
}

func convertPatternToFmt(pattern []byte) string {
pattern = bytes.Replace(pattern, []byte("%Y"), []byte("%d"), -1)
pattern = bytes.Replace(pattern, []byte("%M"), []byte("%02d"), -1)
pattern = bytes.Replace(pattern, []byte("%D"), []byte("%02d"), -1)
pattern = bytes.Replace(pattern, []byte("%H"), []byte("%02d"), -1)
pattern = bytes.Replace(pattern, []byte("%m"), []byte("%02d"), -1)
return string(pattern)
}

// init 初始化获取指定时间元素的函数列表等
func init() {
pathVariableTable = make(map[byte]func(*time.Time) int, 5)
pathVariableTable['Y'] = getYear
pathVariableTable['M'] = getMonth
pathVariableTable['D'] = getDay
pathVariableTable['H'] = getHour
pathVariableTable['m'] = getMin
}
1 change: 0 additions & 1 deletion log/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ type Writer interface {
type Rotater interface {
Rotate() error
RotateByTime(*time.Time) error
SetPathPattern(string, string) error
}

// Flusher 刷新输出
Expand Down
14 changes: 7 additions & 7 deletions log/log_dup_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (

// sysDup 将进程致命错误转储
func sysDup(fd int) error {
// {
// err := syscall.Dup2(fd, 1)
// if err != nil {
// syslog.Println(err.Error())
// // return err
// }
// }
{
err := syscall.Dup2(fd, 1)
if err != nil {
syslog.Println(err.Error())
// return err
}
}
{
err := syscall.Dup2(fd, 2)
if err != nil {
Expand Down
Loading

0 comments on commit 992e196

Please sign in to comment.