Feature: Tail live logs (#27)

* chore: add new yarn.lock

* chore: add pkgs

* feat: push events via server-sent-events

* feat(web): tail live logs

* fix: update irc network

* fix: set baseurl

* fix: headers
This commit is contained in:
Ludvig Lundgren 2021-09-07 22:23:27 +02:00 committed by GitHub
parent 11fcf1ead9
commit 09eb0b1716
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 213 additions and 26 deletions

View file

@ -9,11 +9,16 @@ import (
"github.com/autobrr/autobrr/web"
"github.com/go-chi/chi"
"github.com/r3labs/sse/v2"
"github.com/rs/cors"
)
type Server struct {
address string
baseUrl string
sse *sse.Server
address string
baseUrl string
actionService actionService
authService authService
downloadClientService downloadClientService
@ -22,10 +27,12 @@ type Server struct {
ircService ircService
}
func NewServer(address string, baseUrl string, actionService actionService, authService authService, downloadClientSvc downloadClientService, filterSvc filterService, indexerSvc indexerService, ircSvc ircService) Server {
func NewServer(sse *sse.Server, address string, baseUrl string, actionService actionService, authService authService, downloadClientSvc downloadClientService, filterSvc filterService, indexerSvc indexerService, ircSvc ircService) Server {
return Server{
address: address,
baseUrl: baseUrl,
sse: sse,
address: address,
baseUrl: baseUrl,
actionService: actionService,
authService: authService,
downloadClientService: downloadClientSvc,
@ -51,6 +58,17 @@ func (s Server) Open() error {
func (s Server) Handler() http.Handler {
r := chi.NewRouter()
c := cors.New(cors.Options{
AllowCredentials: true,
AllowedMethods: []string{"HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE"},
AllowOriginFunc: func(origin string) bool { return true },
OptionsPassthrough: true,
// Enable Debugging for testing, consider disabling in production
Debug: false,
})
r.Use(c.Handler)
//r.Get("/", index)
//r.Get("/dashboard", dashboard)
@ -76,6 +94,19 @@ func (s Server) Handler() http.Handler {
r.Route("/filters", newFilterHandler(encoder, s.filterService).Routes)
r.Route("/irc", newIrcHandler(encoder, s.ircService).Routes)
r.Route("/indexer", newIndexerHandler(encoder, s.indexerService, s.ircService).Routes)
r.HandleFunc("/events", func(w http.ResponseWriter, r *http.Request) {
// inject CORS headers to bypass checks
s.sse.Headers = map[string]string{
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"X-Accel-Buffering": "no",
}
s.sse.HTTPHandler(w, r)
})
})
})

View file

@ -408,7 +408,7 @@ func (s *Handler) handleMode(msg *irc.Message) error {
}
func (s *Handler) handlePing(msg *irc.Message) error {
log.Trace().Msgf("%v: PING %v", s.network.Server, msg)
log.Trace().Msgf("%v: %v", s.network.Server, msg)
pong := irc.Message{
Command: "PONG",

View file

@ -7,12 +7,13 @@ import (
"github.com/autobrr/autobrr/internal/domain"
"github.com/r3labs/sse/v2"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"gopkg.in/natefinch/lumberjack.v2"
)
func Setup(cfg domain.Config) {
func Setup(cfg domain.Config, sse *sse.Server) {
zerolog.TimeFieldFormat = time.RFC3339
switch cfg.LogLevel {
@ -47,6 +48,7 @@ func Setup(cfg domain.Config) {
writers = io.MultiWriter(consoleWriter, fileWriter)
}
log.Logger = log.Hook(&ServerSentEventHook{sse: sse})
log.Logger = log.Output(writers)
log.Print("Starting autobrr")

View file

@ -0,0 +1,43 @@
package logger
import (
"encoding/json"
"strings"
"time"
"github.com/r3labs/sse/v2"
"github.com/rs/zerolog"
)
type LogMessage struct {
Time string `json:"time"`
Level string `json:"level"`
Message string `json:"message"`
}
func (m LogMessage) ToJsonString() string {
j, err := json.Marshal(m)
if err != nil {
return ""
}
return string(j)
}
type ServerSentEventHook struct {
sse *sse.Server
}
func (h *ServerSentEventHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
if h.sse != nil {
// publish too logs topic
logMsg := LogMessage{
Time: time.Now().Format(time.RFC3339),
Level: strings.ToUpper(level.String()),
Message: msg,
}
h.sse.Publish("logs", &sse.Event{
Data: []byte(logMsg.ToJsonString()),
})
}
}