123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- package logging
- // Custom logging hooks for powering our logs API.
- // Modeled after https://github.com/sirupsen/logrus/blob/master/hooks/test/test.go
- import (
- "math"
- "os"
- "path/filepath"
- "sync"
- "time"
- rotatelogs "github.com/lestrrat-go/file-rotatelogs"
- "github.com/owncast/owncast/utils"
- "github.com/rifflock/lfshook"
- "github.com/sirupsen/logrus"
- logger "github.com/sirupsen/logrus"
- )
- const maxLogEntries = 500
- // OCLogger represents the owncast internal logging.
- type OCLogger struct {
- Entries []logrus.Entry
- Warnings []logrus.Entry
- mu sync.RWMutex
- }
- // Logger is the shared instance of the internal logger.
- var Logger *OCLogger
- // Setup configures our custom logging destinations.
- func Setup(enableDebugOptions bool, enableVerboseLogging bool) {
- // Create the logging directory if needed
- loggingDirectory := filepath.Dir(getLogFilePath())
- if !utils.DoesFileExists(loggingDirectory) {
- if err := os.Mkdir(loggingDirectory, 0o700); err != nil {
- logger.Errorln("unable to create logs directory", loggingDirectory, err)
- }
- }
- // Write logs to a file
- path := getLogFilePath()
- writer, _ := rotatelogs.New(
- path+".%Y%m%d%H%M",
- rotatelogs.WithLinkName(path),
- rotatelogs.WithMaxAge(time.Duration(86400)*time.Second),
- rotatelogs.WithRotationTime(time.Duration(604800)*time.Second),
- )
- logMapping := lfshook.WriterMap{
- logrus.InfoLevel: writer,
- logrus.DebugLevel: writer,
- logrus.TraceLevel: writer,
- logrus.WarnLevel: writer,
- logrus.ErrorLevel: writer,
- logrus.FatalLevel: writer,
- }
- logger.AddHook(lfshook.NewHook(
- logMapping,
- &logger.TextFormatter{},
- ))
- if enableVerboseLogging {
- logrus.SetLevel(logrus.TraceLevel)
- } else {
- logrus.SetLevel(logrus.InfoLevel)
- }
- // Write to stdout console
- logger.SetOutput(os.Stdout)
- // Write to our custom logging hook for the log API
- _logger := new(OCLogger)
- logger.AddHook(_logger)
- if enableDebugOptions {
- logrus.SetReportCaller(true)
- }
- Logger = _logger
- }
- // Fire runs for every logging request.
- func (l *OCLogger) Fire(e *logger.Entry) error {
- // Store all log messages to return back in the logging API
- l.mu.Lock()
- defer l.mu.Unlock()
- // Append to log entries
- if len(l.Entries) > maxLogEntries {
- l.Entries = l.Entries[1:]
- }
- l.Entries = append(l.Entries, *e)
- if e.Level <= logger.WarnLevel {
- if len(l.Warnings) > maxLogEntries {
- l.Warnings = l.Warnings[1:]
- }
- l.Warnings = append(l.Warnings, *e)
- }
- return nil
- }
- // Levels specifies what log levels we care about.
- func (l *OCLogger) Levels() []logrus.Level {
- return logrus.AllLevels
- }
- // AllEntries returns all entries that were logged.
- func (l *OCLogger) AllEntries() []*logrus.Entry {
- l.mu.RLock()
- defer l.mu.RUnlock()
- // Make a copy so the returned value won't race with future log requests
- logCount := int(math.Min(float64(len(l.Entries)), maxLogEntries))
- entries := make([]*logrus.Entry, logCount)
- for i := 0; i < len(entries); i++ {
- // Make a copy, for safety
- entries[len(entries)-logCount:][i] = &l.Entries[i]
- }
- return entries
- }
- // WarningEntries returns all warning or greater that were logged.
- func (l *OCLogger) WarningEntries() []*logrus.Entry {
- l.mu.RLock()
- defer l.mu.RUnlock()
- // Make a copy so the returned value won't race with future log requests
- logCount := int(math.Min(float64(len(l.Warnings)), maxLogEntries))
- entries := make([]*logrus.Entry, logCount)
- for i := 0; i < len(entries); i++ {
- // Make a copy, for safety
- entries[len(entries)-logCount:][i] = &l.Warnings[i]
- }
- return entries
- }
|