From 109f427693ed2e2282a544cd8d004a6f81276f07 Mon Sep 17 00:00:00 2001 From: dadang Date: Thu, 30 Nov 2023 09:36:05 +0700 Subject: [PATCH] feat : rotate logs --- README.md | 2 +- go.mod | 3 ++ rotate.go | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 go.mod create mode 100644 rotate.go diff --git a/README.md b/README.md index b10f99e..7c94c6b 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# go-rotate-log \ No newline at end of file +# go-rotate-logs diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..58d8d4f --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/sutantodadang/go-rotate-logs + +go 1.21.4 diff --git a/rotate.go b/rotate.go new file mode 100644 index 0000000..312ea7d --- /dev/null +++ b/rotate.go @@ -0,0 +1,128 @@ +package gorotatelogs + +import ( + "os" + "path/filepath" + "strconv" + "strings" + "sync" + "time" +) + +type Config struct { + Directory string + + Filename string + + MaxSize int // Megabyte MB + + BackupName string + + UsingTime bool // if true it will add "-" + FormatTime + + FormatTime string // if no format it will default using rfc3399 +} + +type RotateLogsWriter struct { + config Config + + mut sync.Mutex + + file *os.File +} + +func New(config Config) *RotateLogsWriter { + + w := &RotateLogsWriter{config: config} + + err := w.Rotate() + if err != nil { + return nil + } + + return w + +} + +// write func to satisfy io.writer interface +func (r *RotateLogsWriter) Write(output []byte) (int, error) { + + r.mut.Lock() + + defer r.mut.Unlock() + + return r.file.Write(output) + +} + +func (r *RotateLogsWriter) Rotate() (err error) { + + r.mut.Lock() + + defer r.mut.Unlock() + + if r.file != nil { + + err = r.file.Close() + + r.file = nil + + if err != nil { + return + } + + } + + err = os.MkdirAll(r.config.Directory, os.ModePerm) + if err != nil { + return + } + + str := strings.Split(r.config.Filename, ".log") + + if r.config.UsingTime { + + if r.config.FormatTime == "" { + r.config.FormatTime = time.RFC3339 + } + + r.config.Filename = str[0] + "-" + time.Now().Format(r.config.FormatTime) + ".log" + + } + + pathFile := filepath.Join(r.config.Directory, r.config.Filename) + + dir, err := os.ReadDir(r.config.Filename) + if err != nil { + return + } + + info, err := os.Stat(pathFile) + if err == nil { + + // if file size over maxsize rename to backup and create new file + if (info.Size() / 1000000) > int64(r.config.MaxSize) { + + newStr := strings.Split(r.config.Filename, ".log") + + i := strconv.Itoa(len(dir)) + + err = os.Rename(pathFile, filepath.Join(r.config.Directory, newStr[0]+"-"+r.config.BackupName+"-"+i+".log")) + if err != nil { + return + } + + } + + } else { + return + } + + r.file, err = os.OpenFile(pathFile, os.O_CREATE|os.O_APPEND, os.ModePerm) + if err != nil { + return + } + + return + +}