tslogger- Thread-safe logging, with additional interleaving fuzz-testing.

Safe HaskellNone




Thread-safe logging with bonus controlled-schedule debugging capabilities.

This module supports logging to memory, serializing messages and deferring the work of actually printing them. Another thread can flush the logged messages at its leisure.

The second capability of this infrastructure is to use the debugging print messages as points at which to gate the execution of the program. That is, each logOn call becomes a place where the program blocks and checks in with a central coordinator, which only allows one thread to unblock at a time. Thus, if there are sufficient debug logging messages in the program, this can enable a form of deterministic replay (and quickcheck-style testing of different interleavings). This becomes most useful when there is a log message before each read and write to shared memory.

Note that this library allows compile-time toggling of debug support. When it is compiled out, it should have no overhead. When it is compiled in, it will be controlled by an environment variable dynamically.


Global variables

dbgLvl :: Int Source #

Debugging flag used by pure code to tell if debugging chatter should be active. This is activated by setting the environment variable DEBUG=1..5.

By convention DEBUG=100 turns on full sequentialization of the program and control over the interleavings in concurrent code, enabling systematic debugging of concurrency problems.

Basic Logger interface

newLogger Source #


:: (Int, Int)

What inclusive range of messages do we accept? Default is typically `(0,dbgLvl)`.

-> [OutDest]

Where do we write debugging messages?

-> WaitMode

Do we wait for workers before proceeding sequentially but randomly (fuzz testing event interleavings)?

-> IO Logger 

Create a new logger, which includes forking a coordinator thread. Takes as argument the number of worker threads participating in the computation.

logStrLn :: Logger -> Int -> String -> IO () Source #

Log a string message at a given verbosity level.

logByteStringLn :: Logger -> Int -> ByteString -> IO () Source #

Log a bytestring message at a given verbosity level.

logTextLn :: Logger -> Int -> Text -> IO () Source #

Log a Text message at a given verbosity level.

detailed interface.

logOn :: Logger -> LogMsg -> IO () Source #

Write a log message from the current thread, IF the level of the message falls into the range accepted by the given Logger, otherwise, the message is ignored.

data Logger Source #

A Logger coordinates a set of threads that print debug logging messages.

Loggers are abstract objects supporting only the operations provided by this module and the non-hidden fields of the Logger data type.

data WaitMode Source #

Several different ways we know to wait for quiescence in the concurrent mutator before proceeding.



A fixed set of threads must check-in each round before proceeding.


  • numThreads :: Int

    How many threads total must check in?

  • downThreads :: IO Int

    Poll how many threads WON'T participate this round. After all *productive* threads have checked in this number must grow to eventually include all other threads.


In this mode, logging calls are non-blocking and return immediately, rather than waiting on a central coordinator. This is what we want if we're simply printing debugging output, not controlling the schedule for stress testing.

data LogMsg Source #

We allow logging in O(1) time in String format. In practice string conversions are not that important, because only *thunks* should be logged; the thread printing the logs should deal with forcing those thunks.





This sort of message is chatter and NOT meant to participate in the scheduler-testing framework. | ByteStrMsg { lvl::Int, bbody::ByteString }


data OutDest Source #

A destination for log messages



Output via GHC's traceEvent runtime events.

OutputTo Handle

Printed human-readable output to a handle.


Accumulate output in memory and flush when appropriate.


msgBody :: LogMsg -> String Source #

Convert just the body of the log message to a string.