go: switch to a custom slog-based logging solution
All checks were successful
continuous-integration/drone/push Build is passing

* make all packages use the logger
* add a couple of convenience methods on the logger that enable
  formatting using fmt syntax
This commit is contained in:
leo 2023-04-19 02:12:27 +02:00
parent 613bb0d028
commit 8cc43bba13
Signed by: wanderer
SSH Key Fingerprint: SHA256:Dp8+iwKHSlrMEHzE3bJnPng70I7LEsa3IJXRH/U+idQ
6 changed files with 104 additions and 47 deletions

1
go.mod

@ -9,6 +9,7 @@ require (
github.com/philandstuff/dhall-golang/v6 v6.0.2 github.com/philandstuff/dhall-golang/v6 v6.0.2
github.com/xiaoqidun/entps v0.0.0-20230328150929-94b1b92d8c03 github.com/xiaoqidun/entps v0.0.0-20230328150929-94b1b92d8c03
golang.org/x/crypto v0.6.0 golang.org/x/crypto v0.6.0
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
) )
require ( require (

2
go.sum

@ -101,6 +101,8 @@ github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUA
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

@ -2,24 +2,25 @@ package handlers
import ( import (
"io/fs" "io/fs"
"log"
"git.dotya.ml/mirre-mt/pcmt/config" "git.dotya.ml/mirre-mt/pcmt/config"
"git.dotya.ml/mirre-mt/pcmt/slogging"
) )
var ( var (
conf *config.Config conf *config.Config
appver string appver string
log *slogging.Logger
) )
func setConfig(c *config.Config) { func setConfig(c *config.Config) {
if c != nil { if c != nil {
log.Printf("setting handler config to %#v", conf) log.Info("setting handler config")
// c = conf // c = conf
log.Printf("set handler config to %#v", c)
conf = c conf = c
log.Infof("set handler config to %#v", c)
} else { } else {
log.Println("error passing conf to handlers") log.Warn("error passing conf to handlers")
} }
} }
@ -28,11 +29,11 @@ func getConfig() *config.Config {
} }
func setAppVer(v string) { func setAppVer(v string) {
log.Printf("handlers version: %s", v)
appver = v appver = v
} }
func InitHandlers(version string, appconf *config.Config, tmpls fs.FS) { func InitHandlers(version string, appconf *config.Config, tmpls fs.FS) {
log = slogging.GetLogger()
setConfig(appconf) setConfig(appconf)
setAppVer(version) setAppVer(version)
initTemplates(tmpls) initTemplates(tmpls)

@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"html/template" "html/template"
"io/fs" "io/fs"
"log"
"net/http" "net/http"
"path/filepath" "path/filepath"
"strings" "strings"
@ -31,12 +30,12 @@ func listAllTmpls() []string {
panic(err) panic(err)
} }
// log.Println(files)
for i, v := range files { for i, v := range files {
files[i] = strings.TrimPrefix(v, "templates/") files[i] = strings.TrimPrefix(v, "templates/")
} }
log.Println("returning files") log.Info("returning files")
return files return files
} }
@ -48,7 +47,6 @@ func setFuncMap(t *template.Template) {
return template.HTML(html) return template.HTML(html)
}, },
"pageIs": func(want, got string) bool { "pageIs": func(want, got string) bool {
log.Printf("want: %s, got: %s", want, got)
if want == got { if want == got {
return true return true
} }
@ -77,12 +75,10 @@ func getFuncMap() []template.FuncMap {
func initTemplates(f fs.FS) { func initTemplates(f fs.FS) {
// tmpls := tmpl // tmpls := tmpl
log.Println(tmplFS == nil)
if f != nil || f != tmplFS { if f != nil || f != tmplFS {
tmplFS = f tmplFS = f
} }
log.Println(tmplFS == nil)
// for _, funcs := range getFuncMap() { // for _, funcs := range getFuncMap() {
// // log.Println(funcs) // // log.Println(funcs)
@ -146,7 +142,8 @@ func getTmpl(name string) *template.Template {
// tpl := template.Must(template.New(name).ParseFS(tmplFS, name)) // tpl := template.Must(template.New(name).ParseFS(tmplFS, name))
// templateMap[name] = tpl // templateMap[name] = tpl
// return tpl // return tpl
log.Println("re-reading tmpls")
log.Info("re-reading tmpls")
tpl := template.New("") tpl := template.New("")
setFuncMap(tpl) setFuncMap(tpl)
allTmpls := listAllTmpls() allTmpls := listAllTmpls()
@ -228,7 +225,7 @@ func Index() echo.HandlerFunc {
}, },
) )
if err != nil { if err != nil {
log.Printf("error when executing tmpl: '%q'", err) log.Errorf("error when executing tmpl: '%q'", err)
return err return err
} }
@ -241,17 +238,16 @@ func Signin() echo.HandlerFunc {
session, err := c.Cookie("session") session, err := c.Cookie("session")
if err != nil { if err != nil {
if err == http.ErrNoCookie { if err == http.ErrNoCookie {
log.Println("no session cookie found") log.Info("no session cookie found")
} }
} }
if session != nil { if session != nil {
log.Println("got session") log.Info("got session")
// if err := session.Valid(); err == nil && session.Expires.After(time.Now()) { // if err := session.Valid(); err == nil && session.Expires.After(time.Now()) {
if err := session.Valid(); err == nil { if err := session.Valid(); err == nil {
c.Redirect(302, "/home") c.Redirect(302, "/home")
} else { } else {
log.Println("invalid (or expired) session") log.Warn("invalid (or expired) session", "error", err.Error())
log.Println("error:", err)
} }
} }
@ -312,9 +308,9 @@ func SigninPost(client *ent.Client) echo.HandlerFunc {
var password string var password string
if uname := c.Request().FormValue("username"); uname != "" { if uname := c.Request().FormValue("username"); uname != "" {
username = uname username = uname
log.Printf("authenticating user '%s' at /signin", username) log.Infof("authenticating user '%s' at /signin", username)
} else { } else {
log.Printf("username was not set, returning to /signin") log.Info("username was not set, returning to /signin")
c.Redirect(302, "/signin") c.Redirect(302, "/signin")
@ -323,7 +319,7 @@ func SigninPost(client *ent.Client) echo.HandlerFunc {
if passwd := c.Request().FormValue("password"); passwd != "" { if passwd := c.Request().FormValue("password"); passwd != "" {
password = passwd password = passwd
} else { } else {
log.Printf("password was not set, returning to /signin") log.Info("password was not set, returning to /signin")
c.Redirect(302, "/signin") c.Redirect(302, "/signin")
@ -334,10 +330,11 @@ func SigninPost(client *ent.Client) echo.HandlerFunc {
// Where( // Where(
// user.Username(username), // user.Username(username),
// ); usr != nil { // ); usr != nil {
if usr, err := moduser.QueryUser(context.Background(), client, username); err == nil { ctx := context.WithValue(context.Background(), "logger", log)
log.Println(usr) if usr, err := moduser.QueryUser(ctx, client, username); err == nil {
log.Info("queried user:", &usr.ID)
if usr.Password != password { if usr.Password != password {
log.Println("wrong user credentials, redirecting to /signin") log.Warn("wrong user credentials, redirecting to /signin")
c.Redirect(302, "/signin") c.Redirect(302, "/signin")
} }
@ -357,11 +354,15 @@ func SigninPost(client *ent.Client) echo.HandlerFunc {
} else { } else {
// just log the error instead of returning it to the user and // just log the error instead of returning it to the user and
// redirect back to /signin. // redirect back to /signin.
log.Println(echo.NewHTTPError( log.Warn(
http.StatusText(http.StatusUnauthorized)+" "+err.Error(),
echo.NewHTTPError(
http.StatusUnauthorized, http.StatusUnauthorized,
http.StatusText(http.StatusUnauthorized)+" "+err.Error(), http.StatusText(http.StatusUnauthorized)+" "+err.Error(),
)) ))
c.Redirect(302, "/signin") c.Redirect(302, "/signin")
return nil return nil
} }
@ -389,17 +390,16 @@ func Signup() echo.HandlerFunc {
session, err := c.Cookie("session") session, err := c.Cookie("session")
if err != nil { if err != nil {
if err == http.ErrNoCookie { if err == http.ErrNoCookie {
log.Println("no session cookie found") log.Info("no session cookie found")
} }
} }
if session != nil { if session != nil {
log.Println("got session") log.Info("got session")
// if err := session.Valid(); err == nil && session.Expires.After(time.Now()) { // if err := session.Valid(); err == nil && session.Expires.After(time.Now()) {
if err := session.Valid(); err == nil { if err := session.Valid(); err == nil {
c.Redirect(302, "/home") c.Redirect(302, "/home")
} else { } else {
log.Println("invalid (or expired) session") log.Warn("invalid (or expired) session", "error", err.Error())
log.Println("error:", err)
} }
} }
@ -430,7 +430,7 @@ func Signup() echo.HandlerFunc {
}, },
) )
if err != nil { if err != nil {
log.Printf("error: %q", err) log.Warnf("error: %q", err)
http.Error(c.Response().Writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) http.Error(c.Response().Writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
} }
@ -454,7 +454,8 @@ func SignupPost(client *ent.Client) echo.HandlerFunc {
if uname := c.Request().FormValue("username"); uname != "" { if uname := c.Request().FormValue("username"); uname != "" {
username = uname username = uname
if passwd := c.Request().FormValue("password"); passwd != "" { if passwd := c.Request().FormValue("password"); passwd != "" {
if u, err := moduser.CreateUser(context.Background(), client, username, passwd); err != nil { ctx := context.WithValue(context.Background(), "logger", log)
if u, err := moduser.CreateUser(ctx, client, username, passwd); err != nil {
// TODO: don't return the error to the user, perhaps based // TODO: don't return the error to the user, perhaps based
// on the devel mode. // on the devel mode.
return echo.NewHTTPError( return echo.NewHTTPError(
@ -462,13 +463,13 @@ func SignupPost(client *ent.Client) echo.HandlerFunc {
http.StatusText(http.StatusInternalServerError)+" failed to create schema resources "+err.Error(), http.StatusText(http.StatusInternalServerError)+" failed to create schema resources "+err.Error(),
) )
} else { } else {
log.Printf("successfully registered user '%s': %#v", username, u) log.Infof("successfully registered user '%s': %#v", username, u)
} }
} else { } else {
log.Println("password was not set, returning to /signup") log.Info("user registration: password was not set, returning to /signup")
} }
} else { } else {
log.Printf("username was not set, returning to /signup") log.Info("user registration: username was not set, returning to /signup")
c.Redirect(302, "/signup") c.Redirect(302, "/signup")
@ -516,12 +517,12 @@ func Home() echo.HandlerFunc {
if err != nil { if err != nil {
if err == http.ErrNoCookie { if err == http.ErrNoCookie {
// return err // return err
log.Printf("error no cookie: %q", err) log.Infof("error no cookie: %q", err)
http.Error(c.Response().Writer, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) http.Error(c.Response().Writer, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return nil return nil
} }
log.Println("error:", err) log.Infof("error: %q", err)
http.Error(c.Response().Writer, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) http.Error(c.Response().Writer, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
// fmt.Println("session cookie not found, redirecting to signin page") // fmt.Println("session cookie not found, redirecting to signin page")
@ -529,12 +530,12 @@ func Home() echo.HandlerFunc {
} }
if session != nil { if session != nil {
log.Println("got session") log.Info("got session")
// if err := session.Valid(); err == nil && session.Expires.After(time.Now()) { // if err := session.Valid(); err == nil && session.Expires.After(time.Now()) {
if err := session.Valid(); err == nil { if err := session.Valid(); err == nil {
username = session.Value username = session.Value
} else { } else {
log.Println("invalid or expired session?") log.Warn("invalid or expired session?")
return echo.NewHTTPError(http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized)) return echo.NewHTTPError(http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized))
} }
} }
@ -557,7 +558,7 @@ func Home() echo.HandlerFunc {
) )
if err != nil { if err != nil {
// return err // return err
log.Printf("error: %q", err) log.Warnf("error: %q", err)
return echo.NewHTTPError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) return echo.NewHTTPError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
} }
@ -571,14 +572,14 @@ func Logout() echo.HandlerFunc {
session, err := c.Cookie("session") session, err := c.Cookie("session")
if err != nil { if err != nil {
if errors.Is(err, http.ErrNoCookie) { if errors.Is(err, http.ErrNoCookie) {
fmt.Println("nobody to log out, redirecting to /signin") log.Info("nobody to log out, redirecting to /signin")
c.Redirect(302, "/signin") c.Redirect(302, "/signin")
return nil return nil
} }
log.Printf("error: %q", err) log.Warnf("error: %q", err)
return nil return nil
} }
@ -587,7 +588,7 @@ func Logout() echo.HandlerFunc {
username = session.Value username = session.Value
} }
log.Printf("logging out user '%s'", username) log.Infof("logging out user '%s'", username)
secure := c.Request().URL.Scheme == "https" secure := c.Request().URL.Scheme == "https"
cookieSession := &http.Cookie{ cookieSession := &http.Cookie{
@ -618,7 +619,7 @@ func Logout() echo.HandlerFunc {
}, },
) )
if err != nil { if err != nil {
log.Printf("error: %q", err) log.Warnf("error: %q", err)
return echo.NewHTTPError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) return echo.NewHTTPError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
} }

@ -3,14 +3,16 @@ package user
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"git.dotya.ml/mirre-mt/pcmt/ent" "git.dotya.ml/mirre-mt/pcmt/ent"
"git.dotya.ml/mirre-mt/pcmt/ent/user" "git.dotya.ml/mirre-mt/pcmt/ent/user"
"git.dotya.ml/mirre-mt/pcmt/slogging"
) )
// CreateUser adds a user entry to the database. // CreateUser adds a user entry to the database.
func CreateUser(ctx context.Context, client *ent.Client, username, password string) (*ent.User, error) { func CreateUser(ctx context.Context, client *ent.Client, username, password string) (*ent.User, error) {
log := ctx.Value("logger").(*slogging.Logger)
u, err := client.User. u, err := client.User.
Create(). Create().
SetUsername(username). SetUsername(username).
@ -20,11 +22,15 @@ func CreateUser(ctx context.Context, client *ent.Client, username, password stri
if err != nil { if err != nil {
return nil, fmt.Errorf("failed creating user: %w", err) return nil, fmt.Errorf("failed creating user: %w", err)
} }
log.Println("user was created: ", u)
log.Infof("user was created: %#v", u)
return u, nil return u, nil
} }
func QueryUser(ctx context.Context, client *ent.Client, username string) (*ent.User, error) { func QueryUser(ctx context.Context, client *ent.Client, username string) (*ent.User, error) {
log := ctx.Value("logger").(*slogging.Logger)
u, err := client.User. u, err := client.User.
Query(). Query().
Where(user.Username(username)). Where(user.Username(username)).
@ -34,6 +40,8 @@ func QueryUser(ctx context.Context, client *ent.Client, username string) (*ent.U
if err != nil { if err != nil {
return nil, fmt.Errorf("failed querying user: %w", err) return nil, fmt.Errorf("failed querying user: %w", err)
} }
log.Println("user returned: ", u)
log.Infof("user returned: %#v", u)
return u, nil return u, nil
} }

44
slogging/log.go Normal file

@ -0,0 +1,44 @@
package slogging
import (
"fmt"
"os"
"golang.org/x/exp/slog"
)
type Logger struct {
*slog.Logger
}
// var logger *slog.Logger
var logger *Logger
// func Logger() *slog.Logger {
func GetLogger() *Logger {
return logger
}
func Init(jsonHandler bool) error {
if jsonHandler {
logger = &Logger{slog.New(slog.NewJSONHandler(os.Stderr))}
} else {
logger = &Logger{slog.New(slog.NewTextHandler(os.Stderr))}
}
logger.Info("slog logger initialised")
return nil
}
func (l *Logger) Infof(msg string, args ...any) {
l.Info(fmt.Sprintf(msg, args...))
}
func (l *Logger) Warnf(msg string, args ...any) {
l.Warn(fmt.Sprintf(msg, args...))
}
func (l *Logger) Errorf(msg string, args ...any) {
l.Error(fmt.Sprintf(msg, args...))
}