fix(observabillity): propagate ctx to every log call and add resource to logging
All checks were successful
Build Docker Image / Build-Docker-Image (push) Successful in 5m5s
Build and Push Docker Image / Build-And-Push-Docker-Image (push) Successful in 5m36s

This commit was merged in pull request #187.
This commit is contained in:
2025-06-17 09:42:19 +02:00
parent ff3c7bdf52
commit 6c92206b3c
27 changed files with 288 additions and 266 deletions

View File

@@ -98,9 +98,9 @@ func (handler AuthImpl) handleSignIn() http.HandlerFunc {
if err != nil {
if errors.Is(err, service.ErrInvalidCredentials) {
utils.TriggerToastWithStatus(w, r, "error", "Invalid email or password", http.StatusUnauthorized)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Invalid email or password", http.StatusUnauthorized)
} else {
utils.TriggerToastWithStatus(w, r, "error", "An error occurred", http.StatusInternalServerError)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "An error occurred", http.StatusInternalServerError)
}
return
}
@@ -167,7 +167,7 @@ func (handler AuthImpl) handleVerifyResendComp() http.HandlerFunc {
_, err := w.Write([]byte("<p class=\"mt-8\">Verification email sent</p>"))
if err != nil {
slog.Error("Could not write response", "err", err)
slog.ErrorContext(r.Context(), "Could not write response", "err", err)
}
}
}
@@ -202,13 +202,13 @@ func (handler AuthImpl) handleSignUp() http.HandlerFunc {
var password = r.FormValue("password")
_, err := utils.WaitMinimumTime(securityWaitDuration, func() (any, error) {
slog.Info("signing up", "email", email)
slog.InfoContext(r.Context(), "signing up", "email", email)
user, err := handler.service.SignUp(r.Context(), email, password)
if err != nil {
return nil, err
}
slog.Info("Sending verification email", "to", user.Email)
slog.InfoContext(r.Context(), "Sending verification email", "to", user.Email)
go handler.service.SendVerificationMail(r.Context(), user.Id, user.Email)
return nil, nil
})
@@ -216,19 +216,19 @@ func (handler AuthImpl) handleSignUp() http.HandlerFunc {
if err != nil {
switch {
case errors.Is(err, types.ErrInternal):
utils.TriggerToastWithStatus(w, r, "error", "An error occurred", http.StatusInternalServerError)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "An error occurred", http.StatusInternalServerError)
return
case errors.Is(err, service.ErrInvalidEmail):
utils.TriggerToastWithStatus(w, r, "error", "The email provided is invalid", http.StatusBadRequest)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "The email provided is invalid", http.StatusBadRequest)
return
case errors.Is(err, service.ErrInvalidPassword):
utils.TriggerToastWithStatus(w, r, "error", service.ErrInvalidPassword.Error(), http.StatusBadRequest)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", service.ErrInvalidPassword.Error(), http.StatusBadRequest)
return
}
// If err is "service.ErrAccountExists", then just continue
}
utils.TriggerToastWithStatus(w, r, "success", "An activation link has been send to your email", http.StatusOK)
utils.TriggerToastWithStatus(r.Context(), w, r, "success", "An activation link has been send to your email", http.StatusOK)
}
}
@@ -291,9 +291,9 @@ func (handler AuthImpl) handleDeleteAccountComp() http.HandlerFunc {
err := handler.service.DeleteAccount(r.Context(), user, password)
if err != nil {
if errors.Is(err, service.ErrInvalidCredentials) {
utils.TriggerToastWithStatus(w, r, "error", "Password not correct", http.StatusBadRequest)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Password not correct", http.StatusBadRequest)
} else {
utils.TriggerToastWithStatus(w, r, "error", "Internal Server Error", http.StatusInternalServerError)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError)
}
return
}
@@ -327,7 +327,7 @@ func (handler AuthImpl) handleChangePasswordComp() http.HandlerFunc {
session := middleware.GetSession(r)
user := middleware.GetUser(r)
if session == nil || user == nil {
utils.TriggerToastWithStatus(w, r, "error", "Unathorized", http.StatusUnauthorized)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Unathorized", http.StatusUnauthorized)
return
}
@@ -336,11 +336,11 @@ func (handler AuthImpl) handleChangePasswordComp() http.HandlerFunc {
err := handler.service.ChangePassword(r.Context(), user, session.Id, currPass, newPass)
if err != nil {
utils.TriggerToastWithStatus(w, r, "error", err.Error(), http.StatusBadRequest)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", err.Error(), http.StatusBadRequest)
return
}
utils.TriggerToastWithStatus(w, r, "success", "Password changed", http.StatusOK)
utils.TriggerToastWithStatus(r.Context(), w, r, "success", "Password changed", http.StatusOK)
}
}
@@ -365,7 +365,7 @@ func (handler AuthImpl) handleForgotPasswordComp() http.HandlerFunc {
email := r.FormValue("email")
if email == "" {
utils.TriggerToastWithStatus(w, r, "error", "Please enter an email", http.StatusBadRequest)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Please enter an email", http.StatusBadRequest)
return
}
@@ -375,9 +375,9 @@ func (handler AuthImpl) handleForgotPasswordComp() http.HandlerFunc {
})
if err != nil {
utils.TriggerToastWithStatus(w, r, "error", "Internal Server Error", http.StatusInternalServerError)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError)
} else {
utils.TriggerToastWithStatus(w, r, "info", "If the address exists, an email has been sent.", http.StatusOK)
utils.TriggerToastWithStatus(r.Context(), w, r, "info", "If the address exists, an email has been sent.", http.StatusOK)
}
}
}
@@ -388,8 +388,8 @@ func (handler AuthImpl) handleForgotPasswordResponseComp() http.HandlerFunc {
pageUrl, err := url.Parse(r.Header.Get("Hx-Current-Url"))
if err != nil {
slog.Error("Could not get current URL", "err", err)
utils.TriggerToastWithStatus(w, r, "error", "Internal Server Error", http.StatusInternalServerError)
slog.ErrorContext(r.Context(), "Could not get current URL", "err", err)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError)
return
}
@@ -398,9 +398,9 @@ func (handler AuthImpl) handleForgotPasswordResponseComp() http.HandlerFunc {
err = handler.service.ForgotPassword(r.Context(), token, newPass)
if err != nil {
utils.TriggerToastWithStatus(w, r, "error", err.Error(), http.StatusBadRequest)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", err.Error(), http.StatusBadRequest)
} else {
utils.TriggerToastWithStatus(w, r, "success", "Password changed", http.StatusOK)
utils.TriggerToastWithStatus(r.Context(), w, r, "success", "Password changed", http.StatusOK)
}
}
}

View File

@@ -15,17 +15,17 @@ import (
func handleError(w http.ResponseWriter, r *http.Request, err error) {
switch {
case errors.Is(err, service.ErrUnauthorized):
utils.TriggerToastWithStatus(w, r, "error", "You are not autorized to perform this operation.", http.StatusUnauthorized)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "You are not autorized to perform this operation.", http.StatusUnauthorized)
return
case errors.Is(err, service.ErrBadRequest):
utils.TriggerToastWithStatus(w, r, "error", extractErrorMessage(err), http.StatusBadRequest)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusBadRequest)
return
case errors.Is(err, db.ErrNotFound):
utils.TriggerToastWithStatus(w, r, "error", extractErrorMessage(err), http.StatusNotFound)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusNotFound)
return
}
utils.TriggerToastWithStatus(w, r, "error", "Internal Server Error", http.StatusInternalServerError)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError)
}
func extractErrorMessage(err error) string {

View File

@@ -42,9 +42,9 @@ func CrossSiteRequestForgery(auth service.Auth) func(http.Handler) http.Handler
csrfToken := r.Header.Get("Csrf-Token")
if session == nil || csrfToken == "" || !auth.IsCsrfTokenValid(ctx, csrfToken, session.Id) {
slog.Info("CSRF-Token not correct", "token", csrfToken)
slog.InfoContext(ctx, "CSRF-Token not correct", "token", csrfToken)
if r.Header.Get("Hx-Request") == "true" {
utils.TriggerToastWithStatus(w, r, "error", "CSRF-Token not correct", http.StatusBadRequest)
utils.TriggerToastWithStatus(ctx, w, r, "error", "CSRF-Token not correct", http.StatusBadRequest)
} else {
http.Error(w, "CSRF-Token not correct", http.StatusBadRequest)
}
@@ -55,7 +55,7 @@ func CrossSiteRequestForgery(auth service.Auth) func(http.Handler) http.Handler
token, err := auth.GetCsrfToken(ctx, session)
if err != nil {
if r.Header.Get("Hx-Request") == "true" {
utils.TriggerToastWithStatus(w, r, "error", "Could not generate CSRF Token", http.StatusBadRequest)
utils.TriggerToastWithStatus(ctx, w, r, "error", "Could not generate CSRF Token", http.StatusBadRequest)
} else {
http.Error(w, "Could not generate CSRF Token", http.StatusBadRequest)
}

View File

@@ -33,7 +33,7 @@ func Gzip(next http.Handler) http.Handler {
err := gz.Close()
if err != nil && !errors.Is(err, http.ErrBodyNotAllowed) {
slog.Error("Gzip: could not close Writer", "err", err)
slog.ErrorContext(r.Context(), "Gzip: could not close Writer", "err", err)
}
})
}

View File

@@ -26,7 +26,7 @@ func Log(next http.Handler) http.Handler {
}
next.ServeHTTP(wrapped, r)
slog.Info("request",
slog.InfoContext(r.Context(), "request",
"remoteAddr", r.RemoteAddr,
"status", wrapped.StatusCode,
"method", r.Method,

View File

@@ -22,7 +22,7 @@ func (render *Render) RenderWithStatus(r *http.Request, w http.ResponseWriter, c
w.WriteHeader(status)
err := comp.Render(r.Context(), w)
if err != nil {
slog.Error("Failed to render layout", "err", err)
slog.ErrorContext(r.Context(), "Failed to render layout", "err", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}

View File

@@ -57,7 +57,7 @@ func (handler IndexImpl) handleRootAnd404() http.HandlerFunc {
var err error
comp, err = handler.dashboard(user, htmx, r)
if err != nil {
slog.Error("Failed to get dashboard summary", "err", err)
slog.ErrorContext(r.Context(), "Failed to get dashboard summary", "err", err)
}
} else {
comp = template.Index()

View File

@@ -254,7 +254,7 @@ func (h TransactionImpl) handleRecalculate() http.HandlerFunc {
return
}
utils.TriggerToastWithStatus(w, r, "success", "Balances recalculated, please refresh", http.StatusOK)
utils.TriggerToastWithStatus(r.Context(), w, r, "success", "Balances recalculated, please refresh", http.StatusOK)
}
}

View File

@@ -115,7 +115,7 @@ func (h TransactionRecurringImpl) renderItems(w http.ResponseWriter, r *http.Req
var transactionsRecurring []*types.TransactionRecurring
var err error
if accountId == "" && treasureChestId == "" {
utils.TriggerToastWithStatus(w, r, "error", "Please select an account or treasure chest", http.StatusBadRequest)
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Please select an account or treasure chest", http.StatusBadRequest)
}
if accountId != "" {
transactionsRecurring, err = h.s.GetAllByAccount(r.Context(), user, accountId)