#include "metric_registry.h" #include namespace NMonitoring { namespace { void ConsumeLabels(IMetricConsumer* consumer, const ILabels& labels) { for (auto&& label: labels) { consumer->OnLabel(label.Name(), label.Value()); } } template void ConsumeMetric(TInstant time, IMetricConsumer* consumer, IMetric* metric, TLabelsConsumer&& labelsConsumer) { consumer->OnMetricBegin(metric->Type()); // (1) add labels consumer->OnLabelsBegin(); labelsConsumer(); consumer->OnLabelsEnd(); // (2) add time and value metric->Accept(time, consumer); 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(); } std::shared_ptr TMetricRegistry::SharedInstance() { static auto instance(std::make_shared()); return instance; } TGauge* TMetricRegistry::Gauge(TLabels labels) { return Metric(std::move(labels)); } TGauge* TMetricRegistry::Gauge(ILabelsPtr labels) { return Metric(std::move(labels)); } TLazyGauge* TMetricRegistry::LazyGauge(TLabels labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier)); } TLazyGauge* TMetricRegistry::LazyGauge(ILabelsPtr labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier)); } TIntGauge* TMetricRegistry::IntGauge(TLabels labels) { return Metric(std::move(labels)); } TIntGauge* TMetricRegistry::IntGauge(ILabelsPtr labels) { return Metric(std::move(labels)); } TLazyIntGauge* TMetricRegistry::LazyIntGauge(TLabels labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier)); } TLazyIntGauge* TMetricRegistry::LazyIntGauge(ILabelsPtr labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier)); } TCounter* TMetricRegistry::Counter(TLabels labels) { return Metric(std::move(labels)); } TCounter* TMetricRegistry::Counter(ILabelsPtr labels) { return Metric(std::move(labels)); } TLazyCounter* TMetricRegistry::LazyCounter(TLabels labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier)); } TLazyCounter* TMetricRegistry::LazyCounter(ILabelsPtr labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier)); } TRate* TMetricRegistry::Rate(TLabels labels) { return Metric(std::move(labels)); } TRate* TMetricRegistry::Rate(ILabelsPtr labels) { return Metric(std::move(labels)); } TLazyRate* TMetricRegistry::LazyRate(TLabels labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier)); } TLazyRate* TMetricRegistry::LazyRate(ILabelsPtr labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier)); } THistogram* TMetricRegistry::HistogramCounter(TLabels labels, IHistogramCollectorPtr collector) { return Metric(std::move(labels), std::move(collector), false); } THistogram* TMetricRegistry::HistogramCounter(ILabelsPtr labels, IHistogramCollectorPtr collector) { return Metric(std::move(labels), std::move(collector), false); } THistogram* TMetricRegistry::HistogramCounter(TLabels labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier), false); } THistogram* TMetricRegistry::HistogramCounter(ILabelsPtr labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier), false); } THistogram* TMetricRegistry::HistogramRate(TLabels labels, IHistogramCollectorPtr collector) { return Metric(std::move(labels), std::move(collector), true); } THistogram* TMetricRegistry::HistogramRate(ILabelsPtr labels, IHistogramCollectorPtr collector) { return Metric(std::move(labels), std::move(collector), true); } THistogram* TMetricRegistry::HistogramRate(TLabels labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier), true); } THistogram* TMetricRegistry::HistogramRate(ILabelsPtr labels, std::function supplier) { return Metric(std::move(labels), std::move(supplier), true); } void TMetricRegistry::Reset() { TWriteGuard g{*Lock_}; for (auto& [label, metric] : Metrics_) { switch (metric->Type()) { case EMetricType::GAUGE: static_cast(metric.Get())->Set(.0); break; case EMetricType::IGAUGE: static_cast(metric.Get())->Set(0); break; case EMetricType::COUNTER: static_cast(metric.Get())->Reset(); break; case EMetricType::RATE: static_cast(metric.Get())->Reset(); break; case EMetricType::HIST: case EMetricType::HIST_RATE: static_cast(metric.Get())->Reset(); break; case EMetricType::UNKNOWN: case EMetricType::DSUMMARY: case EMetricType::LOGHIST: break; } } } void TMetricRegistry::Clear() { TWriteGuard g{*Lock_}; Metrics_.clear(); } template TMetric* TMetricRegistry::Metric(TLabelsType&& labels, Args&&... args) { { TReadGuard g{*Lock_}; auto it = Metrics_.find(labels); if (it != Metrics_.end()) { Y_ENSURE(it->second->Type() == type, "cannot create metric " << labels << " with type " << MetricTypeToStr(type) << ", because registry already has same metric with type " << MetricTypeToStr(it->second->Type())); return static_cast(it->second.Get()); } } { IMetricPtr metric = MakeIntrusive(std::forward(args)...); TWriteGuard g{*Lock_}; // decltype(Metrics_)::iterator breaks build on windows THashMap::iterator it; if constexpr (!std::is_convertible_v) { it = Metrics_.emplace(new TLabels{std::forward(labels)}, std::move(metric)).first; } else { it = Metrics_.emplace(std::forward(labels), std::move(metric)).first; } return static_cast(it->second.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> 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.Get(); ConsumeMetric(time, consumer, metric, [&]() { ConsumeLabels(consumer, *labels); }); } 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.Get(); ConsumeMetric(time, consumer, metric, [&]() { ConsumeLabels(consumer, CommonLabels_); ConsumeLabels(consumer, *labels); }); } } }