From 6dde91860ea8d15ba5787743c0762c30c43a629c Mon Sep 17 00:00:00 2001 From: Joe Rozner Date: Tue, 24 Feb 2026 17:12:34 -0800 Subject: [PATCH] Add ctx to logging --- backend/authschemes/auth_bridge.go | 4 ++-- backend/authschemes/auth_bridge_test.go | 7 ++++--- backend/authschemes/localauth/services.go | 2 +- backend/authschemes/oidcauth/oidc_auth.go | 2 +- backend/authschemes/recoveryauth/recovery_auth.go | 2 +- backend/authschemes/webauthn/webauthn.go | 2 +- backend/bin/api/api.go | 11 ++++++----- backend/bin/web/web.go | 11 ++++++----- backend/contentstore/s3presigner.go | 10 +++++----- backend/contentstore/s3store.go | 7 ++++--- backend/database/helpers.go | 3 ++- backend/enhancementservices/runner.go | 12 ++++++------ backend/logging/logging.go | 12 ++++++------ backend/server/middleware/authenticator.go | 8 ++++---- backend/server/middleware/logger.go | 4 ++-- backend/server/remux/response_wrappers.go | 8 ++++---- backend/server/remux/tracing.go | 5 +++-- backend/services/evidence.go | 2 +- backend/services/user.go | 8 ++++---- backend/services/user_test.go | 6 +++--- backend/workers/email.go | 11 ++++++----- 21 files changed, 72 insertions(+), 65 deletions(-) diff --git a/backend/authschemes/auth_bridge.go b/backend/authschemes/auth_bridge.go index c0cf0787d..6b7d83de4 100644 --- a/backend/authschemes/auth_bridge.go +++ b/backend/authschemes/auth_bridge.go @@ -41,8 +41,8 @@ func MakeAuthBridge(db *database.Connection, sessionStore *session.Store, authSc // CreateNewUser allows new users to be registered into the system, if they do not already exist. // Note that slug must be unique -func (ah AShirtAuthBridge) CreateNewUser(profile UserProfile) (*dtos.CreateUserOutput, error) { - return services.CreateUser(ah.db, profile.ToCreateUserInput()) +func (ah AShirtAuthBridge) CreateNewUser(ctx context.Context, profile UserProfile) (*dtos.CreateUserOutput, error) { + return services.CreateUser(ctx, ah.db, profile.ToCreateUserInput()) } // SetAuthSchemeSession sets authscheme specific session data to the current user session. Session data should diff --git a/backend/authschemes/auth_bridge_test.go b/backend/authschemes/auth_bridge_test.go index d786fc643..5b897f759 100644 --- a/backend/authschemes/auth_bridge_test.go +++ b/backend/authschemes/auth_bridge_test.go @@ -1,6 +1,7 @@ package authschemes_test import ( + "context" "encoding/gob" "net/http" "net/http/httptest" @@ -21,7 +22,7 @@ import ( func TestCreateNewUser(t *testing.T) { db, _, bridge := initBridgeTest(t) - newUser, err := bridge.CreateNewUser(authschemes.UserProfile{ + newUser, err := bridge.CreateNewUser(context.Background(), authschemes.UserProfile{ FirstName: "Alice", LastName: "Defaultuser", Email: "alice@example.com", @@ -39,7 +40,7 @@ func TestCreateNewUser(t *testing.T) { require.Equal(t, "slug", user.Slug) // Creating a user with a slug that already exists appends a random number to the slug - newUser, err = bridge.CreateNewUser(authschemes.UserProfile{ + newUser, err = bridge.CreateNewUser(context.Background(), authschemes.UserProfile{ FirstName: "Bob", LastName: "Snooper", Email: "bob@example.com", @@ -260,7 +261,7 @@ func initBridgeTest(t *testing.T) (*database.Connection, *session.Store, authsch } func createDummyUser(t *testing.T, bridge authschemes.AShirtAuthBridge, extra string) int64 { - newUser, err := bridge.CreateNewUser(authschemes.UserProfile{ + newUser, err := bridge.CreateNewUser(context.Background(), authschemes.UserProfile{ FirstName: "Dummy", LastName: "User", Email: "email+" + extra + "@example.com", diff --git a/backend/authschemes/localauth/services.go b/backend/authschemes/localauth/services.go index b58bff735..aea5e5545 100644 --- a/backend/authschemes/localauth/services.go +++ b/backend/authschemes/localauth/services.go @@ -69,7 +69,7 @@ func registerNewUser(ctx context.Context, bridge authschemes.AShirtAuthBridge, i return backend.WrapError("Unable to generate encrypted password", err) } - userResult, err := bridge.CreateNewUser(authschemes.UserProfile{ + userResult, err := bridge.CreateNewUser(ctx, authschemes.UserProfile{ FirstName: info.FirstName, LastName: info.LastName, Slug: strings.ToLower(info.FirstName + "." + info.LastName), diff --git a/backend/authschemes/oidcauth/oidc_auth.go b/backend/authschemes/oidcauth/oidc_auth.go index dc62127d6..d13158775 100644 --- a/backend/authschemes/oidcauth/oidc_auth.go +++ b/backend/authschemes/oidcauth/oidc_auth.go @@ -190,7 +190,7 @@ func (o OIDCAuth) handleCallback(w http.ResponseWriter, r *http.Request, bridge return o.authFailure(w, r, backend.WrapError("Registration is disabled", err), "/autherror/registrationdisabled") } - userResult, err := bridge.CreateNewUser(*userProfile) + userResult, err := bridge.CreateNewUser(r.Context(), *userProfile) if err != nil { return o.authFailure(w, r, backend.WrapError("Create new "+authName+" user failed ["+userProfile.Slug+"]", err), "/autherror/incomplete") } diff --git a/backend/authschemes/recoveryauth/recovery_auth.go b/backend/authschemes/recoveryauth/recovery_auth.go index 451a44be8..662a361ec 100644 --- a/backend/authschemes/recoveryauth/recovery_auth.go +++ b/backend/authschemes/recoveryauth/recovery_auth.go @@ -85,7 +85,7 @@ func (p RecoveryAuthScheme) BindRoutes(r chi.Router, bridge authschemes.AShirtAu if dr.Error != nil { return nil, dr.Error } - userResult, err := bridge.CreateNewUser(profile) + userResult, err := bridge.CreateNewUser(r.Context(), profile) if err != nil { return nil, backend.WrapError("Unable to create new user", err) } diff --git a/backend/authschemes/webauthn/webauthn.go b/backend/authschemes/webauthn/webauthn.go index 3d6b728a7..50d16bd76 100644 --- a/backend/authschemes/webauthn/webauthn.go +++ b/backend/authschemes/webauthn/webauthn.go @@ -145,7 +145,7 @@ func (a WebAuthn) BindRoutes(r chi.Router, bridge authschemes.AShirtAuthBridge) Slug: strings.ToLower(data.UserData.FirstName + "." + data.UserData.LastName), Email: data.UserData.Email, } - userResult, err := bridge.CreateNewUser(userProfile) + userResult, err := bridge.CreateNewUser(r.Context(), userProfile) if err != nil { return nil, backend.WrapError("Unable to create user", err) } diff --git a/backend/bin/api/api.go b/backend/bin/api/api.go index 456dc4ad7..bcd4b518f 100644 --- a/backend/bin/api/api.go +++ b/backend/bin/api/api.go @@ -1,6 +1,7 @@ package main import ( + "context" "errors" "net/http" @@ -17,17 +18,17 @@ func main() { err := config.LoadAPIConfig() logger := logging.SetupStdoutLogging() if err != nil { - logging.Fatal(logger, "Unable to start due to configuration error", "error", err, "action", "exiting") + logging.Fatal(context.Background(), logger,"Unable to start due to configuration error", "error", err, "action", "exiting") } db, err := database.NewConnection(config.DBUri(), "/migrations") if err != nil { - logging.Fatal(logger, "Unable to connect to database", "error", err, "action", "exiting") + logging.Fatal(context.Background(), logger,"Unable to connect to database", "error", err, "action", "exiting") } logger.Info("checking database schema") if err := db.CheckSchema(); err != nil { - logging.Fatal(logger, "schema read error", "error", err) + logging.Fatal(context.Background(), logger,"schema read error", "error", err) } contentStore, err := confighelpers.ChooseContentStoreType(config.AllStoreConfig()) @@ -36,7 +37,7 @@ func main() { contentStore, err = confighelpers.DefaultS3Store() } if err != nil { - logging.Fatal(logger, "store setup error", "error", err) + logging.Fatal(context.Background(), logger,"store setup error", "error", err) } s := chi.NewRouter() @@ -49,5 +50,5 @@ func main() { logger.Info("starting API server", "port", config.Port()) serveErr := http.ListenAndServe(":"+config.Port(), s) - logging.Fatal(logger, "server shutting down", "err", serveErr) + logging.Fatal(context.Background(), logger,"server shutting down", "err", serveErr) } diff --git a/backend/bin/web/web.go b/backend/bin/web/web.go index 1f04cc292..99676879f 100644 --- a/backend/bin/web/web.go +++ b/backend/bin/web/web.go @@ -1,6 +1,7 @@ package main import ( + "context" "errors" "fmt" "log/slog" @@ -32,17 +33,17 @@ func main() { err := config.LoadWebConfig() logger := logging.SetupStdoutLogging() if err != nil { - logging.Fatal(logger, "Unable to start due to configuration error", "error", err, "action", "exiting") + logging.Fatal(context.Background(), logger,"Unable to start due to configuration error", "error", err, "action", "exiting") } db, err := database.NewConnection(config.DBUri(), "/migrations") if err != nil { - logging.Fatal(logger, "Unable to connect to database", "error", err, "action", "exiting") + logging.Fatal(context.Background(), logger,"Unable to connect to database", "error", err, "action", "exiting") } logger.Info("checking database schema") if err := db.CheckSchema(); err != nil { - logging.Fatal(logger, "schema read error", "error", err) + logging.Fatal(context.Background(), logger,"schema read error", "error", err) } contentStore, err := confighelpers.ChooseContentStoreType(config.AllStoreConfig()) @@ -51,7 +52,7 @@ func main() { contentStore, err = confighelpers.DefaultS3Store() } if err != nil { - logging.Fatal(logger, "store setup error", "error", err) + logging.Fatal(context.Background(), logger,"store setup error", "error", err) } logger.Info("Using Storage", "type", contentStore.Name()) @@ -106,7 +107,7 @@ func main() { logger.Info("starting Web server", "port", config.Port()) serveErr := http.ListenAndServe(":"+config.Port(), r) - logging.Fatal(logger, "server shutting down", "err", serveErr) + logging.Fatal(context.Background(), logger,"server shutting down", "err", serveErr) } func handleAuthType(cfg config.AuthInstanceConfig) (authschemes.AuthScheme, error) { diff --git a/backend/contentstore/s3presigner.go b/backend/contentstore/s3presigner.go index 160f34b00..bad63b715 100644 --- a/backend/contentstore/s3presigner.go +++ b/backend/contentstore/s3presigner.go @@ -2,7 +2,7 @@ package contentstore import ( "context" - "log" + "log/slog" "time" "github.com/aws/aws-sdk-go-v2/aws" @@ -12,12 +12,13 @@ import ( type Presigner struct { PresignClient *s3.PresignClient + Logger *slog.Logger } func (presigner Presigner) GetObject( - bucketName string, objectKey string, minutes time.Duration) (*v4.PresignedHTTPRequest, error) { + ctx context.Context, bucketName string, objectKey string, minutes time.Duration) (*v4.PresignedHTTPRequest, error) { contentType := "image/jpeg" - request, err := presigner.PresignClient.PresignGetObject(context.TODO(), &s3.GetObjectInput{ + request, err := presigner.PresignClient.PresignGetObject(ctx, &s3.GetObjectInput{ Bucket: aws.String(bucketName), Key: aws.String(objectKey), ResponseContentType: aws.String(contentType), @@ -25,8 +26,7 @@ func (presigner Presigner) GetObject( opts.Expires = minutes }) if err != nil { - log.Printf("Couldn't get a presigned request to get %v:%v. Here's why: %v\n", - bucketName, objectKey, err) + presigner.Logger.ErrorContext(ctx, "Couldn't get a presigned request", "bucket", bucketName, "key", objectKey, "error", err) } return request, err } diff --git a/backend/contentstore/s3store.go b/backend/contentstore/s3store.go index 8fd7d7f85..b75fe20ab 100644 --- a/backend/contentstore/s3store.go +++ b/backend/contentstore/s3store.go @@ -3,6 +3,7 @@ package contentstore import ( "context" "io" + "log/slog" "time" "github.com/ashirt-ops/ashirt-server/backend" @@ -82,11 +83,11 @@ type URLData struct { ExpirationTime time.Time `json:"expirationTime"` } -func (s *S3Store) SendURLData(key string) (*URLData, error) { +func (s *S3Store) SendURLData(ctx context.Context, key string) (*URLData, error) { minutes := time.Minute * time.Duration(30) presignClient := s3.NewPresignClient(s.s3Client) - presigner := Presigner{PresignClient: presignClient} - presignedGetRequest, err := presigner.GetObject(s.bucketName, key, minutes) + presigner := Presigner{PresignClient: presignClient, Logger: slog.Default()} + presignedGetRequest, err := presigner.GetObject(ctx, s.bucketName, key, minutes) if err != nil { return nil, backend.WrapError("Unable to get presigned URL", err) } diff --git a/backend/database/helpers.go b/backend/database/helpers.go index 1a6d9da03..5f24948c7 100644 --- a/backend/database/helpers.go +++ b/backend/database/helpers.go @@ -1,6 +1,7 @@ package database import ( + "context" "database/sql" "fmt" "strings" @@ -142,7 +143,7 @@ func (c *Connection) execSquirrel(sQuery squirrel.Sqlizer) (sql.Result, error) { } func logQuery(query string, values []interface{}) { - logging.SystemLog("executing query", "query", query, "values", fmt.Sprintf("%v", values)) + logging.SystemLog(context.Background(), "executing query", "query", query, "values", fmt.Sprintf("%v", values)) } // IsEmptyResultSetError returns true if the passed error is a database error resulting diff --git a/backend/enhancementservices/runner.go b/backend/enhancementservices/runner.go index ac9cef18f..6d7e223c1 100644 --- a/backend/enhancementservices/runner.go +++ b/backend/enhancementservices/runner.go @@ -52,7 +52,7 @@ func SendServiceWorkerEvent(db *database.Connection, input SendServiceWorkerEven payloads, _ = input.Builder(tx) }) if err != nil { - input.Logger.Error("Unable to execute service workers", "error", err.Error()) + input.Logger.ErrorContext(workerContext, "Unable to execute service workers", "error", err.Error()) return } @@ -72,9 +72,9 @@ func SendServiceWorkerEvent(db *database.Connection, input SendServiceWorkerEven ) if err != nil { - logger.Error("Unable to run worker", "error", err) + logger.ErrorContext(workerContext, "Unable to run worker", "error", err) } else { - logger.Info("Worker completed") + logger.InfoContext(workerContext, "Worker completed") } }() } @@ -103,7 +103,7 @@ func SendEvidenceCreatedEvent(db *database.Connection, reqLogger *slog.Logger, o helpers.Map(workersToRun, getServiceWorkerName)) }) if err != nil { - reqLogger.Error("Unable to execute service workers", "error", err.Error()) + reqLogger.ErrorContext(workerContext, "Unable to execute service workers", "error", err.Error()) return } @@ -124,9 +124,9 @@ func SendEvidenceCreatedEvent(db *database.Connection, reqLogger *slog.Logger, o ) if err != nil { - logger.Error("Unable to run worker", "error", err) + logger.ErrorContext(workerContext, "Unable to run worker", "error", err) } else { - logger.Info("Worker completed") + logger.InfoContext(workerContext, "Worker completed") } }() } diff --git a/backend/logging/logging.go b/backend/logging/logging.go index d66290bb8..e67ece4c8 100644 --- a/backend/logging/logging.go +++ b/backend/logging/logging.go @@ -57,22 +57,22 @@ func AddRequestLogger(ctx context.Context, baseLogger *slog.Logger) (context.Con // Fatal is an effective copy of go's log.Fatal, but using the logger provided, rather than // using go's native logging. After writing the message, the code will exit with code 1 -func Fatal(logger *slog.Logger, msg string, keyvals ...interface{}) { - logger.Error(msg, keyvals...) +func Fatal(ctx context.Context, logger *slog.Logger, msg string, keyvals ...interface{}) { + logger.ErrorContext(ctx, msg, keyvals...) os.Exit(1) } -func LogWithoutAuth(msg string, keyvals ...interface{}) { +func LogWithoutAuth(ctx context.Context, msg string, keyvals ...interface{}) { if systemLogger != nil { - systemLogger.Info(msg, keyvals...) + systemLogger.InfoContext(ctx, msg, keyvals...) } } // SystemLog provides a system-level logger, which is not tied to any request. // this should be used in situations where either a context is not handy, but logging is important // or for events that are not tied to a request (e.g. losing database connection) -func SystemLog(msg string, keyvals ...interface{}) { +func SystemLog(ctx context.Context, msg string, keyvals ...interface{}) { if systemLogger != nil { - systemLogger.Info(msg, keyvals...) + systemLogger.InfoContext(ctx, msg, keyvals...) } } diff --git a/backend/server/middleware/authenticator.go b/backend/server/middleware/authenticator.go index 8f11e9467..a62e0fff0 100644 --- a/backend/server/middleware/authenticator.go +++ b/backend/server/middleware/authenticator.go @@ -91,7 +91,7 @@ func AuthenticateAppAndInjectCtx(db *database.Connection) MiddlewareFunc { userData, err := authenticateAPI(db, r, body) if err != nil { - logging.LogWithoutAuth( + logging.LogWithoutAuth(r.Context(), "Unable to build user policy", "error", err.Error(), ) @@ -136,7 +136,7 @@ func buildPolicyForUser(ctx context.Context, db *database.Connection, userID int var groupRoles []models.UserGroupOperationPermission - err := db.WithTx(context.Background(), func(tx *database.Transactable) { + err := db.WithTx(ctx, func(tx *database.Transactable) { tx.Select(&roles, sq.Select("operation_id", "role"). From("user_operation_permissions"). Where(sq.Eq{"user_id": userID})) @@ -152,7 +152,7 @@ func buildPolicyForUser(ctx context.Context, db *database.Connection, userID int }) if err != nil { - logging.ReqLogger(ctx).Error("Unable to build user policy", "error", err.Error()) + logging.ReqLogger(ctx).ErrorContext(ctx, "Unable to build user policy", "error", err.Error()) return &policy.Deny{} } roleMap := make(map[int64]policy.OperationRole) @@ -223,7 +223,7 @@ func cloneBody(r *http.Request) (io.Reader, func(), error) { r.Body.Close() err := os.Remove(bodyTmpFile.Name()) if err != nil { - logging.LogWithoutAuth( + logging.LogWithoutAuth(r.Context(), "Unable to remove tmp file", "error", err, "tmpFile", bodyTmpFile.Name(), diff --git a/backend/server/middleware/logger.go b/backend/server/middleware/logger.go index a6e10847c..8f76a1829 100644 --- a/backend/server/middleware/logger.go +++ b/backend/server/middleware/logger.go @@ -30,11 +30,11 @@ func LogRequests(baseLogger *slog.Logger) MiddlewareFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() ctx, logger := logging.AddRequestLogger(r.Context(), baseLogger) - logger.Info("Incoming request", "method", r.Method, "url", r.URL, "from", r.RemoteAddr) + logger.InfoContext(ctx, "Incoming request", "method", r.Method, "url", r.URL, "from", r.RemoteAddr) ww := &responseWriterWrapper{w, 0, 200} next.ServeHTTP(ww, r.WithContext(ctx)) - logger.Info("Request Completed", "status", ww.status, "sizeInBytes", ww.size, "duration", time.Since(start)) + logger.InfoContext(ctx, "Request Completed", "status", ww.status, "sizeInBytes", ww.size, "duration", time.Since(start)) }) } } diff --git a/backend/server/remux/response_wrappers.go b/backend/server/remux/response_wrappers.go index 8f522f931..dab5a3deb 100644 --- a/backend/server/remux/response_wrappers.go +++ b/backend/server/remux/response_wrappers.go @@ -16,7 +16,7 @@ func MediaHandler(handler func(*http.Request) (io.Reader, error)) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data io.Reader var err error - defer watcher(logging.ReqLogger(r.Context()), func(paniced bool) { + defer watcher(r.Context(), logging.ReqLogger(r.Context()), func(paniced bool) { if paniced { err = backend.PanicedError() } @@ -39,7 +39,7 @@ func JSONHandler(handler func(*http.Request) (interface{}, error)) http.HandlerF return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data interface{} var err error - defer watcher(logging.ReqLogger(r.Context()), func(paniced bool) { + defer watcher(r.Context(), logging.ReqLogger(r.Context()), func(paniced bool) { if paniced { err = backend.PanicedError() } @@ -78,10 +78,10 @@ func HandleError(w http.ResponseWriter, r *http.Request, rootErr error) { status = http.StatusInternalServerError publicReason = "An unknown error occurred" loggedReason = err - logging.ReqLogger(r.Context()).Error("handling non-HTTPError", "stacktrace", formatStackTrace(retrace(20))) + logging.ReqLogger(r.Context()).ErrorContext(r.Context(), "handling non-HTTPError", "stacktrace", formatStackTrace(retrace(20))) } - logging.ReqLogger(r.Context()).Error( + logging.ReqLogger(r.Context()).ErrorContext(r.Context(), "Error handling request", "error", loggedReason, "rootError", rootErr, diff --git a/backend/server/remux/tracing.go b/backend/server/remux/tracing.go index 3e8cfd946..b72e7d544 100644 --- a/backend/server/remux/tracing.go +++ b/backend/server/remux/tracing.go @@ -1,6 +1,7 @@ package remux import ( + "context" "fmt" "log/slog" "runtime" @@ -18,12 +19,12 @@ type StackTraceEntry struct { // questionable code. If a panic occurs, this will catch that panic, log the response, // and execute the provided cleanup code. a boolean provided to the cleanup code // indicates if a panic occurred. -func watcher(log *slog.Logger, cleanup func(bool)) { +func watcher(ctx context.Context, log *slog.Logger, cleanup func(bool)) { paniced := false if r := recover(); r != nil { paniced = true strTrace := formatStackTrace(retrace(25)) - log.Error("unexpected panic", "recoveredData", r, "stacktrace", strTrace) + log.ErrorContext(ctx, "unexpected panic", "recoveredData", r, "stacktrace", strTrace) } cleanup(paniced) } diff --git a/backend/services/evidence.go b/backend/services/evidence.go index c1de0dc88..817e47183 100644 --- a/backend/services/evidence.go +++ b/backend/services/evidence.go @@ -378,7 +378,7 @@ func SendURLData(ctx context.Context, db *database.Connection, contentStore *con if err := policy.Require(middleware.Policy(ctx), policy.CanReadOperation{OperationID: operation.ID}); err != nil { return nil, backend.WrapError("Unwilling to read evidence", backend.UnauthorizedReadErr(err)) } - urlData, err := contentStore.SendURLData(evidence.FullImageKey) + urlData, err := contentStore.SendURLData(ctx, evidence.FullImageKey) if err != nil { return nil, backend.WrapError("Unable to get image URL", backend.ServerErr(err)) } diff --git a/backend/services/user.go b/backend/services/user.go index b1b2b007c..de1b3ba08 100644 --- a/backend/services/user.go +++ b/backend/services/user.go @@ -91,7 +91,7 @@ func CreateHeadlessUser(ctx context.Context, db *database.Connection, i CreateUs return nil, backend.WrapError("Unable to create new headless user", backend.UnauthorizedWriteErr(err)) } i.Headless = true - return CreateUser(db, i) + return CreateUser(ctx, db, i) } // CreateUser generates an entry in the users table in the database. No more is done here, but it is expected @@ -102,7 +102,7 @@ func CreateHeadlessUser(ctx context.Context, db *database.Connection, i CreateUs // // Returns a structure containing both the true slug (i.e. what it was mangled to, if it was infact mangled), plus // the associated user_id value -func CreateUser(db *database.Connection, i CreateUserInput) (*dtos.CreateUserOutput, error) { +func CreateUser(ctx context.Context, db *database.Connection, i CreateUserInput) (*dtos.CreateUserOutput, error) { validationErr := i.validate() if validationErr != nil { return nil, backend.WrapError("Unable to create new user", validationErr) @@ -132,7 +132,7 @@ func CreateUser(db *database.Connection, i CreateUserInput) (*dtos.CreateUserOut return nil, backend.WrapError("Unable to create new user after many attempts", backend.DatabaseErr(err)) } - logging.LogWithoutAuth( + logging.LogWithoutAuth(ctx, "Unable to create user with slug; trying alternative", "slug", attemptedSlug, "attempt", attemptNumber, @@ -152,7 +152,7 @@ func CreateUser(db *database.Connection, i CreateUserInput) (*dtos.CreateUserOut if userID == 1 { err := db.Update(sq.Update("users").Set("admin", true).Where(sq.Eq{"id": userID})) if err != nil { - logging.LogWithoutAuth("Unable to make the first user an admin", "error", err.Error()) + logging.LogWithoutAuth(ctx, "Unable to make the first user an admin", "error", err.Error()) } } return &dtos.CreateUserOutput{ diff --git a/backend/services/user_test.go b/backend/services/user_test.go index 925bc6cc5..e5e58d174 100644 --- a/backend/services/user_test.go +++ b/backend/services/user_test.go @@ -25,7 +25,7 @@ func TestCreateUser(t *testing.T) { Email: "luna.lovegood@hogwarts.edu", } - createUserOutput, err := services.CreateUser(db, i) + createUserOutput, err := services.CreateUser(context.Background(), db, i) require.NoError(t, err) require.Equal(t, createUserOutput.RealSlug, i.Slug) luna := getUserProfile(t, db, createUserOutput.UserID) @@ -36,12 +36,12 @@ func TestCreateUser(t *testing.T) { require.Equal(t, luna.LastName, i.LastName) // Verify re-register will fail (due to unique email constraint) - _, err = services.CreateUser(db, i) + _, err = services.CreateUser(context.Background(), db, i) require.Error(t, err) // Verify 2nd user (non-admin, no matching slug) i.Email = "luna.lovegood+extra@hogwarts.edu" // change the password to something that won't exist - createUserOutput, err = services.CreateUser(db, i) + createUserOutput, err = services.CreateUser(context.Background(), db, i) require.NoError(t, err) // Since Luna's already exists, a new slug should be created require.NotEqual(t, i.Slug, createUserOutput.RealSlug) diff --git a/backend/workers/email.go b/backend/workers/email.go index 9ef5d5883..2e316ca6d 100644 --- a/backend/workers/email.go +++ b/backend/workers/email.go @@ -1,6 +1,7 @@ package workers import ( + "context" "fmt" "log/slog" "time" @@ -66,7 +67,7 @@ func (w *EmailWorker) Start() { w.running = true defer func() { if r := recover(); r != nil { - w.logger.Error("recovered from worker panic", "error", r) + w.logger.ErrorContext(context.Background(), "recovered from worker panic", "error", r) } }() w.start() @@ -75,7 +76,7 @@ func (w *EmailWorker) Start() { // start _actually_ starts the worker. func (w *EmailWorker) start() { - w.logger.Info("Starting worker") + w.logger.InfoContext(context.Background(), "Starting worker") go w.run() go func() { <-w.stopChan @@ -122,7 +123,7 @@ func (w *EmailWorker) run() { } err = w.queueEmail(email) if err != nil { - w.logger.Error("Unable to queue email", "error", err.Error()) + w.logger.ErrorContext(context.Background(), "Unable to queue email", "error", err.Error()) continue } } @@ -171,7 +172,7 @@ func (w *EmailWorker) queueEmail(email emailRequest) error { Set("email_status", EmailSent). Where(sq.Eq{"id": email.EmailID})) if err != nil { - w.logger.Error("Unable to set email completed status", "error", err.Error()) + w.logger.ErrorContext(context.Background(), "Unable to set email completed status", "error", err.Error()) } } }, @@ -180,7 +181,7 @@ func (w *EmailWorker) queueEmail(email emailRequest) error { } func setEmailFailed(db *database.Connection, emailID int64, logger *slog.Logger, err error) { - logger.Error("Unable to send email", "err", err.Error()) + logger.ErrorContext(context.Background(), "Unable to send email", "err", err.Error()) db.Update(sq.Update("email_queue"). Set("error_count", sq.Expr("error_count + 1")). SetMap(map[string]interface{}{