commercialhaskell / rio

A standard library for Haskell
Other
836 stars 54 forks source link

Question: is there any chance to move logger to external library and expose some internals? #241

Closed schernichkin closed 1 year ago

schernichkin commented 2 years ago

Motivation:

I like RIO's logging and want to use it in my app. Moreover, I'm intending to use RIO in my app (not solely for logging, but for other good things as well), but my overall project is consisting of app itself and general library, containing most of logic.

I'm fine with RIO dependency in my app, but I don't want to introduce dependency in the general library. I believe you advised somewhere: "Use RIO in apps, abstract over monads in libraries." Not sure, but still I find this practice good. However, I either don't want to abstract over monad in my library. Let's say, my library is running in IO. Still it needs some callbacks for logging. This currently achieved by requesting logging adapter (runServer :: (Text -> IO ()) -> ... where Text -> IO () is logging function).

To achieve it I need to write something like this:

main :: IO ()
main = do
    runServer $ runSimpleApp . logInfo . display 
    return ()

runServer :: (Text -> IO ()) -> IO ()
runServer log = log "Hello, world, server started successfully!"

Real case example would be even worse. Because instead of runSimpleApp I will use more complex initialization. I guess it's not too good performance-wise to run RIO each time I want to log a single message. I also guess that under the hood RIO's logging just requires IO and several parameters which can be passed explicitly. Moreover, having RIO's logging as stand-alone library could eliminate the need of creating separate adapters, it could itself be a logging interface library.

These are just my thoughts, I could be wrong. But they are based on the fact that logging is too common to be included in some specialized library, and logging is done well in RIO, I believe that there will be a benefit from creating a separate library. Discuss please)

snoyberg commented 2 years ago

I have no intention of splitting up the library further. The recommendation I mentioned was about the APIs to expose, and relying on the more general MonadReader pieces in a library.

schernichkin commented 2 years ago

I see. Since you do not want to split the library and I still want to implement logging via callbacks in IO, what would you suggest? Is setupRIOforLoggingAndRun . log<Something> . dispaly good approach or would you recommend something else?

snoyberg commented 2 years ago

The general approach is to rely on unliftio, which generally looks something like:

main = runSimpleApp $ withRunInIO $ \runRioAction -> rest of your app