diff --git a/.gitignore b/.gitignore index c0d624c..5f95a7f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ docker-compose.yml dist/ tmp/** torrents.json +logs/** diff --git a/CHANGELOG.md b/CHANGELOG.md index e257509..fbd3e8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -117,7 +117,10 @@ - Add support for multiple debrid providers - A full-fledged UI for adding torrents, repairing files, viewing config and managing torrents -- Add a more robust logging system - Fix issues with Alldebrid - Fix file transversal bug - - Fix files with no parent directory \ No newline at end of file + - Fix files with no parent directory +- Logging + - Add a more robust logging system + - Add logging to a file + - Add logging to the UI \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 5d31bcd..6146afd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,8 +21,9 @@ FROM scratch COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /blackhole /blackhole COPY --from=builder /app/README.md /README.md +ENV LOG_PATH=/app/logs -EXPOSE 8181 +EXPOSE 8181 8282 VOLUME ["/app"] diff --git a/README.md b/README.md index 8eff445..fe26d5b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,27 @@ This is a Golang implementation go Torrent QbitTorrent with a **Multiple Debrid service support**. +### Table of Contents + +- [Features](#features) +- [Supported Debrid Providers](#supported-debrid-providers) +- [Installation](#installation) + - [Docker Compose](#docker-compose) + - [Binary](#binary) +- [Usage](#usage) +- [Connecting to Sonarr/Radarr](#connecting-to-sonarrradarr) +- [Sample Config](#sample-config) +- [Config Notes](#config-notes) + - [Log Level](#log-level) + - [Max Cache Size](#max-cache-size) + - [Debrid Config](#debrid-config) + - [Proxy Config](#proxy-config) + - [Qbittorrent Config](#qbittorrent-config) + - [Arrs Config](#arrs-config) +- [Proxy](#proxy) +- [Repair Worker](#repair-worker) +- [Changelog](#changelog) +- [TODO](#todo) ### Features @@ -25,7 +46,8 @@ The proxy is useful in filtering out un-cached Real Debrid torrents - [All Debrid](https://alldebrid.com) -#### Installation +### Installation + ##### Docker Compose ```yaml version: '3.7' @@ -38,7 +60,7 @@ services: - "8181:8181" # Proxy user: "1000:1000" volumes: - - ./logs:/app/logs + - ./logs/:/app/logs - /mnt/:/mnt - ~/plex/configs/blackhole/config.json:/app/config.json # Config file, see below environment: diff --git a/common/logger.go b/common/logger.go index dae5ed5..49cac90 100644 --- a/common/logger.go +++ b/common/logger.go @@ -3,12 +3,37 @@ package common import ( "fmt" "github.com/rs/zerolog" + "gopkg.in/natefinch/lumberjack.v2" "os" + "path/filepath" "strings" ) +func GetLogPath() string { + logsDir := os.Getenv("LOG_PATH") + if logsDir == "" { + // Create the logs directory if it doesn't exist + logsDir = "logs" + } + + if err := os.MkdirAll(logsDir, 0755); err != nil { + panic(fmt.Sprintf("Failed to create logs directory: %v", err)) + } + + return filepath.Join(logsDir, "decypharr.log") +} + func NewLogger(prefix string, level string, output *os.File) zerolog.Logger { - writer := zerolog.ConsoleWriter{ + + rotatingLogFile := &lumberjack.Logger{ + Filename: GetLogPath(), + MaxSize: 10, + MaxBackups: 2, + MaxAge: 28, + Compress: true, + } + + consoleWriter := zerolog.ConsoleWriter{ Out: output, TimeFormat: "2006-01-02 15:04:05", NoColor: false, // Set to true if you don't want colors @@ -20,7 +45,21 @@ func NewLogger(prefix string, level string, output *os.File) zerolog.Logger { }, } - logger := zerolog.New(writer). + fileWriter := zerolog.ConsoleWriter{ + Out: rotatingLogFile, + TimeFormat: "2006-01-02 15:04:05", + NoColor: true, // No colors in file output + FormatLevel: func(i interface{}) string { + return strings.ToUpper(fmt.Sprintf("| %-6s|", i)) + }, + FormatMessage: func(i interface{}) string { + return fmt.Sprintf("[%s] %v", prefix, i) + }, + } + + multi := zerolog.MultiLevelWriter(consoleWriter, fileWriter) + + logger := zerolog.New(multi). With(). Timestamp(). Logger(). diff --git a/go.mod b/go.mod index 52b0bbc..4a39397 100644 --- a/go.mod +++ b/go.mod @@ -29,4 +29,5 @@ require ( golang.org/x/net v0.27.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect ) diff --git a/go.sum b/go.sum index d496ac2..59a6b65 100644 --- a/go.sum +++ b/go.sum @@ -288,6 +288,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/qbit/server/routes.go b/pkg/qbit/server/routes.go index 668debd..efd1031 100644 --- a/pkg/qbit/server/routes.go +++ b/pkg/qbit/server/routes.go @@ -45,9 +45,6 @@ func (q *qbitHandler) Routes(r chi.Router) http.Handler { func (u *uiHandler) Routes(r chi.Router) http.Handler { r.Group(func(r chi.Router) { - //if u.debug { - // r.Use(middleware.Logger) - //} r.Get("/", u.IndexHandler) r.Get("/download", u.DownloadHandler) r.Get("/repair", u.RepairHandler) diff --git a/pkg/qbit/server/server.go b/pkg/qbit/server/server.go index 90ad773..96ba27b 100644 --- a/pkg/qbit/server/server.go +++ b/pkg/qbit/server/server.go @@ -11,6 +11,7 @@ import ( "github.com/sirrobot01/debrid-blackhole/pkg/arr" "github.com/sirrobot01/debrid-blackhole/pkg/debrid" "github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared" + "io" "net/http" "os" "os/signal" @@ -41,6 +42,7 @@ func (s *Server) Start(ctx context.Context) error { ui := uiHandler{qbit: s.qbit, logger: common.NewLogger("UI", s.logger.GetLevel().String(), os.Stdout), debug: debug} // Register routes + r.Get("/logs", s.GetLogs) q.Routes(r) ui.Routes(r) @@ -67,3 +69,29 @@ func (s *Server) Start(ctx context.Context) error { s.logger.Info().Msg("Shutting down gracefully...") return srv.Shutdown(context.Background()) } + +func (s *Server) GetLogs(w http.ResponseWriter, r *http.Request) { + logFile := common.GetLogPath() + + // Open and read the file + file, err := os.Open(logFile) + if err != nil { + http.Error(w, "Error reading log file", http.StatusInternalServerError) + return + } + defer file.Close() + + // Set headers + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Header().Set("Content-Disposition", "inline; filename=application.log") + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Expires", "0") + + // Stream the file + _, err = io.Copy(w, file) + if err != nil { + http.Error(w, "Error streaming log file", http.StatusInternalServerError) + return + } +} diff --git a/pkg/qbit/server/templates/index.html b/pkg/qbit/server/templates/index.html index 8387e3a..fa8c7de 100644 --- a/pkg/qbit/server/templates/index.html +++ b/pkg/qbit/server/templates/index.html @@ -22,12 +22,12 @@ Progress Speed Category + Debrid State Actions - @@ -51,6 +51,7 @@ ${formatSpeed(torrent.dlspeed)} ${torrent.category || 'None'} + ${torrent.debrid || 'None'} ${torrent.state}