Use MultiWriter to simplify the writing implementation. Also make it possible to initialize the log target to variable amounts of writers, and doesn't hardcode the use of StdErr as output

This commit is contained in:
Ola Bini 2020-03-26 14:20:13 +00:00
parent d6c4d9f766
commit 8b2c7901ee
No known key found for this signature in database
GPG key ID: 6786A150F6A2B28F
2 changed files with 37 additions and 27 deletions

View file

@ -37,7 +37,7 @@ func main() {
dataDir.Close()
// Set up logging
logtarget.Default, err = logtarget.OpenFile(Args.LogPath)
logtarget.Default, err = logtarget.OpenFile(Args.LogPath, os.Stderr)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to open log file (%v): %v", Args.LogPath, err)
return

View file

@ -21,57 +21,66 @@ type LogTarget interface {
Rotate() error
}
type fileLogTarget struct {
// logTarget is the default implementation of a log
// target. It can write to more than one writer at the same time
// but only rotate one file
type logTarget struct {
mu sync.Mutex
logfn string
file *os.File
w io.Writer
ws []io.Writer
}
// Default is the default log target for the application
// It has to be initialized before used
var Default LogTarget
// OpenWriters returns a log target that will
// log to all the given writers at the same time
func OpenWriters(ws ...io.Writer) LogTarget {
target := &logTarget{}
target.w = io.MultiWriter(ws...)
return target
}
// OpenFile creates a LogTarget pointing to a log file
// and returns it.
// This method will open the file in append-only mode.
func OpenFile(fileName string) (t LogTarget, err error) {
target := &fileLogTarget{}
// It also takes a variable number of writers that are
// other log targets
func OpenFile(fileName string, ws ...io.Writer) (t LogTarget, err error) {
target := &logTarget{}
target.logfn = fileName
target.file, err = os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0650)
if err != nil {
return nil, err
}
target.ws = ws
target.w = io.MultiWriter(append(ws, target.file)...)
return target, nil
}
// Write writes a log message to all registered io.Writers
func (target *fileLogTarget) Write(in []byte) (int, error) {
func (target *logTarget) Write(out []byte) (int, error) {
target.mu.Lock()
defer target.mu.Unlock()
return target.Write(out)
}
// Rotate rotates the current log file, if one is opened.
// This method holds a lock while rotating the log file,
// and all log writes will be held back until the rotation
// is complete.
func (target *logTarget) Rotate() error {
target.mu.Lock()
defer target.mu.Unlock()
if target.file == nil {
panic("no log file opened")
return nil
}
n, err := os.Stderr.Write(in)
if err != nil {
return n, err
}
n, err = target.file.Write(in)
if err != nil {
return n, err
}
return len(in), nil
}
// Rotate rotates the current log file.
// This method holds a lock while rotating the log file,
// and all log writes will be held back until the rotation
// is complete.
func (target *fileLogTarget) Rotate() error {
target.mu.Lock()
defer target.mu.Unlock()
// Close the existing log file
err := target.file.Close()
if err != nil {
@ -82,6 +91,7 @@ func (target *fileLogTarget) Rotate() error {
if err != nil {
return err
}
target.w = io.MultiWriter(append(target.ws, target.file)...)
return nil
}