engine/logwriter.go
Rama main · réplica de lectura del repositorio original.
package engine
import (
"os"
"sync"
"github.com/sirupsen/logrus"
)
// defaultLogPermissions is the file mode for the server log and the access
// logs. It matches the "create" line in the logrotate configuration.
const defaultLogPermissions = 0o640
// logWriter is an append-only log file that keeps its file handle open instead
// of re-opening it for every line, and that can be re-opened after log rotation.
type logWriter struct {
f *os.File
filename string
perm os.FileMode
mu sync.Mutex
}
// openLogWriter opens the given filename for appending, creating it if missing
func openLogWriter(filename string, perm os.FileMode) (*logWriter, error) {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, perm)
if err != nil {
return nil, err
}
return &logWriter{f: f, filename: filename, perm: perm}, nil
}
// Write makes logWriter an io.Writer, so that it can be given to logrus
func (lw *logWriter) Write(p []byte) (int, error) {
lw.mu.Lock()
defer lw.mu.Unlock()
if lw.f == nil {
return len(p), nil
}
return lw.f.Write(p)
}
// WriteLine writes one line, adding the trailing newline
func (lw *logWriter) WriteLine(line string) {
lw.mu.Lock()
defer lw.mu.Unlock()
if lw.f == nil {
return
}
if _, err := lw.f.WriteString(line + "\n"); err != nil {
logrus.Warnf("Can not write to %s: %s", lw.filename, err)
}
}
// Reopen closes and re-opens the log file, for use after log rotation
func (lw *logWriter) Reopen() error {
lw.mu.Lock()
defer lw.mu.Unlock()
if lw.f != nil {
lw.f.Close()
lw.f = nil
}
f, err := os.OpenFile(lw.filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, lw.perm)
if err != nil {
return err
}
lw.f = f
return nil
}
// Close closes the log file, if it is open
func (lw *logWriter) Close() error {
lw.mu.Lock()
defer lw.mu.Unlock()
if lw.f == nil {
return nil
}
err := lw.f.Close()
lw.f = nil
return err
}
// logWriters returns the log files that are in use
func (ac *Config) logWriters() []*logWriter {
var lws []*logWriter
for _, lw := range []*logWriter{ac.commonAccessLog, ac.combinedAccessLog, ac.serverLog} {
if lw != nil {
lws = append(lws, lw)
}
}
return lws
}
// ReopenLogs re-opens the access logs and the server log, after log rotation
func (ac *Config) ReopenLogs() {
for _, lw := range ac.logWriters() {
if err := lw.Reopen(); err != nil {
logrus.Errorf("Could not re-open %s: %s", lw.filename, err)
}
}
}
// closeLogs closes any open log files
func (ac *Config) closeLogs() {
for _, lw := range ac.logWriters() {
lw.Close()
}
}