aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/monlib/metrics/metric_registry.cpp
blob: 245f65702d1db5e65f47ffffed631e7bf1920f8a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
                            
                 







                                                                              
                                                                                                                                                




                                                    
                                           
                                              


                                    
                                                                        
                                        

                                
                                                 
                                                                        
                                                  
 
                                                                 


                                     
                                                                                   
                                                  
                                        

                                            



                                                                        
                                                    


                                                                                      

                                                       


                                                                                      
     
                                                                                              


                                                                                                                        

                                                                                                 


                                                                                                                           
     
                                                          


                                                                                          

                                                             


                                                                                          
     
                                                                                                 


                                                                                                                           

                                                                                                    


                                                                                                                              
     
                                                        


                                                                                          
     
                                                           


                                                                                          
     
                                                                                                


                                                                                                                          

                                                                                                   


                                                                                                                             
     
                                                  


                                                                                    
     
                                                     


                                                                                    
     
                                                                                          


                                                                                                                    

                                                                                             


                                                                                                                       
     
                                                                                                     


                                                                                                                               
     
                                                                                                        


                                                                                                                                  
     
                                                                                                                     


                                                                                                                                               
     
                                                                                                                        


                                                                                                                                                  
     
                                                                                                  


                                                                                                                            

                                                                                                     


                                                                                                                               
     
                                                                                                                  


                                                                                                                                            
     
                                                                                                                     


                                                                                                                                               
     
                                   
                              
                                                     























                                                                
                                   
                              

                         
                                                                                         
                                                                                                
         
                                 
 
                                            
                                                                                             
                                                                 



                                                                                                                                  
             
 
         
                                                                                    
 
                                  
                                                                   
                                                            
                                                                            
                                                                                                                    
                    
                                                                                                       
             
                                                                  
         
 
                                                                        
                              
                               
     
                                                                                  

                                     

                                                   
         
                                                                
 
         
                                 
                                                
                                            
                                         
             
         
                                             









                                                     
         
                                
 
                                                                                  
                             
 
                                             










                                                           

         
#include "metric_registry.h"

#include <memory>

namespace NMonitoring {
    namespace {
        void ConsumeLabels(IMetricConsumer* consumer, const ILabels& labels) {
            for (auto&& label: labels) {
                consumer->OnLabel(label.Name(), label.Value());
            }
        }

        template <typename TLabelsConsumer>
        void ConsumeMetric(TInstant time, IMetricConsumer* consumer, IMetric* metric, TLabelsConsumer&& labelsConsumer, TMetricOpts opts = {}) {
            consumer->OnMetricBegin(metric->Type());

            // (1) add labels
            consumer->OnLabelsBegin();
            labelsConsumer();
            consumer->OnLabelsEnd();
            // (2) add time and value
            metric->Accept(time, consumer);
            // (3) add flag
            consumer->OnMemOnly(opts.MemOnly);
            consumer->OnMetricEnd();
        }
    }

    void WriteLabels(IMetricConsumer* consumer, const ILabels& labels) {
        consumer->OnLabelsBegin();
        ConsumeLabels(consumer, labels);
        consumer->OnLabelsEnd();
    }

    TMetricRegistry::TMetricRegistry() = default;
    TMetricRegistry::TMetricRegistry(TMetricRegistry&& other) = default;

    TMetricRegistry::~TMetricRegistry() = default;

    TMetricRegistry::TMetricRegistry(const TLabels& commonLabels)
        : TMetricRegistry{}
    {
        CommonLabels_ = commonLabels;
    }

    TMetricRegistry& TMetricRegistry::operator=(TMetricRegistry&& other) = default;

    TMetricRegistry* TMetricRegistry::Instance() {
        //return SharedInstance().get();
        return Singleton<TMetricRegistry>();
    }

    std::shared_ptr<TMetricRegistry> TMetricRegistry::SharedInstance() {
        static auto instance(std::make_shared<TMetricRegistry>());
        return instance;
    }

    TGauge* TMetricRegistry::Gauge(TLabels labels) {
        return GaugeWithOpts(std::move(labels));
    }
    TGauge* TMetricRegistry::GaugeWithOpts(TLabels labels, TMetricOpts opts) {
        return Metric<TGauge, EMetricType::GAUGE>(std::move(labels), std::move(opts));
    }

    TGauge* TMetricRegistry::Gauge(ILabelsPtr labels) {
        return GaugeWithOpts(std::move(labels));
    }
    TGauge* TMetricRegistry::GaugeWithOpts(ILabelsPtr labels, TMetricOpts opts) {
        return Metric<TGauge, EMetricType::GAUGE>(std::move(labels), std::move(opts));
    }

    TLazyGauge* TMetricRegistry::LazyGauge(TLabels labels, std::function<double()> supplier) {
        return LazyGaugeWithOpts(std::move(labels), std::move(supplier));
    }
    TLazyGauge* TMetricRegistry::LazyGaugeWithOpts(TLabels labels, std::function<double()> supplier, TMetricOpts opts) {
        return Metric<TLazyGauge, EMetricType::GAUGE>(std::move(labels),std::move(opts), std::move(supplier));
    }

    TLazyGauge* TMetricRegistry::LazyGauge(ILabelsPtr labels, std::function<double()> supplier) {
        return LazyGaugeWithOpts(std::move(labels), std::move(supplier));
    }
    TLazyGauge* TMetricRegistry::LazyGaugeWithOpts(ILabelsPtr labels, std::function<double()> supplier, TMetricOpts opts) {
        return Metric<TLazyGauge, EMetricType::GAUGE>(std::move(labels), std::move(opts), std::move(supplier));
    }

    TIntGauge* TMetricRegistry::IntGauge(TLabels labels) {
        return IntGaugeWithOpts(std::move(labels));
    }
    TIntGauge* TMetricRegistry::IntGaugeWithOpts(TLabels labels, TMetricOpts opts) {
        return Metric<TIntGauge, EMetricType::IGAUGE>(std::move(labels), std::move(opts));
    }

    TIntGauge* TMetricRegistry::IntGauge(ILabelsPtr labels) {
        return IntGaugeWithOpts(std::move(labels));
    }
    TIntGauge* TMetricRegistry::IntGaugeWithOpts(ILabelsPtr labels, TMetricOpts opts) {
        return Metric<TIntGauge, EMetricType::IGAUGE>(std::move(labels), std::move(opts));
    }

    TLazyIntGauge* TMetricRegistry::LazyIntGauge(TLabels labels, std::function<i64()> supplier) {
        return LazyIntGaugeWithOpts(std::move(labels), std::move(supplier));
    }
    TLazyIntGauge* TMetricRegistry::LazyIntGaugeWithOpts(TLabels labels, std::function<i64()> supplier, TMetricOpts opts) {
        return Metric<TLazyIntGauge, EMetricType::IGAUGE>(std::move(labels), std::move(opts), std::move(supplier));
    }

    TLazyIntGauge* TMetricRegistry::LazyIntGauge(ILabelsPtr labels, std::function<i64()> supplier) {
        return LazyIntGaugeWithOpts(std::move(labels), std::move(supplier));
    }
    TLazyIntGauge* TMetricRegistry::LazyIntGaugeWithOpts(ILabelsPtr labels, std::function<i64()> supplier, TMetricOpts opts) {
        return Metric<TLazyIntGauge, EMetricType::IGAUGE>(std::move(labels), std::move(opts), std::move(supplier));
    }

    TCounter* TMetricRegistry::Counter(TLabels labels) {
        return CounterWithOpts(std::move(labels));
    }
    TCounter* TMetricRegistry::CounterWithOpts(TLabels labels, TMetricOpts opts) {
        return Metric<TCounter, EMetricType::COUNTER>(std::move(labels), std::move(opts));
    }

    TCounter* TMetricRegistry::Counter(ILabelsPtr labels) {
        return CounterWithOpts(std::move(labels));
    }
    TCounter* TMetricRegistry::CounterWithOpts(ILabelsPtr labels, TMetricOpts opts) {
        return Metric<TCounter, EMetricType::COUNTER>(std::move(labels), std::move(opts));
    }

    TLazyCounter* TMetricRegistry::LazyCounter(TLabels labels, std::function<ui64()> supplier) {
        return LazyCounterWithOpts(std::move(labels), std::move(supplier));
    }
    TLazyCounter* TMetricRegistry::LazyCounterWithOpts(TLabels labels, std::function<ui64()> supplier, TMetricOpts opts) {
        return Metric<TLazyCounter, EMetricType::COUNTER>(std::move(labels), std::move(opts), std::move(supplier));
    }

    TLazyCounter* TMetricRegistry::LazyCounter(ILabelsPtr labels, std::function<ui64()> supplier) {
        return LazyCounterWithOpts(std::move(labels), std::move(supplier));
    }
    TLazyCounter* TMetricRegistry::LazyCounterWithOpts(ILabelsPtr labels, std::function<ui64()> supplier, TMetricOpts opts) {
        return Metric<TLazyCounter, EMetricType::COUNTER>(std::move(labels), std::move(opts), std::move(supplier));
    }

    TRate* TMetricRegistry::Rate(TLabels labels) {
        return RateWithOpts(std::move(labels));
    }
    TRate* TMetricRegistry::RateWithOpts(TLabels labels, TMetricOpts opts) {
        return Metric<TRate, EMetricType::RATE>(std::move(labels), std::move(opts));
    }

    TRate* TMetricRegistry::Rate(ILabelsPtr labels) {
        return RateWithOpts(std::move(labels));
    }
    TRate* TMetricRegistry::RateWithOpts(ILabelsPtr labels, TMetricOpts opts) {
        return Metric<TRate, EMetricType::RATE>(std::move(labels), std::move(opts));
    }

    TLazyRate* TMetricRegistry::LazyRate(TLabels labels, std::function<ui64()> supplier) {
        return LazyRateWithOpts(std::move(labels), std::move(supplier));
    }
    TLazyRate* TMetricRegistry::LazyRateWithOpts(TLabels labels, std::function<ui64()> supplier, TMetricOpts opts) {
        return Metric<TLazyRate, EMetricType::RATE>(std::move(labels), std::move(opts), std::move(supplier));
    }

    TLazyRate* TMetricRegistry::LazyRate(ILabelsPtr labels, std::function<ui64()> supplier) {
        return LazyRateWithOpts(std::move(labels), std::move(supplier));
    }
    TLazyRate* TMetricRegistry::LazyRateWithOpts(ILabelsPtr labels, std::function<ui64()> supplier, TMetricOpts opts) {
        return Metric<TLazyRate, EMetricType::RATE>(std::move(labels), std::move(opts), std::move(supplier));
    }

    THistogram* TMetricRegistry::HistogramCounter(TLabels labels, IHistogramCollectorPtr collector) {
        return HistogramCounterWithOpts(std::move(labels), std::move(collector));
    }
    THistogram* TMetricRegistry::HistogramCounterWithOpts(TLabels labels, IHistogramCollectorPtr collector, TMetricOpts opts) {
        return Metric<THistogram, EMetricType::HIST>(std::move(labels), std::move(opts), std::move(collector), false);
    }

    THistogram* TMetricRegistry::HistogramCounter(ILabelsPtr labels, IHistogramCollectorPtr collector) {
        return HistogramCounterWithOpts(std::move(labels), std::move(collector));
    }
    THistogram* TMetricRegistry::HistogramCounterWithOpts(ILabelsPtr labels, IHistogramCollectorPtr collector, TMetricOpts opts) {
        return Metric<THistogram, EMetricType::HIST>(std::move(labels), std::move(opts), std::move(collector), false);
    }

    THistogram* TMetricRegistry::HistogramCounter(TLabels labels, std::function<IHistogramCollectorPtr()> supplier) {
        return HistogramCounterWithOpts(std::move(labels), std::move(supplier));
    }
    THistogram* TMetricRegistry::HistogramCounterWithOpts(TLabels labels, std::function<IHistogramCollectorPtr()> supplier, TMetricOpts opts) {
        return Metric<THistogram, EMetricType::HIST>(std::move(labels), std::move(opts), std::move(supplier), false);
    }

    THistogram* TMetricRegistry::HistogramCounter(ILabelsPtr labels, std::function<IHistogramCollectorPtr()> supplier) {
        return HistogramCounterWithOpts(std::move(labels), std::move(supplier));
    }
    THistogram* TMetricRegistry::HistogramCounterWithOpts(ILabelsPtr labels, std::function<IHistogramCollectorPtr()> supplier, TMetricOpts opts) {
        return Metric<THistogram, EMetricType::HIST>(std::move(labels), std::move(opts), std::move(supplier), false);
    }

    THistogram* TMetricRegistry::HistogramRate(TLabels labels, IHistogramCollectorPtr collector) {
        return HistogramRateWithOpts(std::move(labels), std::move(collector));
    }
    THistogram* TMetricRegistry::HistogramRateWithOpts(TLabels labels, IHistogramCollectorPtr collector, TMetricOpts opts) {
        return Metric<THistogram, EMetricType::HIST_RATE>(std::move(labels), std::move(opts), std::move(collector), true);
    }

    THistogram* TMetricRegistry::HistogramRate(ILabelsPtr labels, IHistogramCollectorPtr collector) {
        return HistogramRateWithOpts(std::move(labels), std::move(collector));
    }
    THistogram* TMetricRegistry::HistogramRateWithOpts(ILabelsPtr labels, IHistogramCollectorPtr collector, TMetricOpts opts) {
        return Metric<THistogram, EMetricType::HIST_RATE>(std::move(labels), std::move(opts), std::move(collector), true);
    }

    THistogram* TMetricRegistry::HistogramRate(TLabels labels, std::function<IHistogramCollectorPtr()> supplier) {
        return HistogramRateWithOpts(std::move(labels), std::move(supplier));
    }
    THistogram* TMetricRegistry::HistogramRateWithOpts(TLabels labels, std::function<IHistogramCollectorPtr()> supplier, TMetricOpts opts) {
        return Metric<THistogram, EMetricType::HIST_RATE>(std::move(labels), std::move(opts), std::move(supplier), true);
    }

    THistogram* TMetricRegistry::HistogramRate(ILabelsPtr labels, std::function<IHistogramCollectorPtr()> supplier) {
        return HistogramRateWithOpts(std::move(labels), std::move(supplier));
    }
    THistogram* TMetricRegistry::HistogramRateWithOpts(ILabelsPtr labels, std::function<IHistogramCollectorPtr()> supplier, TMetricOpts opts) {
        return Metric<THistogram, EMetricType::HIST_RATE>(std::move(labels), std::move(opts), std::move(supplier), true);
    }

    void TMetricRegistry::Reset() {
        TWriteGuard g{*Lock_};
        for (auto& [label, metricValue] : Metrics_) {
            auto metric = metricValue.Metric;
            switch (metric->Type()) {
            case EMetricType::GAUGE:
                static_cast<TGauge*>(metric.Get())->Set(.0);
                break;
            case EMetricType::IGAUGE:
                static_cast<TIntGauge*>(metric.Get())->Set(0);
                break;
            case EMetricType::COUNTER:
                static_cast<TCounter*>(metric.Get())->Reset();
                break;
            case EMetricType::RATE:
                static_cast<TRate*>(metric.Get())->Reset();
                break;
            case EMetricType::HIST:
            case EMetricType::HIST_RATE:
                static_cast<THistogram*>(metric.Get())->Reset();
                break;
            case EMetricType::UNKNOWN:
            case EMetricType::DSUMMARY:
            case EMetricType::LOGHIST:
                break;
            }
        }
    }

    void TMetricRegistry::Clear() {
        TWriteGuard g{*Lock_};
        Metrics_.clear();
    }

    template <typename TMetric, EMetricType type, typename TLabelsType, typename... Args>
    TMetric* TMetricRegistry::Metric(TLabelsType&& labels, TMetricOpts&& opts, Args&&... args) {
        {
            TReadGuard g{*Lock_};

            auto it = Metrics_.find(labels);
            if (it != Metrics_.end()) {
                Y_ENSURE(it->second.Metric->Type() == type, "cannot create metric " << labels
                        << " with type " << MetricTypeToStr(type)
                        << ", because registry already has same metric with type " << MetricTypeToStr(it->second.Metric->Type()));
                Y_ENSURE(it->second.Opts.MemOnly == opts.MemOnly,"cannot create metric " << labels
                        << " with memOnly=" << opts.MemOnly
                        << ", because registry already has same metric with memOnly=" << it->second.Opts.MemOnly);
                return static_cast<TMetric*>(it->second.Metric.Get());
            }
        }

        {
            IMetricPtr metric = MakeIntrusive<TMetric>(std::forward<Args>(args)...);

            TWriteGuard g{*Lock_};
            // decltype(Metrics_)::iterator breaks build on windows
            THashMap<ILabelsPtr, TMetricValue>::iterator it;
            TMetricValue metricValue = {metric, opts};
            if constexpr (!std::is_convertible_v<TLabelsType, ILabelsPtr>) {
                it = Metrics_.emplace(new TLabels{std::forward<TLabelsType>(labels)}, std::move(metricValue)).first;
            } else {
                it = Metrics_.emplace(std::forward<TLabelsType>(labels), std::move(metricValue)).first;
            }

            return static_cast<TMetric*>(it->second.Metric.Get());
        }
    }

    void TMetricRegistry::RemoveMetric(const ILabels& labels) noexcept {
        TWriteGuard g{*Lock_};
        Metrics_.erase(labels);
    }

    void TMetricRegistry::Accept(TInstant time, IMetricConsumer* consumer) const {
        consumer->OnStreamBegin();

        if (!CommonLabels_.Empty()) {
            consumer->OnLabelsBegin();
            ConsumeLabels(consumer, CommonLabels_);
            consumer->OnLabelsEnd();
        }

        TVector<std::pair<ILabelsPtr, TMetricValue>> tmpMetrics;

        {
            TReadGuard g{*Lock_};
            tmpMetrics.reserve(Metrics_.size());
            for (const auto& it: Metrics_) {
                tmpMetrics.push_back(it);
            }
        }

        for (const auto& it: tmpMetrics) {
            ILabels* labels = it.first.Get();
            IMetric* metric = it.second.Metric.Get();
            TMetricOpts opts = it.second.Opts;
            ConsumeMetric(
                time,
                consumer,
                metric,
                [&]() {
                    ConsumeLabels(consumer, *labels);
                },
                opts
            );
        }

        consumer->OnStreamEnd();
    }

    void TMetricRegistry::Append(TInstant time, IMetricConsumer* consumer) const {
        TReadGuard g{*Lock_};

        for (const auto& it: Metrics_) {
            ILabels* labels = it.first.Get();
            IMetric* metric = it.second.Metric.Get();
            TMetricOpts opts = it.second.Opts;
            ConsumeMetric(
                time,
                consumer,
                metric,
                [&]() {
                    ConsumeLabels(consumer, CommonLabels_);
                    ConsumeLabels(consumer, *labels);
                },
                opts
            );
        }
    }
}