Skip to content

Conversation

@Raveline
Copy link
Contributor

@Raveline Raveline commented Jun 2, 2025

Ensures that uncaught exception leaves a log, so it's easier to know what happened and debuggers are not left in the dark. Unfortunately, this adds a constraint to the underlying monad.

@Raveline Raveline requested a review from arybczak June 2, 2025 15:11
@Raveline Raveline force-pushed the log-unhandled-exception-and-user-abort branch from 7324698 to 366add1 Compare June 2, 2025 15:14
ask = lift ask
local = mapLogT . local

-- | Run a 'LogT' computation.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove the haddock?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I'm stupid 😬

import Control.Monad.Writer.Class
import Data.Aeson
import Data.Text (Text)
import Data.Text (Text, pack)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need pack, aeson handles string conversions itself.

logAttention "Uncaught exception raised" $ object ["error" .= (pack . show $ e)]
throwM e
ExitCaseAbort ->
logAttention_ "Process was aborted manually"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExitCaseAbort does not mean process was aborted, it means the computation was aborted with means other than runtime exception (like the error from ExceptT if the stack happens to have it).

@arybczak
Copy link
Collaborator

arybczak commented Jun 3, 2025

Please check that it logs the exception when cron exits with the exception (and provide associated kontrakcja PR).

@Raveline
Copy link
Contributor Author

Raveline commented Jun 3, 2025

You were right to ask, because it doesn't work :(
Presumably my generalBracket implementation is faulty ? What about relyong on MonadCatch (one rank below Mask), catching any exception, logging it, and rethrowing it ?

@Raveline
Copy link
Contributor Author

Raveline commented Jun 4, 2025

All right, finally manage to make it work.

  • We probably must create a dedicated variant of runLogT that handles exception, lest some of our dependency break due to the added constraints. So you must explicit require a runner that logs exceptions;
  • I'm afraid we'll also have to create variants in scrive-commons, unless we can find a way around our use of Servant's DelayedIO, which doesn't offer any useful instance for us: https://hackage.haskell.org/package/servant-server-0.17/candidate/docs/Servant-Server-Internal-DelayedIO.html#t:DelayedIO
  • I also suggest using MonadCatch rather than MonadMask and simply using catch though. The implementation is much simpler and less confusing, plus it is a more "common" monad.

@Raveline Raveline force-pushed the log-unhandled-exception-and-user-abort branch from c84f054 to c75ec4f Compare June 11, 2025 15:33
@Raveline
Copy link
Contributor Author

OK, here is a (hopefully) final version using MonadBaseControl. @arybczak, I've tested it with the full pipeline and it works.

@theophile-scrive
Copy link
Contributor

I'm afraid we'll also have to create variants in scrive-commons, unless we can find a way around our use of Servant's DelayedIO, which doesn't offer any useful instance for us: hackage.haskell.org/package/servant-server-0.17/candidate/docs/Servant-Server-Internal-DelayedIO.html#t:DelayedIO

Anything that I can help with for that particular issue?

Copy link
Collaborator

@arybczak arybczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks 👍

Also needs a version bump to 0.13.0.0 and a changelog entry.

runLogT component logger maxLogLevel m = runReaderT
(unLogT $ liftedCatch m (\(SomeException e) -> do
logAttention "Uncaught exception" $ object ["error" .= show e]
E.throw e)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
E.throw e)
liftBase $ E.throwIO e)

@arybczak
Copy link
Collaborator

Anything that I can help with for that particular issue?

@theophile-scrive You can add MonadCatch and MonadMask instances for DelayedIO when you have a moment.

@arybczak
Copy link
Collaborator

Please don't merge yet, I'm wondering about this comment.

Rather than patching runLogT directly, add a composable utility
Copy link
Collaborator

@arybczak arybczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix missing dots at the end of sentences.

cabal-version: 3.0
name: log-base
version: 0.12.0.1
version: 0.13.0.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be 0.12.1.0 now since we're not changing runLogT.

@@ -1,3 +1,6 @@
# log-base-0.13.0.0 (2025-06-23)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# log-base-0.13.0.0 (2025-06-23)
# log-base-0.12.1.0 (2025-??-??)

I'll set the date when a release is made.

, runLogT
, mapLogT
, logMessageIO
, logExceptions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put it after runLogT on the list so it matches place in the code.

} -- 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure

http-client,
http-types,
log-base >= 0.10 && <0.13,
log-base >= 0.10 && <0.14,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need this now (same below).

@Raveline Raveline force-pushed the log-unhandled-exception-and-user-abort branch from 00ae1a2 to c8f1072 Compare June 24, 2025 12:39
@Raveline
Copy link
Contributor Author

Applied your suggestions and added the missing dots.

Copy link
Collaborator

@arybczak arybczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you 👍

@arybczak arybczak merged commit 36318d6 into master Jun 26, 2025
8 checks passed
@arybczak arybczak deleted the log-unhandled-exception-and-user-abort branch June 26, 2025 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants