base-4.8.0.0: Debug/Trace.hs
{-# LANGUAGE Unsafe #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE UnboxedTuples #-}
-----------------------------------------------------------------------------
-- |
-- Module : Debug.Trace
-- Copyright : (c) The University of Glasgow 2001
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : provisional
-- Portability : portable
--
-- Functions for tracing and monitoring execution.
--
-- These can be useful for investigating bugs or performance problems.
-- They should /not/ be used in production code.
--
-----------------------------------------------------------------------------
module Debug.Trace (
-- * Tracing
-- $tracing
trace,
traceId,
traceShow,
traceShowId,
traceStack,
traceIO,
traceM,
traceShowM,
putTraceMsg,
-- * Eventlog tracing
-- $eventlog_tracing
traceEvent,
traceEventIO,
-- * Execution phase markers
-- $markers
traceMarker,
traceMarkerIO,
) where
import System.IO.Unsafe
import Foreign.C.String
import GHC.Base
import qualified GHC.Foreign
import GHC.IO.Encoding
import GHC.Ptr
import GHC.Show
import GHC.Stack
import Data.List
-- $tracing
--
-- The 'trace', 'traceShow' and 'traceIO' functions print messages to an output
-- stream. They are intended for \"printf debugging\", that is: tracing the flow
-- of execution and printing interesting values.
--
-- All these functions evaluate the message completely before printing
-- it; so if the message is not fully defined, none of it will be
-- printed.
--
-- The usual output stream is 'System.IO.stderr'. For Windows GUI applications
-- (that have no stderr) the output is directed to the Windows debug console.
-- Some implementations of these functions may decorate the string that\'s
-- output to indicate that you\'re tracing.
-- | The 'traceIO' function outputs the trace message from the IO monad.
-- This sequences the output with respect to other IO actions.
--
-- @since 4.5.0.0
traceIO :: String -> IO ()
traceIO msg = do
withCString "%s\n" $ \cfmt -> do
-- NB: debugBelch can't deal with null bytes, so filter them
-- out so we don't accidentally truncate the message. See Trac #9395
let (nulls, msg') = partition (=='\0') msg
withCString msg' $ \cmsg ->
debugBelch cfmt cmsg
when (not (null nulls)) $
withCString "WARNING: previous trace message had null bytes" $ \cmsg ->
debugBelch cfmt cmsg
-- don't use debugBelch() directly, because we cannot call varargs functions
-- using the FFI.
foreign import ccall unsafe "HsBase.h debugBelch2"
debugBelch :: CString -> CString -> IO ()
-- |
putTraceMsg :: String -> IO ()
putTraceMsg = traceIO
{-# DEPRECATED putTraceMsg "Use 'Debug.Trace.traceIO'" #-} -- deprecated in 7.4
{-# NOINLINE trace #-}
{-|
The 'trace' function outputs the trace message given as its first argument,
before returning the second argument as its result.
For example, this returns the value of @f x@ but first outputs the message.
> trace ("calling f with x = " ++ show x) (f x)
The 'trace' function should /only/ be used for debugging, or for monitoring
execution. The function is not referentially transparent: its type indicates
that it is a pure function but it has the side effect of outputting the
trace message.
-}
trace :: String -> a -> a
trace string expr = unsafePerformIO $ do
traceIO string
return expr
{-|
Like 'trace' but returns the message instead of a third value.
@since 4.7.0.0
-}
traceId :: String -> String
traceId a = trace a a
{-|
Like 'trace', but uses 'show' on the argument to convert it to a 'String'.
This makes it convenient for printing the values of interesting variables or
expressions inside a function. For example here we print the value of the
variables @x@ and @z@:
> f x y =
> traceShow (x, z) $ result
> where
> z = ...
> ...
-}
traceShow :: (Show a) => a -> b -> b
traceShow = trace . show
{-|
Like 'traceShow' but returns the shown value instead of a third value.
@since 4.7.0.0
-}
traceShowId :: (Show a) => a -> a
traceShowId a = trace (show a) a
{-|
Like 'trace' but returning unit in an arbitrary monad. Allows for convenient
use in do-notation. Note that the application of 'trace' is not an action in the
monad, as 'traceIO' is in the 'IO' monad.
> ... = do
> x <- ...
> traceM $ "x: " ++ show x
> y <- ...
> traceM $ "y: " ++ show y
@since 4.7.0.0
-}
traceM :: (Monad m) => String -> m ()
traceM string = trace string $ return ()
{-|
Like 'traceM', but uses 'show' on the argument to convert it to a 'String'.
> ... = do
> x <- ...
> traceMShow $ x
> y <- ...
> traceMShow $ x + y
@since 4.7.0.0
-}
traceShowM :: (Show a, Monad m) => a -> m ()
traceShowM = traceM . show
-- | like 'trace', but additionally prints a call stack if one is
-- available.
--
-- In the current GHC implementation, the call stack is only
-- availble if the program was compiled with @-prof@; otherwise
-- 'traceStack' behaves exactly like 'trace'. Entries in the call
-- stack correspond to @SCC@ annotations, so it is a good idea to use
-- @-fprof-auto@ or @-fprof-auto-calls@ to add SCC annotations automatically.
--
-- @since 4.5.0.0
traceStack :: String -> a -> a
traceStack str expr = unsafePerformIO $ do
traceIO str
stack <- currentCallStack
when (not (null stack)) $ traceIO (renderStack stack)
return expr
-- $eventlog_tracing
--
-- Eventlog tracing is a performance profiling system. These functions emit
-- extra events into the eventlog. In combination with eventlog profiling
-- tools these functions can be used for monitoring execution and
-- investigating performance problems.
--
-- Currently only GHC provides eventlog profiling, see the GHC user guide for
-- details on how to use it. These function exists for other Haskell
-- implementations but no events are emitted. Note that the string message is
-- always evaluated, whether or not profiling is available or enabled.
{-# NOINLINE traceEvent #-}
-- | The 'traceEvent' function behaves like 'trace' with the difference that
-- the message is emitted to the eventlog, if eventlog profiling is available
-- and enabled at runtime.
--
-- It is suitable for use in pure code. In an IO context use 'traceEventIO'
-- instead.
--
-- Note that when using GHC's SMP runtime, it is possible (but rare) to get
-- duplicate events emitted if two CPUs simultaneously evaluate the same thunk
-- that uses 'traceEvent'.
--
-- @since 4.5.0.0
traceEvent :: String -> a -> a
traceEvent msg expr = unsafeDupablePerformIO $ do
traceEventIO msg
return expr
-- | The 'traceEventIO' function emits a message to the eventlog, if eventlog
-- profiling is available and enabled at runtime.
--
-- Compared to 'traceEvent', 'traceEventIO' sequences the event with respect to
-- other IO actions.
--
-- @since 4.5.0.0
traceEventIO :: String -> IO ()
traceEventIO msg =
GHC.Foreign.withCString utf8 msg $ \(Ptr p) -> IO $ \s ->
case traceEvent# p s of s' -> (# s', () #)
-- $markers
--
-- When looking at a profile for the execution of a program we often want to
-- be able to mark certain points or phases in the execution and see that
-- visually in the profile.
-- For example, a program might have several distinct phases with different
-- performance or resource behaviour in each phase. To properly interpret the
-- profile graph we really want to see when each phase starts and ends.
--
-- Markers let us do this: we can annotate the program to emit a marker at
-- an appropriate point during execution and then see that in a profile.
--
-- Currently this feature is only supported in GHC by the eventlog tracing
-- system, but in future it may also be supported by the heap profiling or
-- other profiling tools. These function exists for other Haskell
-- implementations but they have no effect. Note that the string message is
-- always evaluated, whether or not profiling is available or enabled.
{-# NOINLINE traceMarker #-}
-- | The 'traceMarker' function emits a marker to the eventlog, if eventlog
-- profiling is available and enabled at runtime. The @String@ is the name of
-- the marker. The name is just used in the profiling tools to help you keep
-- clear which marker is which.
--
-- This function is suitable for use in pure code. In an IO context use
-- 'traceMarkerIO' instead.
--
-- Note that when using GHC's SMP runtime, it is possible (but rare) to get
-- duplicate events emitted if two CPUs simultaneously evaluate the same thunk
-- that uses 'traceMarker'.
--
-- @since 4.7.0.0
traceMarker :: String -> a -> a
traceMarker msg expr = unsafeDupablePerformIO $ do
traceMarkerIO msg
return expr
-- | The 'traceMarkerIO' function emits a marker to the eventlog, if eventlog
-- profiling is available and enabled at runtime.
--
-- Compared to 'traceMarker', 'traceMarkerIO' sequences the event with respect to
-- other IO actions.
--
-- @since 4.7.0.0
traceMarkerIO :: String -> IO ()
traceMarkerIO msg =
GHC.Foreign.withCString utf8 msg $ \(Ptr p) -> IO $ \s ->
case traceMarker# p s of s' -> (# s', () #)