diff --git a/docs/examples/infrastructure/grafana/clio_dashboard.json b/docs/examples/infrastructure/grafana/clio_dashboard.json index 08a7bead..810653db 100644 --- a/docs/examples/infrastructure/grafana/clio_dashboard.json +++ b/docs/examples/infrastructure/grafana/clio_dashboard.json @@ -18,6 +18,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, + "id": 1, "links": [], "liveNow": false, "panels": [ @@ -85,9 +86,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.2.0", + "pluginVersion": "10.4.0", "targets": [ { "datasource": { @@ -105,6 +108,372 @@ "title": "Service state", "type": "stat" }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "blue", + "index": 0, + "text": "No" + }, + "1": { + "color": "green", + "index": 1, + "text": "Yes" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 3, + "y": 0 + }, + "id": 14, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.4.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "read_only", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Read only", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "blue", + "index": 0, + "text": "No" + }, + "1": { + "color": "green", + "index": 1, + "text": "Yes" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 6, + "y": 0 + }, + "id": 15, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.4.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "etl_writing", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Writing data to DB", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "green", + "index": 0, + "text": "No" + }, + "1": { + "color": "red", + "index": 1, + "text": "Yes" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 9, + "y": 0 + }, + "id": 16, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.4.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "etl_amendment_blocked", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Amendment blocked", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "timestamp(etl_last_publish_seconds) - etl_last_publish_seconds", + "format": "time_series", + "instant": false, + "legendFormat": "ledger age", + "range": true, + "refId": "A" + } + ], + "title": "Ledger Age", + "transformations": [ + { + "id": "filterByValue", + "options": { + "filters": [ + { + "config": { + "id": "lower", + "options": { + "value": 31500000 + } + }, + "fieldName": "ledger age" + } + ], + "match": "all", + "type": "include" + } + } + ], + "type": "timeseries" + }, { "datasource": { "type": "prometheus", @@ -166,9 +535,9 @@ }, "gridPos": { "h": 8, - "w": 9, - "x": 3, - "y": 0 + "w": 12, + "x": 0, + "y": 8 }, "id": 2, "options": { @@ -263,7 +632,7 @@ "h": 8, "w": 12, "x": 12, - "y": 0 + "y": 8 }, "id": 9, "options": { @@ -358,7 +727,7 @@ "h": 8, "w": 12, "x": 0, - "y": 8 + "y": 16 }, "id": 11, "options": { @@ -453,7 +822,7 @@ "h": 8, "w": 12, "x": 12, - "y": 8 + "y": 16 }, "id": 6, "options": { @@ -550,7 +919,7 @@ "h": 8, "w": 12, "x": 0, - "y": 16 + "y": 24 }, "id": 10, "options": { @@ -645,7 +1014,7 @@ "h": 8, "w": 12, "x": 12, - "y": 16 + "y": 24 }, "id": 8, "options": { @@ -740,7 +1109,7 @@ "h": 8, "w": 12, "x": 0, - "y": 24 + "y": 32 }, "id": 4, "options": { @@ -839,7 +1208,7 @@ "h": 8, "w": 12, "x": 12, - "y": 24 + "y": 32 }, "id": 12, "options": { @@ -973,7 +1342,7 @@ "h": 8, "w": 12, "x": 0, - "y": 32 + "y": 40 }, "id": 5, "options": { @@ -1081,7 +1450,7 @@ "h": 8, "w": 12, "x": 12, - "y": 32 + "y": 40 }, "id": 3, "options": { @@ -1186,9 +1555,9 @@ }, "gridPos": { "h": 8, - "w": 10, + "w": 12, "x": 0, - "y": 40 + "y": 48 }, "id": 7, "options": { @@ -1222,7 +1591,7 @@ } ], "refresh": "5s", - "schemaVersion": 38, + "schemaVersion": 39, "tags": [], "templating": { "list": [] @@ -1235,6 +1604,6 @@ "timezone": "", "title": "Clio", "uid": "aeaae84e-c194-47b2-ad65-86e45eebb815", - "version": 3, + "version": 1, "weekStart": "" } diff --git a/src/etl/ETLService.cpp b/src/etl/ETLService.cpp index 21f275e4..0b8badfe 100644 --- a/src/etl/ETLService.cpp +++ b/src/etl/ETLService.cpp @@ -276,7 +276,7 @@ ETLService::ETLService( { startSequence_ = config.maybeValue("start_sequence"); finishSequence_ = config.maybeValue("finish_sequence"); - state_.isReadOnly = config.valueOr("read_only", state_.isReadOnly); + state_.isReadOnly = config.valueOr("read_only", static_cast(state_.isReadOnly)); extractorThreads_ = config.valueOr("extractor_threads", extractorThreads_); txnThreshold_ = config.valueOr("txn_threshold", txnThreshold_); } diff --git a/src/etl/ETLService.hpp b/src/etl/ETLService.hpp index 076afd4d..b73d7b46 100644 --- a/src/etl/ETLService.hpp +++ b/src/etl/ETLService.hpp @@ -212,8 +212,8 @@ public: boost::json::object result; result["etl_sources"] = loadBalancer_->toJson(); - result["is_writer"] = state_.isWriting.load(); - result["read_only"] = state_.isReadOnly; + result["is_writer"] = static_cast(state_.isWriting); + result["read_only"] = static_cast(state_.isReadOnly); auto last = ledgerPublisher_.getLastPublish(); if (last.time_since_epoch().count() != 0) result["last_publish_age_seconds"] = std::to_string(ledgerPublisher_.lastPublishAgeSeconds()); diff --git a/src/etl/SystemState.hpp b/src/etl/SystemState.hpp index f3694e02..9aa398e1 100644 --- a/src/etl/SystemState.hpp +++ b/src/etl/SystemState.hpp @@ -19,6 +19,10 @@ #pragma once +#include "util/prometheus/Bool.hpp" +#include "util/prometheus/Label.hpp" +#include "util/prometheus/Prometheus.hpp" + #include namespace etl { @@ -33,9 +37,19 @@ struct SystemState { * In strict read-only mode, the process will never attempt to become the ETL writer, and will only publish ledgers * as they are written to the database. */ - bool isReadOnly = false; + util::prometheus::Bool isReadOnly = PrometheusService::boolMetric( + "read_only", + util::prometheus::Labels{}, + "Whether the process is in strict read-only mode" + ); + + /** @brief Whether the process is writing to the database. */ + util::prometheus::Bool isWriting = PrometheusService::boolMetric( + "etl_writing", + util::prometheus::Labels{}, + "Whether the process is writing to the database" + ); - std::atomic_bool isWriting = false; /**< @brief Whether the process is writing to the database. */ std::atomic_bool isStopping = false; /**< @brief Whether the software is stopping. */ std::atomic_bool writeConflict = false; /**< @brief Whether a write conflict was detected. */ @@ -46,7 +60,11 @@ struct SystemState { * arrived from rippled and therefore can't extract the ledger diff. When this happens, Clio can't proceed with ETL * and should log this error and only handle RPC requests. */ - std::atomic_bool isAmendmentBlocked = false; + util::prometheus::Bool isAmendmentBlocked = PrometheusService::boolMetric( + "etl_amendment_blocked", + util::prometheus::Labels{}, + "Whether clio detected an amendment block" + ); }; } // namespace etl diff --git a/src/etl/impl/LedgerPublisher.hpp b/src/etl/impl/LedgerPublisher.hpp index 8ea55df8..2c72ea93 100644 --- a/src/etl/impl/LedgerPublisher.hpp +++ b/src/etl/impl/LedgerPublisher.hpp @@ -25,6 +25,8 @@ #include "etl/SystemState.hpp" #include "util/Assert.hpp" #include "util/log/Logger.hpp" +#include "util/prometheus/Counter.hpp" +#include "util/prometheus/Prometheus.hpp" #include #include @@ -75,8 +77,11 @@ class LedgerPublisher { std::chrono::time_point lastCloseTime_; mutable std::shared_mutex closeTimeMtx_; - std::chrono::time_point lastPublish_; - mutable std::shared_mutex publishTimeMtx_; + std::reference_wrapper lastPublishSeconds_ = PrometheusService::counterInt( + "etl_last_publish_seconds", + {}, + "Seconds since epoch of the last published ledger" + ); std::optional lastPublishedSequence_; mutable std::shared_mutex lastPublishedSeqMtx_; @@ -232,8 +237,8 @@ public: std::chrono::time_point getLastPublish() const { - std::shared_lock const lck(publishTimeMtx_); - return lastPublish_; + return std::chrono::time_point{std::chrono::seconds{lastPublishSeconds_.get().value() + }}; } /** @@ -273,8 +278,9 @@ private: void setLastPublishTime() { - std::scoped_lock const lck(publishTimeMtx_); - lastPublish_ = std::chrono::system_clock::now(); + using namespace std::chrono; + auto const nowSeconds = duration_cast(system_clock::now().time_since_epoch()).count(); + lastPublishSeconds_.get().set(nowSeconds); } void diff --git a/src/util/prometheus/Bool.hpp b/src/util/prometheus/Bool.hpp new file mode 100644 index 00000000..1326c312 --- /dev/null +++ b/src/util/prometheus/Bool.hpp @@ -0,0 +1,89 @@ +//------------------------------------------------------------------------------ +/* + This file is part of clio: https://github.com/XRPLF/clio + Copyright (c) 2024, the clio developers. + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#pragma once + +#include "util/Assert.hpp" +#include "util/prometheus/Gauge.hpp" + +#include +#include + +namespace util::prometheus { + +template +concept SomeBoolImpl = requires(T a) { + { + a.set(0) + } -> std::same_as; + { + a.value() + } -> std::same_as; +}; + +/** + * @brief A wrapped to provide bool interface for a Prometheus metric + * @note Prometheus does not have a native bool type, so we use a counter with a value of 0 or 1 + */ +template +class AnyBool { + std::reference_wrapper impl_; + +public: + /** + * @brief Construct a bool metric + * + * @param impl The implementation of the metric + */ + explicit AnyBool(ImplType& impl) : impl_(impl) + { + } + + /** + * @brief Set the value of the bool metric + * + * @param value The value to set + * @return A reference to the metric + */ + AnyBool& + operator=(bool value) + { + impl_.get().set(value ? 1 : 0); + return *this; + } + + /** + * @brief Get the value of the bool metric + * + * @return The value of the metric + */ + operator bool() const + { + auto const value = impl_.get().value(); + ASSERT(value == 0 || value == 1, "Invalid value for bool: {}", value); + return value == 1; + } +}; + +/** + * @brief Alias for Prometheus bool metric with GaugeInt implementation + */ +using Bool = AnyBool; + +} // namespace util::prometheus diff --git a/src/util/prometheus/Counter.hpp b/src/util/prometheus/Counter.hpp index 05b5c9ee..4708867e 100644 --- a/src/util/prometheus/Counter.hpp +++ b/src/util/prometheus/Counter.hpp @@ -83,6 +83,18 @@ struct AnyCounter : MetricBase, impl::AnyCounterBase { return *this; } + /** + * @brief Set the value of the counter + * + * @param value The value to set the counter to + */ + void + set(ValueType value) + { + ASSERT(value >= this->value(), "Cannot decrease a counter {}", this->name()); + this->pimpl_->set(value); + } + /** * @brief Reset the counter to zero */ diff --git a/src/util/prometheus/Prometheus.cpp b/src/util/prometheus/Prometheus.cpp index 595fc2b5..22c7f11a 100644 --- a/src/util/prometheus/Prometheus.cpp +++ b/src/util/prometheus/Prometheus.cpp @@ -21,6 +21,7 @@ #include "util/Assert.hpp" #include "util/config/Config.hpp" +#include "util/prometheus/Bool.hpp" #include "util/prometheus/Counter.hpp" #include "util/prometheus/Gauge.hpp" #include "util/prometheus/Histogram.hpp" @@ -52,6 +53,13 @@ convertBaseTo(MetricBase& metricBase) } // namespace +Bool +PrometheusImpl::boolMetric(std::string name, Labels labels, std::optional description) +{ + auto& metric = gaugeInt(std::move(name), std::move(labels), std::move(description)); + return Bool{metric}; +} + CounterInt& PrometheusImpl::counterInt(std::string name, Labels labels, std::optional description) { @@ -175,6 +183,12 @@ PrometheusService::init(util::Config const& config) instance_ = std::make_unique(enabled, compressReply); } +util::prometheus::Bool +PrometheusService::boolMetric(std::string name, util::prometheus::Labels labels, std::optional description) +{ + return instance().boolMetric(std::move(name), std::move(labels), std::move(description)); +} + util::prometheus::CounterInt& PrometheusService::counterInt(std::string name, util::prometheus::Labels labels, std::optional description) { diff --git a/src/util/prometheus/Prometheus.hpp b/src/util/prometheus/Prometheus.hpp index 12deb1e3..fe9629bd 100644 --- a/src/util/prometheus/Prometheus.hpp +++ b/src/util/prometheus/Prometheus.hpp @@ -20,6 +20,7 @@ #pragma once #include "util/config/Config.hpp" +#include "util/prometheus/Bool.hpp" #include "util/prometheus/Counter.hpp" #include "util/prometheus/Gauge.hpp" #include "util/prometheus/Histogram.hpp" @@ -54,6 +55,18 @@ public: virtual ~PrometheusInterface() = default; + /** + * @brief Get a bool based metric. It will be created if it doesn't exist + * @note Prometheus does not have a native bool type, so we use a counter with a value of 0 or 1 + * + * @param name The name of the metric + * @param labels The labels of the metric + * @param description The description of the metric + * @return The bool object + */ + virtual Bool + boolMetric(std::string name, Labels labels, std::optional description = std::nullopt) = 0; + /** * @brief Get an integer based counter metric. It will be created if it doesn't exist * @@ -176,6 +189,9 @@ class PrometheusImpl : public PrometheusInterface { public: using PrometheusInterface::PrometheusInterface; + Bool + boolMetric(std::string name, Labels labels, std::optional description = std::nullopt) override; + CounterInt& counterInt(std::string name, Labels labels, std::optional description) override; @@ -242,6 +258,22 @@ public: */ void static init(util::Config const& config = util::Config{}); + /** + * @brief Get a bool based metric. It will be created if it doesn't exist + * @note Prometheus does not have a native bool type, so we use a counter with a value of 0 or 1 + * + * @param name The name of the metric + * @param labels The labels of the metric + * @param description The description of the metric + * @return The bool object + */ + static util::prometheus::Bool + boolMetric( + std::string name, + util::prometheus::Labels labels, + std::optional description = std::nullopt + ); + /** * @brief Get an integer based counter metric. It will be created if it doesn't exist * diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index d6c0dc6f..9b172a1c 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -97,6 +97,7 @@ target_sources( util/BatchingTests.cpp util/LedgerUtilsTests.cpp # Prometheus support + util/prometheus/BoolTests.cpp util/prometheus/CounterTests.cpp util/prometheus/GaugeTests.cpp util/prometheus/HistogramTests.cpp diff --git a/unittests/Main.cpp b/unittests/Main.cpp index a867dd96..a99ca734 100644 --- a/unittests/Main.cpp +++ b/unittests/Main.cpp @@ -19,7 +19,6 @@ #include "util/TerminationHandler.hpp" #include "util/TestGlobals.hpp" -#include "util/prometheus/Prometheus.hpp" #include @@ -33,7 +32,6 @@ int main(int argc, char* argv[]) { util::setTerminationHandler(); - PrometheusService::init(); testing::InitGoogleTest(&argc, argv); TestGlobals::instance().parse(argc, argv); diff --git a/unittests/etl/AmendmentBlockHandlerTests.cpp b/unittests/etl/AmendmentBlockHandlerTests.cpp index 45450f46..e2c2c5ba 100644 --- a/unittests/etl/AmendmentBlockHandlerTests.cpp +++ b/unittests/etl/AmendmentBlockHandlerTests.cpp @@ -21,6 +21,7 @@ #include "etl/impl/AmendmentBlock.hpp" #include "util/FakeAmendmentBlockAction.hpp" #include "util/Fixtures.hpp" +#include "util/MockPrometheus.hpp" #include #include @@ -32,8 +33,7 @@ using namespace testing; using namespace etl; -class AmendmentBlockHandlerTest : public NoLoggerFixture { -protected: +struct AmendmentBlockHandlerTest : util::prometheus::WithPrometheus, NoLoggerFixture { using AmendmentBlockHandlerType = impl::AmendmentBlockHandler; boost::asio::io_context ioc_; diff --git a/unittests/etl/CacheLoaderTests.cpp b/unittests/etl/CacheLoaderTests.cpp index 8c348f3f..cbe7689d 100644 --- a/unittests/etl/CacheLoaderTests.cpp +++ b/unittests/etl/CacheLoaderTests.cpp @@ -24,6 +24,7 @@ #include "etl/impl/FakeDiffProvider.hpp" #include "util/Fixtures.hpp" #include "util/MockCache.hpp" +#include "util/MockPrometheus.hpp" #include "util/async/context/BasicExecutionContext.hpp" #include "util/config/Config.hpp" @@ -43,7 +44,7 @@ namespace { constexpr auto SEQ = 30; -struct CacheLoaderTest : MockBackendTest { +struct CacheLoaderTest : util::prometheus::WithPrometheus, MockBackendTest { void SetUp() override { diff --git a/unittests/etl/CursorProviderTests.cpp b/unittests/etl/CursorProviderTests.cpp index 40da9dc8..6803e455 100644 --- a/unittests/etl/CursorProviderTests.cpp +++ b/unittests/etl/CursorProviderTests.cpp @@ -21,6 +21,7 @@ #include "etl/impl/CursorProvider.hpp" #include "etl/impl/FakeDiffProvider.hpp" #include "util/Fixtures.hpp" +#include "util/MockPrometheus.hpp" #include #include @@ -36,7 +37,7 @@ namespace { constexpr auto SEQ = 30; -struct CursorProviderTest : MockBackendTestNaggy { +struct CursorProviderTest : util::prometheus::WithPrometheus, MockBackendTestNaggy { DiffProvider diffProvider; }; struct ParametrizedCursorProviderTest : CursorProviderTest, WithParamInterface {}; diff --git a/unittests/etl/ExtractorTests.cpp b/unittests/etl/ExtractorTests.cpp index 3fefded8..0e9b3103 100644 --- a/unittests/etl/ExtractorTests.cpp +++ b/unittests/etl/ExtractorTests.cpp @@ -24,6 +24,7 @@ #include "util/MockExtractionDataPipe.hpp" #include "util/MockLedgerFetcher.hpp" #include "util/MockNetworkValidatedLedgers.hpp" +#include "util/MockPrometheus.hpp" #include #include @@ -34,8 +35,7 @@ using namespace testing; using namespace etl; -class ETLExtractorTest : public NoLoggerFixture { -protected: +struct ETLExtractorTest : util::prometheus::WithPrometheus, NoLoggerFixture { using ExtractionDataPipeType = MockExtractionDataPipe; using LedgerFetcherType = MockLedgerFetcher; using ExtractorType = etl::impl::Extractor; @@ -48,7 +48,6 @@ protected: std::unique_ptr extractor_; -public: void SetUp() override { diff --git a/unittests/etl/GrpcSourceTests.cpp b/unittests/etl/GrpcSourceTests.cpp index 0be696b5..76997655 100644 --- a/unittests/etl/GrpcSourceTests.cpp +++ b/unittests/etl/GrpcSourceTests.cpp @@ -20,6 +20,7 @@ #include "etl/impl/GrpcSource.hpp" #include "util/Fixtures.hpp" #include "util/MockBackend.hpp" +#include "util/MockPrometheus.hpp" #include "util/MockXrpLedgerAPIService.hpp" #include "util/TestObject.hpp" #include "util/config/Config.hpp" @@ -39,7 +40,9 @@ using namespace etl::impl; -struct GrpcSourceTests : NoLoggerFixture, unittests::util::WithMockXrpLedgerAPIService { +struct GrpcSourceTests : NoLoggerFixture, + util::prometheus::WithPrometheus, + unittests::util::WithMockXrpLedgerAPIService { GrpcSourceTests() : WithMockXrpLedgerAPIService("localhost:50051") , mockBackend_(std::make_shared>(util::Config{})) diff --git a/unittests/etl/LedgerPublisherTests.cpp b/unittests/etl/LedgerPublisherTests.cpp index eec82ecb..aa9dbb56 100644 --- a/unittests/etl/LedgerPublisherTests.cpp +++ b/unittests/etl/LedgerPublisherTests.cpp @@ -23,6 +23,7 @@ #include "etl/impl/LedgerPublisher.hpp" #include "util/Fixtures.hpp" #include "util/MockCache.hpp" +#include "util/MockPrometheus.hpp" #include "util/MockSubscriptionManager.hpp" #include "util/TestObject.hpp" #include "util/config/Config.hpp" @@ -49,7 +50,10 @@ static auto constexpr LEDGERHASH = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A static auto constexpr SEQ = 30; static auto constexpr AGE = 800; -class ETLLedgerPublisherTest : public MockBackendTest, public SyncAsioContextTest, public MockSubscriptionManagerTest { +struct ETLLedgerPublisherTest : util::prometheus::WithPrometheus, + MockBackendTest, + SyncAsioContextTest, + MockSubscriptionManagerTest { void SetUp() override { diff --git a/unittests/etl/TransformerTests.cpp b/unittests/etl/TransformerTests.cpp index eee59bee..44bf5e26 100644 --- a/unittests/etl/TransformerTests.cpp +++ b/unittests/etl/TransformerTests.cpp @@ -25,6 +25,7 @@ #include "util/MockExtractionDataPipe.hpp" #include "util/MockLedgerLoader.hpp" #include "util/MockLedgerPublisher.hpp" +#include "util/MockPrometheus.hpp" #include "util/StringUtils.hpp" #include @@ -46,8 +47,7 @@ constexpr static auto RAW_HEADER = "3E2232B33EF57CECAC2816E3122816E31A0A00F8377CD95DFA484CFAE282656A58" "CE5AA29652EFFD80AC59CD91416E4E13DBBE"; -class ETLTransformerTest : public MockBackendTest { -protected: +struct ETLTransformerTest : util::prometheus::WithPrometheus, MockBackendTest { using DataType = FakeFetchResponse; using ExtractionDataPipeType = MockExtractionDataPipe; using LedgerLoaderType = MockLedgerLoader; @@ -64,7 +64,6 @@ protected: std::unique_ptr transformer_; -public: void SetUp() override { diff --git a/unittests/feed/FeedTestUtil.hpp b/unittests/feed/FeedTestUtil.hpp index d33ac159..804e4165 100644 --- a/unittests/feed/FeedTestUtil.hpp +++ b/unittests/feed/FeedTestUtil.hpp @@ -20,6 +20,7 @@ #pragma once #include "util/Fixtures.hpp" +#include "util/MockPrometheus.hpp" #include "util/MockWsBase.hpp" #include "web/interface/ConnectionBase.hpp" @@ -33,7 +34,7 @@ // Base class for feed tests, providing easy way to access the received feed template -class FeedBaseTest : public SyncAsioContextTest, public MockBackendTest { +class FeedBaseTest : public util::prometheus::WithPrometheus, public SyncAsioContextTest, public MockBackendTest { protected: std::shared_ptr sessionPtr; std::shared_ptr testFeedPtr; diff --git a/unittests/feed/SubscriptionManagerTests.cpp b/unittests/feed/SubscriptionManagerTests.cpp index f5564c0e..6d78aedb 100644 --- a/unittests/feed/SubscriptionManagerTests.cpp +++ b/unittests/feed/SubscriptionManagerTests.cpp @@ -21,6 +21,7 @@ #include "feed/FeedTestUtil.hpp" #include "feed/SubscriptionManager.hpp" #include "util/Fixtures.hpp" +#include "util/MockPrometheus.hpp" #include "util/MockWsBase.hpp" #include "util/TestObject.hpp" #include "web/interface/ConnectionBase.hpp" @@ -52,7 +53,9 @@ namespace json = boost::json; using namespace feed; using namespace feed::impl; -class SubscriptionManagerTest : public MockBackendTest, public SyncAsioContextTest { +class SubscriptionManagerTest : public util::prometheus::WithPrometheus, + public MockBackendTest, + public SyncAsioContextTest { protected: std::shared_ptr SubscriptionManagerPtr; std::shared_ptr session; diff --git a/unittests/rpc/RPCHelpersTests.cpp b/unittests/rpc/RPCHelpersTests.cpp index 7205173e..fa608162 100644 --- a/unittests/rpc/RPCHelpersTests.cpp +++ b/unittests/rpc/RPCHelpersTests.cpp @@ -23,6 +23,7 @@ #include "rpc/RPCHelpers.hpp" #include "rpc/common/Types.hpp" #include "util/Fixtures.hpp" +#include "util/MockPrometheus.hpp" #include "util/TestObject.hpp" #include @@ -57,7 +58,7 @@ constexpr static auto INDEX1 = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B25 constexpr static auto INDEX2 = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC322"; constexpr static auto TXNID = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC321"; -class RPCHelpersTest : public MockBackendTest, public SyncAsioContextTest { +class RPCHelpersTest : public util::prometheus::WithPrometheus, public MockBackendTest, public SyncAsioContextTest { void SetUp() override { diff --git a/unittests/rpc/handlers/SubscribeTests.cpp b/unittests/rpc/handlers/SubscribeTests.cpp index 1e08bc71..c1cbaa93 100644 --- a/unittests/rpc/handlers/SubscribeTests.cpp +++ b/unittests/rpc/handlers/SubscribeTests.cpp @@ -25,7 +25,6 @@ #include "rpc/common/Types.hpp" #include "rpc/handlers/Subscribe.hpp" #include "util/Fixtures.hpp" -#include "util/MockPrometheus.hpp" #include "util/MockWsBase.hpp" #include "util/TestObject.hpp" #include "web/interface/ConnectionBase.hpp" @@ -62,7 +61,7 @@ constexpr static auto PAYS20XRPGETS10USDBOOKDIR = "7B1767D41DBCE79D9585CF9D0262A constexpr static auto INDEX1 = "1B8590C01B0006EDFA9ED60296DD052DC5E90F99659B25014D08E1BC983515BC"; constexpr static auto INDEX2 = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC321"; -class RPCSubscribeHandlerTest : public util::prometheus::WithPrometheus, public HandlerBaseTest { +class RPCSubscribeHandlerTest : public HandlerBaseTest { protected: void SetUp() override diff --git a/unittests/util/Fixtures.hpp b/unittests/util/Fixtures.hpp index 318cf8b4..8ebede49 100644 --- a/unittests/util/Fixtures.hpp +++ b/unittests/util/Fixtures.hpp @@ -24,6 +24,7 @@ #include "util/MockCounters.hpp" #include "util/MockETLService.hpp" #include "util/MockLoadBalancer.hpp" +#include "util/MockPrometheus.hpp" #include "util/MockSubscriptionManager.hpp" #include "util/log/Logger.hpp" @@ -349,6 +350,7 @@ protected: */ template