Files
gocryptotrader/log/logger_rotate.go
Ryan O'Hara-Reid ac692b04f4 log: fix bug, expand test coverage and slightly optimize (#847)
* log: fix bugs expand coverage and optimise

* log: fix linter issues

* log: fix linter issue and pack methods in same file

* log: drop defer

* logger: move global check inside getfields  and remove unused test function

* logger: Increase note thanks @gloriouscode

* logger: wrap error with writer type

* logger: change variable name

* logger: change variable names and remove validsublogger func as it doesn't add functionality over a standard map call

* logs: error when unsupported output is applied on setup calls

* logs: add glorious suggestion

* logger: add protection to reduce olympic gold medal races

* logger: fix linter issues

* log: glorious niterinos
2021-11-30 16:43:27 +11:00

135 lines
2.5 KiB
Go

package log
import (
"errors"
"fmt"
"os"
"path/filepath"
"time"
"github.com/thrasher-corp/gocryptotrader/common/file"
)
var (
errExceedsMaxFileSize = errors.New("exceeds max file size")
errFileNameIsEmpty = errors.New("filename is empty")
)
// Write implementation to satisfy io.Writer handles length check and rotation
func (r *Rotate) Write(output []byte) (n int, err error) {
r.mu.Lock()
defer r.mu.Unlock()
outputLen := int64(len(output))
if outputLen > r.maxSize() {
return 0, fmt.Errorf(
"write length %v %w %v", outputLen, errExceedsMaxFileSize, r.maxSize(),
)
}
if r.output == nil {
err = r.openOrCreateFile(outputLen)
if err != nil {
return 0, err
}
}
if *r.Rotate {
if r.size+outputLen > r.maxSize() {
err = r.rotateFile()
if err != nil {
return 0, err
}
}
}
n, err = r.output.Write(output)
r.size += int64(n)
return n, err
}
func (r *Rotate) openOrCreateFile(n int64) error {
logFile := filepath.Join(LogPath, r.FileName)
info, err := os.Stat(logFile)
if err != nil {
if os.IsNotExist(err) {
return r.openNew()
}
return fmt.Errorf("error opening log file info: %s", err)
}
if *r.Rotate {
if info.Size()+n >= r.maxSize() {
return r.rotateFile()
}
}
file, err := os.OpenFile(logFile, os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
return r.openNew()
}
r.output = file
r.size = info.Size()
return nil
}
func (r *Rotate) openNew() error {
if r.FileName == "" {
return fmt.Errorf("cannot open new file: %w", errFileNameIsEmpty)
}
name := filepath.Join(LogPath, r.FileName)
_, err := os.Stat(name)
if err == nil {
timestamp := time.Now().Format("2006-01-02T15-04-05")
newName := filepath.Join(LogPath, timestamp+"-"+r.FileName)
err = file.Move(name, newName)
if err != nil {
return fmt.Errorf("can't rename log file: %s", err)
}
}
file, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
if err != nil {
return fmt.Errorf("can't open new logfile: %s", err)
}
r.output = file
r.size = 0
return nil
}
func (r *Rotate) close() (err error) {
if r.output == nil {
return nil
}
err = r.output.Close()
r.output = nil
return err
}
// Close handler for open file
func (r *Rotate) Close() error {
r.mu.Lock()
defer r.mu.Unlock()
return r.close()
}
func (r *Rotate) rotateFile() (err error) {
err = r.close()
if err != nil {
return
}
return r.openNew()
}
func (r *Rotate) maxSize() int64 {
if r.MaxSize == 0 {
return defaultMaxSize * megabyte
}
return r.MaxSize * megabyte
}