{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE ScopedTypeVariables #-}

#if defined(mingw32_HOST_OS)
#define WINDOWS
#endif
#if defined(linux_HOST_OS)
#define LINUX
#endif
#if defined(darwin_HOST_OS)
#define DARWIN
#endif

module Cardano.RTView.NodeState.Updater
    ( launchNodeStateUpdater
    ) where

import           Cardano.Prelude hiding (modifyMVar_)

import           Cardano.BM.Backend.Switchboard (Switchboard, readLogBuffer)
import           Cardano.BM.Data.Aggregated (Measurable (..))
import           Cardano.BM.Data.Counter (Platform (..))
import           Cardano.BM.Data.LogItem (LOContent (..), LOMeta (..), LogObject (..),
                                          MonitorAction (..), utc2ns)
import           Cardano.BM.Trace (Trace)
import           Control.Concurrent.MVar.Strict (MVar, modifyMVar_)
import qualified Data.Aeson as A
import           Data.List ((!!))
import           Data.Map.Strict ((!?))
import qualified Data.Map.Strict as Map
import qualified Data.Text as T
import           Data.Time.Clock (NominalDiffTime, diffUTCTime)
import           GHC.Clock (getMonotonicTimeNSec)

import           Cardano.RTView.ErrorBuffer (ErrorBuffer, readErrorBuffer)
import           Cardano.RTView.NodeState.Parsers (extractPeersInfo)
import           Cardano.RTView.NodeState.Types (NodeError (..), NodeInfo (..),
                                                 NodeMetrics (..), NodeState (..),
                                                 NodesState)

-- | This function is running in a separate thread.
--   It takes |LogObject|s with nodes' metrics from |LogBuffer|,
--   extracts these metrics and updates corresponding values
--   in the |NodesState|.
launchNodeStateUpdater
  :: Trace IO Text
  -> Switchboard Text
  -> ErrorBuffer Text
  -> MVar NodesState
  -> IO ()
launchNodeStateUpdater :: Trace IO Text
-> Switchboard Text -> ErrorBuffer Text -> MVar NodesState -> IO ()
launchNodeStateUpdater Trace IO Text
_tr Switchboard Text
switchBoard ErrorBuffer Text
errBuff MVar NodesState
nsMVar = IO () -> IO ()
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
  -- logDebug tr "Try to update nodes' state..."
  -- Take current |LogObject|s from the |ErrorBuffer|.
  [(Text, LogObject Text)]
currentErrLogObjects <- ErrorBuffer Text -> IO [(Text, LogObject Text)]
forall a. ErrorBuffer a -> IO [(Text, LogObject a)]
readErrorBuffer ErrorBuffer Text
errBuff
  [(Text, LogObject Text)]
-> ((Text, LogObject Text) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(Text, LogObject Text)]
currentErrLogObjects (((Text, LogObject Text) -> IO ()) -> IO ())
-> ((Text, LogObject Text) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Text
loggerName, LogObject Text
errLogObject) ->
    MVar NodesState -> Text -> LogObject Text -> IO ()
updateNodesStateErrors MVar NodesState
nsMVar Text
loggerName LogObject Text
errLogObject
  -- Take current |LogObject|s from the |LogBuffer|.
  [(Text, LogObject Text)]
currentLogObjects <- Switchboard Text -> IO [(Text, LogObject Text)]
forall a. Switchboard a -> IO [(Text, LogObject a)]
readLogBuffer Switchboard Text
switchBoard
  [(Text, LogObject Text)]
-> ((Text, LogObject Text) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(Text, LogObject Text)]
currentLogObjects (((Text, LogObject Text) -> IO ()) -> IO ())
-> ((Text, LogObject Text) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Text
loggerName, LogObject Text
logObject) ->
    MVar NodesState -> Text -> LogObject Text -> IO ()
updateNodesState MVar NodesState
nsMVar Text
loggerName LogObject Text
logObject
  -- Check for updates in the |LogBuffer| every second.
  Int -> IO ()
threadDelay Int
1000000

-- | Update NodeState for particular node based on loggerName.
--   Please note that this function updates only Error-messages (if errors occurred).
updateNodesStateErrors
  :: MVar NodesState
  -> Text
  -> LogObject Text
  -> IO ()
updateNodesStateErrors :: MVar NodesState -> Text -> LogObject Text -> IO ()
updateNodesStateErrors MVar NodesState
nsMVar Text
loggerName (LogObject Text
_ LOMeta
aMeta LOContent Text
aContent) = do
  -- Check the name of the node this logObject came from.
  -- It is assumed that configuration contains correct names of remote nodes and
  -- loggers for them, for example:
  --   1. "a" - name of remote node in getAcceptAt.
  --   2. "cardano-rt-view.acceptor.a" - name of the logger which receives
  --        |LogObject|s from that node.
  -- So currently logger name for metrics has the following format:
  -- #buffered.cardano-rt-view.acceptor.a.NAME_OF_METRICS_GROUP.NAME_OF_METRIC,
  -- where "a" is the node name (from TraceAcceptor).
  let loggerNameParts :: [Text]
loggerNameParts = (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Bool
T.null) ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Text -> [Text]
T.splitOn Text
"." Text
loggerName
      nameOfNode :: Text
nameOfNode = [Text]
loggerNameParts [Text] -> Int -> Text
forall a. [a] -> Int -> a
!! Int
3

  MVar NodesState -> (NodesState -> IO NodesState) -> IO ()
forall a. NFData a => MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar NodesState
nsMVar ((NodesState -> IO NodesState) -> IO ())
-> (NodesState -> IO NodesState) -> IO ()
forall a b. (a -> b) -> a -> b
$ \NodesState
currentNodesState -> do
    let nodesStateWith :: NodeState -> IO NodesState
        nodesStateWith :: NodeState -> IO NodesState
nodesStateWith NodeState
newState = NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return (NodesState -> IO NodesState) -> NodesState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ (NodeState -> NodeState) -> Text -> NodesState -> NodesState
forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
Map.adjust (NodeState -> NodeState -> NodeState
forall a b. a -> b -> a
const NodeState
newState) Text
nameOfNode NodesState
currentNodesState

    case NodesState
currentNodesState NodesState -> Text -> Maybe NodeState
forall k a. Ord k => Map k a -> k -> Maybe a
!? Text
nameOfNode of
      Just NodeState
ns -> NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> LOMeta -> LOContent Text -> NodeState
forall a. Show a => NodeState -> LOMeta -> LOContent a -> NodeState
updateNodeErrors NodeState
ns LOMeta
aMeta LOContent Text
aContent
      Maybe NodeState
Nothing -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState

-- | Update NodeState for particular node based on loggerName.
updateNodesState
  :: MVar NodesState
  -> Text
  -> LogObject Text
  -> IO ()
updateNodesState :: MVar NodesState -> Text -> LogObject Text -> IO ()
updateNodesState MVar NodesState
nsMVar Text
loggerName (LogObject Text
aName LOMeta
aMeta LOContent Text
aContent) = do
  -- Check the name of the node this logObject came from.
  -- It is assumed that configuration contains correct names of remote nodes and
  -- loggers for them, for example:
  --   1. "a" - name of remote node in getAcceptAt.
  --   2. "cardano-rt-view.acceptor.a" - name of the logger which receives
  --        |LogObject|s from that node.
  -- So currently logger name for metrics has the following format:
  -- #buffered.cardano-rt-view.acceptor.a.NAME_OF_METRICS_GROUP.NAME_OF_METRIC,
  -- where "a" is the node name (from TraceAcceptor).
  let loggerNameParts :: [Text]
loggerNameParts = (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Bool
T.null) ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Text -> [Text]
T.splitOn Text
"." Text
loggerName
      nameOfNode :: Text
nameOfNode = [Text]
loggerNameParts [Text] -> Int -> Text
forall a. [a] -> Int -> a
!! Int
3

  Word64
now <- IO Word64
getMonotonicTimeNSec

  MVar NodesState -> (NodesState -> IO NodesState) -> IO ()
forall a. NFData a => MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar NodesState
nsMVar ((NodesState -> IO NodesState) -> IO ())
-> (NodesState -> IO NodesState) -> IO ()
forall a b. (a -> b) -> a -> b
$ \NodesState
currentNodesState -> do
    let nodesStateWith :: NodeState -> IO NodesState
        nodesStateWith :: NodeState -> IO NodesState
nodesStateWith NodeState
newState = NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return (NodesState -> IO NodesState) -> NodesState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ (NodeState -> NodeState) -> Text -> NodesState -> NodesState
forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
Map.adjust (NodeState -> NodeState -> NodeState
forall a b. a -> b -> a
const NodeState
newState) Text
nameOfNode NodesState
currentNodesState

    case NodesState
currentNodesState NodesState -> Text -> Maybe NodeState
forall k a. Ord k => Map k a -> k -> Maybe a
!? Text
nameOfNode of
      Just NodeState
ns ->
        if | Text
"cardano.node.metrics.peersFromNodeKernel" Text -> Text -> Bool
`T.isInfixOf` Text
aName ->
            case LOContent Text
aContent of
              LogStructured Object
peersInfo ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Object -> NodeState
updatePeersInfo NodeState
ns Object
peersInfo
              LOContent Text
_ -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState
           | Text
"cardano.node.metrics" Text -> Text -> Bool
`T.isInfixOf` Text
aName ->
            case LOContent Text
aContent of
              LogValue Text
"upTime" (Nanoseconds Word64
upTimeInNs) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> Word64 -> NodeState
updateNodeUpTime NodeState
ns Word64
upTimeInNs Word64
now
              LogValue Text
"txsInMempool" (PureI Integer
txsInMempool) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> NodeState
updateMempoolTxs NodeState
ns Integer
txsInMempool
              LogValue Text
"mempoolBytes" (PureI Integer
mempoolBytes) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> NodeState
updateMempoolBytes NodeState
ns Integer
mempoolBytes
              LogValue Text
"txsProcessedNum" (PureI Integer
processedTxsNum) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> NodeState
updateTxsProcessed NodeState
ns Integer
processedTxsNum
              LogValue Text
"blocksForgedNum" (PureI Integer
forgedBlocksNum) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateBlocksForged NodeState
ns Integer
forgedBlocksNum Word64
now
              LogValue Text
"nodeCannotForge" (PureI Integer
cannotForge) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> NodeState
updateNodeCannotForge NodeState
ns Integer
cannotForge
              LogValue Text
"nodeIsLeaderNum" (PureI Integer
leaderNum) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateNodeIsLeader NodeState
ns Integer
leaderNum Word64
now
              LogValue Text
"slotsMissedNum" (PureI Integer
missedSlotsNum) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateSlotsMissed NodeState
ns Integer
missedSlotsNum Word64
now
              LOContent Text
_ -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState
           | Text
"cardano.node-metrics" Text -> Text -> Bool
`T.isInfixOf` Text
aName ->
            case LOContent Text
aContent of
#ifdef WINDOWS
              LogValue "Stat.CPUTime" (Microseconds microsecs) ->
                nodesStateWith $ updateCPUSecs ns (microsecs * 1000) aMeta now
#endif
#ifdef DARWIN
              LogValue "Mem.resident_size" (Bytes bytes) ->
                nodesStateWith $ updateMemoryBytes ns bytes now
              LogValue "Sys.CPUTime" (Nanoseconds nanosecs) ->
                nodesStateWith $ updateCPUSecs ns nanosecs aMeta now
              LogValue "Net.ifd_0-ibytes" (Bytes inBytes) ->
                nodesStateWith $ updateNetworkIn ns inBytes aMeta now
              LogValue "Net.ifd_0-obytes" (Bytes outBytes) ->
                nodesStateWith $ updateNetworkOut ns outBytes aMeta now
#endif
#ifdef LINUX
              LogValue Text
"Mem.resident" (PureI Integer
pages) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateMemoryPages NodeState
ns Integer
pages Word64
now
              LogValue Text
"IO.rchar" (Bytes Word64
bytesWereRead) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateDiskRead NodeState
ns Word64
bytesWereRead LOMeta
aMeta Word64
now
              LogValue Text
"IO.wchar" (Bytes Word64
bytesWereWritten) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateDiskWrite NodeState
ns Word64
bytesWereWritten LOMeta
aMeta Word64
now
              LogValue Text
"Stat.cputicks" (PureI Integer
ticks) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> LOMeta -> Word64 -> NodeState
updateCPUTicks NodeState
ns Integer
ticks LOMeta
aMeta Word64
now
              LogValue Text
"Net.IpExt:InOctets" (Bytes Word64
inBytes) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateNetworkIn NodeState
ns Word64
inBytes LOMeta
aMeta Word64
now
              LogValue Text
"Net.IpExt:OutOctets" (Bytes Word64
outBytes) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateNetworkOut NodeState
ns Word64
outBytes LOMeta
aMeta Word64
now
#endif
              LogValue Text
"Sys.Platform" (PureI Integer
pfid) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Int -> NodeState
updateNodePlatform NodeState
ns (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
pfid)
              LogValue Text
"RTS.maxUsedMemBytes" (Bytes Word64
bytesAllocated) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> Word64 -> NodeState
updateRTSBytesAllocated NodeState
ns Word64
bytesAllocated Word64
now
              LogValue Text
"RTS.gcLiveBytes" (Bytes Word64
usedMemBytes) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> Word64 -> NodeState
updateRTSBytesUsed NodeState
ns Word64
usedMemBytes Word64
now
              LogValue Text
"RTS.gcCpuNs" (Nanoseconds Word64
gcCpuNs) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> Word64 -> NodeState
updateGcCpuNs NodeState
ns Word64
gcCpuNs Word64
now
              LogValue Text
"RTS.gcElapsedNs" (Nanoseconds Word64
gcElapsedNs) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Word64 -> Word64 -> NodeState
updateGcElapsedNs NodeState
ns Word64
gcElapsedNs Word64
now
              LogValue Text
"RTS.gcNum" (PureI Integer
gcNum) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateGcNum NodeState
ns Integer
gcNum Word64
now
              LogValue Text
"RTS.gcMajorNum" (PureI Integer
gcMajorNum) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateGcMajorNum NodeState
ns Integer
gcMajorNum Word64
now
              LOContent Text
_ -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState
           | Text
"cardano.node.Forge.metrics" Text -> Text -> Bool
`T.isInfixOf` Text
aName ->
            case LOContent Text
aContent of
              LogValue Text
"operationalCertificateStartKESPeriod" (PureI Integer
oCertStartKesPeriod) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateCertStartKESPeriod NodeState
ns Integer
oCertStartKesPeriod Word64
now
              LogValue Text
"currentKESPeriod" (PureI Integer
currentKesPeriod) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateCurrentKESPeriod NodeState
ns Integer
currentKesPeriod Word64
now
              LogValue Text
"remainingKESPeriods" (PureI Integer
kesPeriodsUntilExpiry) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateRemainingKESPeriods NodeState
ns Integer
kesPeriodsUntilExpiry Word64
now
              LOContent Text
_ -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState
           | Text
"cardano.node.release" Text -> Text -> Bool
`T.isInfixOf` Text
aName ->
            case LOContent Text
aContent of
              LogMessage Text
protocol ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Text -> NodeState
updateNodeProtocol NodeState
ns Text
protocol
              LOContent Text
_ -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState
           | Text
"cardano.node.version" Text -> Text -> Bool
`T.isInfixOf` Text
aName ->
            case LOContent Text
aContent of
              LogMessage Text
version ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Text -> NodeState
updateNodeVersion NodeState
ns Text
version
              LOContent Text
_ -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState
           | Text
"cardano.node.commit" Text -> Text -> Bool
`T.isInfixOf` Text
aName ->
            case LOContent Text
aContent of
              LogMessage Text
commit ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Text -> NodeState
updateNodeCommit NodeState
ns Text
commit
              LOContent Text
_ -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState
           | Bool
otherwise ->
            case LOContent Text
aContent of
              LogValue Text
"density" (PureD Double
density) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Double -> Word64 -> NodeState
updateChainDensity NodeState
ns Double
density Word64
now
              LogValue Text
"blockNum" (PureI Integer
blockNum) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateBlocksNumber NodeState
ns Integer
blockNum Word64
now
              LogValue Text
"slotInEpoch" (PureI Integer
slotNum) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateSlotInEpoch NodeState
ns Integer
slotNum Word64
now
              LogValue Text
"epoch" (PureI Integer
epoch) ->
                NodeState -> IO NodesState
nodesStateWith (NodeState -> IO NodesState) -> NodeState -> IO NodesState
forall a b. (a -> b) -> a -> b
$ NodeState -> Integer -> Word64 -> NodeState
updateEpoch NodeState
ns Integer
epoch Word64
now
              LOContent Text
_ -> NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState
      Maybe NodeState
Nothing ->
        -- This is a problem, because it means that configuration is unexpected one:
        -- name of node in getAcceptAt doesn't correspond to the name of loggerName.
        NodesState -> IO NodesState
forall (m :: * -> *) a. Monad m => a -> m a
return NodesState
currentNodesState

-- Updaters for particular node state's fields.

updateNodeUpTime :: NodeState -> Word64 -> Word64 -> NodeState
updateNodeUpTime :: NodeState -> Word64 -> Word64 -> NodeState
updateNodeUpTime NodeState
ns Word64
upTimeInNs Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niUpTime :: Word64
niUpTime = Word64
upTimeInNs
      , niUpTimeLastUpdate :: Word64
niUpTimeLastUpdate = Word64
now
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateNodeErrors :: Show a => NodeState -> LOMeta -> LOContent a -> NodeState
updateNodeErrors :: NodeState -> LOMeta -> LOContent a -> NodeState
updateNodeErrors NodeState
ns (LOMeta UTCTime
timeStamp Text
_ Text
_ Severity
sev PrivacyAnnotation
_) LOContent a
aContent = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = NodeInfo
currentNi { niNodeErrors :: [NodeError]
niNodeErrors = UTCTime -> Severity -> String -> NodeError
NodeError UTCTime
timeStamp Severity
sev String
errorMessage NodeError -> [NodeError] -> [NodeError]
forall a. a -> [a] -> [a]
: [NodeError]
currentErrors }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns
  currentErrors :: [NodeError]
currentErrors = NodeInfo -> [NodeError]
niNodeErrors NodeInfo
currentNi
  errorMessage :: String
errorMessage =
    case LOContent a
aContent of
      LogMessage a
msg -> a -> String
forall a b. (Show a, ConvertText String b) => a -> b
show a
msg
      LogError Text
eMsg -> Text -> String
T.unpack Text
eMsg
      LogStructured Object
obj -> Object -> String
forall a b. (Show a, ConvertText String b) => a -> b
show Object
obj
      LogStructuredText Object
_ Text
txt -> Text -> String
T.unpack Text
txt
      MonitoringEffect (MonitorAlert Text
msg) -> String
"Monitor alert: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Text -> String
T.unpack Text
msg
      MonitoringEffect MonitorAction
_ -> String
""
      LOContent a
_ -> String
"UNPARSED_ERROR_MESSAGE"

updatePeersInfo :: NodeState -> A.Object -> NodeState
updatePeersInfo :: NodeState -> Object -> NodeState
updatePeersInfo NodeState
ns Object
peersInfo = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = NodeInfo
currentNi { niPeersInfo :: [PeerInfo]
niPeersInfo = [PeerInfo]
newPeersInfo }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns
  newPeersInfo :: [PeerInfo]
newPeersInfo = Object -> [PeerInfo]
extractPeersInfo Object
peersInfo

updateNodeProtocol :: NodeState -> Text -> NodeState
updateNodeProtocol :: NodeState -> Text -> NodeState
updateNodeProtocol NodeState
ns Text
protocol = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = NodeInfo
currentNi { niNodeProtocol :: String
niNodeProtocol = Text -> String
T.unpack Text
protocol }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateNodeVersion :: NodeState -> Text -> NodeState
updateNodeVersion :: NodeState -> Text -> NodeState
updateNodeVersion NodeState
ns Text
version = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = NodeInfo
currentNi { niNodeVersion :: String
niNodeVersion = Text -> String
T.unpack Text
version }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateNodeCommit :: NodeState -> Text -> NodeState
updateNodeCommit :: NodeState -> Text -> NodeState
updateNodeCommit NodeState
ns Text
commit = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niNodeCommit :: String
niNodeCommit      = Text -> String
T.unpack Text
commit
      , niNodeShortCommit :: String
niNodeShortCommit = Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
7 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
commit
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateNodePlatform :: NodeState -> Int -> NodeState
updateNodePlatform :: NodeState -> Int -> NodeState
updateNodePlatform NodeState
ns Int
platfid = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  platform :: Platform
platform = Int -> Platform
forall a. Enum a => Int -> a
toEnum Int
platfid :: Platform
  newNi :: NodeInfo
newNi = NodeInfo
currentNi { niNodePlatform :: String
niNodePlatform = Platform -> String
forall a b. (Show a, ConvertText String b) => a -> b
show Platform
platform }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateMemoryPages :: NodeState -> Integer -> Word64 -> NodeState
updateMemoryPages :: NodeState -> Integer -> Word64 -> NodeState
updateMemoryPages NodeState
ns Integer
pages Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmMemory :: Double
nmMemory         = Double
mBytes
      , nmMemoryMax :: Double
nmMemoryMax      = Double
newMax
      , nmMemoryMaxTotal :: Double
nmMemoryMaxTotal = Double
newMaxTotal
      , nmMemoryPercent :: Double
nmMemoryPercent  = Double
mBytes Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
newMaxTotal Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100.0
      , nmMemoryLastUpdate :: Word64
nmMemoryLastUpdate = Word64
now
      }
  currentNm :: NodeMetrics
currentNm   = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  prevMax :: Double
prevMax     = NodeMetrics -> Double
nmMemoryMax NodeMetrics
currentNm
  newMax :: Double
newMax      = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
prevMax Double
mBytes
  newMaxTotal :: Double
newMaxTotal = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
newMax Double
200.0
  mBytes :: Double
mBytes      = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
pages Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
pageSize) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024 :: Double
  pageSize :: Integer
pageSize    = Integer
4096 :: Integer

#ifdef DARWIN
updateMemoryBytes :: NodeState -> Word64 -> Word64 -> NodeState
updateMemoryBytes ns bytes now = ns { nsMetrics = newNm }
 where
  newNm =
    currentNm
      { nmMemory         = mBytes
      , nmMemoryMax      = newMax
      , nmMemoryMaxTotal = newMaxTotal
      , nmMemoryPercent  = mBytes / newMaxTotal * 100.0
      , nmMemoryLastUpdate = now
      }
  currentNm   = nsMetrics ns
  prevMax     = nmMemoryMax currentNm
  newMax      = max prevMax mBytes
  newMaxTotal = max newMax 200.0
  mBytes      = fromIntegral bytes / 1024 / 1024 :: Double
#endif

updateDiskRead :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateDiskRead :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateDiskRead NodeState
ns Word64
bytesWereRead LOMeta
meta Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmDiskUsageR :: Double
nmDiskUsageR           = Double
currentDiskRate
      , nmDiskUsageRPercent :: Double
nmDiskUsageRPercent    = Double
diskUsageRPercent
      , nmDiskUsageRLast :: Word64
nmDiskUsageRLast       = Word64
bytesWereRead
      , nmDiskUsageRNs :: Word64
nmDiskUsageRNs         = Word64
currentTimeInNs
      , nmDiskUsageRMax :: Double
nmDiskUsageRMax        = Double
maxDiskRate
      , nmDiskUsageRMaxTotal :: Double
nmDiskUsageRMaxTotal   = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
maxDiskRate Double
1.0
      , nmDiskUsageRAdaptTime :: UTCTime
nmDiskUsageRAdaptTime  = UTCTime
newAdaptTime
      , nmDiskUsageRLastUpdate :: Word64
nmDiskUsageRLastUpdate = Word64
now
      }
  currentNm :: NodeMetrics
currentNm         = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  currentTimeInNs :: Word64
currentTimeInNs   = UTCTime -> Word64
utc2ns (LOMeta -> UTCTime
tstamp LOMeta
meta)
  timeDiff :: Double
timeDiff          = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
currentTimeInNs Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmDiskUsageRNs NodeMetrics
currentNm) :: Double
  timeDiffInSecs :: Double
timeDiffInSecs    = Double
timeDiff Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000000000
  bytesDiff :: Double
bytesDiff         = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
bytesWereRead Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmDiskUsageRLast NodeMetrics
currentNm) :: Double
  bytesDiffInKB' :: Double
bytesDiffInKB'    = Double
bytesDiff Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024
  bytesDiffInKB :: Double
bytesDiffInKB     = if Double
bytesDiffInKB' Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
500.0 -- To prevent an overflow if the node was restarted.
                        then Double
1.0
                        else Double
bytesDiffInKB'
  currentDiskRate :: Double
currentDiskRate   = Double
bytesDiffInKB Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
timeDiffInSecs
  lastAdaptTime :: UTCTime
lastAdaptTime     = NodeMetrics -> UTCTime
nmDiskUsageRAdaptTime NodeMetrics
currentNm
  timeElapsed :: NominalDiffTime
timeElapsed       = UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime (LOMeta -> UTCTime
tstamp LOMeta
meta) UTCTime
lastAdaptTime
  ( Double
maxDiskRate
    , UTCTime
newAdaptTime ) =
        if NominalDiffTime
timeElapsed NominalDiffTime -> NominalDiffTime -> Bool
forall a. Ord a => a -> a -> Bool
>= NominalDiffTime
adaptPeriod
          then ((NodeMetrics -> Double
nmDiskUsageRMax NodeMetrics
currentNm Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
currentDiskRate) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2, LOMeta -> UTCTime
tstamp LOMeta
meta)
          else (Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
currentDiskRate (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ NodeMetrics -> Double
nmDiskUsageRMax NodeMetrics
currentNm, UTCTime
lastAdaptTime)
  diskUsageRPercent :: Double
diskUsageRPercent = Double
currentDiskRate Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
maxDiskRate Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100.0)

updateDiskWrite :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateDiskWrite :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateDiskWrite NodeState
ns Word64
bytesWereWritten LOMeta
meta Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmDiskUsageW :: Double
nmDiskUsageW           = Double
currentDiskRate
      , nmDiskUsageWPercent :: Double
nmDiskUsageWPercent    = Double
diskUsageWPercent
      , nmDiskUsageWLast :: Word64
nmDiskUsageWLast       = Word64
bytesWereWritten
      , nmDiskUsageWNs :: Word64
nmDiskUsageWNs         = Word64
currentTimeInNs
      , nmDiskUsageWMax :: Double
nmDiskUsageWMax        = Double
maxDiskRate
      , nmDiskUsageWMaxTotal :: Double
nmDiskUsageWMaxTotal   = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
maxDiskRate Double
1.0
      , nmDiskUsageWAdaptTime :: UTCTime
nmDiskUsageWAdaptTime  = UTCTime
newAdaptTime
      , nmDiskUsageWLastUpdate :: Word64
nmDiskUsageWLastUpdate = Word64
now
      }
  currentNm :: NodeMetrics
currentNm         = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  currentTimeInNs :: Word64
currentTimeInNs   = UTCTime -> Word64
utc2ns (LOMeta -> UTCTime
tstamp LOMeta
meta)
  timeDiff :: Double
timeDiff          = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
currentTimeInNs Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmDiskUsageWNs NodeMetrics
currentNm) :: Double
  timeDiffInSecs :: Double
timeDiffInSecs    = Double
timeDiff Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000000000
  bytesDiff :: Double
bytesDiff         = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
bytesWereWritten Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmDiskUsageWLast NodeMetrics
currentNm) :: Double
  bytesDiffInKB' :: Double
bytesDiffInKB'    = Double
bytesDiff Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024
  bytesDiffInKB :: Double
bytesDiffInKB     = if Double
bytesDiffInKB' Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
500.0 -- To prevent an overflow if the node was restarted.
                        then Double
1.0
                        else Double
bytesDiffInKB'
  currentDiskRate :: Double
currentDiskRate   = Double
bytesDiffInKB Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
timeDiffInSecs
  lastAdaptTime :: UTCTime
lastAdaptTime     = NodeMetrics -> UTCTime
nmDiskUsageWAdaptTime NodeMetrics
currentNm
  timeElapsed :: NominalDiffTime
timeElapsed       = UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime (LOMeta -> UTCTime
tstamp LOMeta
meta) UTCTime
lastAdaptTime
  ( Double
maxDiskRate
    , UTCTime
newAdaptTime ) =
        if NominalDiffTime
timeElapsed NominalDiffTime -> NominalDiffTime -> Bool
forall a. Ord a => a -> a -> Bool
>= NominalDiffTime
adaptPeriod
          then ((NodeMetrics -> Double
nmDiskUsageWMax NodeMetrics
currentNm Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
currentDiskRate) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2, LOMeta -> UTCTime
tstamp LOMeta
meta)
          else (Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
currentDiskRate (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ NodeMetrics -> Double
nmDiskUsageWMax NodeMetrics
currentNm, UTCTime
lastAdaptTime)
  diskUsageWPercent :: Double
diskUsageWPercent = Double
currentDiskRate Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
maxDiskRate Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100.0)

-- | Adaptaion period for disk usage max values.
--   We have to adapt the max value to the new situation periodically,
--   because it might get very high once, and then it will stay there forever.
adaptPeriod :: NominalDiffTime
adaptPeriod :: NominalDiffTime
adaptPeriod = Integer -> NominalDiffTime
forall a. Num a => Integer -> a
fromInteger (Integer -> NominalDiffTime) -> Integer -> NominalDiffTime
forall a b. (a -> b) -> a -> b
$ Integer
60 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
2 -- 2 minutes.

updateCPUTicks :: NodeState -> Integer -> LOMeta -> Word64 -> NodeState
updateCPUTicks :: NodeState -> Integer -> LOMeta -> Word64 -> NodeState
updateCPUTicks NodeState
ns Integer
ticks LOMeta
meta Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmCPUPercent :: Double
nmCPUPercent    = Double
cpuperc Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100.0
      , nmCPULast :: Integer
nmCPULast       = Integer
ticks
      , nmCPUNs :: Word64
nmCPUNs         = Word64
tns
      , nmCPULastUpdate :: Word64
nmCPULastUpdate = Word64
now
      }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  tns :: Word64
tns       = UTCTime -> Word64
utc2ns (UTCTime -> Word64) -> UTCTime -> Word64
forall a b. (a -> b) -> a -> b
$ LOMeta -> UTCTime
tstamp LOMeta
meta
  tdiff :: Double
tdiff     = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
0.1 (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
tns Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmCPUNs NodeMetrics
currentNm) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000000000 :: Double
  cpuperc :: Double
cpuperc   = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
ticks Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- NodeMetrics -> Integer
nmCPULast NodeMetrics
currentNm) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
clktck Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
tdiff
  clktck :: Integer
clktck    = Integer
100 :: Integer

#if defined(DARWIN) || defined(WINDOWS)
updateCPUSecs :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateCPUSecs ns nanosecs meta now = ns { nsMetrics = newNm }
 where
  newNm =
    currentNm
      { nmCPUPercent    = if cpuperc < 0 then 0 else if cpuperc > 20.0 then nmCPUPercent currentNm else cpuperc * 100.0
      , nmCPULast       = fromIntegral nanosecs
      , nmCPUNs         = tns
      , nmCPULastUpdate = now
      }
  currentNm = nsMetrics ns
  tns       = utc2ns $ tstamp meta
  tdiff     = max 0.1 $ fromIntegral (tns - nmCPUNs currentNm) / 1000000000 :: Double
  deltacpu  = fromIntegral nanosecs - nmCPULast currentNm
  cpuperc   = fromIntegral deltacpu / 100000000 / tdiff
#endif

updateNetworkIn :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateNetworkIn :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateNetworkIn NodeState
ns Word64
inBytes LOMeta
meta Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmNetworkUsageIn :: Double
nmNetworkUsageIn           = Double
currentNetRate
      , nmNetworkUsageInPercent :: Double
nmNetworkUsageInPercent    = Double
currentNetRate Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
maxNetRate Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100.0)
      , nmNetworkUsageInLast :: Word64
nmNetworkUsageInLast       = Word64
inBytes
      , nmNetworkUsageInNs :: Word64
nmNetworkUsageInNs         = Word64
currentTimeInNs
      , nmNetworkUsageInMax :: Double
nmNetworkUsageInMax        = Double
maxNetRate
      , nmNetworkUsageInMaxTotal :: Double
nmNetworkUsageInMaxTotal   = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
maxNetRate Double
1.0
      , nmNetworkUsageInLastUpdate :: Word64
nmNetworkUsageInLastUpdate = Word64
now
      }
  currentNm :: NodeMetrics
currentNm       = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  currentTimeInNs :: Word64
currentTimeInNs = UTCTime -> Word64
utc2ns (LOMeta -> UTCTime
tstamp LOMeta
meta)
  timeDiff :: Double
timeDiff        = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
currentTimeInNs Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmNetworkUsageInNs NodeMetrics
currentNm) :: Double
  timeDiffInSecs :: Double
timeDiffInSecs  = Double
timeDiff Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000000000
  bytesDiff :: Double
bytesDiff       = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
inBytes Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmNetworkUsageInLast NodeMetrics
currentNm) :: Double
  bytesDiffInKB :: Double
bytesDiffInKB   = Double
bytesDiff Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024
  currentNetRate :: Double
currentNetRate  = Double
bytesDiffInKB Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
timeDiffInSecs
  maxNetRate :: Double
maxNetRate      = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
currentNetRate (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ NodeMetrics -> Double
nmNetworkUsageInMax NodeMetrics
currentNm

updateNetworkOut :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateNetworkOut :: NodeState -> Word64 -> LOMeta -> Word64 -> NodeState
updateNetworkOut NodeState
ns Word64
outBytes LOMeta
meta Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmNetworkUsageOut :: Double
nmNetworkUsageOut           = Double
currentNetRate
      , nmNetworkUsageOutPercent :: Double
nmNetworkUsageOutPercent    = Double
currentNetRate Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
maxNetRate Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100.0)
      , nmNetworkUsageOutLast :: Word64
nmNetworkUsageOutLast       = Word64
outBytes
      , nmNetworkUsageOutNs :: Word64
nmNetworkUsageOutNs         = Word64
currentTimeInNs
      , nmNetworkUsageOutMax :: Double
nmNetworkUsageOutMax        = Double
maxNetRate
      , nmNetworkUsageOutMaxTotal :: Double
nmNetworkUsageOutMaxTotal   = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
maxNetRate Double
1.0
      , nmNetworkUsageOutLastUpdate :: Word64
nmNetworkUsageOutLastUpdate = Word64
now
      }
  currentNm :: NodeMetrics
currentNm       = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  currentTimeInNs :: Word64
currentTimeInNs = UTCTime -> Word64
utc2ns (LOMeta -> UTCTime
tstamp LOMeta
meta)
  timeDiff :: Double
timeDiff        = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
currentTimeInNs Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmNetworkUsageOutNs NodeMetrics
currentNm) :: Double
  timeDiffInSecs :: Double
timeDiffInSecs  = Double
timeDiff Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000000000
  bytesDiff :: Double
bytesDiff       = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
outBytes Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- NodeMetrics -> Word64
nmNetworkUsageOutLast NodeMetrics
currentNm) :: Double
  bytesDiffInKB :: Double
bytesDiffInKB   = Double
bytesDiff Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024
  currentNetRate :: Double
currentNetRate  = Double
bytesDiffInKB Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
timeDiffInSecs
  maxNetRate :: Double
maxNetRate      = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
currentNetRate (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ NodeMetrics -> Double
nmNetworkUsageOutMax NodeMetrics
currentNm

updateMempoolTxs :: NodeState -> Integer -> NodeState
updateMempoolTxs :: NodeState -> Integer -> NodeState
updateMempoolTxs NodeState
ns Integer
txsInMempool = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmMempoolTxsNumber :: Word64
nmMempoolTxsNumber  = Integer -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
txsInMempool
      , nmMempoolTxsPercent :: Double
nmMempoolTxsPercent =   Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
txsInMempool
                              Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
maxTxs
                              Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100.0
      , nmMempoolMaxTxs :: Integer
nmMempoolMaxTxs = Integer
maxTxs
      }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  maxTxs :: Integer
maxTxs = Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
max Integer
txsInMempool (NodeMetrics -> Integer
nmMempoolMaxTxs NodeMetrics
currentNm)

updateMempoolBytes :: NodeState -> Integer -> NodeState
updateMempoolBytes :: NodeState -> Integer -> NodeState
updateMempoolBytes NodeState
ns Integer
mempoolBytes = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmMempoolBytes :: Word64
nmMempoolBytes = Integer -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
mempoolBytes
      , nmMempoolBytesPercent :: Double
nmMempoolBytesPercent =   Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
mempoolBytes
                                Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
maxBytes
                                Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100.0
      , nmMempoolMaxBytes :: Integer
nmMempoolMaxBytes = Integer
maxBytes
      }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  maxBytes :: Integer
maxBytes = Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
max Integer
mempoolBytes (NodeMetrics -> Integer
nmMempoolMaxBytes NodeMetrics
currentNm)

updateTxsProcessed :: NodeState -> Integer -> NodeState
updateTxsProcessed :: NodeState -> Integer -> NodeState
updateTxsProcessed NodeState
ns Integer
txsProcessed = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = NodeInfo
currentNi { niTxsProcessed :: Integer
niTxsProcessed = Integer
txsProcessed }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateBlocksForged :: NodeState -> Integer -> Word64 -> NodeState
updateBlocksForged :: NodeState -> Integer -> Word64 -> NodeState
updateBlocksForged NodeState
ns Integer
blocksForged Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niBlocksForgedNumber :: Integer
niBlocksForgedNumber = Integer
blocksForged
      , niBlocksForgedNumberLastUpdate :: Word64
niBlocksForgedNumberLastUpdate = Word64
now
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateNodeCannotForge :: NodeState -> Integer -> NodeState
updateNodeCannotForge :: NodeState -> Integer -> NodeState
updateNodeCannotForge NodeState
ns Integer
cannotForge = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niNodeCannotForge :: Integer
niNodeCannotForge = Integer
cannotForge
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateNodeIsLeader :: NodeState -> Integer -> Word64 -> NodeState
updateNodeIsLeader :: NodeState -> Integer -> Word64 -> NodeState
updateNodeIsLeader NodeState
ns Integer
nodeIsLeader Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niNodeIsLeaderNum :: Integer
niNodeIsLeaderNum = Integer
nodeIsLeader
      , niNodeIsLeaderNumLastUpdate :: Word64
niNodeIsLeaderNumLastUpdate = Word64
now
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateSlotsMissed :: NodeState -> Integer -> Word64 -> NodeState
updateSlotsMissed :: NodeState -> Integer -> Word64 -> NodeState
updateSlotsMissed NodeState
ns Integer
slotsMissed Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niSlotsMissedNumber :: Integer
niSlotsMissedNumber = Integer
slotsMissed
      , niSlotsMissedNumberLastUpdate :: Word64
niSlotsMissedNumberLastUpdate = Word64
now
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateRTSBytesAllocated :: NodeState -> Word64 -> Word64 -> NodeState
updateRTSBytesAllocated :: NodeState -> Word64 -> Word64 -> NodeState
updateRTSBytesAllocated NodeState
ns Word64
bytesAllocated Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmRTSMemoryAllocated :: Double
nmRTSMemoryAllocated = Double
mBytes
      , nmRTSMemoryLastUpdate :: Word64
nmRTSMemoryLastUpdate = Word64
now
      }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  mBytes :: Double
mBytes    = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
bytesAllocated Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024 :: Double

updateRTSBytesUsed :: NodeState -> Word64 -> Word64 -> NodeState
updateRTSBytesUsed :: NodeState -> Word64 -> Word64 -> NodeState
updateRTSBytesUsed NodeState
ns Word64
usedMemBytes Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm =
    NodeMetrics
currentNm
      { nmRTSMemoryUsed :: Double
nmRTSMemoryUsed = Double
mBytes
      , nmRTSMemoryUsedPercent :: Double
nmRTSMemoryUsedPercent =   Double
mBytes
                                 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ NodeMetrics -> Double
nmRTSMemoryAllocated NodeMetrics
currentNm
                                 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100.0
      , nmRTSMemoryLastUpdate :: Word64
nmRTSMemoryLastUpdate = Word64
now
      }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  mBytes :: Double
mBytes    = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
usedMemBytes Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024 :: Double

updateGcCpuNs :: NodeState -> Word64 -> Word64 -> NodeState
updateGcCpuNs :: NodeState -> Word64 -> Word64 -> NodeState
updateGcCpuNs NodeState
ns Word64
gcCpuNs Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm     = NodeMetrics
currentNm { nmRTSGcCpu :: Double
nmRTSGcCpu = Double
seconds
                        , nmRTSGcCpuLastUpdate :: Word64
nmRTSGcCpuLastUpdate = Word64
now
                        }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  seconds :: Double
seconds   = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
gcCpuNs Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000000000 :: Double

updateGcElapsedNs :: NodeState -> Word64 -> Word64 -> NodeState
updateGcElapsedNs :: NodeState -> Word64 -> Word64 -> NodeState
updateGcElapsedNs NodeState
ns Word64
gcElapsedNs Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm     = NodeMetrics
currentNm { nmRTSGcElapsed :: Double
nmRTSGcElapsed = Double
seconds
                        , nmRTSGcElapsedLastUpdate :: Word64
nmRTSGcElapsedLastUpdate = Word64
now
                        }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns
  seconds :: Double
seconds   = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
gcElapsedNs Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000000000 :: Double

updateGcNum :: NodeState -> Integer -> Word64 -> NodeState
updateGcNum :: NodeState -> Integer -> Word64 -> NodeState
updateGcNum NodeState
ns Integer
gcNum Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm     = NodeMetrics
currentNm { nmRTSGcNum :: Integer
nmRTSGcNum = Integer
gcNum
                        , nmRTSGcNumLastUpdate :: Word64
nmRTSGcNumLastUpdate = Word64
now
                        }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns

updateGcMajorNum :: NodeState -> Integer -> Word64 -> NodeState
updateGcMajorNum :: NodeState -> Integer -> Word64 -> NodeState
updateGcMajorNum NodeState
ns Integer
gcMajorNum Word64
now = NodeState
ns { nsMetrics :: NodeMetrics
nsMetrics = NodeMetrics
newNm }
 where
  newNm :: NodeMetrics
newNm     = NodeMetrics
currentNm { nmRTSGcMajorNum :: Integer
nmRTSGcMajorNum = Integer
gcMajorNum
                        , nmRTSGcMajorNumLastUpdate :: Word64
nmRTSGcMajorNumLastUpdate = Word64
now
                        }
  currentNm :: NodeMetrics
currentNm = NodeState -> NodeMetrics
nsMetrics NodeState
ns

updateCertStartKESPeriod :: NodeState -> Integer -> Word64 -> NodeState
updateCertStartKESPeriod :: NodeState -> Integer -> Word64 -> NodeState
updateCertStartKESPeriod NodeState
ns Integer
oCertStartKesPeriod Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niOpCertStartKESPeriod :: Integer
niOpCertStartKESPeriod = Integer
oCertStartKesPeriod
      , niOpCertStartKESPeriodLastUpdate :: Word64
niOpCertStartKESPeriodLastUpdate = Word64
now
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateCurrentKESPeriod :: NodeState -> Integer -> Word64 -> NodeState
updateCurrentKESPeriod :: NodeState -> Integer -> Word64 -> NodeState
updateCurrentKESPeriod NodeState
ns Integer
currentKesPeriod Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niCurrentKESPeriod :: Integer
niCurrentKESPeriod = Integer
currentKesPeriod
      , niCurrentKESPeriodLastUpdate :: Word64
niCurrentKESPeriodLastUpdate = Word64
now
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateRemainingKESPeriods :: NodeState -> Integer -> Word64 -> NodeState
updateRemainingKESPeriods :: NodeState -> Integer -> Word64 -> NodeState
updateRemainingKESPeriods NodeState
ns Integer
kesPeriodsUntilExpiry Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi =
    NodeInfo
currentNi
      { niRemainingKESPeriods :: Integer
niRemainingKESPeriods = Integer
kesPeriodsUntilExpiry
      , niRemainingKESPeriodsLastUpdate :: Word64
niRemainingKESPeriodsLastUpdate = Word64
now
      }
  currentNi :: NodeInfo
currentNi = NodeState -> NodeInfo
nsInfo NodeState
ns

updateChainDensity :: NodeState -> Double -> Word64 -> NodeState
updateChainDensity :: NodeState -> Double -> Word64 -> NodeState
updateChainDensity NodeState
ns Double
density Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = (NodeState -> NodeInfo
nsInfo NodeState
ns) { niChainDensity :: Double
niChainDensity = Double
chainDensity
                      , niChainDensityLastUpdate :: Word64
niChainDensityLastUpdate = Word64
now
                      }
  chainDensity :: Double
chainDensity = Double
0.05 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
density Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100.0

updateBlocksNumber :: NodeState -> Integer -> Word64 -> NodeState
updateBlocksNumber :: NodeState -> Integer -> Word64 -> NodeState
updateBlocksNumber NodeState
ns Integer
blockNum Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = (NodeState -> NodeInfo
nsInfo NodeState
ns) { niBlocksNumber :: Integer
niBlocksNumber = Integer
blockNum
                      , niBlocksNumberLastUpdate :: Word64
niBlocksNumberLastUpdate = Word64
now
                      }

updateSlotInEpoch :: NodeState -> Integer -> Word64 -> NodeState
updateSlotInEpoch :: NodeState -> Integer -> Word64 -> NodeState
updateSlotInEpoch NodeState
ns Integer
slotNum Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = (NodeState -> NodeInfo
nsInfo NodeState
ns) { niSlot :: Integer
niSlot = Integer
slotNum
                      , niSlotLastUpdate :: Word64
niSlotLastUpdate = Word64
now
                      }

updateEpoch :: NodeState -> Integer -> Word64 -> NodeState
updateEpoch :: NodeState -> Integer -> Word64 -> NodeState
updateEpoch NodeState
ns Integer
epoch Word64
now = NodeState
ns { nsInfo :: NodeInfo
nsInfo = NodeInfo
newNi }
 where
  newNi :: NodeInfo
newNi = (NodeState -> NodeInfo
nsInfo NodeState
ns) { niEpoch :: Integer
niEpoch = Integer
epoch
                      , niEpochLastUpdate :: Word64
niEpochLastUpdate = Word64
now
                      }