\subsection{Cardano.BM.Setup}
\label{code:Cardano.BM.Setup}

\begin{figure}[ht]
\centering{
  \includegraphics[scale=0.54]{SetupProcedure.pdf}
}
\caption{Setup procedure}
\end{figure}

%if style == newcode
\begin{code}

module Cardano.BM.Setup
    (
      setupTrace
    , setupTrace_
    , shutdown
    , withTrace
    ) where

import           Control.Exception.Safe (MonadMask, bracket)
import           Control.Monad.IO.Class (MonadIO, liftIO)
import           Data.Aeson (FromJSON, ToJSON)
import           Data.Text (Text)
import qualified Cardano.BM.Configuration as Config
import           Cardano.BM.Data.Tracer (ToObject)
import qualified Cardano.BM.Backend.Switchboard as Switchboard
import           Cardano.BM.Trace (Trace, appendName, natTrace)

\end{code}
%endif

\subsubsection{setupTrace}\label{code:setupTrace}\index{setupTrace}
Setup a new |Trace| with either a given |Configuration|
or a |FilePath| to a configuration file. After all tracing operations have ended;
|shutdownTrace| must be called.
\begin{code}

setupTrace :: (MonadIO m, ToJSON a, FromJSON a, ToObject a) => Either FilePath Config.Configuration -> Text -> m (Trace m a)
setupTrace :: Either FilePath Configuration -> Text -> m (Trace m a)
setupTrace (Left FilePath
cfgFile) Text
name = do
    Configuration
c <- IO Configuration -> m Configuration
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Configuration -> m Configuration)
-> IO Configuration -> m Configuration
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Configuration
Config.setup FilePath
cfgFile
    (Trace m a, Switchboard a) -> Trace m a
forall a b. (a, b) -> a
fst ((Trace m a, Switchboard a) -> Trace m a)
-> m (Trace m a, Switchboard a) -> m (Trace m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Configuration -> Text -> m (Trace m a, Switchboard a)
forall (m :: * -> *) a.
(MonadIO m, ToJSON a, FromJSON a, ToObject a) =>
Configuration -> Text -> m (Trace m a, Switchboard a)
setupTrace_ Configuration
c Text
name
setupTrace (Right Configuration
c) Text
name = (Trace m a, Switchboard a) -> Trace m a
forall a b. (a, b) -> a
fst ((Trace m a, Switchboard a) -> Trace m a)
-> m (Trace m a, Switchboard a) -> m (Trace m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Configuration -> Text -> m (Trace m a, Switchboard a)
forall (m :: * -> *) a.
(MonadIO m, ToJSON a, FromJSON a, ToObject a) =>
Configuration -> Text -> m (Trace m a, Switchboard a)
setupTrace_ Configuration
c Text
name

setupTrace_ :: (MonadIO m, ToJSON a, FromJSON a, ToObject a) => Config.Configuration -> Text -> m (Trace m a, Switchboard.Switchboard a)
setupTrace_ :: Configuration -> Text -> m (Trace m a, Switchboard a)
setupTrace_ Configuration
c Text
name = do
    Switchboard a
sb <- IO (Switchboard a) -> m (Switchboard a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Switchboard a) -> m (Switchboard a))
-> IO (Switchboard a) -> m (Switchboard a)
forall a b. (a -> b) -> a -> b
$ Configuration -> IO (Switchboard a)
forall (t :: * -> *) a. IsBackend t a => Configuration -> IO (t a)
Switchboard.realize Configuration
c

    let tr :: Trace m a
tr = Text -> Trace m a -> Trace m a
forall (m :: * -> *) a. Text -> Trace m a -> Trace m a
appendName Text
name (Trace m a -> Trace m a) -> Trace m a -> Trace m a
forall a b. (a -> b) -> a -> b
$ (forall x. IO x -> m x)
-> Tracer IO (Text, LogObject a) -> Trace m a
forall (m :: * -> *) (n :: * -> *) a.
(forall x. m x -> n x)
-> Tracer m (Text, LogObject a) -> Tracer n (Text, LogObject a)
natTrace forall x. IO x -> m x
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Configuration -> Switchboard a -> Tracer IO (Text, LogObject a)
forall (eff :: * -> *) a.
IsEffectuator eff a =>
Configuration -> eff a -> Trace IO a
Switchboard.mainTraceConditionally Configuration
c Switchboard a
sb)
    (Trace m a, Switchboard a) -> m (Trace m a, Switchboard a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Trace m a
tr,Switchboard a
sb)

\end{code}

\subsubsection{shutdown}\label{code:shutdown}\index{shutdown}
Shut down the Switchboard and all the |Trace|s related to it.
\begin{code}
shutdown :: (ToJSON a, FromJSON a, ToObject a) => Switchboard.Switchboard a -> IO ()
shutdown :: Switchboard a -> IO ()
shutdown = Switchboard a -> IO ()
forall (t :: * -> *) a. IsBackend t a => t a -> IO ()
Switchboard.unrealize

\end{code}

\subsubsection{withTrace}\label{code:withTrace}\index{withTrace}
Setup a |Trace| from |Configuration| and pass it to the action. At the end,
shutdown all the components and close the trace.
\begin{code}
withTrace :: (MonadIO m, MonadMask m, ToJSON a, FromJSON a, ToObject a) =>  Config.Configuration -> Text -> (Trace m a -> m t) -> m t
withTrace :: Configuration -> Text -> (Trace m a -> m t) -> m t
withTrace Configuration
cfg Text
name Trace m a -> m t
action =
    m (Trace m a, Switchboard a)
-> ((Trace m a, Switchboard a) -> m ())
-> ((Trace m a, Switchboard a) -> m t)
-> m t
forall (m :: * -> *) a b c.
MonadMask m =>
m a -> (a -> m b) -> (a -> m c) -> m c
bracket
        (Configuration -> Text -> m (Trace m a, Switchboard a)
forall (m :: * -> *) a.
(MonadIO m, ToJSON a, FromJSON a, ToObject a) =>
Configuration -> Text -> m (Trace m a, Switchboard a)
setupTrace_ Configuration
cfg Text
name)              -- aquire
        (\(Trace m a
_,Switchboard a
sb) -> IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Switchboard a -> IO ()
forall a.
(ToJSON a, FromJSON a, ToObject a) =>
Switchboard a -> IO ()
shutdown Switchboard a
sb)   -- release
        (\(Trace m a
tr,Switchboard a
_) -> Trace m a -> m t
action Trace m a
tr)              -- action

\end{code}