better logging

This commit is contained in:
Simon Martens
2024-11-16 17:30:14 +01:00
parent 527fbfa000
commit 84fa6f7fa4
17 changed files with 221 additions and 106 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
KGPZ/ KGPZ/
tmp/
data_git/ data_git/
cache_geo/ cache_geo/
cache_gnd/ cache_gnd/

View File

@@ -6,6 +6,7 @@ import (
"sync" "sync"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers" "github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers" "github.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
) )
@@ -44,12 +45,9 @@ func (k *KGPZ) Init() {
} }
func NewKGPZ(config *providers.ConfigProvider) *KGPZ { func NewKGPZ(config *providers.ConfigProvider) *KGPZ {
if config == nil { helpers.AssertNonNil(config, "Config is nil")
panic("ConfigProvider is nil")
}
if err := config.Validate(); err != nil { if err := config.Validate(); err != nil {
helpers.MaybePanic(err, "Error validating config") helpers.Assert(err, "Error validating config")
} }
return &KGPZ{Config: config} return &KGPZ{Config: config}
@@ -65,10 +63,10 @@ func (k *KGPZ) Serialize() {
defer k.gmu.Unlock() defer k.gmu.Unlock()
issues, err := getXMLFiles(filepath.Join(k.Config.FolderPath, ISSUES_DIR)) issues, err := getXMLFiles(filepath.Join(k.Config.FolderPath, ISSUES_DIR))
helpers.MaybePanic(err, "Error getting issues") helpers.Assert(err, "Error getting issues")
pieces, err := getXMLFiles(filepath.Join(k.Config.FolderPath, PIECES_DIR)) pieces, err := getXMLFiles(filepath.Join(k.Config.FolderPath, PIECES_DIR))
helpers.MaybePanic(err, "Error getting pieces") helpers.Assert(err, "Error getting pieces")
lib := providers.NewLibrary( lib := providers.NewLibrary(
[]string{filepath.Join(k.Config.FolderPath, AGENTS_PATH)}, []string{filepath.Join(k.Config.FolderPath, AGENTS_PATH)},
@@ -122,6 +120,7 @@ func (k *KGPZ) IsDebug() bool {
func (k *KGPZ) Pull() { func (k *KGPZ) Pull() {
go func() { go func() {
logging.Info("Pulling Repository...")
k.gmu.Lock() k.gmu.Lock()
if k.Repo == nil { if k.Repo == nil {
@@ -130,17 +129,13 @@ func (k *KGPZ) Pull() {
} }
err, changed := k.Repo.Pull() err, changed := k.Repo.Pull()
if err != nil { logging.Error(err, "Error pulling GitProvider")
helpers.LogOnErr(&k.Repo, err, "Error pulling repo")
}
// Need to unlock here to prevent deadlock, since Serialize locks the same mutex // Need to unlock here to prevent deadlock, since Serialize locks the same mutex
k.gmu.Unlock() k.gmu.Unlock()
if changed { if changed {
if k.IsDebug() { logging.ObjDebug(&k.Repo, "Remote changed. Reparsing...")
helpers.LogOnDebug(&k.Repo, "GitProvider changed")
}
k.Serialize() k.Serialize()
} }
}() }()
@@ -149,7 +144,7 @@ func (k *KGPZ) Pull() {
func (k *KGPZ) initRepo() { func (k *KGPZ) initRepo() {
gp, err := providers.NewGitProvider(k.Config.Config.GitURL, k.Config.Config.FolderPath, k.Config.Config.GitBranch) gp, err := providers.NewGitProvider(k.Config.Config.GitURL, k.Config.Config.FolderPath, k.Config.Config.GitBranch)
if err != nil { if err != nil {
helpers.LogOnErr(&gp, err, "Error creating GitProvider") logging.ObjErr(&gp, err, "Error creating GitProvider")
return return
} }
@@ -158,9 +153,7 @@ func (k *KGPZ) initRepo() {
k.gmu.Unlock() k.gmu.Unlock()
k.Pull() k.Pull()
if k.IsDebug() { logging.ObjDebug(&k.Repo, "GitProvider initialized")
helpers.LogOnDebug(&gp, "GitProvider")
}
} }
func (k *KGPZ) Shutdown() { func (k *KGPZ) Shutdown() {

View File

@@ -5,9 +5,13 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
const (
START_YEAR = "1764"
)
func GetYear(kgpz *app.KGPZ) fiber.Handler { func GetYear(kgpz *app.KGPZ) fiber.Handler {
return func(c *fiber.Ctx) error { return func(c *fiber.Ctx) error {
y := c.Params("year", "1764") y := c.Params("year", START_YEAR)
if len(y) != 4 { if len(y) != 4 {
return c.SendStatus(fiber.StatusBadRequest) return c.SendStatus(fiber.StatusBadRequest)
} }
@@ -16,6 +20,7 @@ func GetYear(kgpz *app.KGPZ) fiber.Handler {
if len(issues.Issues) == 0 { if len(issues.Issues) == 0 {
return c.SendStatus(fiber.StatusNotFound) return c.SendStatus(fiber.StatusNotFound)
} }
return c.Render("/", fiber.Map{"model": issues}) return c.Render("/", fiber.Map{"model": issues})
} }
} }

View File

@@ -1,24 +1,43 @@
package helpers package helpers
import ( import (
"fmt"
"os" "os"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
) )
func Panic(err error, msg string) { func Assert(err error, msg ...string) {
fmt.Println(msg)
if err != nil {
fmt.Println("Error: ", err)
}
os.Exit(1)
}
func MaybePanic(err error, msg string) {
if err == nil { if err == nil {
return return
} }
fmt.Println(msg) logging.Error(err, msg...)
fmt.Println("Error: ", err) os.Exit(1)
}
func AssertNonNil(obj interface{}, msg ...string) {
if obj != nil {
return
}
logging.Error(nil, msg...)
os.Exit(1)
}
func AssertNil(obj interface{}, msg ...string) {
if obj == nil {
return
}
logging.Error(nil, msg...)
os.Exit(1)
}
func AssertStr(str string, msg ...string) {
if str != "" {
return
}
logging.Error(nil, msg...)
os.Exit(1) os.Exit(1)
} }

View File

@@ -1,6 +1,8 @@
package helpers package helpers
import "sync" import (
"sync"
)
type EventMux[T any] struct { type EventMux[T any] struct {
// INFO: This is a simple event multiplexer that allows to subscribe to events and to publish them. // INFO: This is a simple event multiplexer that allows to subscribe to events and to publish them.

View File

@@ -1,26 +0,0 @@
package helpers
import "fmt"
func LogOnDebug[T fmt.Stringer](object *T, msg string) {
if msg != "" {
fmt.Println(msg)
}
if object != nil {
fmt.Println(*object)
}
}
func LogOnErr[T fmt.Stringer](object *T, err error, msg string) {
if err != nil {
if msg != "" {
fmt.Println(msg)
}
if object != nil {
fmt.Println(*object)
}
fmt.Println("Error: ", err)
}
}

View File

@@ -0,0 +1,66 @@
package logging
import (
"fmt"
"log/slog"
)
func ObjDebug[T fmt.Stringer](object *T, msg string) {
if msg != "" {
slog.Debug(msg)
}
if object != nil {
obj := *object
slog.Debug(obj.String())
}
}
func ObjErr[T fmt.Stringer](object *T, err error, msg ...string) {
if err == nil {
return
}
if len(msg) > 0 {
for _, m := range msg {
slog.Error(m)
}
}
if object != nil {
obj := *object
slog.Debug(obj.String())
}
slog.Error(err.Error())
}
func Error(err error, msg ...string) {
if err == nil {
return
}
if len(msg) > 0 {
for _, m := range msg {
slog.Error(m)
}
}
slog.Error(err.Error())
}
func Info(msg ...string) {
if len(msg) > 0 {
for _, m := range msg {
slog.Info(m)
}
}
}
func SetDebug() {
slog.SetLogLoggerLevel(slog.LevelDebug)
}
func SetInfo() {
slog.SetLogLoggerLevel(slog.LevelInfo)
}

57
helpers/parselog.go Normal file
View File

@@ -0,0 +1,57 @@
package helpers
import "sync"
type LogMessage struct {
Commit string
File string
Message string
Fatal bool
}
type ParseLogger struct {
mu sync.Mutex
Messages []LogMessage
}
func NewParseLog() *ParseLogger {
return &ParseLogger{
Messages: make([]LogMessage, 0),
}
}
func (p *ParseLogger) AddMessage(commit, file, message string, fatal bool) {
p.mu.Lock()
defer p.mu.Unlock()
p.Messages = append(p.Messages, LogMessage{
Commit: commit,
File: file,
Message: message,
Fatal: fatal,
})
}
func (p *ParseLogger) Fatal() bool {
p.mu.Lock()
defer p.mu.Unlock()
for _, m := range p.Messages {
if m.Fatal {
return true
}
}
return false
}
func (p *ParseLogger) GetMessages() []LogMessage {
p.mu.Lock()
defer p.mu.Unlock()
res := make([]LogMessage, len(p.Messages))
copy(res, p.Messages)
return res
}
func (p *ParseLogger) Clear() {
p.mu.Lock()
defer p.mu.Unlock()
p.Messages = make([]LogMessage, 0)
}

View File

@@ -3,10 +3,10 @@ package helpers
import ( import (
"errors" "errors"
"io/fs" "io/fs"
"log"
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
) )
@@ -96,7 +96,6 @@ func (fw *FileWatcher) Watch() error {
return return
} }
if !event.Has(fsnotify.Chmod) { if !event.Has(fsnotify.Chmod) {
log.Println("event:", event)
fw.mu.Lock() fw.mu.Lock()
for _, wf := range fw.wf { for _, wf := range fw.wf {
wf(event.Name) wf(event.Name)
@@ -107,7 +106,7 @@ func (fw *FileWatcher) Watch() error {
if !ok { if !ok {
return return
} }
log.Println("error:", err) logging.Error(err)
} }
} }
}() }()

View File

@@ -8,6 +8,7 @@ import (
"github.com/Theodor-Springmann-Stiftung/kgpz_web/app" "github.com/Theodor-Springmann-Stiftung/kgpz_web/app"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers" "github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers" "github.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/server" "github.com/Theodor-Springmann-Stiftung/kgpz_web/server"
) )
@@ -31,7 +32,13 @@ const (
func main() { func main() {
cfg := providers.NewConfigProvider([]string{DEV_CONFIG, DEFAULT_CONFIG}) cfg := providers.NewConfigProvider([]string{DEV_CONFIG, DEFAULT_CONFIG})
if err := cfg.Read(); err != nil { if err := cfg.Read(); err != nil {
helpers.MaybePanic(err, "Error reading config") helpers.Assert(err, "Error reading config")
}
if cfg.Config.Debug {
logging.SetDebug()
} else {
logging.SetInfo()
} }
kgpz := app.NewKGPZ(cfg) kgpz := app.NewKGPZ(cfg)
@@ -51,17 +58,17 @@ func Start(k *app.KGPZ, s *server.Server) {
go func() { go func() {
sig := <-sigs sig := <-sigs
fmt.Println("Received signal. Cleaning up.") logging.Info("Signal received, Cleaning up...")
// INFO: here we add cleanup functions // INFO: here we add cleanup functions
if sig == syscall.SIGTERM { if sig == syscall.SIGTERM {
s.Stop() s.Stop()
fmt.Println("Server stopped. Waiting for FS.") logging.Info("Server stopped. Waiting for FS.")
} else { } else {
s.Kill() s.Kill()
fmt.Println("Server killed. Waiting for FS.") logging.Info("Server killed. Waiting for FS.")
} }
k.Shutdown() k.Shutdown()
fmt.Println("FS stopped. Exiting.") logging.Info("Shutdown complete.")
done <- true done <- true
}() }()
@@ -72,10 +79,8 @@ func Start(k *app.KGPZ, s *server.Server) {
var input string var input string
fmt.Scanln(&input) fmt.Scanln(&input)
if input == "r" { if input == "r" {
fmt.Println("Restarting server.")
s.Restart() s.Restart()
} else if input == "p" { } else if input == "p" {
fmt.Println("Pulling repo.")
k.Pull() k.Pull()
} else if input == "q" { } else if input == "q" {
sigs <- os.Signal(syscall.SIGTERM) sigs <- os.Signal(syscall.SIGTERM)
@@ -85,5 +90,4 @@ func Start(k *app.KGPZ, s *server.Server) {
} }
<-done <-done
fmt.Println("Cleanup finished. Exiting.")
} }

View File

@@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers" "github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/kelseyhightower/envconfig" "github.com/kelseyhightower/envconfig"
) )
@@ -68,15 +69,14 @@ func (c *ConfigProvider) Validate() error {
func readSettingsFile(cfg *Config, path string) *Config { func readSettingsFile(cfg *Config, path string) *Config {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {
fmt.Println("Error: ", err) logging.Error(err, "Error opening config file "+path)
fmt.Println("Coudln't open ", path)
return cfg return cfg
} }
defer f.Close() defer f.Close()
dec := json.NewDecoder(f) dec := json.NewDecoder(f)
err = dec.Decode(cfg) err = dec.Decode(cfg)
helpers.MaybePanic(err, "Error decoding config.json") helpers.Assert(err, "Error decoding config file")
return cfg return cfg
} }

View File

@@ -6,6 +6,8 @@ import (
"io" "io"
"os" "os"
"sync" "sync"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
) )
type KGPZXML[T any] interface { type KGPZXML[T any] interface {
@@ -48,7 +50,7 @@ func (l *Library) Serialize() {
err := l.Agents.Serialize() err := l.Agents.Serialize()
if err != nil { if err != nil {
l.Agents = nil l.Agents = nil
fmt.Println(err)
} }
}() }()
@@ -57,7 +59,7 @@ func (l *Library) Serialize() {
err := l.Places.Serialize() err := l.Places.Serialize()
if err != nil { if err != nil {
l.Places = nil l.Places = nil
fmt.Println(err)
} }
}() }()
@@ -66,7 +68,7 @@ func (l *Library) Serialize() {
err := l.Works.Serialize() err := l.Works.Serialize()
if err != nil { if err != nil {
l.Works = nil l.Works = nil
fmt.Println(err)
} }
}() }()
@@ -75,7 +77,7 @@ func (l *Library) Serialize() {
err := l.Categories.Serialize() err := l.Categories.Serialize()
if err != nil { if err != nil {
l.Categories = nil l.Categories = nil
fmt.Println(err)
} }
}() }()
@@ -84,7 +86,7 @@ func (l *Library) Serialize() {
err := l.Issues.Serialize() err := l.Issues.Serialize()
if err != nil { if err != nil {
l.Issues = nil l.Issues = nil
fmt.Println(err)
} }
}() }()
@@ -93,7 +95,7 @@ func (l *Library) Serialize() {
err := l.Pieces.Serialize() err := l.Pieces.Serialize()
if err != nil { if err != nil {
l.Pieces = nil l.Pieces = nil
fmt.Println(err)
} }
}() }()
@@ -109,7 +111,7 @@ func (p *XMLProvider[T]) Serialize() error {
defer wg.Done() defer wg.Done()
var data T var data T
if err := UnmarshalFile(path, &data); err != nil { if err := UnmarshalFile(path, &data); err != nil {
fmt.Println(err)
return return
} }
p.mu.Lock() p.mu.Lock()
@@ -131,11 +133,10 @@ func (a *XMLProvider[T]) String() string {
func UnmarshalFile[T any](filename string, data *T) error { func UnmarshalFile[T any](filename string, data *T) error {
xmlFile, err := os.Open(filename) xmlFile, err := os.Open(filename)
if err != nil { if err != nil {
fmt.Println(err)
return err return err
} }
fmt.Println("Successfully opened " + filename)
defer xmlFile.Close() defer xmlFile.Close()
logging.Info("Opened " + filename)
byteValue, _ := io.ReadAll(xmlFile) byteValue, _ := io.ReadAll(xmlFile)
xml.Unmarshal(byteValue, data) xml.Unmarshal(byteValue, data)

View File

@@ -1,14 +1,13 @@
package server package server
import ( import (
"fmt"
"log"
"sync" "sync"
"time" "time"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/app" "github.com/Theodor-Springmann-Stiftung/kgpz_web/app"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/controllers" "github.com/Theodor-Springmann-Stiftung/kgpz_web/controllers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers" "github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers" "github.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/templating" "github.com/Theodor-Springmann-Stiftung/kgpz_web/templating"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/views" "github.com/Theodor-Springmann-Stiftung/kgpz_web/views"
@@ -55,7 +54,7 @@ type Server struct {
func Create(k *app.KGPZ, c *providers.ConfigProvider) *Server { func Create(k *app.KGPZ, c *providers.ConfigProvider) *Server {
if c == nil || k == nil { if c == nil || k == nil {
log.Println("Error creating server") logging.Error(nil, "Config or KGPZ is posssibly nil while tying to create server")
return nil return nil
} }
@@ -78,7 +77,7 @@ func (s *Server) Watcher() error {
s.watcher = watcher s.watcher = watcher
s.watcher.Append(func(path string) { s.watcher.Append(func(path string) {
log.Println("Restarting server") logging.Info("File changed: ", path)
time.Sleep(200 * time.Millisecond) time.Sleep(200 * time.Millisecond)
s.Restart() s.Restart()
}) })
@@ -159,10 +158,7 @@ func (s *Server) Start() {
if s.Config.Debug { if s.Config.Debug {
err := s.Watcher() err := s.Watcher()
if err != nil { logging.Error(err, "Error setting up file watcher")
log.Println("Error watching files")
log.Println(err)
}
} }
} }
@@ -200,9 +196,10 @@ func (s *Server) runner(srv *fiber.App) {
go func() { go func() {
defer s.shutdown.Done() defer s.shutdown.Done()
logging.Info("Starting server on ", s.Config.Address+":"+s.Config.Port)
if err := srv.Listen(s.Config.Address + ":" + s.Config.Port); err != nil { if err := srv.Listen(s.Config.Address + ":" + s.Config.Port); err != nil {
fmt.Println(err) logging.Error(err, "Error starting server")
fmt.Println("Error starting server")
return return
} }
@@ -213,16 +210,19 @@ func (s *Server) runner(srv *fiber.App) {
defer cleanup.Done() defer cleanup.Done()
clean := <-s.running clean := <-s.running
logging.Info("Server shutdown requested")
if clean { if clean {
if err := srv.ShutdownWithTimeout(SERVER_TIMEOUT); err != nil { if err := srv.ShutdownWithTimeout(SERVER_TIMEOUT); err != nil {
fmt.Println(err) logging.Error(err, "Error closing server cleanly. Shutting server down by force.")
fmt.Println("Error shutting down server") clean = false
} }
s.cache.Close() s.cache.Close()
} else { }
if !clean {
if err := srv.ShutdownWithTimeout(0); err != nil { if err := srv.ShutdownWithTimeout(0); err != nil {
fmt.Println(err) logging.Error(err, "Error closing server by force.")
fmt.Println("Error closing server")
} }
} }
}() }()

View File

@@ -1,11 +1,11 @@
package templating package templating
import ( import (
"fmt"
"html/template" "html/template"
"io/fs" "io/fs"
"sync" "sync"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
"github.com/yalue/merged_fs" "github.com/yalue/merged_fs"
) )
@@ -36,10 +36,7 @@ func (r *LayoutRegistry) Register(fs fs.FS) *LayoutRegistry {
func (r *LayoutRegistry) Load() error { func (r *LayoutRegistry) Load() error {
r.once.Do(func() { r.once.Do(func() {
err := r.load() err := r.load()
if err != nil { helpers.Assert(err, "Error loading layouts. Exiting.")
fmt.Println(err)
panic(-1)
}
}) })
return nil return nil

View File

@@ -1,13 +1,13 @@
package templating package templating
import ( import (
"fmt"
"html/template" "html/template"
"io/fs" "io/fs"
"os" "os"
"strings" "strings"
"sync" "sync"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
"github.com/yalue/merged_fs" "github.com/yalue/merged_fs"
) )
@@ -36,10 +36,7 @@ func (r *TemplateRegistry) Register(path string, fs fs.FS) *TemplateRegistry {
func (r *TemplateRegistry) Load() error { func (r *TemplateRegistry) Load() error {
r.once.Do(func() { r.once.Do(func() {
err := r.load() err := r.load()
if err != nil { helpers.Assert(err, "Error loading templates. Exiting.")
fmt.Println(err)
panic(-1)
}
}) })
return nil return nil
} }

View File

@@ -1 +1 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1

BIN
tmp/main

Binary file not shown.