diff options
author | Derrick <actown@users.noreply.github.com> | 2020-04-12 05:08:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-12 05:08:06 +0300 |
commit | a31e58979d3780c0ad367c21aecce61c1f6f8362 (patch) | |
tree | 89e353901a36910ab4da7bc9d685e5a815aba927 | |
parent | f4d41de53623b2486b0c46db6b613aa600079e54 (diff) | |
parent | 8b2c7901ee2512c4adfd33ee59be5c3b787c05e7 (diff) |
Merge pull request #54 from olabiniV2/stderr_logging
Refactor logtarget
-rw-r--r-- | cmd/grumble/grumble.go | 4 | ||||
-rw-r--r-- | cmd/grumble/server.go | 2 | ||||
-rw-r--r-- | cmd/grumble/signal_unix.go | 2 | ||||
-rw-r--r-- | pkg/logtarget/logtarget.go | 85 |
4 files changed, 55 insertions, 38 deletions
diff --git a/cmd/grumble/grumble.go b/cmd/grumble/grumble.go index 56eaa9a..139eadc 100644 --- a/cmd/grumble/grumble.go +++ b/cmd/grumble/grumble.go @@ -37,14 +37,14 @@ func main() { dataDir.Close() // Set up logging - err = logtarget.Target.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 } log.SetPrefix("[G] ") log.SetFlags(log.LstdFlags | log.Lmicroseconds) - log.SetOutput(&logtarget.Target) + log.SetOutput(logtarget.Default) log.Printf("Grumble") log.Printf("Using data directory: %s", Args.DataDir) diff --git a/cmd/grumble/server.go b/cmd/grumble/server.go index acc1fab..7a1c45b 100644 --- a/cmd/grumble/server.go +++ b/cmd/grumble/server.go @@ -156,7 +156,7 @@ func NewServer(id int64) (s *Server, err error) { s.Channels[0] = NewChannel(0, "Root") s.nextChanId = 1 - s.Logger = log.New(&logtarget.Target, fmt.Sprintf("[%v] ", s.Id), log.LstdFlags|log.Lmicroseconds) + s.Logger = log.New(logtarget.Default, fmt.Sprintf("[%v] ", s.Id), log.LstdFlags|log.Lmicroseconds) return } diff --git a/cmd/grumble/signal_unix.go b/cmd/grumble/signal_unix.go index 7127f24..9066b49 100644 --- a/cmd/grumble/signal_unix.go +++ b/cmd/grumble/signal_unix.go @@ -20,7 +20,7 @@ func SignalHandler() { signal.Notify(sigchan, syscall.SIGUSR2, syscall.SIGTERM, syscall.SIGINT) for sig := range sigchan { if sig == syscall.SIGUSR2 { - err := logtarget.Target.Rotate() + err := logtarget.Default.Rotate() if err != nil { fmt.Fprintf(os.Stderr, "unable to rotate log file: %v", err) } diff --git a/pkg/logtarget/logtarget.go b/pkg/logtarget/logtarget.go index 46a2eb2..1b69a3b 100644 --- a/pkg/logtarget/logtarget.go +++ b/pkg/logtarget/logtarget.go @@ -6,7 +6,7 @@ package logtarget import ( - "bytes" + "io" "os" "sync" ) @@ -15,56 +15,72 @@ import ( // LogTarget to be registered with the regular Go log package. // LogTarget multiplexes its incoming writes to multiple optional // output writers, and one main output writer (the log file). -type LogTarget struct { - mu sync.Mutex - logfn string - file *os.File - memLog *bytes.Buffer -} - -var Target LogTarget +type LogTarget interface { + io.Writer -// Write writes a log message to all registered io.Writers -func (target *LogTarget) Write(in []byte) (int, error) { - target.mu.Lock() - defer target.mu.Unlock() - - if target.file == nil { - panic("no log file opened") - } + Rotate() error +} - n, err := os.Stderr.Write(in) - if err != nil { - return n, err - } +// 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 +} - n, err = target.file.Write(in) - if err != nil { - return n, err - } +// Default is the default log target for the application +// It has to be initialized before used +var Default LogTarget - return len(in), nil +// 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 opens the main log file for writing. +// OpenFile creates a LogTarget pointing to a log file +// and returns it. // This method will open the file in append-only mode. -func (target *LogTarget) OpenFile(fn string) (err error) { - target.logfn = fn - target.file, err = os.OpenFile(target.logfn, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0650) +// 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 err + return nil, err } - return nil + target.ws = ws + target.w = io.MultiWriter(append(ws, target.file)...) + return target, nil } -// Rotate rotates the current log file. +// Write writes a log message to all registered io.Writers +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 { +func (target *logTarget) Rotate() error { target.mu.Lock() defer target.mu.Unlock() + if target.file == nil { + return nil + } + // Close the existing log file err := target.file.Close() if err != nil { @@ -75,6 +91,7 @@ func (target *LogTarget) Rotate() error { if err != nil { return err } + target.w = io.MultiWriter(append(target.ws, target.file)...) return nil } |