Data.Tracer.ThreadSafe
MVar-based thread-safe wrapper.
Functions
newThreadSafeTracer
Create a thread-safe tracer by synchronizing access to the underlying tracer.
This ensures that trace calls from multiple threads are serialized, preventing interleaved output when the underlying tracer is not thread-safe.
Parameters:
unsafe- the underlying (potentially unsafe) tracer
Returns: A new thread-safe tracer
Examples
Concurrent Logging
import Control.Concurrent.Async (forConcurrently_)
import Data.Tracer.Contrib
main :: IO ()
main = logTracer Nothing $ \tracer -> do
safeTracer <- newThreadSafeTracer tracer
forConcurrently_ [1..10] $ \i ->
traceWith safeTracer $ "Thread " ++ show i ++ " reporting"
With Timestamps
import Control.Concurrent.Async (forConcurrently_)
import Data.Tracer.Contrib
main :: IO ()
main = logTracer Nothing $ \tracer -> do
-- Apply transformations before making thread-safe
let timestamped = addTimestampsTracer tracer
safeTracer <- newThreadSafeTracer timestamped
forConcurrently_ [1..5] $ \i -> do
traceWith safeTracer $ "Start " ++ show i
threadDelay 1000
traceWith safeTracer $ "End " ++ show i
Notes
- Each call to
newThreadSafeTracercreates a new independent MVar - The synchronization serializes trace calls - high-frequency tracing from many threads may become a bottleneck
- Only the
traceWithcall is synchronized - any work done to produce the message happens before acquiring the lock - For highest performance with many threads, consider batching or async logging