#pragma once #include "metric_consumer.h" #include #include namespace NMonitoring { /////////////////////////////////////////////////////////////////////////////// // IMetric /////////////////////////////////////////////////////////////////////////////// class IMetric : public TThrRefBase { public: virtual ~IMetric() = default; virtual EMetricType Type() const noexcept = 0; virtual void Accept(TInstant time, IMetricConsumer* consumer) const = 0; }; using IMetricPtr = TIntrusivePtr; class IGauge: public IMetric { public: EMetricType Type() const noexcept final { return EMetricType::GAUGE; } virtual double Add(double n) noexcept = 0; virtual void Set(double n) noexcept = 0; virtual double Get() const noexcept = 0; virtual void Reset() noexcept { Set(0); } }; class ILazyGauge: public IMetric { public: EMetricType Type() const noexcept final { return EMetricType::GAUGE; } virtual double Get() const noexcept = 0; }; class IIntGauge: public IMetric { public: EMetricType Type() const noexcept final { return EMetricType::IGAUGE; } virtual i64 Add(i64 n) noexcept = 0; virtual i64 Inc() noexcept { return Add(1); } virtual i64 Dec() noexcept { return Add(-1); } virtual void Set(i64 value) noexcept = 0; virtual i64 Get() const noexcept = 0; virtual void Reset() noexcept { Set(0); } }; class ILazyIntGauge: public IMetric { public: EMetricType Type() const noexcept final { return EMetricType::IGAUGE; } virtual i64 Get() const noexcept = 0; }; class ICounter: public IMetric { public: EMetricType Type() const noexcept final { return EMetricType::COUNTER; } virtual ui64 Inc() noexcept { return Add(1); } virtual ui64 Add(ui64 n) noexcept = 0; virtual ui64 Get() const noexcept = 0; virtual void Reset() noexcept = 0; }; class ILazyCounter: public IMetric { public: EMetricType Type() const noexcept final { return EMetricType::COUNTER; } virtual ui64 Get() const noexcept = 0; }; class IRate: public IMetric { public: EMetricType Type() const noexcept final { return EMetricType::RATE; } virtual ui64 Inc() noexcept { return Add(1); } virtual ui64 Add(ui64 n) noexcept = 0; virtual ui64 Get() const noexcept = 0; virtual void Reset() noexcept = 0; }; class ILazyRate: public IMetric { public: EMetricType Type() const noexcept final { return EMetricType::RATE; } virtual ui64 Get() const noexcept = 0; }; class IHistogram: public IMetric { public: explicit IHistogram(bool isRate) : IsRate_{isRate} { } EMetricType Type() const noexcept final { return IsRate_ ? EMetricType::HIST_RATE : EMetricType::HIST; } virtual void Record(double value) = 0; virtual void Record(double value, ui32 count) = 0; virtual IHistogramSnapshotPtr TakeSnapshot() const = 0; virtual void Reset() = 0; protected: const bool IsRate_; }; /////////////////////////////////////////////////////////////////////////////// // TGauge /////////////////////////////////////////////////////////////////////////////// class TGauge final: public IGauge { public: explicit TGauge(double value = 0.0) { Set(value); } double Add(double n) noexcept override { double newValue; double oldValue = Get(); do { newValue = oldValue + n; } while (!Value_.compare_exchange_weak(oldValue, newValue, std::memory_order_release, std::memory_order_consume)); return newValue; } void Set(double n) noexcept override { Value_.store(n, std::memory_order_relaxed); } double Get() const noexcept override { return Value_.load(std::memory_order_relaxed); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnDouble(time, Get()); } private: std::atomic Value_; }; /////////////////////////////////////////////////////////////////////////////// // TLazyGauge /////////////////////////////////////////////////////////////////////////////// class TLazyGauge final: public ILazyGauge { public: explicit TLazyGauge(std::function supplier) : Supplier_(std::move(supplier)) { } double Get() const noexcept override { return Supplier_(); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnDouble(time, Get()); } private: std::function Supplier_; }; /////////////////////////////////////////////////////////////////////////////// // TIntGauge /////////////////////////////////////////////////////////////////////////////// class TIntGauge final: public IIntGauge { public: explicit TIntGauge(i64 value = 0) { Set(value); } i64 Add(i64 n) noexcept override { return Value_.fetch_add(n, std::memory_order_relaxed) + n; } void Set(i64 value) noexcept override { Value_.store(value, std::memory_order_relaxed); } i64 Get() const noexcept override { return Value_.load(std::memory_order_relaxed); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnInt64(time, Get()); } private: std::atomic_int64_t Value_; }; /////////////////////////////////////////////////////////////////////////////// // TLazyIntGauge /////////////////////////////////////////////////////////////////////////////// class TLazyIntGauge final: public ILazyIntGauge { public: explicit TLazyIntGauge(std::function supplier) : Supplier_(std::move(supplier)) { } i64 Get() const noexcept override { return Supplier_(); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnInt64(time, Get()); } private: std::function Supplier_; }; /////////////////////////////////////////////////////////////////////////////// // TCounter /////////////////////////////////////////////////////////////////////////////// class TCounter final: public ICounter { public: explicit TCounter(ui64 value = 0) { Value_.store(value, std::memory_order_relaxed); } ui64 Add(ui64 n) noexcept override { return Value_.fetch_add(n, std::memory_order_relaxed) + n; } ui64 Get() const noexcept override { return Value_.load(std::memory_order_relaxed); } void Reset() noexcept override { Value_.store(0, std::memory_order_relaxed); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnUint64(time, Get()); } private: std::atomic_uint64_t Value_; }; /////////////////////////////////////////////////////////////////////////////// // TLazyCounter /////////////////////////////////////////////////////////////////////////////// class TLazyCounter final: public ILazyCounter { public: explicit TLazyCounter(std::function supplier) : Supplier_(std::move(supplier)) { } ui64 Get() const noexcept override { return Supplier_(); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnUint64(time, Get()); } private: std::function Supplier_; }; /////////////////////////////////////////////////////////////////////////////// // TRate /////////////////////////////////////////////////////////////////////////////// class TRate final: public IRate { public: explicit TRate(ui64 value = 0) { Value_.store(value, std::memory_order_relaxed); } ui64 Add(ui64 n) noexcept override { return Value_.fetch_add(n, std::memory_order_relaxed) + n; } ui64 Get() const noexcept override { return Value_.load(std::memory_order_relaxed); } void Reset() noexcept override { Value_.store(0, std::memory_order_relaxed); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnUint64(time, Get()); } private: std::atomic_uint64_t Value_; }; /////////////////////////////////////////////////////////////////////////////// // TLazyRate /////////////////////////////////////////////////////////////////////////////// class TLazyRate final: public ILazyRate { public: explicit TLazyRate(std::function supplier) : Supplier_(std::move(supplier)) { } ui64 Get() const noexcept override { return Supplier_(); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnUint64(time, Get()); } private: std::function Supplier_; }; /////////////////////////////////////////////////////////////////////////////// // THistogram /////////////////////////////////////////////////////////////////////////////// class THistogram final: public IHistogram { public: THistogram(IHistogramCollectorPtr collector, bool isRate) : IHistogram(isRate) , Collector_(std::move(collector)) { } THistogram(std::function makeHistogramCollector, bool isRate) : IHistogram(isRate) , Collector_(makeHistogramCollector()) { } void Record(double value) override { Collector_->Collect(value); } void Record(double value, ui32 count) override { Collector_->Collect(value, count); } void Accept(TInstant time, IMetricConsumer* consumer) const override { consumer->OnHistogram(time, TakeSnapshot()); } IHistogramSnapshotPtr TakeSnapshot() const override { return Collector_->Snapshot(); } void Reset() override { Collector_->Reset(); } private: IHistogramCollectorPtr Collector_; }; }