fb-util-0.1.0.1: Control/Trace/VLog.hs
{-
Copyright (c) Meta Platforms, Inc. and affiliates.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree.
-}
{-# LANGUAGE ViewPatterns, CPP #-}
module Control.Trace.VLog (
vlogTracer,
TraceWithPriority (..),
vlogTracerWithPriority,
vlogShowTracer,
vlogTextTracer,
) where
import Control.Monad (when)
import Control.Monad.Catch (
ExitCase (
ExitCaseAbort,
ExitCaseException,
ExitCaseSuccess
),
)
import Control.Monad.IO.Class
import Control.Trace.Core
import Data.Some
import Data.Text (Text)
import GHC.Stack
import TextShow (
TextShow,
showt,
)
import qualified Util.Log.String as String
import Util.Log.Text
vlogShowTracer :: TextShow a => (a -> Int) -> Tracer a
vlogShowTracer =
vlogTracer
(\(showt -> x) -> ("BEGIN " <> x, \e -> "END" <> renderExitCase e <> x))
showt
renderExitCase :: Some ExitCase -> Text
renderExitCase (Some ExitCaseAbort {}) = "(aborted) "
renderExitCase (Some (ExitCaseException e)) = "(" <> showt e <> ") "
renderExitCase (Some ExitCaseSuccess {}) = " "
vlogTextTracer :: Int -> Tracer Text
vlogTextTracer p =
vlogTracer
(\x -> ("BEGIN " <> x, \e -> "END" <> renderExitCase e <> x))
id
(const p)
data TraceWithPriority
= Skip
| T !Int !Text
| S !Int !String
vlogTracerWithPriority :: Tracer TraceWithPriority
vlogTracerWithPriority = Tracer {..}
where
logMsg_ :: (HasCallStack, MonadIO m) => TraceWithPriority -> m ()
logMsg_ Skip = pure ()
logMsg_ x = withFrozenCallStack $ case x of
T p t -> vlog p t
S p s -> String.vlog p s
#if __GLASGOW_HASKELL__ < 902
Skip -> error "unreachable"
#endif
traceMsg_ msg =
case msg of
T p t -> do
vlog p ("BEGIN " <> t)
return ( \res -> case res of
ExitCaseSuccess {} -> vlog p ("END " <> t)
ExitCaseAbort {} -> vlog p ("ABORTED " <> t)
ExitCaseException e -> vlog p ("FAILED " <> t <> ": " <> showt e)
)
S p t -> do
String.vlog p ("BEGIN " <> t)
return ( \res -> case res of
ExitCaseSuccess {} -> String.vlog p ("END " <> t)
ExitCaseAbort {} -> String.vlog p ("ABORTED " <> t)
ExitCaseException e ->
String.vlog p ("FAILED " <> t <> ": " <> show e)
)
Skip -> return $ const $ return ()
vlogTracer ::
forall a.
-- | render BEGIN and END messages
(a -> (Text, Some ExitCase -> Text)) ->
-- | render LOG message
(a -> Text) ->
-- | Priority (use -1 to skip)
(a -> Int) ->
Tracer a
vlogTracer beginend log_ prio = Tracer {..}
where
logMsg_ :: a -> IO ()
logMsg_ msg =
let p = prio msg
in when (p >= 0) $ vlog p $ log_ msg
traceMsg_ :: a -> IO (ExitCase b -> IO ())
traceMsg_ msg = do
let p = prio msg
(b, e) = beginend msg
if p >= 0
then vlog p b >> return (\res -> vlog p (e $ mkSome res))
else return $ const $ return ()