I'm trying to set up logging in a RIO application; yet, I don't seem to understand the logging interface.
RIO documentation encourages to define a logger and run the application as follows:
withLogFunc logOptions $ \lf -> do
let env = Env -- application specific environment
{ appLogFunc = lf
, appOtherStuff = ...
}
runRIO env $ do
logInfo "Starting app"
myApp ...
That is, withLogFunc
brackets execution of the actual application - why?
I want to hoist my RIO monad into Servant, so this bracketing approach gets in the way. What I'd like to do is to define an environment for use with RIO, say:
data Env = Env
{ config :: ...
, logger :: !LogFunc
}
make the environment an instance of the HasLogFunc
typeclass:
instance HasLogFunc Env where
logFuncL = lens logger (\x y -> x { logger = y })
and then create a value of the Env
type before passing it to runRIO
, instead of passing the entire application execution as a function parameter to withLogFunc
.
That is, I would like something along the lines
let env = Env {
config = ...
logger = mkLogFunc ...
}
in runRIO env $ do
logInfo "Starting app"
...
However, I do not understand how to create a LogFunc
as part of the environment separately. In this way, I could hoist runRIO
into a Servant server (server :: S.ServerT UserApi (RIO Env)
) and then execute the latter. It appears that the RIO logging interface discourages this. Why? What am I missing?
Thanks for any insights!