From 366add1d7e57476c2b22a4af28b6df8cc67fef20 Mon Sep 17 00:00:00 2001 From: Raveline Date: Mon, 2 Jun 2025 17:09:56 +0200 Subject: [PATCH 01/14] [CORE-7914] Log an unhandled exception or a user abort before the computation ends --- log-base/src/Log/Monad.hs | 41 ++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index c656c3b..9445466 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -24,7 +24,7 @@ import Control.Monad.State.Class import Control.Monad.Trans.Control import Control.Monad.Writer.Class import Data.Aeson -import Data.Text (Text) +import Data.Text (Text, pack) import Data.Time import qualified Control.Monad.Fail as MF import qualified Control.Exception as E @@ -46,26 +46,35 @@ instance MonadReader r m => MonadReader r (LogT m) where ask = lift ask local = mapLogT . local --- | Run a 'LogT' computation. --- --- Note that in the case of asynchronous/bulk loggers 'runLogT' --- doesn't guarantee that all messages are actually written to the log --- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger' --- for that. -runLogT :: Text -- ^ Application component name to use. +runLogT :: (MonadMask m, MonadBase IO m) + => Text -- ^ Application component name to use. -> Logger -- ^ The logging back-end to use. -> LogLevel -- ^ The maximum log level allowed to be logged. -- Only messages less or equal than this level with be logged. -> LogT m a -- ^ The 'LogT' computation to run. -> m a -runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv { - leLogger = logger -, leComponent = component -, leDomain = [] -, leData = [] -, leMaxLogLevel = maxLogLevel -} -- We can't do synchronisation here, since 'runLogT' can be invoked - -- quite often from the application (e.g. on every request). +runLogT component logger maxLogLevel m = + fst <$> runReaderT + (unLogT $ + generalBracket + (pure ()) + (\_ -> \case + ExitCaseSuccess _ -> pure () + ExitCaseException (SomeException e) -> do + logAttention "Uncaught exception raised" $ object ["error" .= (pack . show $ e)] + throwM e + ExitCaseAbort -> + logAttention_ "Process was aborted manually" + ) + (const m)) + LoggerEnv + { leLogger = logger + , leComponent = component + , leDomain = [] + , leData = [] + , leMaxLogLevel = maxLogLevel + } -- We can't do synchronisation here, since 'runLogT' can be invoked + -- quite often from the application (e.g. on every request). -- | Transform the computation inside a 'LogT'. mapLogT :: (m a -> n b) -> LogT m a -> LogT n b From ab30e99f624e37dc5bf28f939338c34b5fa4d75d Mon Sep 17 00:00:00 2001 From: Raveline Date: Tue, 3 Jun 2025 10:31:12 +0200 Subject: [PATCH 02/14] Apply PR suggestions --- log-base/src/Log/Monad.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 9445466..e41b17e 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -24,7 +24,7 @@ import Control.Monad.State.Class import Control.Monad.Trans.Control import Control.Monad.Writer.Class import Data.Aeson -import Data.Text (Text, pack) +import Data.Text (Text) import Data.Time import qualified Control.Monad.Fail as MF import qualified Control.Exception as E @@ -46,6 +46,7 @@ instance MonadReader r m => MonadReader r (LogT m) where ask = lift ask local = mapLogT . local +-- | Run a 'LogT' computation runLogT :: (MonadMask m, MonadBase IO m) => Text -- ^ Application component name to use. -> Logger -- ^ The logging back-end to use. @@ -61,10 +62,10 @@ runLogT component logger maxLogLevel m = (\_ -> \case ExitCaseSuccess _ -> pure () ExitCaseException (SomeException e) -> do - logAttention "Uncaught exception raised" $ object ["error" .= (pack . show $ e)] + logAttention "Uncaught exception raised" $ object ["error" .= show e] throwM e ExitCaseAbort -> - logAttention_ "Process was aborted manually" + logAttention_ "Process was aborted" ) (const m)) LoggerEnv From e9c4bb4289446dbd0ce9b16ac44dd2229a068493 Mon Sep 17 00:00:00 2001 From: Raveline Date: Wed, 4 Jun 2025 09:37:09 +0200 Subject: [PATCH 03/14] [EXPERIMENT] Try with catch --- log-base/src/Log/Monad.hs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index e41b17e..009ba30 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -47,7 +47,7 @@ instance MonadReader r m => MonadReader r (LogT m) where local = mapLogT . local -- | Run a 'LogT' computation -runLogT :: (MonadMask m, MonadBase IO m) +runLogT :: (MonadCatch m, MonadBase IO m) => Text -- ^ Application component name to use. -> Logger -- ^ The logging back-end to use. -> LogLevel -- ^ The maximum log level allowed to be logged. @@ -55,19 +55,12 @@ runLogT :: (MonadMask m, MonadBase IO m) -> LogT m a -- ^ The 'LogT' computation to run. -> m a runLogT component logger maxLogLevel m = - fst <$> runReaderT - (unLogT $ - generalBracket - (pure ()) - (\_ -> \case - ExitCaseSuccess _ -> pure () - ExitCaseException (SomeException e) -> do + runReaderT + (unLogT $ do + m `catch` + (\(SomeException e) -> do logAttention "Uncaught exception raised" $ object ["error" .= show e] - throwM e - ExitCaseAbort -> - logAttention_ "Process was aborted" - ) - (const m)) + throwM e)) LoggerEnv { leLogger = logger , leComponent = component From 33b5d3df6462d4fc0eba2b7045b763fc94381105 Mon Sep 17 00:00:00 2001 From: Raveline Date: Wed, 4 Jun 2025 10:10:10 +0200 Subject: [PATCH 04/14] Trying something --- log-base/src/Log/Monad.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 009ba30..80c67ff 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -60,7 +60,7 @@ runLogT component logger maxLogLevel m = m `catch` (\(SomeException e) -> do logAttention "Uncaught exception raised" $ object ["error" .= show e] - throwM e)) + error "In a catch")) LoggerEnv { leLogger = logger , leComponent = component From 60cd44267957f70177b566dda1f0260b83f58661 Mon Sep 17 00:00:00 2001 From: Raveline Date: Wed, 4 Jun 2025 10:22:00 +0200 Subject: [PATCH 05/14] Have a dedicated runner that logs on exception --- log-base/src/Log/Monad.hs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 80c67ff..fb31eed 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -6,6 +6,7 @@ module Log.Monad ( , InnerLogT , LogT(..) , runLogT + , runLogTAttentionOnFailure , mapLogT , logMessageIO , getLoggerIO @@ -47,14 +48,41 @@ instance MonadReader r m => MonadReader r (LogT m) where local = mapLogT . local -- | Run a 'LogT' computation -runLogT :: (MonadCatch m, MonadBase IO m) +-- +-- Note that in the case of asynchronous/bulk loggers 'runLogT' +-- doesn't guarantee that all messages are actually written to the log +-- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger' +-- for that. +runLogT :: Text -- ^ Application component name to use. + -> Logger -- ^ The logging back-end to use. + -> LogLevel -- ^ The maximum log level allowed to be logged. + -- Only messages less or equal than this level with be logged. + -> LogT m a -- ^ The 'LogT' computation to run. + -> m a +runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv { + leLogger = logger +, leComponent = component +, leDomain = [] +, leData = [] +, leMaxLogLevel = maxLogLevel +} -- We can't do synchronisation here, since 'runLogT' can be invoked + -- quite often from the application (e.g. on every request). + + +-- | Run a 'LogT' computation and log any uncaught exception +-- +-- Note that in the case of asynchronous/bulk loggers 'runLogT' +-- doesn't guarantee that all messages are actually written to the log +-- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger' +-- for that. +runLogTAttentionOnFailure :: (MonadCatch m, MonadBase IO m) => Text -- ^ Application component name to use. -> Logger -- ^ The logging back-end to use. -> LogLevel -- ^ The maximum log level allowed to be logged. -- Only messages less or equal than this level with be logged. -> LogT m a -- ^ The 'LogT' computation to run. -> m a -runLogT component logger maxLogLevel m = +runLogTAttentionOnFailure component logger maxLogLevel m = runReaderT (unLogT $ do m `catch` From d7d8cc20d7590a0b55b15137e4a7bf6f785f7a36 Mon Sep 17 00:00:00 2001 From: Raveline Date: Wed, 4 Jun 2025 10:36:23 +0200 Subject: [PATCH 06/14] Retrying with MonadMask --- log-base/src/Log/Monad.hs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index fb31eed..9fddfa3 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -75,7 +75,7 @@ runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv { -- doesn't guarantee that all messages are actually written to the log -- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger' -- for that. -runLogTAttentionOnFailure :: (MonadCatch m, MonadBase IO m) +runLogTAttentionOnFailure :: (MonadBase IO m, MonadMask m) => Text -- ^ Application component name to use. -> Logger -- ^ The logging back-end to use. -> LogLevel -- ^ The maximum log level allowed to be logged. @@ -83,12 +83,19 @@ runLogTAttentionOnFailure :: (MonadCatch m, MonadBase IO m) -> LogT m a -- ^ The 'LogT' computation to run. -> m a runLogTAttentionOnFailure component logger maxLogLevel m = - runReaderT - (unLogT $ do - m `catch` - (\(SomeException e) -> do + fst <$> runReaderT + (unLogT $ + generalBracket + (pure ()) + (\_ -> \case + ExitCaseSuccess _ -> pure () + ExitCaseException (SomeException e) -> do logAttention "Uncaught exception raised" $ object ["error" .= show e] - error "In a catch")) + error "In a catch" + ExitCaseAbort -> + logAttention_ "Process was aborted" + ) + (const m)) LoggerEnv { leLogger = logger , leComponent = component From c75ec4f827efcd7d0efc1e1bbf04bbdd0aff7fdf Mon Sep 17 00:00:00 2001 From: Raveline Date: Wed, 11 Jun 2025 17:32:06 +0200 Subject: [PATCH 07/14] Use MonadBaseControl IO --- log-base/src/Log/Monad.hs | 58 ++++++++++++--------------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 9fddfa3..4a28c5e 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -6,7 +6,6 @@ module Log.Monad ( , InnerLogT , LogT(..) , runLogT - , runLogTAttentionOnFailure , mapLogT , logMessageIO , getLoggerIO @@ -47,19 +46,25 @@ instance MonadReader r m => MonadReader r (LogT m) where ask = lift ask local = mapLogT . local --- | Run a 'LogT' computation +-- | Run a 'LogT' computation and log any uncaught exceptions. -- -- Note that in the case of asynchronous/bulk loggers 'runLogT' -- doesn't guarantee that all messages are actually written to the log -- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger' -- for that. -runLogT :: Text -- ^ Application component name to use. +runLogT :: (MonadBaseControl IO m) + => Text -- ^ Application component name to use. -> Logger -- ^ The logging back-end to use. -> LogLevel -- ^ The maximum log level allowed to be logged. -- Only messages less or equal than this level with be logged. -> LogT m a -- ^ The 'LogT' computation to run. -> m a -runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv { +runLogT component logger maxLogLevel m = runReaderT + (unLogT $ liftedCatch m (\(SomeException e) -> do + logAttention "Uncaught exception" $ object ["error" .= show e] + E.throw e) + ) + LoggerEnv { leLogger = logger , leComponent = component , leDomain = [] @@ -68,42 +73,15 @@ runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv { } -- We can't do synchronisation here, since 'runLogT' can be invoked -- quite often from the application (e.g. on every request). - --- | Run a 'LogT' computation and log any uncaught exception --- --- Note that in the case of asynchronous/bulk loggers 'runLogT' --- doesn't guarantee that all messages are actually written to the log --- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger' --- for that. -runLogTAttentionOnFailure :: (MonadBase IO m, MonadMask m) - => Text -- ^ Application component name to use. - -> Logger -- ^ The logging back-end to use. - -> LogLevel -- ^ The maximum log level allowed to be logged. - -- Only messages less or equal than this level with be logged. - -> LogT m a -- ^ The 'LogT' computation to run. - -> m a -runLogTAttentionOnFailure component logger maxLogLevel m = - fst <$> runReaderT - (unLogT $ - generalBracket - (pure ()) - (\_ -> \case - ExitCaseSuccess _ -> pure () - ExitCaseException (SomeException e) -> do - logAttention "Uncaught exception raised" $ object ["error" .= show e] - error "In a catch" - ExitCaseAbort -> - logAttention_ "Process was aborted" - ) - (const m)) - LoggerEnv - { leLogger = logger - , leComponent = component - , leDomain = [] - , leData = [] - , leMaxLogLevel = maxLogLevel - } -- We can't do synchronisation here, since 'runLogT' can be invoked - -- quite often from the application (e.g. on every request). +-- Generalized version of catch taken from `lifted-base` +liftedCatch :: (MonadBaseControl IO m, Exception e) + => m a -- ^ The computation to run + -> (e -> m a) -- ^ Handler to invoke if an exception is raised + -> m a +liftedCatch a handler = control $ \runInIO -> + E.catch + (runInIO a) + (\e -> runInIO $ handler e) -- | Transform the computation inside a 'LogT'. mapLogT :: (m a -> n b) -> LogT m a -> LogT n b From ff00dce570dc5023435d7d125da4d9c91a87f5f6 Mon Sep 17 00:00:00 2001 From: Raveline Date: Mon, 23 Jun 2025 17:10:29 +0200 Subject: [PATCH 08/14] Apply PR suggestions --- log-base/src/Log/Monad.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 4a28c5e..82ec5c8 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -62,7 +62,7 @@ runLogT :: (MonadBaseControl IO m) runLogT component logger maxLogLevel m = runReaderT (unLogT $ liftedCatch m (\(SomeException e) -> do logAttention "Uncaught exception" $ object ["error" .= show e] - E.throw e) + liftBase $ E.throwIO e) ) LoggerEnv { leLogger = logger @@ -81,7 +81,7 @@ liftedCatch :: (MonadBaseControl IO m, Exception e) liftedCatch a handler = control $ \runInIO -> E.catch (runInIO a) - (\e -> runInIO $ handler e) + (runInIO . handler) -- | Transform the computation inside a 'LogT'. mapLogT :: (m a -> n b) -> LogT m a -> LogT n b From cf221901f8ba60e83eba32c8672a305c2c5a6d88 Mon Sep 17 00:00:00 2001 From: Raveline Date: Mon, 23 Jun 2025 17:13:30 +0200 Subject: [PATCH 09/14] Bump version and update changelog --- log-base/CHANGELOG.md | 3 +++ log-base/log-base.cabal | 2 +- log-elasticsearch/log-elasticsearch.cabal | 2 +- log-postgres/log-postgres.cabal | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/log-base/CHANGELOG.md b/log-base/CHANGELOG.md index e4bc2a1..09bf919 100644 --- a/log-base/CHANGELOG.md +++ b/log-base/CHANGELOG.md @@ -1,3 +1,6 @@ +# log-base-0.13.0.0 (2025-06-23) +* Log unhandled exceptions + # log-base-0.12.0.1 (2023-03-14) * Add support for GHC 9.6. diff --git a/log-base/log-base.cabal b/log-base/log-base.cabal index e355aef..89d5376 100644 --- a/log-base/log-base.cabal +++ b/log-base/log-base.cabal @@ -1,6 +1,6 @@ cabal-version: 3.0 name: log-base -version: 0.12.0.1 +version: 0.13.0.0 synopsis: Structured logging solution (base package) description: A library that provides a way to record structured log diff --git a/log-elasticsearch/log-elasticsearch.cabal b/log-elasticsearch/log-elasticsearch.cabal index 68c68a6..6b377b2 100644 --- a/log-elasticsearch/log-elasticsearch.cabal +++ b/log-elasticsearch/log-elasticsearch.cabal @@ -40,7 +40,7 @@ library deepseq, http-client, http-types, - log-base >= 0.10 && <0.13, + log-base >= 0.10 && <0.14, network-uri, semigroups, text, diff --git a/log-postgres/log-postgres.cabal b/log-postgres/log-postgres.cabal index 14aef2b..1a4fa53 100644 --- a/log-postgres/log-postgres.cabal +++ b/log-postgres/log-postgres.cabal @@ -35,7 +35,7 @@ library , hpqtypes >= 1.9.1.2 , http-client >= 0.5 , lifted-base >= 0.2 - , log-base >= 0.10 && < 0.13 + , log-base >= 0.10 && < 0.14 , mtl >= 2.2 , semigroups >= 0.16 , split >= 0.2 From 11a85b44e4d660c88a453e90ceaf79d5ced665fc Mon Sep 17 00:00:00 2001 From: Raveline Date: Tue, 24 Jun 2025 14:16:15 +0200 Subject: [PATCH 10/14] Provide exceptions logging as a function Rather than patching runLogT directly, add a composable utility --- log-base/CHANGELOG.md | 2 +- log-base/src/Log/Monad.hs | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/log-base/CHANGELOG.md b/log-base/CHANGELOG.md index 09bf919..ae1c41f 100644 --- a/log-base/CHANGELOG.md +++ b/log-base/CHANGELOG.md @@ -1,5 +1,5 @@ # log-base-0.13.0.0 (2025-06-23) -* Log unhandled exceptions +* Add utility function to log unhandled exceptions # log-base-0.12.0.1 (2023-03-14) * Add support for GHC 9.6. diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 82ec5c8..2efac1a 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -8,6 +8,7 @@ module Log.Monad ( , runLogT , mapLogT , logMessageIO + , logExceptions , getLoggerIO ) where @@ -46,25 +47,19 @@ instance MonadReader r m => MonadReader r (LogT m) where ask = lift ask local = mapLogT . local --- | Run a 'LogT' computation and log any uncaught exceptions. +-- | Run a 'LogT' computation. -- -- Note that in the case of asynchronous/bulk loggers 'runLogT' -- doesn't guarantee that all messages are actually written to the log -- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger' -- for that. -runLogT :: (MonadBaseControl IO m) - => Text -- ^ Application component name to use. +runLogT :: Text -- ^ Application component name to use. -> Logger -- ^ The logging back-end to use. -> LogLevel -- ^ The maximum log level allowed to be logged. -- Only messages less or equal than this level with be logged. -> LogT m a -- ^ The 'LogT' computation to run. -> m a -runLogT component logger maxLogLevel m = runReaderT - (unLogT $ liftedCatch m (\(SomeException e) -> do - logAttention "Uncaught exception" $ object ["error" .= show e] - liftBase $ E.throwIO e) - ) - LoggerEnv { +runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv { leLogger = logger , leComponent = component , leDomain = [] @@ -73,6 +68,15 @@ runLogT component logger maxLogLevel m = runReaderT } -- We can't do synchronisation here, since 'runLogT' can be invoked -- quite often from the application (e.g. on every request). +-- | Unsure uncaught exceptions get logged +-- Convenient to compose right after `runLogT` so any exception +-- will show up. +logExceptions :: (MonadBaseControl IO m, MonadLog m) => m a -> m a +logExceptions f = + liftedCatch f $ \(SomeException e) -> do + logAttention "Uncaught exception" $ object ["error" .= show e] + liftBase $ E.throwIO e + -- Generalized version of catch taken from `lifted-base` liftedCatch :: (MonadBaseControl IO m, Exception e) => m a -- ^ The computation to run From c8f1072e900ce6a21c582a376771060e67343d72 Mon Sep 17 00:00:00 2001 From: Raveline Date: Tue, 24 Jun 2025 14:38:17 +0200 Subject: [PATCH 11/14] Apply PR suggestions --- log-base/CHANGELOG.md | 4 ++-- log-base/log-base.cabal | 2 +- log-base/src/Log/Monad.hs | 6 +++--- log-elasticsearch/log-elasticsearch.cabal | 2 +- log-postgres/log-postgres.cabal | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/log-base/CHANGELOG.md b/log-base/CHANGELOG.md index ae1c41f..f538851 100644 --- a/log-base/CHANGELOG.md +++ b/log-base/CHANGELOG.md @@ -1,5 +1,5 @@ -# log-base-0.13.0.0 (2025-06-23) -* Add utility function to log unhandled exceptions +# log-base-0.12.0.1 (2025-??-??) +* Add utility function to log unhandled exceptions. # log-base-0.12.0.1 (2023-03-14) * Add support for GHC 9.6. diff --git a/log-base/log-base.cabal b/log-base/log-base.cabal index 89d5376..3ca4fda 100644 --- a/log-base/log-base.cabal +++ b/log-base/log-base.cabal @@ -1,6 +1,6 @@ cabal-version: 3.0 name: log-base -version: 0.13.0.0 +version: 0.12.1.0 synopsis: Structured logging solution (base package) description: A library that provides a way to record structured log diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 2efac1a..8b07f0b 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -6,9 +6,9 @@ module Log.Monad ( , InnerLogT , LogT(..) , runLogT + , logExceptions , mapLogT , logMessageIO - , logExceptions , getLoggerIO ) where @@ -68,7 +68,7 @@ runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv { } -- We can't do synchronisation here, since 'runLogT' can be invoked -- quite often from the application (e.g. on every request). --- | Unsure uncaught exceptions get logged +-- | Ensure uncaught exceptions get logged. -- Convenient to compose right after `runLogT` so any exception -- will show up. logExceptions :: (MonadBaseControl IO m, MonadLog m) => m a -> m a @@ -77,7 +77,7 @@ logExceptions f = logAttention "Uncaught exception" $ object ["error" .= show e] liftBase $ E.throwIO e --- Generalized version of catch taken from `lifted-base` +-- Generalized version of catch taken from `lifted-base`. liftedCatch :: (MonadBaseControl IO m, Exception e) => m a -- ^ The computation to run -> (e -> m a) -- ^ Handler to invoke if an exception is raised diff --git a/log-elasticsearch/log-elasticsearch.cabal b/log-elasticsearch/log-elasticsearch.cabal index 6b377b2..68c68a6 100644 --- a/log-elasticsearch/log-elasticsearch.cabal +++ b/log-elasticsearch/log-elasticsearch.cabal @@ -40,7 +40,7 @@ library deepseq, http-client, http-types, - log-base >= 0.10 && <0.14, + log-base >= 0.10 && <0.13, network-uri, semigroups, text, diff --git a/log-postgres/log-postgres.cabal b/log-postgres/log-postgres.cabal index 1a4fa53..14aef2b 100644 --- a/log-postgres/log-postgres.cabal +++ b/log-postgres/log-postgres.cabal @@ -35,7 +35,7 @@ library , hpqtypes >= 1.9.1.2 , http-client >= 0.5 , lifted-base >= 0.2 - , log-base >= 0.10 && < 0.14 + , log-base >= 0.10 && < 0.13 , mtl >= 2.2 , semigroups >= 0.16 , split >= 0.2 From d93c066a84ff7769a52803fb3bcb5ef0ee443fd8 Mon Sep 17 00:00:00 2001 From: Raveline Date: Thu, 26 Jun 2025 14:02:39 +0200 Subject: [PATCH 12/14] Add missing dots --- log-base/src/Log/Monad.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 8b07f0b..3c5f662 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -79,8 +79,8 @@ logExceptions f = -- Generalized version of catch taken from `lifted-base`. liftedCatch :: (MonadBaseControl IO m, Exception e) - => m a -- ^ The computation to run - -> (e -> m a) -- ^ Handler to invoke if an exception is raised + => m a -- ^ The computation to run. + -> (e -> m a) -- ^ Handler to invoke if an exception is raised. -> m a liftedCatch a handler = control $ \runInIO -> E.catch From dacd3a5f8a8c3365d8880331b9930954adf645f6 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Thu, 26 Jun 2025 14:47:54 +0200 Subject: [PATCH 13/14] Change error to exception --- log-base/src/Log/Monad.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/log-base/src/Log/Monad.hs b/log-base/src/Log/Monad.hs index 3c5f662..3aee980 100644 --- a/log-base/src/Log/Monad.hs +++ b/log-base/src/Log/Monad.hs @@ -74,7 +74,7 @@ runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv { logExceptions :: (MonadBaseControl IO m, MonadLog m) => m a -> m a logExceptions f = liftedCatch f $ \(SomeException e) -> do - logAttention "Uncaught exception" $ object ["error" .= show e] + logAttention "Uncaught exception" $ object ["exception" .= show e] liftBase $ E.throwIO e -- Generalized version of catch taken from `lifted-base`. From b0f83848f121b15293a751c412be4ece2edf6001 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Thu, 26 Jun 2025 14:51:08 +0200 Subject: [PATCH 14/14] fix changelog --- log-base/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/log-base/CHANGELOG.md b/log-base/CHANGELOG.md index f538851..e50d4ca 100644 --- a/log-base/CHANGELOG.md +++ b/log-base/CHANGELOG.md @@ -1,4 +1,4 @@ -# log-base-0.12.0.1 (2025-??-??) +# log-base-0.12.1.0 (2025-??-??) * Add utility function to log unhandled exceptions. # log-base-0.12.0.1 (2023-03-14)