git.iko.soy/distributed-process
on master help sign in
remove support for disabling tracing (since we now fire events anyway)
commit28beaa269c8d8e1abb118b6c3653576b14bc9479 authorTim Watson <watson.timothy@gmail.com> dateFri 30 Aug 2013, 21:24 (13 years ago) parente2d0cf7
7 files changed+57−95
src/Control/Distributed/Process/Debug.hs+25−29 src/Control/Distributed/Process/Internal/Trace/Primitives.hs+2−17 src/Control/Distributed/Process/Internal/Trace/Tracer.hs+2−2 src/Control/Distributed/Process/Internal/Types.hs+8−9 src/Control/Distributed/Process/Management/Agent.hs+17−23 src/Control/Distributed/Process/Node.hs+1−1 tests/TestTracing.hs+2−14
src/Control/Distributed/Process/Debug.hs+25−29
@@ -17,16 +17,14 @@
1717--
1818-- [Enabling Tracing]
1919--
20−-- Tracing is disabled by default, because it carries a relatively small, but
21−-- tangible cost. To enable tracing, the environment variable
22−-- @DISTRIBUTED_PROCESS_TRACE_ENABLED@ must be set to some value (actual content
23−-- is ignored). When the environment variable /is/ set, the system will
24−-- generate /trace events/ in various circumstances - see 'TraceEvent' for a
25−-- list of all the published events. A user can additionally publish custom
26−-- trace events in the form of 'TraceEvLog' log messages or pass custom
27−-- (i.e., completely user defined) event data using the 'traceMessage' function.
28−-- If the environment variable is not set, no trace events will ever be
29−-- published.
20+-- Throughout the lifecycle of a local node, the distributed-process runtime
21+-- generates /trace events/, describing internal runtime activities such as
22+-- the spawning and death of processes, message sending, delivery and so on.
23+-- See the 'TraceEvent' type's documentation for a list of all the published
24+-- event types.
25+-- Users can additionally publish custom trace events in the form of
26+-- 'TraceEvLog' log messages or pass custom (i.e., completely user defined)
27+-- event data using the 'traceMessage' function.
3028--
3129-- All published traces are forwarded to a /tracer process/, which can be
3230-- specified (and changed) at runtime using 'traceEnable'. Some pre-defined
@@ -37,15 +35,15 @@
3735--
3836-- [Working with multiple tracer processes]
3937--
40−-- The system tracing facility only ever writes to a single tracer process. This
38+-- The tracing facility only ever writes to a single tracer process. This
4139-- invariant insulates the tracer controller and ensures a fast path for
4240-- handling all trace events. /This/ module provides facilities for layering
4341-- trace handlers using Cloud Haskell's built-in delegation primitives.
4442--
4543-- The 'startTracer' function wraps the registered @tracer@ process with the
46−-- supplied handler and also forwarding trace events to the original tracer.
44+-- supplied handler and also forwards trace events to the original tracer.
4745-- The corresponding 'stopTracer' function terminates tracer processes in
48−-- reverse of the order in which they were started, and re-establishes the
46+-- reverse of the order in which they were started, and re-registers the
4947-- previous tracer process.
5048--
5149-- [Built in tracers]
@@ -53,22 +51,21 @@
5351-- The built in tracers provide a simple /logging/ facility that writes trace
5452-- events out to either a log file, @stderr@ or the GHC eventlog. These tracers
5553-- can be configured using environment variables, or specified manually using
56−-- the 'traceEnable' function. The base tracer process cannot be
54+-- the 'traceEnable' function.
5755--
5856-- When a new local node is started, the contents of several environment
59−-- variables are checked to determine how the default tracer process
60−-- will handle trace events. If none of these variables is set, then the
61−-- trace events will be effectively ignored, although they will still be
62−-- generated and passed through the system. Only one configuration will be
63−-- chosen - the first that contains a (valid) value. These environment
64−-- variables, in the order they're checked, are:
57+-- variables are checked to determine which default tracer process is selected.
58+-- If none of these variables is set, a no-op tracer process is installed,
59+-- which effectively ignores all trace messages. Note that in this case,
60+-- trace events are still generated and passed through the system.
61+-- Only one default tracer will be chosen - the first that contains a (valid)
62+-- value. These environment variables, in the order they're examined, are:
6563--
6664-- 1. @DISTRIBUTED_PROCESS_TRACE_FILE@
6765-- This is checked for a valid file path. If it exists and the file can be
6866-- opened for writing, all trace output will be directed thence. If the supplied
69−-- path is invalid, or the file is unavailable for writing - e.g., because
70−-- another node has already started tracing to it - then this tracer will be
71−-- disabled.
67+-- path is invalid, or the file is unavailable for writing, this tracer will not
68+-- be selected.
7269--
7370-- 2. @DISTRIBUTED_PROCESS_TRACE_CONSOLE@
7471-- This is checked for /any/ non-empty value. If set, then all trace output will
@@ -81,8 +78,10 @@
8178-- Users of the /simplelocalnet/ Cloud Haskell backend should also note that
8279-- because the trace file option only supports trace output from a single node
8380-- (so as to avoid interleaving), a file trace configured for the master node
84−-- will prevent slaves from tracing to the file and will need to fall back to
85−-- the console or eventlog tracers instead.
81+-- will prevent slaves from tracing to the file. They will need to fall back to
82+-- the console or eventlog tracers instead, which can be accomplished by setting
83+-- one of these environment variables /as well/, since the latter will only be
84+-- selected on slaves (when the file tracer selection fails).
8685--
8786-- Support for writing to the eventlog requires specific intervention to work,
8887-- without which, written traces are silently dropped/ignored and no output will
@@ -97,7 +96,6 @@ module Control.Distributed.Process.Debug
9796 , TraceFlags(..)
9897 , TraceSubject(..)
9998 -- * Configuring Tracing
100− , isTracingEnabled
10199 , enableTrace
102100 , enableTraceAsync
103101 , disableTrace
@@ -167,7 +165,6 @@ import Control.Distributed.Process.Internal.Trace.Primitives
167165 , setTraceFlags
168166 , setTraceFlagsAsync
169167 , getTraceFlags
170− , isTracingEnabled
171168 , traceOn
172169 , traceOff
173170 , traceOnly
@@ -264,8 +261,7 @@ traceProxy pid act = do
264261-- supplied tracers (i.e., processes started via 'startTracer') have exited,
265262-- subsequent calls to this function will have no effect.
266263--
267−-- If tracing support is disabled for the node, this function will also
268−-- have no effect. If the last tracer to have been registered was not started
264+-- If the last tracer to have been registered was not started
269265-- with 'startTracer' then the behaviour of this function is /undefined/.
270266stopTracer :: Process ()
271267stopTracer =
src/Control/Distributed/Process/Internal/Trace/Primitives.hs+2−17
@@ -13,7 +13,6 @@ module Control.Distributed.Process.Internal.Trace.Primitives
1313 , traceLogFmt
1414 , traceMessage
1515 -- * Configuring A Tracer
16− , isTracingEnabled
1716 , defaultTraceFlags
1817 , enableTrace
1918 , enableTraceAsync
@@ -99,14 +98,6 @@ traceOn = Just TraceAll
9998traceOff :: Maybe TraceSubject
10099traceOff = Nothing
101100
102−-- | Determine whether or not tracing has been enabled.
103−isTracingEnabled :: Process Bool
104−isTracingEnabled = do
105− processNode <$> ask >>= return . isActive . tracer . localEventBus
106− where
107− isActive InactiveTracer = False
108− isActive (ActiveTracer _ _) = True
109−
110101-- | Enable tracing to the supplied process.
111102enableTraceAsync :: ProcessId -> Process ()
112103enableTraceAsync pid = withLocalTracer $ \t -> liftIO $ Tracer.enableTrace t pid
@@ -169,20 +160,14 @@ withLocalTracer act = do
169160withLocalTracerSync :: (MxEventBus -> SendPort TraceOk -> IO ()) -> Process ()
170161withLocalTracerSync act = do
171162 (sp, rp) <- newChan
172− withLocalTracer $ \t -> do
173− case (tracer t) of
174− InactiveTracer -> error "TraceDisabled"
175− _ -> liftIO $ (act t sp)
163+ withLocalTracer $ \t -> liftIO $ (act t sp)
176164 TraceOk <- receiveChan rp
177165 return ()
178166
179167withRegisteredTracer :: (ProcessId -> Process a) -> Process a
180168withRegisteredTracer act = do
181169 (sp, rp) <- newChan
182− withLocalTracer $ \t -> do
183− case (tracer t) of
184− InactiveTracer -> error "TraceDisabled"
185− _ -> liftIO $ Tracer.getCurrentTraceClient t sp
170+ withLocalTracer $ \t -> liftIO $ Tracer.getCurrentTraceClient t sp
186171 currentTracer <- receiveChan rp
187172 case currentTracer of
188173 Nothing -> do { (Just p') <- whereis "tracer.initial"; act p' }
src/Control/Distributed/Process/Internal/Trace/Tracer.hs+2−2
@@ -191,8 +191,8 @@ logfileTracer p = do
191191
192192traceController :: MVar ((Weak (CQueue Message))) -> Process ()
193193traceController mv = do
194− -- This breach of encapsulation is deliberate: we don't want to tie up
195− -- the node's internal control channel if we can possibly help it!
194+ -- See the documentation for mxAgentController for a
195+ -- commentary that explains this breach of encapsulation
196196 weakQueue <- processWeakQ <$> ask
197197 liftIO $ putMVar mv weakQueue
198198 initState <- initialState
src/Control/Distributed/Process/Internal/Types.hs+8−9
@@ -199,15 +199,14 @@ nullProcessId nid =
199199-- Local nodes and processes --
200200--------------------------------------------------------------------------------
201201
202−data Tracer =
203− InactiveTracer
204− | ActiveTracer
205− {
206− tracerPid :: !ProcessId
207− , weakQ :: !(Weak (CQueue Message))
208− }
209−
210−-- | Required for the system management and tracing facilities
202+-- | Provides access to the trace controller.
203+data Tracer = Tracer
204+ {
205+ tracerPid :: !ProcessId
206+ , weakQ :: !(Weak (CQueue Message))
207+ }
208+
209+-- | Required for the system management and tracing facilities.
211210data MxEventBus =
212211 MxEventBusInitialising
213212 | MxEventBus
src/Control/Distributed/Process/Management/Agent.hs+17−23
@@ -66,16 +66,17 @@ type AgentConfig =
6666-- @LocalNode@ would be inelegant. We forward messages directly to the
6767-- trace controller's message queue, just as the @MxEventBus@ that's
6868-- set up on the @LocalNode@ forwards messages directly to us. This
69−-- also optimises the code path for tracing and avoids overloading the
70−-- node controller with additional routing, at the cost of a little
71−-- more complexity for us here.
69+-- optimises the code path for tracing and avoids overloading the node
70+-- node controller's internal control plane with additional routing, at the
71+-- cost of a little more complexity and two cases where we break
72+-- encapsulation.
7273--
7374mxAgentController :: Fork
7475 -> MVar AgentConfig
7576 -> Process ()
7677mxAgentController forkProcess mv = do
7778 node <- processNode <$> ask
78− trc <- liftIO $ startTracing forkProcess node
79+ trc <- liftIO $ startTracing forkProcess
7980 sigbus <- liftIO $ newBroadcastTChanIO
8081 weakQueue <- processWeakQ <$> ask
8182 liftIO $ putMVar mv (trc, weakQueue, mxAgent forkProcess sigbus)
@@ -88,14 +89,15 @@ mxAgentController forkProcess mv = do
8889 -- our mailbox, the dequeue (i.e., matchMessage) can fail and
8990 -- crash this process, which we DO NOT want. Alternatively,
9091 -- we handle IO exceptions here explicitly, since we don't want
91− -- this process to every crash, and the assumption we therefore
92+ -- this process to ever crash, and the assumption we therefore
9293 -- make is thus:
9394 --
94− -- 1. only ThreadKilled can tell this thread to terminate
95+ -- 1. only ThreadKilled can tell this process to terminate
9596 -- 2. all other exceptions are invalid and should be ignored
9697 --
97− -- The outcome of course, is that /bad/ calls to mxNotify will
98− -- be silently ignored.
98+ -- The outcome of course, is that /bad/ calls to mxNotify
99+ -- (e.g., passing unevaluated thunks that will crash when
100+ -- they're eventually forced) are thus silently ignored.
99101 --
100102 matchAny (\msg -> liftIO $ broadcast bus tracer msg)
101103 ] `catches` [Handler (\ThreadKilled -> die "Killed"),
@@ -107,8 +109,7 @@ mxAgentController forkProcess mv = do
107109 atomicBroadcast ch tmQueue msg
108110
109111 tracerQueue :: Tracer -> IO (Maybe (CQueue Message))
110− tracerQueue InactiveTracer = return Nothing
111− tracerQueue (ActiveTracer _ wQ) = deRefWeak wQ
112+ tracerQueue (Tracer _ wQ) = deRefWeak wQ
112113
113114 atomicBroadcast :: TChan Message
114115 -> Maybe (CQueue Message)
@@ -125,17 +126,10 @@ mxAgent fork chan handler = (atomically (dupTChan chan)) >>= fork . run handler
125126 run handler' chan' = do
126127 (liftIO $ atomically $ readTChan chan') >>= handler' >> run handler' chan'
127128
128−startTracing :: Fork -> LocalNode -> IO Tracer
129−startTracing forkProcess node =
130− -- TODO: use tryGetEnv once we drop support for GHC 7.2.x
131− Ex.catch
132− (getEnv "DISTRIBUTED_PROCESS_TRACE_ENABLED" >> startTracing' forkProcess node)
133− (\(_ :: IOError) -> return InactiveTracer)
134− where
135− startTracing' :: Fork -> LocalNode -> IO Tracer
136− startTracing' fork' n = do
137− mv <- newEmptyMVar
138− pid <- fork' $ traceController mv
139− wQ <- liftIO $ takeMVar mv
140− return $ ActiveTracer pid wQ
129+startTracing :: Fork -> IO Tracer
130+startTracing forkProcess = do
131+ mv <- newEmptyMVar
132+ pid <- forkProcess $ traceController mv
133+ wQ <- liftIO $ takeMVar mv
134+ return $ Tracer pid wQ
141135
src/Control/Distributed/Process/Node.hs+1−1
@@ -258,7 +258,7 @@ startDefaultTracer :: LocalNode -> IO ()
258258startDefaultTracer node' = do
259259 let t = localEventBus node'
260260 case t of
261− MxEventBus _ (ActiveTracer pid _) _ _ -> do
261+ MxEventBus _ (Tracer pid _) _ _ -> do
262262 runProcess node' $ register "trace.controller" pid
263263 pid' <- forkProcess node' defaultTracer
264264 enableTrace (localEventBus node') pid'
tests/TestTracing.hs+2−14
@@ -328,11 +328,8 @@ tests node1 = do
328328 -- various tracers will race with one another and
329329 -- we'll get garbage results (or worse, deadlocks)
330330 lock <- liftIO $ newMVar ()
331− enabled <- checkTraceEnabled
332− case enabled of
333− True ->
334− return [
335− testGroup "Tracing" [
331+ return [
332+ testGroup "Tracing" [
336333 testCase "Spawn Tracing"
337334 (delayedAssertion
338335 "expected dead process-info to be ProcessInfoNone"
@@ -366,14 +363,6 @@ tests node1 = do
366363 "expected blah"
367364 node1 True testRemoteTraceRelay lock)
368365 ] ]
369− False ->
370− return []
371−
372−checkTraceEnabled :: IO Bool
373−checkTraceEnabled =
374− Ex.catch (getEnv "DISTRIBUTED_PROCESS_TRACE_ENABLED" >> return True)
375− (\(_ :: IOError) -> return False)
376−
377366
378367mkNode :: String -> IO LocalNode
379368mkNode port = do
@@ -383,7 +372,6 @@ mkNode port = do
383372
384373main :: IO ()
385374main = do
386− setEnv "DISTRIBUTED_PROCESS_TRACE_ENABLED" "true" True
387375 node1 <- mkNode "8081"
388376 testData <- tests node1
389377 defaultMain testData