@@ -6,7 +6,6 @@ module Log.Monad (
66 , InnerLogT
77 , LogT (.. )
88 , runLogT
9- , runLogTAttentionOnFailure
109 , mapLogT
1110 , logMessageIO
1211 , getLoggerIO
@@ -47,19 +46,25 @@ instance MonadReader r m => MonadReader r (LogT m) where
4746 ask = lift ask
4847 local = mapLogT . local
4948
50- -- | Run a 'LogT' computation
49+ -- | Run a 'LogT' computation and log any uncaught exceptions.
5150--
5251-- Note that in the case of asynchronous/bulk loggers 'runLogT'
5352-- doesn't guarantee that all messages are actually written to the log
5453-- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger'
5554-- for that.
56- runLogT :: Text -- ^ Application component name to use.
55+ runLogT :: (MonadBaseControl IO m )
56+ => Text -- ^ Application component name to use.
5757 -> Logger -- ^ The logging back-end to use.
5858 -> LogLevel -- ^ The maximum log level allowed to be logged.
5959 -- Only messages less or equal than this level with be logged.
6060 -> LogT m a -- ^ The 'LogT' computation to run.
6161 -> m a
62- runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv {
62+ runLogT component logger maxLogLevel m = runReaderT
63+ (unLogT $ liftedCatch m (\ (SomeException e) -> do
64+ logAttention " Uncaught exception" $ object [" error" .= show e]
65+ E. throw e)
66+ )
67+ LoggerEnv {
6368 leLogger = logger
6469, leComponent = component
6570, leDomain = []
@@ -68,42 +73,16 @@ runLogT component logger maxLogLevel m = runReaderT (unLogT m) LoggerEnv {
6873} -- We can't do synchronisation here, since 'runLogT' can be invoked
6974 -- quite often from the application (e.g. on every request).
7075
76+ -- Generalized version of catch taken from `lifted-base`
77+ liftedCatch :: (MonadBaseControl IO m , Exception e )
78+ => m a -- ^ The computation to run
79+ -> (e -> m a ) -- ^ Handler to invoke if an exception is raised
80+ -> m a
81+ liftedCatch a handler = control $ \ runInIO ->
82+ E. catch
83+ (runInIO a)
84+ (\ e -> runInIO $ handler e)
7185
72- -- | Run a 'LogT' computation and log any uncaught exception
73- --
74- -- Note that in the case of asynchronous/bulk loggers 'runLogT'
75- -- doesn't guarantee that all messages are actually written to the log
76- -- once it finishes. Use 'withPGLogger' or 'withElasticSearchLogger'
77- -- for that.
78- runLogTAttentionOnFailure :: (MonadBase IO m , MonadMask m )
79- => Text -- ^ Application component name to use.
80- -> Logger -- ^ The logging back-end to use.
81- -> LogLevel -- ^ The maximum log level allowed to be logged.
82- -- Only messages less or equal than this level with be logged.
83- -> LogT m a -- ^ The 'LogT' computation to run.
84- -> m a
85- runLogTAttentionOnFailure component logger maxLogLevel m =
86- fst <$> runReaderT
87- (unLogT $
88- generalBracket
89- (pure () )
90- (\ _ -> \ case
91- ExitCaseSuccess _ -> pure ()
92- ExitCaseException (SomeException e) -> do
93- logAttention " Uncaught exception raised" $ object [" error" .= show e]
94- error " In a catch"
95- ExitCaseAbort ->
96- logAttention_ " Process was aborted"
97- )
98- (const m))
99- LoggerEnv
100- { leLogger = logger
101- , leComponent = component
102- , leDomain = []
103- , leData = []
104- , leMaxLogLevel = maxLogLevel
105- } -- We can't do synchronisation here, since 'runLogT' can be invoked
106- -- quite often from the application (e.g. on every request).
10786
10887-- | Transform the computation inside a 'LogT'.
10988mapLogT :: (m a -> n b ) -> LogT m a -> LogT n b
0 commit comments