Ctrl K
ComunidadGuías…

engine/logwriter.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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()
	}
}