Skip to content
Open
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
6 changes: 6 additions & 0 deletions cardano-submit-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## vNext

## 10.2 -- Oct 2025

* Replace the older tracing & metric system — `iohk-monitoring` with `trace-dispatcher`
* Change prometheus metric type from `gauge` to `counter`
* Use slightly different prometheus suffix for counters: `counter` instead of `count`

## 10.0 -- Oct 2024

* Bump for Node 10.0
Expand Down
12 changes: 6 additions & 6 deletions cardano-submit-api/cardano-submit-api.cabal
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cabal-version: 3.0

name: cardano-submit-api
version: 10.1.1
version: 10.2.0
synopsis: A web server that allows transactions to be POSTed to the cardano chain
description: A web server that allows transactions to be POSTed to the cardano chain.
homepage: https://github.com/intersectmbo/cardano-node
Expand Down Expand Up @@ -43,37 +43,37 @@ library
, cardano-binary
, cardano-cli ^>= 10.12
, cardano-crypto-class ^>= 2.2
, containers
, ekg-core
, http-media
, iohk-monitoring
, mtl
, network
, optparse-applicative-fork
, ouroboros-consensus-cardano
, ouroboros-network ^>= 0.21.2
, ouroboros-network-protocols
, prometheus >= 2.2.4
, ekg-prometheus-adapter
, safe-exceptions
, servant
, servant-server
, streaming-commons
, text
, transformers-except
, trace-dispatcher
, warp
, yaml

hs-source-dirs: src

exposed-modules: Cardano.TxSubmit

other-modules: Cardano.TxSubmit.CLI.Parsers
, Cardano.TxSubmit.CLI.Types
, Cardano.TxSubmit.Config
, Cardano.TxSubmit.Metrics
, Cardano.TxSubmit.Orphans
, Cardano.TxSubmit.Rest.Parsers
, Cardano.TxSubmit.Rest.Types
, Cardano.TxSubmit.Rest.Web
, Cardano.TxSubmit.Tracing.ToObjectOrphans
, Cardano.TxSubmit.Tracing.TraceSubmitApi
, Cardano.TxSubmit.Types
, Cardano.TxSubmit.Util
, Cardano.TxSubmit.Web
Expand Down
52 changes: 35 additions & 17 deletions cardano-submit-api/src/Cardano/TxSubmit.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,43 @@ module Cardano.TxSubmit
, TxSubmitCommand(..)
) where

import qualified Cardano.BM.Setup as Logging
import Cardano.BM.Trace (Trace, logInfo)
import qualified Cardano.BM.Trace as Logging
import Cardano.Logging (BackendConfig (..), ConfigOption (ConfBackend, ConfSeverity),
FormatLogging (HumanFormatColoured), SeverityF (SeverityF), SeverityS (Info),
Trace, TraceConfig, configureTracers, ekgTracer, emptyConfigReflection,
emptyTraceConfig, mkCardanoTracer, readConfigurationWithDefault, standardTracer,
tcOptions, traceWith)
import Cardano.TxSubmit.CLI.Parsers (opts)
import Cardano.TxSubmit.CLI.Types (ConfigFile (unConfigFile), TxSubmitCommand (..),
TxSubmitNodeParams (..))
import Cardano.TxSubmit.Config (GenTxSubmitNodeConfig (..), ToggleLogging (..),
TxSubmitNodeConfig, readTxSubmitNodeConfig)
import Cardano.TxSubmit.Metrics (registerMetricsServer)
import Cardano.TxSubmit.Tracing.TraceSubmitApi (TraceSubmitApi (..))
import Cardano.TxSubmit.Web (runTxSubmitServer)

import qualified Control.Concurrent.Async as Async
import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.Text (Text)
import Data.Map
import qualified System.Metrics as EKG
import System.Metrics.Prometheus.Registry (RegistrySample, sample)
import System.Remote.Monitoring.Prometheus (defaultOptions, toPrometheusRegistry)

defaultTraceConfig :: TraceConfig
defaultTraceConfig =
emptyTraceConfig
{ tcOptions = Data.Map.fromList
[([], [ ConfSeverity (SeverityF (Just Info))
, ConfBackend [Stdout HumanFormatColoured, EKGBackend]])
]
}

runTxSubmitWebapi :: TxSubmitNodeParams -> IO ()
runTxSubmitWebapi tsnp = do
tsnc <- readTxSubmitNodeConfig (unConfigFile tspConfigFile)
trce <- mkTracer tsnc
(metrics, runMetricsServer) <- registerMetricsServer trce tspMetricsPort
tracingConfig <- readConfigurationWithDefault (unConfigFile tspConfigFile) defaultTraceConfig
(trce, registrySample) <- mkTraceDispatcher tracingConfig
Async.withAsync
(runTxSubmitServer trce metrics tspWebserverConfig tspProtocol tspNetworkId tspSocketPath)
(runTxSubmitServer trce tspWebserverConfig tspProtocol tspNetworkId tspSocketPath)
$ \txSubmitServer ->
Async.withAsync runMetricsServer $ \_ ->
Async.withAsync (registerMetricsServer trce registrySample tspMetricsPort) $ \_ ->
Async.wait txSubmitServer
logInfo trce "runTxSubmitWebapi: Stopping TxSubmit API"
traceWith trce ApplicationStopping
where
TxSubmitNodeParams
{ tspProtocol
Expand All @@ -43,7 +54,14 @@ runTxSubmitWebapi tsnp = do
, tspConfigFile
} = tsnp

mkTracer :: TxSubmitNodeConfig -> IO (Trace IO Text)
mkTracer enc = case tscToggleLogging enc of
LoggingOn -> liftIO $ Logging.setupTrace (Right $ tscLoggingConfig enc) "cardano-tx-submit"
LoggingOff -> pure Logging.nullTracer
mkTraceDispatcher :: TraceConfig -> IO (Trace IO TraceSubmitApi, IO RegistrySample)
mkTraceDispatcher config = do
trBase <- standardTracer
ekgStore <- EKG.newStore
let registry = toPrometheusRegistry ekgStore (defaultOptions mempty) -- Convert EKG metrics store to prometheus metrics registry on-demand
trEkg <- ekgTracer config ekgStore
configReflection <- emptyConfigReflection
tr <- mkCardanoTracer trBase mempty (Just trEkg) ["TxSubmitApi"]
configureTracers configReflection config [tr]
traceWith tr ApplicationInitializeMetrics
pure (tr, registry >>= sample)
63 changes: 0 additions & 63 deletions cardano-submit-api/src/Cardano/TxSubmit/Config.hs

This file was deleted.

61 changes: 17 additions & 44 deletions cardano-submit-api/src/Cardano/TxSubmit/Metrics.hs
Original file line number Diff line number Diff line change
@@ -1,66 +1,39 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

module Cardano.TxSubmit.Metrics
( TxSubmitMetrics (..)
, makeMetrics
, registerMetricsServer
)
(registerMetricsServer)
where

import Cardano.Api.Pretty (textShow)

import Cardano.BM.Data.Trace (Trace)
import Cardano.BM.Trace (logError, logInfo, logWarning)
import Cardano.Logging (Trace, traceWith)
import Cardano.TxSubmit.Tracing.TraceSubmitApi (TraceSubmitApi (..))

import Control.Exception.Safe
import Control.Monad.Reader (MonadReader (ask), ReaderT (runReaderT))
import Data.Text (Text)
import qualified Data.Text as T
import System.Metrics.Prometheus.Concurrent.RegistryT (RegistryT (..), registerGauge,
runRegistryT, unRegistryT)
import System.Metrics.Prometheus.Http.Scrape (serveMetricsT)
import System.Metrics.Prometheus.Metric.Gauge (Gauge)

data TxSubmitMetrics = TxSubmitMetrics
{ tsmCount :: Gauge
, tsmFailCount :: Gauge
}
import System.Metrics.Prometheus.Http.Scrape (serveMetrics)
import System.Metrics.Prometheus.Registry (RegistrySample)

-- | Register metrics server. Returns metrics and an IO action which starts metrics server and should
-- be passed to 'withAsync'.
registerMetricsServer
:: Trace IO Text
:: Trace IO TraceSubmitApi
-> IO RegistrySample
-> Int
-> IO (TxSubmitMetrics, IO ())
registerMetricsServer tracer metricsPort =
runRegistryT $ do
metrics <- makeMetrics
registry <- RegistryT ask
let runServer =
tryWithPort metricsPort $ \port -> do
logInfo tracer $ "Starting metrics server on port " <> textShow port
flip runReaderT registry . unRegistryT $ serveMetricsT port []
pure (metrics, runServer)
-> IO ()
registerMetricsServer tracer registrySample metricsPort = do
tryWithPort metricsPort $ \port -> do
traceWith tracer $ MetricsServerStarted port
serveMetrics port [] registrySample
where

-- try opening the metrics server on the specified port, if it fails, try using next. Gives up after 1000 attempts and disables metrics server.
tryWithPort :: Int -> (Int -> IO ()) -> IO ()
tryWithPort startingPort f = go startingPort
where
go port = do
catch @_ @IOException (f port) $ \e -> do
logWarning tracer $ T.pack $ "Metrics server error: " <> displayException e
traceWith tracer $ MetricsServerError e
if port <= (startingPort + 1000)
then do
logWarning tracer $ "Could not allocate metrics server port " <> textShow port <> " - trying next available..."
traceWith tracer $ MetricsServerPortOccupied port
go $ port + 1
else do
logError tracer $
"Could not allocate any metrics port until " <> textShow port <> " - metrics endpoint disabled"
pure ()

makeMetrics :: RegistryT IO TxSubmitMetrics
makeMetrics =
TxSubmitMetrics
<$> registerGauge "tx_submit_count" mempty
<*> registerGauge "tx_submit_fail_count" mempty
else
traceWith tracer $ MetricsServerPortNotBound port
12 changes: 5 additions & 7 deletions cardano-submit-api/src/Cardano/TxSubmit/Rest/Web.hs
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
{-# LANGUAGE OverloadedStrings #-}

module Cardano.TxSubmit.Rest.Web
( runSettings
)
where

import Cardano.Api.Pretty (textShow)

import Cardano.BM.Trace (Trace, logInfo)
import Cardano.Logging.Trace (traceWith)
import qualified Cardano.Logging.Types as TraceD
import Cardano.TxSubmit.Tracing.TraceSubmitApi (TraceSubmitApi (..))

import Control.Exception (bracket)
import Data.Streaming.Network (bindPortTCP)
import Data.Text (Text)
import Network.Socket (close, getSocketName, withSocketsDo)
import Network.Wai.Handler.Warp (Settings, getHost, getPort, runSettingsSocket)

import Servant (Application)

-- | Like 'Network.Wai.Handler.Warp.runSettings', except with better logging.
runSettings :: Trace IO Text -> Settings -> Application -> IO ()
runSettings :: TraceD.Trace IO TraceSubmitApi -> Settings -> Application -> IO ()
runSettings trace settings app =
withSocketsDo $
bracket
(bindPortTCP (getPort settings) (getHost settings))
close
( \socket -> do
addr <- getSocketName socket
logInfo trace $ "Web API listening on port " <> textShow addr
traceWith trace $ EndpointListeningOnPort addr
runSettingsSocket settings socket app
)

This file was deleted.

Loading
Loading