1-- | Simple (internal) system logging/tracing support.
2module Control.Distributed.Process.Internal.Trace
11import Control.Concurrent (forkIO)
12import Control.Concurrent.Chan (writeChan)
13import Control.Concurrent.STM
20import Control.Distributed.Process.Internal.Types
24 , Identifier(ProcessIdentifier)
25 , ProcessSignal(NamedSend)
30import Control.Exception
34 , AsyncException(ThreadKilled)
36import Data.List (intersperse)
37import Data.Time.Clock (getCurrentTime)
38import Data.Time.Format (formatTime)
39import Debug.Trace (traceEventIO)
41import Prelude hiding (catch)
43import System.Environment (getEnv)
53import System.Locale (defaultTimeLocale)
57 | forall a. (Show a) => Trace a
59startTracing :: LocalNode -> IO LocalNode
61 tracer <- defaultTracer node
62 return node { localTracer = tracer }
64defaultTracer :: LocalNode -> IO Tracer
65defaultTracer node = do
66 catch (getEnv "DISTRIBUTED_PROCESS_TRACE_FILE" >>= logfileTracer)
67 (\(_ :: IOError) -> defaultTracerAux node)
69defaultTracerAux :: LocalNode -> IO Tracer
70defaultTracerAux node = do
71 catch (getEnv "DISTRIBUTED_PROCESS_TRACE_CONSOLE" >> procTracer node)
72 (\(_ :: IOError) -> return (EventLogTracer traceEventIO))
73 where procTracer :: LocalNode -> IO Tracer
74 procTracer n = return $ (LocalNodeTracer n)
76logfileTracer :: FilePath -> IO Tracer
79 h <- openFile p AppendMode
80 hSetBuffering h LineBuffering
81 tid <- forkIO $ logger h q `catch` (\(_ :: SomeException) ->
82 hClose h >> return ())
83 return $ LogFileTracer tid q h
84 where logger :: Handle -> TQueue String -> IO ()
85 logger h q' = forever' $ do
86 msg <- atomically $ readTQueue q'
88 hPutStrLn h $ msg ++ (formatTime defaultTimeLocale " - %c" now)
90-- TODO: compatibility layer for GHC/base versions (e.g., where's killThread?)
92stopTracer :: Tracer -> IO () -- overzealous but harmless duplication of hClose
93stopTracer (LogFileTracer tid _ h) = throwTo tid ThreadKilled >> hClose h
94stopTracer _ = return ()
96trace :: Tracer -> String -> IO ()
97trace (LogFileTracer _ q _) msg = atomically $ writeTQueue q msg
98trace (LocalNodeTracer n) msg = sendTraceMsg n msg
99trace (EventLogTracer t) msg = t msg
100trace InactiveTracer _ = return ()
107 trace t $ concat (intersperse d (map toS ls))
108 where toS :: TraceArg -> String
110 toS (Trace a) = show a
112sendTraceMsg :: LocalNode -> String -> IO ()
113sendTraceMsg node string = do
114 now <- getCurrentTime
115 msg <- return $ (formatTime defaultTimeLocale "%c" now, string)
116 emptyPid <- return $ (nullProcessId (localNodeId node))
117 traceMsg <- return $ NCMsg {
118 ctrlMsgSender = ProcessIdentifier (emptyPid)
119 , ctrlMsgSignal = (NamedSend "logger" (createMessage msg))
121 writeChan (localCtrlChan node) traceMsg
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list