{-# LANGUAGE CPP #-} -- | Profiling utilities -- -- Function 'markEvent' is normally just an alias for 'traceEventIO'. However, -- when grapey is compiled with the @strace@ flag enabled, 'markEvent' also -- writes the string to /dev/null using a posix @write@ call. This will show -- up in the output of @strace@, thereby making it possible to relate strace -- events to user events. module KVStore.Util.Profiling ( markEvent , markNonStreaming ) where import Debug.Trace (traceEventIO) import Control.Exception (bracket_) import Network.GRPC.Common.StreamType import Network.GRPC.Common import Network.GRPC.Server.StreamType (ServerHandler') import Network.GRPC.Server.StreamType qualified as Server #ifdef STRACE import Control.Monad import System.IO.Unsafe (unsafePerformIO) import System.Posix #endif {------------------------------------------------------------------------------- markEvent -------------------------------------------------------------------------------} #ifdef STRACE devNull :: Fd {-# NOINLINE devNull #-} devNull = unsafePerformIO $ do #if MIN_VERSION_unix(2,8,0) openFd "/dev/null" WriteOnly defaultFileFlags #else openFd "/dev/null" WriteOnly Nothing defaultFileFlags #endif markEvent :: String -> IO () markEvent str' = do -- We also write to /dev/null; the benefit of doing this is that this will -- show up in the strace output, allowing us to relate events to syscalls. _bytesWritten <- fdWrite devNull str when (fromIntegral _bytesWritten /= length str) $ error "markEvent: fdWrite failed to write complete string" traceEventIO str where str = str' ++ "\n" #else markEvent :: String -> IO () markEvent = traceEventIO #endif {------------------------------------------------------------------------------- Derived -------------------------------------------------------------------------------} markNonStreaming :: SupportsStreamingType rpc NonStreaming => String -> (Input rpc -> IO (Output rpc)) -> ServerHandler' NonStreaming IO rpc markNonStreaming label handler = Server.mkNonStreaming $ \inp -> bracket_ (markEvent $ "HANDLER start " ++ label) (markEvent $ "HANDLER stop " ++ label) (handler inp)