diff options
Diffstat (limited to 'modules/log')
-rw-r--r-- | modules/log/conn.go | 12 | ||||
-rw-r--r-- | modules/log/console.go | 14 | ||||
-rw-r--r-- | modules/log/event.go | 64 | ||||
-rw-r--r-- | modules/log/file.go | 13 | ||||
-rw-r--r-- | modules/log/log.go | 37 | ||||
-rw-r--r-- | modules/log/smtp.go | 5 |
6 files changed, 144 insertions, 1 deletions
diff --git a/modules/log/conn.go b/modules/log/conn.go index 8816664526..1abe44c1d4 100644 --- a/modules/log/conn.go +++ b/modules/log/conn.go @@ -77,6 +77,13 @@ func (i *connWriter) connect() error { return nil } +func (i *connWriter) releaseReopen() error { + if i.innerWriter != nil { + return i.connect() + } + return nil +} + // ConnLogger implements LoggerProvider. // it writes messages in keep-live tcp connection. type ConnLogger struct { @@ -119,6 +126,11 @@ func (log *ConnLogger) GetName() string { return "conn" } +// ReleaseReopen causes the ConnLogger to reconnect to the server +func (log *ConnLogger) ReleaseReopen() error { + return log.out.(*connWriter).releaseReopen() +} + func init() { Register("conn", NewConn) } diff --git a/modules/log/console.go b/modules/log/console.go index 6cfca8a733..a805021f0b 100644 --- a/modules/log/console.go +++ b/modules/log/console.go @@ -68,6 +68,20 @@ func (log *ConsoleLogger) Init(config string) error { func (log *ConsoleLogger) Flush() { } +// ReleaseReopen causes the console logger to reconnect to os.Stdout +func (log *ConsoleLogger) ReleaseReopen() error { + if log.Stderr { + log.NewWriterLogger(&nopWriteCloser{ + w: os.Stderr, + }) + } else { + log.NewWriterLogger(&nopWriteCloser{ + w: os.Stdout, + }) + } + return nil +} + // GetName returns the default name for this implementation func (log *ConsoleLogger) GetName() string { return "console" diff --git a/modules/log/event.go b/modules/log/event.go index 37efa3c230..6975bf749d 100644 --- a/modules/log/event.go +++ b/modules/log/event.go @@ -29,6 +29,7 @@ type EventLogger interface { GetLevel() Level GetStacktraceLevel() Level GetName() string + ReleaseReopen() error } // ChannelledLog represents a cached channel to a LoggerProvider @@ -117,6 +118,11 @@ func (l *ChannelledLog) Flush() { l.flush <- true } +// ReleaseReopen this ChannelledLog +func (l *ChannelledLog) ReleaseReopen() error { + return l.loggerProvider.ReleaseReopen() +} + // GetLevel gets the level of this ChannelledLog func (l *ChannelledLog) GetLevel() Level { return l.loggerProvider.GetLevel() @@ -145,6 +151,7 @@ type MultiChannelledLog struct { level Level stacktraceLevel Level closed chan bool + paused chan bool } // NewMultiChannelledLog a new logger instance with given logger provider and config. @@ -159,6 +166,7 @@ func NewMultiChannelledLog(name string, bufferLength int64) *MultiChannelledLog stacktraceLevel: NONE, close: make(chan bool), closed: make(chan bool), + paused: make(chan bool), } return m } @@ -229,6 +237,33 @@ func (m *MultiChannelledLog) closeLoggers() { m.closed <- true } +// Pause pauses this Logger +func (m *MultiChannelledLog) Pause() { + m.paused <- true +} + +// Resume resumes this Logger +func (m *MultiChannelledLog) Resume() { + m.paused <- false +} + +// ReleaseReopen causes this logger to tell its subloggers to release and reopen +func (m *MultiChannelledLog) ReleaseReopen() error { + m.mutex.Lock() + defer m.mutex.Unlock() + var accumulatedErr error + for _, logger := range m.loggers { + if err := logger.ReleaseReopen(); err != nil { + if accumulatedErr == nil { + accumulatedErr = fmt.Errorf("Error whilst reopening: %s Error: %v", logger.GetName(), err) + } else { + accumulatedErr = fmt.Errorf("Error whilst reopening: %s Error: %v & %v", logger.GetName(), err, accumulatedErr) + } + } + } + return accumulatedErr +} + // Start processing the MultiChannelledLog func (m *MultiChannelledLog) Start() { m.mutex.Lock() @@ -238,8 +273,35 @@ func (m *MultiChannelledLog) Start() { } m.started = true m.mutex.Unlock() + paused := false for { + if paused { + select { + case paused = <-m.paused: + if !paused { + m.ResetLevel() + } + case _, ok := <-m.flush: + if !ok { + m.closeLoggers() + return + } + m.mutex.Lock() + for _, logger := range m.loggers { + logger.Flush() + } + m.mutex.Unlock() + case <-m.close: + m.closeLoggers() + return + } + continue + } select { + case paused = <-m.paused: + if paused && m.level < INFO { + m.level = INFO + } case event, ok := <-m.queue: if !ok { m.closeLoggers() @@ -275,7 +337,7 @@ func (m *MultiChannelledLog) LogEvent(event *Event) error { select { case m.queue <- event: return nil - case <-time.After(60 * time.Second): + case <-time.After(100 * time.Millisecond): // We're blocked! return ErrTimeout{ Name: m.name, diff --git a/modules/log/file.go b/modules/log/file.go index 877820b8be..925d83f2b7 100644 --- a/modules/log/file.go +++ b/modules/log/file.go @@ -249,6 +249,19 @@ func (log *FileLogger) Flush() { _ = log.mw.fd.Sync() } +// ReleaseReopen releases and reopens log files +func (log *FileLogger) ReleaseReopen() error { + closingErr := log.mw.fd.Close() + startingErr := log.StartLogger() + if startingErr != nil { + if closingErr != nil { + return fmt.Errorf("Error during closing: %v Error during starting: %v", closingErr, startingErr) + } + return startingErr + } + return closingErr +} + // GetName returns the default name for this implementation func (log *FileLogger) GetName() string { return "file" diff --git a/modules/log/log.go b/modules/log/log.go index 71e88491f1..2a35b5752c 100644 --- a/modules/log/log.go +++ b/modules/log/log.go @@ -5,6 +5,7 @@ package log import ( + "fmt" "os" "runtime" "strings" @@ -192,6 +193,42 @@ func IsFatal() bool { return GetLevel() <= FATAL } +// Pause pauses all the loggers +func Pause() { + NamedLoggers.Range(func(key, value interface{}) bool { + logger := value.(*Logger) + logger.Pause() + logger.Flush() + return true + }) +} + +// Resume resumes all the loggers +func Resume() { + NamedLoggers.Range(func(key, value interface{}) bool { + logger := value.(*Logger) + logger.Resume() + return true + }) +} + +// ReleaseReopen releases and reopens logging files +func ReleaseReopen() error { + var accumulatedErr error + NamedLoggers.Range(func(key, value interface{}) bool { + logger := value.(*Logger) + if err := logger.ReleaseReopen(); err != nil { + if accumulatedErr == nil { + accumulatedErr = fmt.Errorf("Error reopening %s: %v", key.(string), err) + } else { + accumulatedErr = fmt.Errorf("Error reopening %s: %v & %v", key.(string), err, accumulatedErr) + } + } + return true + }) + return accumulatedErr +} + // Close closes all the loggers func Close() { l, ok := NamedLoggers.Load(DEFAULT) diff --git a/modules/log/smtp.go b/modules/log/smtp.go index f912299a73..edf4943619 100644 --- a/modules/log/smtp.go +++ b/modules/log/smtp.go @@ -97,6 +97,11 @@ func (log *SMTPLogger) sendMail(p []byte) (int, error) { func (log *SMTPLogger) Flush() { } +// ReleaseReopen does nothing +func (log *SMTPLogger) ReleaseReopen() error { + return nil +} + // GetName returns the default name for this implementation func (log *SMTPLogger) GetName() string { return "smtp" |