Skip to content

RTView: important fixes #4259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions cardano-tracer/bench/cardano-tracer-bench.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{-# LANGUAGE OverloadedStrings #-}

import Control.Concurrent.Extra (newLock)
import Control.Concurrent.STM.TVar (newTVarIO)
import Criterion.Main
import qualified Data.List.NonEmpty as NE
import Data.Time.Clock (getCurrentTime)
Expand Down Expand Up @@ -29,7 +30,8 @@ main = do
to100 <- generate 100
to1000 <- generate 1000

connectedNodes <- initConnectedNodes
connectedNodes <- initConnectedNodes
connectedNodesNames <- initConnectedNodesNames
acceptedMetrics <- initAcceptedMetrics
savedTO <- initSavedTraceObjects

Expand All @@ -42,12 +44,15 @@ main = do

currentLogLock <- newLock
currentDPLock <- newLock
eventsQueues <- initEventsQueues dpRequestors currentDPLock
eventsQueues <- initEventsQueues connectedNodesNames dpRequestors currentDPLock

rtViewPageOpened <- newTVarIO False

let te1 =
TracerEnv
{ teConfig = c1
, teConnectedNodes = connectedNodes
, teConnectedNodesNames = connectedNodesNames
, teAcceptedMetrics = acceptedMetrics
, teSavedTO = savedTO
, teBlockchainHistory = chainHistory
Expand All @@ -58,11 +63,13 @@ main = do
, teEventsQueues = eventsQueues
, teDPRequestors = dpRequestors
, teProtocolsBrake = protocolsBrake
, teRTViewPageOpened = rtViewPageOpened
}
te2 =
TracerEnv
{ teConfig = c2
, teConnectedNodes = connectedNodes
, teConnectedNodesNames = connectedNodesNames
, teAcceptedMetrics = acceptedMetrics
, teSavedTO = savedTO
, teBlockchainHistory = chainHistory
Expand All @@ -73,6 +80,7 @@ main = do
, teEventsQueues = eventsQueues
, teDPRequestors = dpRequestors
, teProtocolsBrake = protocolsBrake
, teRTViewPageOpened = rtViewPageOpened
}

removePathForcibly root
Expand Down
2 changes: 2 additions & 0 deletions cardano-tracer/cardano-tracer.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ library
, aeson-pretty
, async
, async-extras
, bimap
, blaze-html
, blaze-markup
, bytestring
Expand Down Expand Up @@ -299,6 +300,7 @@ benchmark cardano-tracer-bench
, directory
, extra
, filepath
, stm
, time
, trace-dispatcher

Expand Down
11 changes: 7 additions & 4 deletions cardano-tracer/src/Cardano/Tracer/Acceptors/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module Cardano.Tracer.Acceptors.Utils

import Control.Concurrent.STM (atomically)
import Control.Concurrent.STM.TVar (TVar, newTVarIO, modifyTVar')
import qualified Data.Bimap as BM
import qualified Data.Map.Strict as M
import qualified Data.Set as S
import Data.Time.Clock.System (getSystemTime, systemToUTCTime)
Expand Down Expand Up @@ -64,13 +65,15 @@ removeDisconnectedNode
:: TracerEnv
-> ConnectionId LocalAddress
-> IO ()
removeDisconnectedNode TracerEnv{teConnectedNodes, teAcceptedMetrics, teDPRequestors} connId =
removeDisconnectedNode tracerEnv connId =
-- Remove all the stuff related to disconnected node.
atomically $ do
modifyTVar' teConnectedNodes $ S.delete nodeId
modifyTVar' teAcceptedMetrics $ M.delete nodeId
modifyTVar' teDPRequestors $ M.delete nodeId
modifyTVar' teConnectedNodes $ S.delete nodeId
modifyTVar' teConnectedNodesNames $ BM.delete nodeId
modifyTVar' teAcceptedMetrics $ M.delete nodeId
modifyTVar' teDPRequestors $ M.delete nodeId
where
TracerEnv{teConnectedNodes, teConnectedNodesNames, teAcceptedMetrics, teDPRequestors} = tracerEnv
nodeId = connIdToNodeId connId

notifyAboutNodeDisconnected
Expand Down
27 changes: 15 additions & 12 deletions cardano-tracer/src/Cardano/Tracer/Environment.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,23 @@ import Cardano.Tracer.Configuration
import Cardano.Tracer.Handlers.RTView.Notifications.Types
import Cardano.Tracer.Handlers.RTView.State.Historical
import Cardano.Tracer.Handlers.RTView.State.TraceObjects
import Cardano.Tracer.Handlers.RTView.UI.Types
import Cardano.Tracer.Types

-- | Environment for all functions.
data TracerEnv = TracerEnv
{ teConfig :: !TracerConfig
, teConnectedNodes :: !ConnectedNodes
, teAcceptedMetrics :: !AcceptedMetrics
, teSavedTO :: !SavedTraceObjects
, teBlockchainHistory :: !BlockchainHistory
, teResourcesHistory :: !ResourcesHistory
, teTxHistory :: !TransactionsHistory
, teCurrentLogLock :: !Lock
, teCurrentDPLock :: !Lock
, teEventsQueues :: !EventsQueues
, teDPRequestors :: !DataPointRequestors
, teProtocolsBrake :: !ProtocolsBrake
{ teConfig :: !TracerConfig
, teConnectedNodes :: !ConnectedNodes
, teConnectedNodesNames :: !ConnectedNodesNames
, teAcceptedMetrics :: !AcceptedMetrics
, teSavedTO :: !SavedTraceObjects
, teBlockchainHistory :: !BlockchainHistory
, teResourcesHistory :: !ResourcesHistory
, teTxHistory :: !TransactionsHistory
, teCurrentLogLock :: !Lock
, teCurrentDPLock :: !Lock
, teEventsQueues :: !EventsQueues
, teDPRequestors :: !DataPointRequestors
, teProtocolsBrake :: !ProtocolsBrake
, teRTViewPageOpened :: !WebPageStatus
}
20 changes: 10 additions & 10 deletions cardano-tracer/src/Cardano/Tracer/Handlers/Logs/File.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import System.FilePath ((</>))

import Cardano.Logging (Namespace, TraceObject (..))

import Cardano.Tracer.Configuration (LogFormat (..))
import Cardano.Tracer.Handlers.Logs.Utils (createEmptyLog, isItLog)
import Cardano.Tracer.Types (NodeId (..))
import Cardano.Tracer.Utils (nl)
import Cardano.Tracer.Configuration
import Cardano.Tracer.Handlers.Logs.Utils
import Cardano.Tracer.Types
import Cardano.Tracer.Utils

-- | Append the list of 'TraceObject's to the latest log via symbolic link.
--
Expand All @@ -36,20 +36,20 @@ import Cardano.Tracer.Utils (nl)
-- the symbolic link will be switched to the new log file and writing can
-- be interrupted. To prevent it, we use 'Lock'.
writeTraceObjectsToFile
:: NodeId
:: NodeName
-> Lock
-> FilePath
-> LogFormat
-> [TraceObject]
-> IO ()
writeTraceObjectsToFile nodeId currentLogLock rootDir format traceObjects = do
writeTraceObjectsToFile nodeName currentLogLock rootDir format traceObjects = do
rootDirAbs <- makeAbsolute rootDir
let converter = case format of
ForHuman -> traceObjectToText
ForMachine -> traceObjectToJSON
let itemsToWrite = mapMaybe converter traceObjects
unless (null itemsToWrite) $ do
pathToCurrentLog <- getPathToCurrentlog nodeId rootDirAbs format
pathToCurrentLog <- getPathToCurrentlog nodeName rootDirAbs format
let preparedLine = TE.encodeUtf8 $ T.concat itemsToWrite
withLock currentLogLock $
BS.appendFile pathToCurrentLog preparedLine
Expand All @@ -66,16 +66,16 @@ writeTraceObjectsToFile nodeId currentLogLock rootDir format traceObjects = do
-- logs from node N
--
getPathToCurrentlog
:: NodeId
:: NodeName
-> FilePath
-> LogFormat
-> IO FilePath
getPathToCurrentlog (NodeId anId) rootDirAbs format =
getPathToCurrentlog nodeName rootDirAbs format =
ifM (doesDirectoryExist subDirForLogs)
getPathToCurrentLogIfExists
prepareLogsStructure
where
subDirForLogs = rootDirAbs </> T.unpack anId
subDirForLogs = rootDirAbs </> T.unpack nodeName

getPathToCurrentLogIfExists = do
logsWeNeed <- filter (isItLog format) <$> listFiles subDirForLogs
Expand Down
12 changes: 6 additions & 6 deletions cardano-tracer/src/Cardano/Tracer/Handlers/Logs/Journal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ import Systemd.Journal (Priority (..), message, mkJournalField, priori
import Cardano.Logging (TraceObject (..))
import qualified Cardano.Logging as L

import Cardano.Tracer.Types (NodeId (..))
import Cardano.Tracer.Types
#else
import Cardano.Logging (TraceObject)

import Cardano.Tracer.Types (NodeId)
import Cardano.Tracer.Types
#endif

#ifdef LINUX
-- | Store 'TraceObject's in Linux systemd's journal service.
writeTraceObjectsToJournal :: NodeId -> [TraceObject] -> IO ()
writeTraceObjectsToJournal (NodeId anId) = mapM_ (sendJournalFields . mkJournalFields)
writeTraceObjectsToJournal :: NodeName -> [TraceObject] -> IO ()
writeTraceObjectsToJournal nodeName = mapM_ (sendJournalFields . mkJournalFields)
where
mkJournalFields trOb@TraceObject{toHuman, toMachine} =
case (toHuman, toMachine) of
Expand All @@ -45,7 +45,7 @@ writeTraceObjectsToJournal (NodeId anId) = mapM_ (sendJournalFields . mkJournalF
(Nothing, Nothing) -> HM.empty

mkJournalFields' TraceObject{toSeverity, toNamespace, toThreadId, toTimestamp} msg =
syslogIdentifier anId
syslogIdentifier nodeName
<> message msg
<> priority (mkPriority toSeverity)
<> HM.fromList
Expand Down Expand Up @@ -73,6 +73,6 @@ writeTraceObjectsToJournal (NodeId anId) = mapM_ (sendJournalFields . mkJournalF
mkPriority L.Emergency = Emergency
#else
-- It works on Linux only.
writeTraceObjectsToJournal :: NodeId -> [TraceObject] -> IO ()
writeTraceObjectsToJournal :: NodeName -> [TraceObject] -> IO ()
writeTraceObjectsToJournal _ _ = return ()
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ traceObjectsHandler
-> [TraceObject] -- ^ The list of received 'TraceObject's (may be empty).
-> IO ()
traceObjectsHandler _ _ [] = return ()
traceObjectsHandler TracerEnv{teConfig, teCurrentLogLock, teSavedTO} nodeId traceObjects = do
traceObjectsHandler tracerEnv nodeId traceObjects = do
nodeName <- askNodeName tracerEnv nodeId
forConcurrently_ (NE.nub logging) $ \LoggingParams{logMode, logRoot, logFormat} ->
showProblemIfAny verbosity $
case logMode of
FileMode -> writeTraceObjectsToFile nodeId teCurrentLogLock logRoot logFormat traceObjects
JournalMode -> writeTraceObjectsToJournal nodeId traceObjects
FileMode -> writeTraceObjectsToFile nodeName teCurrentLogLock logRoot logFormat traceObjects
JournalMode -> writeTraceObjectsToJournal nodeName traceObjects
whenJust hasRTView . const $
saveTraceObjects teSavedTO nodeId traceObjects
where
TracerEnv{teConfig, teCurrentLogLock, teSavedTO} = tracerEnv
TracerConfig{logging, verbosity, hasRTView} = teConfig
36 changes: 19 additions & 17 deletions cardano-tracer/src/Cardano/Tracer/Handlers/Metrics/Monitoring.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

Expand All @@ -22,9 +23,10 @@ import Graphics.UI.Threepenny.Core (UI, Element, liftIO, set, (#), (#+
import System.Remote.Monitoring (forkServerWith, serverThreadId)
import System.Time.Extra (sleep)

import Cardano.Tracer.Configuration (Endpoint (..))
import Cardano.Tracer.Handlers.RTView.SSL.Certs (placeDefaultSSLFiles)
import Cardano.Tracer.Types (AcceptedMetrics, ConnectedNodes, NodeId (..))
import Cardano.Tracer.Configuration
import Cardano.Tracer.Environment
import Cardano.Tracer.Handlers.RTView.SSL.Certs
import Cardano.Tracer.Types

-- | 'ekg' package allows to run only one EKG server, to display only one web page
-- for particular EKG.Store. Since 'cardano-tracer' can be connected to any number
Expand All @@ -37,17 +39,16 @@ import Cardano.Tracer.Types (AcceptedMetrics, ConnectedNodes, NodeId (
-- the EKG server will be restarted and the monitoring page will display the metrics
-- received from that node.
runMonitoringServer
:: (Endpoint, Endpoint) -- ^ (web page with list of connected nodes, EKG web page).
-> ConnectedNodes
-> AcceptedMetrics
:: TracerEnv
-> (Endpoint, Endpoint) -- ^ (web page with list of connected nodes, EKG web page).
-> IO ()
runMonitoringServer (Endpoint listHost listPort, monitorEP) connectedNodes acceptedMetrics = do
runMonitoringServer tracerEnv (Endpoint listHost listPort, monitorEP) = do
-- Pause to prevent collision between "Listening"-notifications from servers.
sleep 0.2
(certFile, keyFile) <- placeDefaultSSLFiles
UI.startGUI (config certFile keyFile) $ \window -> do
void $ return window # set UI.title "EKG Monitoring Nodes"
void $ mkPageBody window connectedNodes monitorEP acceptedMetrics
void $ mkPageBody window tracerEnv monitorEP
where
config cert key = UI.defaultConfig
{ UI.jsSSLBind = Just . encodeUtf8 . T.pack $ listHost
Expand All @@ -64,12 +65,11 @@ type CurrentEKGServer = TMVar (NodeId, ThreadId)
-- corresponding to currently connected nodes.
mkPageBody
:: UI.Window
-> ConnectedNodes
-> TracerEnv
-> Endpoint
-> AcceptedMetrics
-> UI Element
mkPageBody window connectedNodes mEP@(Endpoint monitorHost monitorPort) acceptedMetrics = do
nodes <- liftIO $ S.toList <$> readTVarIO connectedNodes
mkPageBody window tracerEnv mEP@(Endpoint monitorHost monitorPort) = do
nodes <- liftIO $ S.toList <$> readTVarIO teConnectedNodes
nodesHrefs <-
if null nodes
then UI.string "There are no connected nodes yet"
Expand All @@ -85,23 +85,25 @@ mkPageBody window connectedNodes mEP@(Endpoint monitorHost monitorPort) accepted
# set UI.text (T.unpack anId)
]
void $ UI.on UI.click nodeLink $ const $
restartEKGServer nodeId acceptedMetrics mEP currentServer
restartEKGServer tracerEnv nodeId mEP currentServer
return $ UI.element nodeLink
UI.ul #+ nodesLinks
UI.getBody window #+ [ UI.element nodesHrefs ]
where
TracerEnv{teConnectedNodes} = tracerEnv

-- | After clicking on the node's href, the user will be redirected to the monitoring page
-- which is rendered by 'ekg' package. But before, we have to check if EKG server is
-- already launched, and if so, restart the server if needed.
restartEKGServer
:: NodeId
-> AcceptedMetrics
:: TracerEnv
-> NodeId
-> Endpoint
-> CurrentEKGServer
-> UI ()
restartEKGServer newNodeId acceptedMetrics
restartEKGServer TracerEnv{teAcceptedMetrics} newNodeId
(Endpoint monitorHost monitorPort) currentServer = liftIO $ do
metrics <- readTVarIO acceptedMetrics
metrics <- readTVarIO teAcceptedMetrics
whenJust (metrics M.!? newNodeId) $ \(storeForSelectedNode, _) ->
atomically (tryReadTMVar currentServer) >>= \case
Just (_curNodeId, _sThread) ->
Expand Down
Loading