mirror of
https://github.com/stashapp/stash.git
synced 2025-12-07 08:54:10 +01:00
* Fix logs from scraper and plugins not being shown in UI Using `logger.` in the logger package to write logs is "incorrect". This as the package contains a variable named `logger` which contains the logrus instance. So instead of the log line being handled by the custom log implementation / wrapper which makes sure the lines are shown in the UI as well, it's written to logrus directly meaning the wrapper is skipped. This "issue" is obviously triggered because in any other place `logger.X` can be used and it will used the custom logger package / wrapper which works fine. * Add plugin / scraper name to logging output Indicate which plugin / scraper wrote a log message by including its name to the `[Scrape]` prefix. * Add missing addLogItem call
283 lines
5.2 KiB
Go
283 lines
5.2 KiB
Go
package logger
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type LogItem struct {
|
|
Time time.Time `json:"time"`
|
|
Type string `json:"type"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
var logger = logrus.New()
|
|
var progressLogger = logrus.New()
|
|
|
|
var LogCache []LogItem
|
|
var mutex = &sync.Mutex{}
|
|
var logSubs []chan []LogItem
|
|
var waiting = false
|
|
var lastBroadcast = time.Now()
|
|
var logBuffer []LogItem
|
|
|
|
// Init initialises the logger based on a logging configuration
|
|
func Init(logFile string, logOut bool, logLevel string) {
|
|
var file *os.File
|
|
customFormatter := new(logrus.TextFormatter)
|
|
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
|
|
customFormatter.ForceColors = true
|
|
customFormatter.FullTimestamp = true
|
|
logger.SetFormatter(customFormatter)
|
|
|
|
if logFile != "" {
|
|
var err error
|
|
file, err = os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
|
|
|
if err != nil {
|
|
fmt.Printf("Could not open '%s' for log output due to error: %s\n", logFile, err.Error())
|
|
}
|
|
}
|
|
|
|
if file != nil && logOut {
|
|
mw := io.MultiWriter(os.Stderr, file)
|
|
logger.Out = mw
|
|
} else if file != nil {
|
|
logger.Out = file
|
|
}
|
|
|
|
// otherwise, output to StdErr
|
|
|
|
SetLogLevel(logLevel)
|
|
}
|
|
|
|
func SetLogLevel(level string) {
|
|
logger.Level = logLevelFromString(level)
|
|
}
|
|
|
|
func logLevelFromString(level string) logrus.Level {
|
|
ret := logrus.InfoLevel
|
|
|
|
if level == "Debug" {
|
|
ret = logrus.DebugLevel
|
|
} else if level == "Warning" {
|
|
ret = logrus.WarnLevel
|
|
} else if level == "Error" {
|
|
ret = logrus.ErrorLevel
|
|
} else if level == "Trace" {
|
|
ret = logrus.TraceLevel
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func addLogItem(l *LogItem) {
|
|
mutex.Lock()
|
|
l.Time = time.Now()
|
|
LogCache = append([]LogItem{*l}, LogCache...)
|
|
if len(LogCache) > 30 {
|
|
LogCache = LogCache[:len(LogCache)-1]
|
|
}
|
|
mutex.Unlock()
|
|
go broadcastLogItem(l)
|
|
}
|
|
|
|
func GetLogCache() []LogItem {
|
|
mutex.Lock()
|
|
|
|
ret := make([]LogItem, len(LogCache))
|
|
copy(ret, LogCache)
|
|
|
|
mutex.Unlock()
|
|
|
|
return ret
|
|
}
|
|
|
|
func SubscribeToLog(stop chan int) <-chan []LogItem {
|
|
ret := make(chan []LogItem, 100)
|
|
|
|
go func() {
|
|
<-stop
|
|
unsubscribeFromLog(ret)
|
|
}()
|
|
|
|
mutex.Lock()
|
|
logSubs = append(logSubs, ret)
|
|
mutex.Unlock()
|
|
|
|
return ret
|
|
}
|
|
|
|
func unsubscribeFromLog(toRemove chan []LogItem) {
|
|
mutex.Lock()
|
|
for i, c := range logSubs {
|
|
if c == toRemove {
|
|
logSubs = append(logSubs[:i], logSubs[i+1:]...)
|
|
}
|
|
}
|
|
close(toRemove)
|
|
mutex.Unlock()
|
|
}
|
|
|
|
func doBroadcastLogItems() {
|
|
// assumes mutex held
|
|
|
|
for _, c := range logSubs {
|
|
// don't block waiting to broadcast
|
|
select {
|
|
case c <- logBuffer:
|
|
default:
|
|
}
|
|
}
|
|
|
|
logBuffer = nil
|
|
waiting = false
|
|
lastBroadcast = time.Now()
|
|
}
|
|
|
|
func broadcastLogItem(l *LogItem) {
|
|
mutex.Lock()
|
|
|
|
logBuffer = append(logBuffer, *l)
|
|
|
|
// don't send more than once per second
|
|
if !waiting {
|
|
// if last broadcast was under a second ago, wait until a second has
|
|
// passed
|
|
timeSinceBroadcast := time.Since(lastBroadcast)
|
|
if timeSinceBroadcast.Seconds() < 1 {
|
|
waiting = true
|
|
time.AfterFunc(time.Second-timeSinceBroadcast, func() {
|
|
mutex.Lock()
|
|
doBroadcastLogItems()
|
|
mutex.Unlock()
|
|
})
|
|
} else {
|
|
doBroadcastLogItems()
|
|
}
|
|
}
|
|
// if waiting then adding it to the buffer is sufficient
|
|
|
|
mutex.Unlock()
|
|
}
|
|
|
|
func init() {
|
|
progressLogger.SetFormatter(new(ProgressFormatter))
|
|
}
|
|
|
|
func Progressf(format string, args ...interface{}) {
|
|
progressLogger.Infof(format, args...)
|
|
l := &LogItem{
|
|
Type: "progress",
|
|
Message: fmt.Sprintf(format, args...),
|
|
}
|
|
addLogItem(l)
|
|
|
|
}
|
|
|
|
func Trace(args ...interface{}) {
|
|
logger.Trace(args...)
|
|
l := &LogItem{
|
|
Type: "trace",
|
|
Message: fmt.Sprint(args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Tracef(format string, args ...interface{}) {
|
|
logger.Tracef(format, args...)
|
|
l := &LogItem{
|
|
Type: "trace",
|
|
Message: fmt.Sprintf(format, args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Debug(args ...interface{}) {
|
|
logger.Debug(args...)
|
|
l := &LogItem{
|
|
Type: "debug",
|
|
Message: fmt.Sprint(args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Debugf(format string, args ...interface{}) {
|
|
logger.Debugf(format, args...)
|
|
l := &LogItem{
|
|
Type: "debug",
|
|
Message: fmt.Sprintf(format, args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Info(args ...interface{}) {
|
|
logger.Info(args...)
|
|
l := &LogItem{
|
|
Type: "info",
|
|
Message: fmt.Sprint(args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Infof(format string, args ...interface{}) {
|
|
logger.Infof(format, args...)
|
|
l := &LogItem{
|
|
Type: "info",
|
|
Message: fmt.Sprintf(format, args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Warn(args ...interface{}) {
|
|
logger.Warn(args...)
|
|
l := &LogItem{
|
|
Type: "warn",
|
|
Message: fmt.Sprint(args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Warnf(format string, args ...interface{}) {
|
|
logger.Warnf(format, args...)
|
|
l := &LogItem{
|
|
Type: "warn",
|
|
Message: fmt.Sprintf(format, args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Error(args ...interface{}) {
|
|
logger.Error(args...)
|
|
l := &LogItem{
|
|
Type: "error",
|
|
Message: fmt.Sprint(args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Errorf(format string, args ...interface{}) {
|
|
logger.Errorf(format, args...)
|
|
l := &LogItem{
|
|
Type: "error",
|
|
Message: fmt.Sprintf(format, args...),
|
|
}
|
|
addLogItem(l)
|
|
}
|
|
|
|
func Fatal(args ...interface{}) {
|
|
logger.Fatal(args...)
|
|
}
|
|
|
|
func Fatalf(format string, args ...interface{}) {
|
|
logger.Fatalf(format, args...)
|
|
}
|
|
|
|
//func WithRequest(req *http.Request) *logrus.Entry {
|
|
// return logger.WithFields(RequestFields(req))
|
|
//}
|