This seems like a type of architecture / best practice question than anything specific to Haskell if I don't understand something.
It looks like your application should use a logging system such as hslogger . The general approach is for each component of your code to create log messages with attached priority. Then you can use the application with different priority levels, so that, for example, critical errors can be displayed on the console, while debugging and information level errors go to the log files.
It is sometimes useful to use Debug.Trace.traceEvent and Debug.Trace.traceEventIO instead of a logging system, especially if you suspect a concurrency problem, since the ghc event log also logs information about the collection / switching of flows and garbage collection. But overall, this is not a substitute for the actual logging structure.
In addition, you can use assert as a sanity check so that "impossible" conditions do not arise.
John l
source share