Files
clio/src/data/BackendCounters.hpp
2026-05-01 15:31:45 +01:00

179 lines
4.8 KiB
C++

#pragma once
#include "util/prometheus/Counter.hpp"
#include "util/prometheus/Gauge.hpp"
#include "util/prometheus/Histogram.hpp"
#include <boost/json/object.hpp>
#include <chrono>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
namespace data {
/**
* @brief A concept for a class that can be used to count backend operations.
*/
template <typename T>
concept SomeBackendCounters = requires(T a) {
typename T::PtrType;
{ a.registerTooBusy() } -> std::same_as<void>;
{ a.registerWriteSync(std::chrono::steady_clock::time_point{}) } -> std::same_as<void>;
{ a.registerWriteSyncRetry() } -> std::same_as<void>;
{ a.registerWriteStarted() } -> std::same_as<void>;
{ a.registerWriteFinished(std::chrono::steady_clock::time_point{}) } -> std::same_as<void>;
{ a.registerWriteRetry() } -> std::same_as<void>;
{ a.registerReadStarted(std::uint64_t{}) } -> std::same_as<void>;
{
a.registerReadFinished(std::chrono::steady_clock::time_point{}, std::uint64_t{})
} -> std::same_as<void>;
{ a.registerReadRetry(std::uint64_t{}) } -> std::same_as<void>;
{ a.registerReadError(std::uint64_t{}) } -> std::same_as<void>;
{ a.report() } -> std::same_as<boost::json::object>;
};
/**
* @brief Holds statistics about the backend.
*
* @note This class is thread-safe.
*/
class BackendCounters {
public:
using PtrType = std::shared_ptr<BackendCounters>;
/**
* @brief Create a new BackendCounters object
*
* @return A shared pointer to the new BackendCounters object
*/
static PtrType
make();
/**
* @brief Register that the backend was too busy to process a request
*/
void
registerTooBusy();
/**
* @brief Register that a write operation was started
*
* @param startTime The time the operation was started
*/
void
registerWriteSync(std::chrono::steady_clock::time_point startTime);
/**
* @brief Register that a write operation was retried
*/
void
registerWriteSyncRetry();
/**
* @brief Register that a write operation was started
*/
void
registerWriteStarted();
/**
* @brief Register that a write operation was finished
*
* @param startTime The time the operation was started
*/
void
registerWriteFinished(std::chrono::steady_clock::time_point startTime);
/**
* @brief Register that a write operation was retried
*/
void
registerWriteRetry();
/**
* @brief Register that one or more read operations were started
*
* @param count The number of operations started
*/
void
registerReadStarted(std::uint64_t count = 1u);
/**
* @brief Register that one or more read operations were finished
*
* @param startTime The time the operations were started
* @param count The number of operations finished
*/
void
registerReadFinished(std::chrono::steady_clock::time_point startTime, std::uint64_t count = 1u);
/**
* @brief Register that one or more read operations were retried
*
* @param count The number of operations retried
*/
void
registerReadRetry(std::uint64_t count = 1u);
/**
* @brief Register that one or more read operations had an error
*
* @param count The number of operations with an error
*/
void
registerReadError(std::uint64_t count = 1u);
/**
* @brief Get a report of the backend counters
*
* @return The report
*/
[[nodiscard]] boost::json::object
report() const;
private:
BackendCounters();
class AsyncOperationCounters {
public:
AsyncOperationCounters(std::string name);
void
registerStarted(std::uint64_t count);
void
registerFinished(std::uint64_t count);
void
registerRetry(std::uint64_t count);
void
registerError(std::uint64_t count);
[[nodiscard]] boost::json::object
report() const;
private:
std::string name_;
std::reference_wrapper<util::prometheus::GaugeInt> pendingCounter_;
std::reference_wrapper<util::prometheus::CounterInt> completedCounter_;
std::reference_wrapper<util::prometheus::CounterInt> retryCounter_;
std::reference_wrapper<util::prometheus::CounterInt> errorCounter_;
};
std::reference_wrapper<util::prometheus::CounterInt> tooBusyCounter_;
std::reference_wrapper<util::prometheus::CounterInt> writeSyncCounter_;
std::reference_wrapper<util::prometheus::CounterInt> writeSyncRetryCounter_;
AsyncOperationCounters asyncWriteCounters_{"write_async"};
AsyncOperationCounters asyncReadCounters_{"read_async"};
std::reference_wrapper<util::prometheus::HistogramInt> readDurationHistogram_;
std::reference_wrapper<util::prometheus::HistogramInt> writeDurationHistogram_;
};
} // namespace data