{-# LANGUAGE CPP #-}
module Development.IDE.Monitoring.EKG(monitoring) where

import           Development.IDE.Types.Logger     (Logger)
import           Development.IDE.Types.Monitoring (Monitoring (..))
#ifdef MONITORING_EKG
import           Control.Concurrent               (killThread)
import           Control.Concurrent.Async         (async, waitCatch)
import           Control.Monad                    (forM_)
import           Data.Text                        (pack)
import           Development.IDE.Types.Logger     (logInfo)
import qualified System.Metrics                   as Monitoring
import qualified System.Remote.Monitoring.Wai     as Monitoring

-- | Monitoring using EKG
monitoring :: Logger -> Int -> IO Monitoring
monitoring logger port = do
    store <- Monitoring.newStore
    Monitoring.registerGcMetrics store
    let registerCounter name read = Monitoring.registerCounter name read store
        registerGauge name read = Monitoring.registerGauge name read store
        start = do
            server <- do
                let startServer = Monitoring.forkServerWith store "localhost" port
                -- this can fail if the port is busy, throwing an async exception back to us
                -- to handle that, wrap the server thread in an async
                mb_server <- async startServer >>= waitCatch
                case mb_server of
                    Right s -> do
                        logInfo logger $ pack $
                            "Started monitoring server on port " <> show port
                        return $ Just s
                    Left e -> do
                        logInfo logger $ pack $
                            "Unable to bind monitoring server on port "
                            <> show port <> ":" <> show e
                        return Nothing
            return $ forM_ server $ \s -> do
                logInfo logger "Stopping monitoring server"
                killThread $ Monitoring.serverThreadId s
    return $ Monitoring {..}

#else

monitoring :: Logger -> Int -> IO Monitoring
monitoring :: Logger -> Int -> IO Monitoring
monitoring Logger
_ Int
_ = forall a. Monoid a => a
mempty

#endif