aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/monlib/metrics/metric.h
blob: cf736e8d808e4c9932c61cc3355c576ad131492f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11









                                                                                   
                                        





                                                                                
                                              
                                  
           
                                                 








                                                  






                                                 
                                     
           
                                                 
















                                                 







                                                 
                                    
           
                                                 









                                              







                                                 
                                 
           
                                                 






                                              
                                          
      







                                                 
                                      




                                        
                                                                        
         
                                                          





                                                               

                                                                                   
                                       



                                             

                                                
                
                                                                                                                              
 
                            
         
                                                       
         
                                                          





                                                                              
                                   

                                                                                   




















                                                                                   
                                                                                   
                                             



                                           
                                                                      
         
                                                           
         
                                                          





                                                                              
                                   

                                                                                   




















                                                                                   



                                                                                   
                                                           
         
                                                                      
         
                                                          
         
                                                       





                                                                              
                                    

                                                                                   




















                                                                                   
                                                                                   
                                     
                                        
                                                           
         
                                                                      
         
                                                          









                                                                              
                                    

                                                                                   




















                                                                                   
                                                                                   
                                               
                                                                 
                                              

         




                                                                                               







                                                                              
                                                        
         
                                                             

                                          
                               
                                
 


                                          
#pragma once

#include "metric_consumer.h"

#include <util/datetime/base.h>
#include <util/generic/ptr.h>

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<IMetric>;

    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<double> Value_;
    };

    ///////////////////////////////////////////////////////////////////////////////
    // TLazyGauge
    ///////////////////////////////////////////////////////////////////////////////
    class TLazyGauge final: public ILazyGauge {
    public:
        explicit TLazyGauge(std::function<double()> 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<double()> 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<i64()> 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<i64()> 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<ui64()> 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<ui64()> 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<ui64()> 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<ui64()> Supplier_;
    };

    ///////////////////////////////////////////////////////////////////////////////
    // THistogram
    ///////////////////////////////////////////////////////////////////////////////
    class THistogram final: public IHistogram {
    public:
        THistogram(IHistogramCollectorPtr collector, bool isRate)
            : IHistogram(isRate)
            , Collector_(std::move(collector))
        {
        }

        THistogram(std::function<IHistogramCollectorPtr()> 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_;
    };
}