@@ -10,24 +10,25 @@
11-- [Tracing/Debugging Facilities]
11-- [Tracing/Debugging Facilities]
13−-- Cloud Haskell provides a general purpose tracing mechanism that allows a
13+-- Cloud Haskell provides a general purpose tracing mechanism, allowing a
14−-- user supplied /tracer process/ to receive messages when certain events
14+-- user supplied /tracer process/ to receive messages when certain classes of
15−-- take place. It's possible to use this facility to debug a running system
15+-- system events occur. It's possible to use this facility to aid in debugging
16−-- and/or generate runtime monitoring data in a variety of formats.
16+-- and/or perform other diagnostic tasks to a program at runtime.
18-- [Enabling Tracing]
18-- [Enabling Tracing]
20−-- Tracing is disabled by default, because it carries a (relatively small, but
20+-- Tracing is disabled by default, because it carries a relatively small, but
21−-- real) cost at runtime. To enable any kind of tracing to work, the environment
21+-- tangible cost. To enable tracing, the environment variable
22−-- variable @DISTRIBUTED_PROCESS_TRACE_ENABLED@ must be set (the contents are
22+-- @DISTRIBUTED_PROCESS_TRACE_ENABLED@ must be set to some value (the contents
23−-- ignored). When the environment variable /is/ set, the system will generate
23+-- are ignored). When the environment variable /is/ set, the system will
24−-- a /trace events/ in various circumstances - see 'TraceEvent' for a list of
24+-- generate /trace events/ in various circumstances - see 'TraceEvent' for a
25−-- all the published events. A user can additionally publish custom trace events
25+-- list of all the published events. A user can additionally publish custom
26−-- in the form of 'TraceEvLog' log messages or pass custom (i.e., completely
26+-- trace events in the form of 'TraceEvLog' log messages or pass custom
27−-- user defined) event data using the 'traceMessage' function. If the
27+-- (i.e., completely user defined) event data using the 'traceMessage' function.
28−-- environment variable is not set, no trace events will ever be published.
28+-- If the environment variable is not set, no trace events will ever be
30−-- All published trace events are forwarded to a /tracer process/, which can be
31+-- All published traces are forwarded to a /tracer process/, which can be
31-- specified (and changed) at runtime using 'traceEnable'. Some pre-defined
32-- specified (and changed) at runtime using 'traceEnable'. Some pre-defined
32-- tracer processes are provided for conveniently printing to stderr, a log file
33-- tracer processes are provided for conveniently printing to stderr, a log file
33-- or the GHC eventlog.
34-- or the GHC eventlog.
@@ -100,16 +101,15 @@ module Control.Distributed.Process.Debug
100 , enableTrace
101 , enableTrace
101 , enableTraceAsync
102 , enableTraceAsync
102 , disableTrace
103 , disableTrace
104 , withTracer
104 , withTracer
105 , withFlags
105 , withFlags
106 , getTraceFlags
106 , getTraceFlags
107 , setTraceFlags
107 , setTraceFlags
108 , setTraceFlagsAsync
108 , setTraceFlagsAsync
109 , defaultTraceFlags
109 , defaultTraceFlags
110− , Tracer.traceOn
110+ , traceOn
111− , Tracer.traceOnly
111+ , traceOnly
112− , Tracer.traceOff
112+ , traceOff
113 -- * Debugging
113 -- * Debugging
114 , startTracer
114 , startTracer
115 , stopTracer
115 , stopTracer
@@ -117,6 +117,10 @@ module Control.Distributed.Process.Debug
117 , traceLog
117 , traceLog
118 , traceLogFmt
118 , traceLogFmt
119 , traceMessage
119 , traceMessage
120+ -- * Working with remote nodes
121+ , Remote.remoteTable
122+ , Remote.startTraceRelay
123+ , Remote.setTraceFlagsRemote
120 -- * Built in tracers
124 -- * Built in tracers
121 , systemLoggerTracer
125 , systemLoggerTracer
122 , logfileTracer
126 , logfileTracer
@@ -129,12 +133,9 @@ import Control.Distributed.Process.Internal.Primitives
130 , finally
134 , finally
134 , whereis
136 , whereis
136 , newChan
138 , newChan
138 , receiveChan
139 , receiveChan
139 , receiveWait
140 , receiveWait
140 , matchIf
141 , matchIf
@@ -143,6 +144,9 @@ import Control.Distributed.Process.Internal.Primitives
143 , monitor
144 , monitor
147+import Control.Distributed.Process.Internal.Spawn
146import Control.Distributed.Process.Internal.Types
150import Control.Distributed.Process.Internal.Types
147 ( Tracer(..)
151 ( Tracer(..)
148 , LocalNode(..)
152 , LocalNode(..)
@@ -151,6 +155,7 @@ import Control.Distributed.Process.Internal.Types
151 , LocalProcess(..)
155 , LocalProcess(..)
152 , SendPort(..)
156 , SendPort(..)
153 , ProcessMonitorNotification(..)
157 , ProcessMonitorNotification(..)
155import Control.Distributed.Process.Internal.Trace.Types
160import Control.Distributed.Process.Internal.Trace.Types
156 ( TraceArg(..)
161 ( TraceArg(..)
@@ -165,22 +170,23 @@ import Control.Distributed.Process.Internal.Trace.Tracer
165 , logfileTracer
170 , logfileTracer
166 , eventLogTracer
171 , eventLogTracer
168−import qualified Control.Distributed.Process.Internal.Trace.Primitives as Tracer
173+import Control.Distributed.Process.Internal.Trace.Primitives
169− ( traceLog
174+ ( withRegisteredTracer
172 , enableTrace
175 , enableTrace
173− , enableTraceSync
176+ , enableTraceAsync
174 , disableTrace
177 , disableTrace
176 , setTraceFlags
178 , setTraceFlags
177− , setTraceFlagsSync
179+ , setTraceFlagsAsync
178 , getTraceFlags
180 , getTraceFlags
179− , getCurrentTraceClient
181+ , isTracingEnabled
180 , traceOn
182 , traceOn
181 , traceOff
183 , traceOff
182 , traceOnly
184 , traceOnly
189+import qualified Control.Distributed.Process.Internal.Trace.Remote as Remote
184import Control.Distributed.Process.Node
190import Control.Distributed.Process.Node
185import Control.Distributed.Process.Serializable
191import Control.Distributed.Process.Serializable
@@ -222,7 +228,6 @@ withTracer :: forall a.
222 -> Process a
228 -> Process a
223 -> Process (Either SomeException a)
229 -> Process (Either SomeException a)
224withTracer handler proc = do
230withTracer handler proc = do
225− say "starting new tracer"
226 previous <- whereis "tracer"
231 previous <- whereis "tracer"
227 tracer <- startTracer handler
232 tracer <- startTracer handler
228 finally (try proc)
233 finally (try proc)
@@ -234,42 +239,36 @@ withTracer handler proc = do
234 Nothing -> return ()
239 Nothing -> return ()
235 Just p -> do
240 Just p -> do
236 ref <- monitor tracer
241 ref <- monitor tracer
237− say "resetting to previous tracer" >> enableTrace p
238− say "stopping tracer"
239 send tracer TraceEvDisable
242 send tracer TraceEvDisable
240− say $ "waiting for EXIT from tracer " ++ (show tracer)
241 receiveWait [
243 receiveWait [
242 matchIf (\(ProcessMonitorNotification ref' _ _) -> ref == ref')
244 matchIf (\(ProcessMonitorNotification ref' _ _) -> ref == ref')
243− (\_ -> say "seen EXIT ok")
245+ (\_ -> return ())
246-- | Evaluate @proc@ with the supplied flags enabled. Any previously set
248-- | Evaluate @proc@ with the supplied flags enabled. Any previously set
247−-- flags are restored immediately afterwards.
249+-- trace flags are restored immediately afterwards.
248withFlags :: forall a.
250withFlags :: forall a.
249 TraceFlags
251 TraceFlags
250 -> Process a
252 -> Process a
251 -> Process (Either SomeException a)
253 -> Process (Either SomeException a)
252withFlags flags proc = do
254withFlags flags proc = do
253− (sp, rp) <- newChan
255+ oldFlags <- getTraceFlags
254− withLocalTracer $ \t -> liftIO $ Tracer.getTraceFlags t sp
255− oldFlags <- receiveChan rp
256 finally (setTraceFlags flags >> try proc)
256 finally (setTraceFlags flags >> try proc)
257− (setTraceFlags oldFlags >> say "exit withFlags")
257+ (setTraceFlags oldFlags)
259traceProxy :: ProcessId -> (TraceEvent -> Process ()) -> Process ()
259traceProxy :: ProcessId -> (TraceEvent -> Process ()) -> Process ()
260traceProxy pid act = do
260traceProxy pid act = do
261− say "tracing has started"
262 proxy pid $ \(ev :: TraceEvent) ->
261 proxy pid $ \(ev :: TraceEvent) ->
263 case ev of
262 case ev of
264− (TraceEvTakeover p) -> say ((show p) ++ " has taken over...") >> return False
263+ (TraceEvTakeover p) -> return False
265− TraceEvDisable -> say "dying - disabled..." >> die "disabled"
264+ TraceEvDisable -> die "disabled"
266− _ -> say ("act on " ++ (show ev)) >> act ev >> return True
265+ _ -> act ev >> return True
268-- | Stops a user supplied tracer started with 'startTracer'.
267-- | Stops a user supplied tracer started with 'startTracer'.
269-- Note that only one tracer process can be active at any given time.
268-- Note that only one tracer process can be active at any given time.
270-- This process will stop the last process started with 'startTracer'.
269-- This process will stop the last process started with 'startTracer'.
271-- If 'startTracer' is called multiple times, successive calls to this
270-- If 'startTracer' is called multiple times, successive calls to this
272−-- function will stop the tracers in the reverse order in which they were
271+-- function will stop the tracers in the reverse order which they were
273-- started.
272-- started.
275-- This function will never stop the system tracer (i.e., the tracer
274-- This function will never stop the system tracer (i.e., the tracer
@@ -278,10 +277,8 @@ traceProxy pid act = do
278-- subsequent calls to this function will have no effect.
277-- subsequent calls to this function will have no effect.
280-- If tracing support is disabled for the node, this function will also
279-- If tracing support is disabled for the node, this function will also
281−-- have no effect. If the last tracer to have been registered (or the process
280+-- have no effect. If the last tracer to have been registered was not started
282−-- registered with the label @"tracer"@ at the time the stop instruction
283−-- is received) was not started with 'startTracer' then the behaviour of
281+-- with 'startTracer' then the behaviour of this function is /undefined/.
284−-- this function is /undefined/.
285stopTracer :: Process ()
282stopTracer :: Process ()
286stopTracer =
283stopTracer =
287 withRegisteredTracer $ \pid -> do
284 withRegisteredTracer $ \pid -> do
@@ -293,86 +290,3 @@ stopTracer =
293 True -> return ()
290 True -> return ()
294 False -> send pid TraceEvDisable
291 False -> send pid TraceEvDisable
296−withRegisteredTracer :: (ProcessId -> Process a) -> Process a
297−withRegisteredTracer act = do
299− withLocalTracer $ \t -> liftIO $ Tracer.getCurrentTraceClient t sp
300− currentTracer <- receiveChan rp
301− case currentTracer of
302− Nothing -> do { (Just p') <- whereis "tracer.initial"; act p' }
305−-- | Determine whether or not tracing has been enabled.
306−isTracingEnabled :: Process Bool
307−isTracingEnabled = do
308− node <- processNode <$> ask
309− case (localTracer node) of
310− (ActiveTracer _ _) -> return True
313−-- | Enable tracing to the supplied process.
314−enableTraceAsync :: ProcessId -> Process ()
315−enableTraceAsync pid = withLocalTracer $ \t -> liftIO $ Tracer.enableTrace t pid
317−-- TODO: refactor _Sync versions of trace configuration functions...
319−-- | Enable tracing to the supplied process and wait for a @TraceOk@
320−-- response from the trace coordinator process.
321−enableTrace :: ProcessId -> Process ()
323− withLocalTracerSync $ \t sp -> Tracer.enableTraceSync t sp pid
325−-- | Disable the currently configured trace.
326−disableTraceAsync :: Process ()
327−disableTraceAsync = withLocalTracer $ \t -> liftIO $ Tracer.disableTrace t
329−-- | Disable the currently configured trace and wait for a @TraceOk@
330−-- response from the trace coordinator process.
331−disableTrace :: Process ()
333− withLocalTracerSync $ \t sp -> Tracer.disableTraceSync t sp
335−getTraceFlags :: Process TraceFlags
338− withLocalTracer $ \t -> liftIO $ Tracer.getTraceFlags t sp
341−-- | Set the given flags for the current tracer.
342−setTraceFlagsAsync :: TraceFlags -> Process ()
343−setTraceFlagsAsync f = withLocalTracer $ \t -> liftIO $ Tracer.setTraceFlags t f
345−-- | Set the given flags for the current tracer and wait for a @TraceOk@
346−-- response from the trace coordinator process.
347−setTraceFlags :: TraceFlags -> Process ()
349− withLocalTracerSync $ \t sp -> Tracer.setTraceFlagsSync t sp f
351−withLocalTracerSync :: (Tracer -> SendPort TraceOk -> IO ()) -> Process ()
352−withLocalTracerSync act = do
354− withLocalTracer $ \t -> liftIO $ (act t sp)
355− TraceOk <- receiveChan rp
358−-- | Send a log message to the internal tracing facility. If tracing is
359−-- enabled, this will create a custom trace log event.
361−traceLog :: String -> Process ()
362−traceLog s = withLocalTracer $ \t -> liftIO $ Tracer.traceLog t s
364−-- | Send a log message to the internal tracing facility, using the given
365−-- list of printable 'TraceArg's interspersed with the preceding delimiter.
367−traceLogFmt :: String -> [TraceArg] -> Process ()
368−traceLogFmt d ls = withLocalTracer $ \t -> liftIO $ Tracer.traceLogFmt t d ls
370−-- | Send an arbitrary 'Message' to the tracer process.
371−traceMessage :: Serializable m => m -> Process ()
372−traceMessage msg = withLocalTracer $ \t -> liftIO $ Tracer.traceMessage t msg
374−withLocalTracer :: (Tracer -> Process ()) -> Process ()
375−withLocalTracer act = do
376− node <- processNode <$> ask
377− act (localTracer node)