haskellloggingpersistentesqueleto

How to enable automatic logging of SQL statements with Persistent


I have searched for a clear answer to this question but haven't been able to find one yet - How do I enable automatic logging of SQL statements being executed by persistent? Can someone give me a small example program for this?

Following is an example program that currently does not have logging. How do I enable logging in it?

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
    Person
    name Text
    status Text Maybe
    deriving Show
|]

main :: IO ()
main = runSqlite ":memory:" $ do
    runMigration migrateAll
    insert (Person "Oliver Charles" Nothing)
    insert (Person "Jon Snow" Nothing)
    insert (Person "Marky Mark" (Just "helloo helloo"))
    noStatusPeople >>= mapM_ (liftIO . print)
    where
        noStatusPeople =
            select $ from $ \person -> do
                where_ (person ^. PersonStatus ==. val Nothing)
                return (person ^. PersonName)

Solution

  • You need to call your SQL code in a Monad that implements MonadLogger and not just IO. (see http://hackage.haskell.org/package/monad-logger-0.3.13.1/docs/Control-Monad-Logger.html#v:runStdoutLoggingT). However, runSqlite already sets up the logging (to none...) for you, so you need to use the lower level function withSqliteConn. So for example, if you change your code to:

    import Control.Monad.Logger
    import Control.Monad.Trans.Resource
    
    runResourceT $ runStdoutLoggingT $ withSqliteConn ":memory:" . runSqlConn  $ do...
    

    (with the proper dependencies on resourcet and monad-logger), you can have your SQL statement written to standard out.

    As a real-life example, have a look at my scion-class-browser project: in https://github.com/JPMoresmau/scion-class-browser/blob/5ab9c7576f8faf93299826e72defe70dd5b6dd6f/src/Server/PersistentCommands.hs#L93 you see the call to runSqlite. runLogging is a helper function, to switch between logging or no logging, defined in https://github.com/JPMoresmau/scion-class-browser/blob/f7f2ab0de4f4edb01b307411abf0aa951a3c7c48/src/Scion/PersistentBrowser/DbTypes.hs#L16 (the currently build version does not log, replace by the commented out code).

    Of course, you can instead of using a simple dump to stdout or stderr, write your own implementation of MonadLogger that does what you want.

    As a side note, your code doesn't print out the matching records because you shouldn't compare with val Nothing but instead use isNothing:

    where_ (isNothing $ person ^. PersonStatus)