@@ -16,9 +16,19 @@ import Control.Concurrent.STM
16 , writeTQueue
16 , writeTQueue
17 , atomically
17 , atomically
19−import Control.Distributed.Process.Internal.Types (forever', Tracer(..))
19+import Control.Distributed.Process.Internal.Types
23+import Control.Exception
20−import Control.Exception (catch, throwTo, AsyncException(ThreadKilled))
27+ , AsyncException(ThreadKilled)
21import Data.List (intersperse)
29import Data.List (intersperse)
30+import Data.Time.Clock (getCurrentTime)
31+import Data.Time.Format (formatTime)
22import Debug.Trace (traceEventIO)
32import Debug.Trace (traceEventIO)
24import Prelude hiding (catch)
34import Prelude hiding (catch)
@@ -27,9 +37,13 @@ import System.Environment (getEnv)
27import System.IO
37import System.IO
29 , IOMode(AppendMode)
39 , IOMode(AppendMode)
30− , withFile
40+ , BufferMode(..)
31− , hPutStr
41+ , openFile
46+import System.Locale (defaultTimeLocale)
34defaultTracer :: IO Tracer
48defaultTracer :: IO Tracer
35defaultTracer = do
49defaultTracer = do
@@ -39,23 +53,26 @@ defaultTracer = do
39logfileTracer :: FilePath -> IO Tracer
53logfileTracer :: FilePath -> IO Tracer
40logfileTracer p = do
54logfileTracer p = do
41 q <- newTQueueIO
55 q <- newTQueueIO
42− tid <- forkIO $ withFile p AppendMode (\h -> logger h q)
56+ h <- openFile p AppendMode
57+ hSetBuffering h LineBuffering
58+ tid <- forkIO $ logger h q `catch` (\(_ :: SomeException) ->
59+ hClose h >> return ())
43− return $ LogFileTracer tid q
60+ return $ LogFileTracer tid q h
44 where logger :: Handle -> TQueue String -> IO ()
61 where logger :: Handle -> TQueue String -> IO ()
45 logger h q' = forever' $ do
62 logger h q' = forever' $ do
46 msg <- atomically $ readTQueue q'
63 msg <- atomically $ readTQueue q'
47− hPutStr h msg
64+ now <- getCurrentTime
48− logger h q'
65+ hPutStrLn h $ msg ++ (formatTime defaultTimeLocale " - %c" now)
50−-- TODO: compatibility layer (conditional compilation?) for GHC/base versions
67+-- TODO: compatibility layer for GHC/base versions (e.g., where's killThread?)
52−stopTracer :: Tracer -> IO ()
69+stopTracer :: Tracer -> IO () -- overzealous but harmless duplication of hClose
53−stopTracer (LogFileTracer tid _) = throwTo tid ThreadKilled -- cf killThread
70+stopTracer (LogFileTracer tid _ h) = throwTo tid ThreadKilled >> hClose h
54−stopTracer _ = return ()
71+stopTracer _ = return ()
56trace :: Tracer -> String -> IO ()
73trace :: Tracer -> String -> IO ()
57−trace (LogFileTracer _ q) msg = atomically $ writeTQueue q msg
74+trace (LogFileTracer _ q _) msg = atomically $ writeTQueue q msg
58−trace (EventLogTracer t) msg = t msg
75+trace (EventLogTracer t) msg = t msg
60traceFormat :: Tracer
77traceFormat :: Tracer