From 129b1c960bc41052a3ea052ecdfe9eb73d9dd66f Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Tue, 17 Oct 2023 15:44:31 +0300 Subject: [PATCH] feat: some logging improvements --- cmd/felu/main.go | 23 +++++++++++-------- internal/config/config.go | 4 ++++ internal/db/db.go | 3 +++ internal/db/migrations.go | 21 +++++++++-------- internal/dns/query.go | 4 ++-- internal/handlers/auth.go | 3 +-- internal/handlers/domains.go | 3 +-- internal/handlers/user.go | 5 ++-- internal/handlers/users.go | 3 +-- internal/log/log.go | 44 ++++++++++++++++++++++++++++++++++++ 10 files changed, 84 insertions(+), 29 deletions(-) create mode 100644 internal/log/log.go diff --git a/cmd/felu/main.go b/cmd/felu/main.go index 8102849..3dd59da 100644 --- a/cmd/felu/main.go +++ b/cmd/felu/main.go @@ -7,14 +7,16 @@ package main import ( - "log" + "log/slog" "net/http" + "os" "strconv" "time" "git.src.quest/~skye/felu-ddns/internal/config" "git.src.quest/~skye/felu-ddns/internal/db" "git.src.quest/~skye/felu-ddns/internal/dns" + "git.src.quest/~skye/felu-ddns/internal/log" "git.src.quest/~skye/felu-ddns/internal/routers" "github.com/alexedwards/scs/v2" "golang.org/x/sync/errgroup" @@ -28,16 +30,19 @@ var ( ) func main() { - log.Print("[felu] Starting up...") - config.InitConfig() + log.InitDefaultLogger(config.FeluConfig.LogLevel) + slog.Info("Starting up...") + if err := db.InitDB(); err != nil { - log.Fatalf("[felu] Failed to initialize database: '%s'", err) + slog.Error("Failed to initialize database", slog.Any("err", err)) + os.Exit(1) } defer db.DBConn.Close() if err := db.InitAdminUser(); err != nil { - log.Fatalf("[felu] Failed to initialize admin user: '%s'", err) + slog.Error("Failed to initialize admin user", slog.Any("err", err)) + os.Exit(1) } sessionManager = scs.New() @@ -57,12 +62,12 @@ func main() { WriteTimeout: 10 * time.Second, } - log.Printf("[felu] Serving frontend at '%s'", config.FeluConfig.FrontendBindAddr) + slog.Info("Serving frontend", slog.String("addr", config.FeluConfig.FrontendBindAddr)) g.Go(func() error { return frontend.ListenAndServe() }) - log.Printf("[felu] Serving api at '%s'", config.FeluConfig.APIBindAddr) + slog.Info("Serving API", slog.String("addr", config.FeluConfig.APIBindAddr)) g.Go(func() error { return api.ListenAndServe() }) @@ -70,12 +75,12 @@ func main() { dnsIP := config.FeluConfig.DNSBindIP dnsPort := strconv.Itoa(int(config.FeluConfig.DNSBindPort)) dnsAddr := dnsIP + ":" + dnsPort - log.Printf("[felu] Serving DNS at '%s'", dnsAddr) + slog.Info("Serving DNS", slog.String("addr", dnsAddr)) g.Go(func() error { return dns.Run(dnsAddr) }) if err := g.Wait(); err != nil { - log.Fatalf("[felu] Error while running: %s", err) + slog.Info("Error while running", slog.Any("err", err)) } } diff --git a/internal/config/config.go b/internal/config/config.go index c1c3aa5..0ba3991 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -18,6 +18,8 @@ type config struct { // Initial password for the admin user, only used if no admin account (e.g. first boot) InitialAdminPwd string + LogLevel string + // Data directory, with trailing slash DataDir string @@ -38,6 +40,8 @@ func InitConfig() { InitialAdminEmail: util.LoadEnvStr("FELU_INITIAL_ADMIN_EMAIL", "admin@example.com"), InitialAdminPwd: util.LoadEnvStr("FELU_INITIAL_ADMIN_PWD", "feluadmin"), + LogLevel: util.LoadEnvStr("FELU_LOG_LEVEL", "info"), + DataDir: util.LoadEnvStr("FELU_DB_PATH", "/var/felu/"), FrontendBindAddr: util.LoadEnvStr("FELU_FRONTEND_BIND_ADDR", "0.0.0.0:8080"), diff --git a/internal/db/db.go b/internal/db/db.go index 896a341..84c9950 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -8,6 +8,7 @@ package db import ( "database/sql" + "log/slog" "git.src.quest/~skye/felu-ddns/internal/config" _ "github.com/mattn/go-sqlite3" @@ -36,10 +37,12 @@ func InitAdminUser() error { defer rows.Close() if rows.Next() { // There is at least one... + slog.Info("Existing admin user found") return nil } // Since we're here, it's assumed no admin accounts exist + slog.Info("Creating initial admin user") err = CreateAdmin(config.FeluConfig.InitialAdminEmail, config.FeluConfig.InitialAdminPwd) if err != nil { return err diff --git a/internal/db/migrations.go b/internal/db/migrations.go index 8b06208..3535fb9 100644 --- a/internal/db/migrations.go +++ b/internal/db/migrations.go @@ -8,13 +8,14 @@ package db import ( "fmt" - "log" + "log/slog" + "os" ) var migrationsTable string = "schema_migrations" func runMigrations() { - log.Print("[felu/db] Running migrations") + slog.Info("Running migrations") var schemaVersion int = 0 @@ -26,19 +27,20 @@ func runMigrations() { migrationsTable) err := DBConn.QueryRow(schemaVersionQuery).Scan(&schemaVersion) if err != nil { - log.Print("[felu/db] No schema version found, running all migrations") + slog.Info("No schema version found, running all migrations") } else { - log.Printf("[felu/db] Currently on schema version %d", schemaVersion) + slog.Info("Current schema", slog.Int("version", schemaVersion)) } migrations := migrations() if schemaVersion != len(migrations) { for i := 0; i < len(migrations); i++ { if i >= schemaVersion { - log.Printf("[felu/db] Running migration %d", i + 1) // + 1 is just a visual thing + slog.Info("Running migration", slog.Int("version", i + 1)) // + 1 is just a visual thing _, err := DBConn.Exec(migrations[i]) if err != nil { - log.Fatalf("[felu/db] Migration %d failed to run!", i) + slog.Error("Migration failed to run!", slog.Int("version", i)) + os.Exit(1) } } } @@ -51,12 +53,13 @@ func runMigrations() { migrationsTable, schemaVersion) _, err = DBConn.Exec(schemaMigrationInsertQuery) if err != nil { - log.Fatal("[felu/db] Migrations ran, but was not able to create migration entry") + slog.Error("Migrations ran, but was not able to create migration entry") + os.Exit(1) } else { - log.Print("[felu/db] Migrations ran successfully") + slog.Info("Migrations ran successfully") } } else { - log.Printf("[felu/db] Already on schema version %d, no migrations to run", schemaVersion) + slog.Info("No migrations to run") } } diff --git a/internal/dns/query.go b/internal/dns/query.go index 0f4ddc8..fb5f0de 100644 --- a/internal/dns/query.go +++ b/internal/dns/query.go @@ -7,7 +7,7 @@ package dns import ( - "log" + "log/slog" "net" "strings" @@ -25,7 +25,7 @@ func parseQuery(m *dns.Msg, r *dns.Msg) { } func handleARecord(q *dns.Question, m *dns.Msg, r *dns.Msg) { - log.Printf("[felu/dns] Query for '%s'", q.Name) + slog.Info("A Record Query", slog.String("qname", q.Name)) if index := strings.IndexByte(q.Name, '.'); index >= 0 { aRecord, err := db.FetchDomainARecord(q.Name[:index]) diff --git a/internal/handlers/auth.go b/internal/handlers/auth.go index e8f39fa..2245420 100644 --- a/internal/handlers/auth.go +++ b/internal/handlers/auth.go @@ -7,7 +7,6 @@ package handlers import ( - "log" "net/http" "git.src.quest/~skye/felu-ddns/internal/db" @@ -24,8 +23,8 @@ func AuthLogin(sm *scs.SessionManager) gin.HandlerFunc { return func(c *gin.Context) { data := &postAuthLoginData{} if err := c.Bind(data); err != nil { - log.Printf("[felu] ERROR: Could not bind login details: %v", err) c.String(http.StatusBadRequest, "Could not bind login details") + c.Abort() return } diff --git a/internal/handlers/domains.go b/internal/handlers/domains.go index 821b7b1..faf7a9e 100644 --- a/internal/handlers/domains.go +++ b/internal/handlers/domains.go @@ -7,7 +7,6 @@ package handlers import ( - "log" "net" "net/http" "regexp" @@ -26,8 +25,8 @@ func PostDomain() gin.HandlerFunc { return func(c *gin.Context) { data := &postDomainData{} if err := c.Bind(data); err != nil { - log.Printf("[felu] ERROR: Could not bind domain data: %v", err) c.String(http.StatusBadRequest, "Could not bind domain data") + c.Abort() return } diff --git a/internal/handlers/user.go b/internal/handlers/user.go index a1622c0..b6ec89b 100644 --- a/internal/handlers/user.go +++ b/internal/handlers/user.go @@ -7,7 +7,6 @@ package handlers import ( - "log" "net/http" "git.src.quest/~skye/felu-ddns/internal/db" @@ -25,8 +24,8 @@ func PostUserPassword() gin.HandlerFunc { return func(c *gin.Context) { data := &postUserPasswordData{} if err := c.Bind(data); err != nil { - log.Printf("[felu] ERROR: Could not bind password data: %v", err) c.String(http.StatusBadRequest, "Could not bind password data") + c.Abort() return } @@ -74,8 +73,8 @@ func PostUserEmail() gin.HandlerFunc { return func(c *gin.Context) { data := &postUserEmailData{} if err := c.Bind(data); err != nil { - log.Printf("[felu] ERROR: Could not bind email data: %v", err) c.String(http.StatusBadRequest, "Could not bind email data") + c.Abort() return } diff --git a/internal/handlers/users.go b/internal/handlers/users.go index b2830b3..86f15fc 100644 --- a/internal/handlers/users.go +++ b/internal/handlers/users.go @@ -7,7 +7,6 @@ package handlers import ( - "log" "net/http" "git.src.quest/~skye/felu-ddns/internal/db" @@ -23,8 +22,8 @@ func PostUser() gin.HandlerFunc { return func(c *gin.Context) { data := &postUserData{} if err := c.Bind(data); err != nil { - log.Printf("[felu] ERROR: Could not bind user data: %v", err) c.String(http.StatusBadRequest, "Could not bind user data") + c.Abort() return } diff --git a/internal/log/log.go b/internal/log/log.go new file mode 100644 index 0000000..5204869 --- /dev/null +++ b/internal/log/log.go @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 Jonni Liljamo + * + * This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for + * more information. + */ +package log + +import ( + "log/slog" + "os" + "path/filepath" +) + +func InitDefaultLogger(logLevel string) { + var feluLogLevel = new(slog.LevelVar) + switch logLevel { + case "debug": + feluLogLevel.Set(slog.LevelDebug) + case "info": + feluLogLevel.Set(slog.LevelInfo) + case "warning": + feluLogLevel.Set(slog.LevelWarn) + case "error": + feluLogLevel.Set(slog.LevelError) + } + + replace := func(groups []string, a slog.Attr) slog.Attr { + if a.Key == slog.SourceKey { + source := a.Value.Any().(*slog.Source) + source.File = filepath.Base(source.File) + } + + return a + } + + logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ + Level: feluLogLevel, + AddSource: true, + ReplaceAttr: replace, + })) + + slog.SetDefault(logger) +} -- 2.44.1