From 5f289b778f873cb51d638cc6b11e47e12290fb02 Mon Sep 17 00:00:00 2001 From: Marc Scholten Date: Fri, 15 Mar 2024 20:57:48 +0100 Subject: [PATCH] Allow overriding the logger in the controller context (#1923) * Allow overriding the logger in the controller context * added more comments --- IHP/Controller/Context.hs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/IHP/Controller/Context.hs b/IHP/Controller/Context.hs index 61a8cd3bc..0ddb744cd 100644 --- a/IHP/Controller/Context.hs +++ b/IHP/Controller/Context.hs @@ -10,6 +10,7 @@ import qualified Data.Typeable as Typeable import IHP.Controller.RequestContext import IHP.FrameworkConfig import IHP.Log.Types +import System.IO.Unsafe (unsafePerformIO) -- | A container storing useful data along the request lifecycle, such as the request, the current user, set current view layout, flash messages, ... -- @@ -137,5 +138,28 @@ instance HasField "frameworkConfig" ControllerContext FrameworkConfig where getField controllerContext = controllerContext.requestContext.frameworkConfig {-# INLINABLE getField #-} +-- The following hack is bad, but allows us to override the logger using 'putContext' +-- The alternative would be https://github.com/digitallyinduced/ihp/pull/1921 which is also not very nice +-- +-- This can be useful to customize the log formatter for all actions of an app: +-- +-- > import IHP.Log.Types +-- > import IHP.Controller.Context +-- > +-- > instance InitControllerContext WebApplication where +-- > initContext = do +-- > let defaultLogger :: Logger = ?context.frameworkConfig.logger +-- > let withUserIdLogger :: Logger = { Log.formatter = userIdFormatter defaultLogger.formatter } +-- > putContext withUserIdLogger +-- > +-- > userIdFormatter :: (?context :: Context) => Log.LogFormatter -> Log.LogFormatter +-- > userIdFormatter existingFormatter time level string = +-- > existingFormatter time level (prependUserId string) +-- > +-- > preprendUserId :: (?context :: Context) => Text -> Text +-- > preprendUserId string = "userId: " <> show currentUserId <> " " <> string +-- +-- This design mistake should be fixed in IHP v2 instance HasField "logger" ControllerContext Logger where - getField controllerContext = controllerContext.frameworkConfig.logger + getField context@(FrozenControllerContext { customFields }) = fromMaybe context.frameworkConfig.logger (TypeMap.lookup @Logger customFields) + getField context = (unsafePerformIO (freeze context)).logger -- Hacky, but there's no better way. The only way to retrieve the logger here, is by reading from the IORef in an unsafe way