(Engine) Logger - fixes issues with multiwriter go routine (#347)

* Fixes goroutine leak and comments

* passed error down from newLogEvent to each sub logger to handle and display

* Update loggers.go
This commit is contained in:
Andrew
2019-09-02 09:58:23 +10:00
committed by Adrian Gallagher
parent 5e9d13f7be
commit 833a866506
7 changed files with 41 additions and 25 deletions

View File

@@ -22,6 +22,7 @@ func (l *Logger) newLogEvent(data, header string, w io.Writer) error {
if w == nil {
return errors.New("io.Writer not set")
}
e := eventPool.Get().(*LogEvent)
e.output = w
e.data = append(e.data, []byte(header)...)
@@ -34,11 +35,12 @@ func (l *Logger) newLogEvent(data, header string, w io.Writer) error {
if data == "" || data[len(data)-1] != '\n' {
e.data = append(e.data, '\n')
}
e.output.Write(e.data)
_, err := e.output.Write(e.data)
e.data = e.data[:0]
eventPool.Put(e)
return nil
return err
}
// CloseLogger is called on shutdown of application
@@ -58,6 +60,7 @@ func validSubLogger(s string) (bool, *subLogger) {
return false, nil
}
// Level retries the current sublogger levels
func Level(s string) (*Levels, error) {
found, logger := validSubLogger(s)
if !found {
@@ -67,6 +70,7 @@ func Level(s string) (*Levels, error) {
return &logger.Levels, nil
}
// SetLevel sets sublogger levels
func SetLevel(s, level string) (*Levels, error) {
found, logger := validSubLogger(s)
if !found {

View File

@@ -11,7 +11,7 @@ func (mw *multiWriter) Add(writer io.Writer) {
mw.mu.Unlock()
}
// Remove removes exisiting writer from multiwriter slice
// Remove removes existing writer from multiwriter slice
func (mw *multiWriter) Remove(writer io.Writer) {
mw.mu.Lock()
@@ -37,8 +37,10 @@ func (mw *multiWriter) Write(p []byte) (n int, err error) {
n int
err error
}
mw.mu.RLock()
defer mw.mu.RUnlock()
results := make(chan data)
results := make(chan data, len(mw.writers))
for _, wr := range mw.writers {
go func(w io.Writer, p []byte, ch chan data) {
@@ -51,10 +53,7 @@ func (mw *multiWriter) Write(p []byte) (n int, err error) {
ch <- data{n, io.ErrShortWrite}
return
}
select {
case ch <- data{n, nil}:
default:
}
ch <- data{n, nil}
}(wr, p, results)
}

View File

@@ -72,13 +72,12 @@ func (r *Rotate) openOrCreateFile(n int64) error {
func (r *Rotate) openNew() error {
name := filepath.Join(LogPath, r.FileName)
t := time.Now()
timestamp := t.Format("2006-01-02T15-04-05")
newName := filepath.Join(LogPath, timestamp+"-"+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 = os.Rename(name, newName)
if err != nil {
return fmt.Errorf("can't rename log file: %s", err)
@@ -105,6 +104,7 @@ func (r *Rotate) close() (err error) {
return err
}
// Close handler for open file
func (r *Rotate) Close() error {
r.mu.Lock()
defer r.mu.Unlock()

View File

@@ -27,7 +27,6 @@ func getWriters(s *SubLoggerConfig) io.Writer {
m.Add(ioutil.Discard)
}
}
return m
}

View File

@@ -51,6 +51,7 @@ type Logger struct {
Spacer string
}
// Levels flags for each sub logger type
type Levels struct {
Info, Debug, Warn, Error bool
}
@@ -61,6 +62,7 @@ type subLogger struct {
output io.Writer
}
// LogEvent holds the data sent to the log and which multiwriter to send to
type LogEvent struct {
data []byte
output io.Writer
@@ -68,14 +70,17 @@ type LogEvent struct {
type multiWriter struct {
writers []io.Writer
mu sync.Mutex
mu sync.RWMutex
}
var (
logger = &Logger{}
logger = &Logger{}
// FileLoggingConfiguredCorrectly flag set during config check if file logging meets requirements
FileLoggingConfiguredCorrectly bool
GlobalLogConfig = &Config{} // GlobalLogConfig hold global configuration options for logger
GlobalLogFile = &Rotate{}
// GlobalLogConfig holds global configuration options for logger
GlobalLogConfig = &Config{}
// GlobalLogFile hold global configuration options for file logger
GlobalLogFile = &Rotate{}
eventPool = &sync.Pool{
New: func() interface{} {
@@ -85,5 +90,6 @@ var (
},
}
// LogPath system path to store log files in
LogPath string
)

View File

@@ -2,6 +2,7 @@ package logger
import (
"fmt"
"log"
)
// Info takes a pointer subLogger struct and string sends to newLogEvent
@@ -14,7 +15,7 @@ func Info(sl *subLogger, data string) {
return
}
logger.newLogEvent(data, logger.InfoHeader, sl.output)
displayError(logger.newLogEvent(data, logger.InfoHeader, sl.output))
}
// Infoln takes a pointer subLogger struct and interface sends to newLogEvent
@@ -27,7 +28,7 @@ func Infoln(sl *subLogger, v ...interface{}) {
return
}
logger.newLogEvent(fmt.Sprintln(v...), logger.InfoHeader, sl.output)
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.InfoHeader, sl.output))
}
// Infof takes a pointer subLogger struct, string & interface formats and sends to Info()
@@ -53,7 +54,7 @@ func Debug(sl *subLogger, data string) {
return
}
logger.newLogEvent(data, logger.DebugHeader, sl.output)
displayError(logger.newLogEvent(data, logger.DebugHeader, sl.output))
}
// Debugln takes a pointer subLogger struct, string and interface sends to newLogEvent
@@ -66,7 +67,7 @@ func Debugln(sl *subLogger, v ...interface{}) {
return
}
logger.newLogEvent(fmt.Sprintln(v...), logger.DebugHeader, sl.output)
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.DebugHeader, sl.output))
}
// Debugf takes a pointer subLogger struct, string & interface formats and sends to Info()
@@ -92,7 +93,7 @@ func Warn(sl *subLogger, data string) {
return
}
logger.newLogEvent(data, logger.WarnHeader, sl.output)
displayError(logger.newLogEvent(data, logger.WarnHeader, sl.output))
}
// Warnln takes a pointer subLogger struct & interface formats and sends to newLogEvent()
@@ -105,7 +106,7 @@ func Warnln(sl *subLogger, v ...interface{}) {
return
}
logger.newLogEvent(fmt.Sprintln(v...), logger.WarnHeader, sl.output)
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.WarnHeader, sl.output))
}
// Warnf takes a pointer subLogger struct, string & interface formats and sends to Warn()
@@ -131,7 +132,7 @@ func Error(sl *subLogger, data ...interface{}) {
return
}
logger.newLogEvent(fmt.Sprint(data...), logger.ErrorHeader, sl.output)
displayError(logger.newLogEvent(fmt.Sprint(data...), logger.ErrorHeader, sl.output))
}
// Errorln takes a pointer subLogger struct, string & interface formats and sends to newLogEvent()
@@ -144,7 +145,7 @@ func Errorln(sl *subLogger, v ...interface{}) {
return
}
logger.newLogEvent(fmt.Sprintln(v...), logger.ErrorHeader, sl.output)
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.ErrorHeader, sl.output))
}
// Errorf takes a pointer subLogger struct, string & interface formats and sends to Debug()
@@ -159,3 +160,9 @@ func Errorf(sl *subLogger, data string, v ...interface{}) {
Error(sl, fmt.Sprintf(data, v...))
}
func displayError(err error) {
if err != nil {
log.Printf("Logger write error: %v\n", err)
}
}

View File

@@ -1,5 +1,6 @@
package logger
//nolint
var (
subLoggers = map[string]*subLogger{}