diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/monlib/dynamic_counters/counters.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/monlib/dynamic_counters/counters.h')
-rw-r--r-- | library/cpp/monlib/dynamic_counters/counters.h | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/library/cpp/monlib/dynamic_counters/counters.h b/library/cpp/monlib/dynamic_counters/counters.h new file mode 100644 index 0000000000..dc178cfbe0 --- /dev/null +++ b/library/cpp/monlib/dynamic_counters/counters.h @@ -0,0 +1,374 @@ +#pragma once + +#include <library/cpp/monlib/counters/counters.h> +#include <library/cpp/monlib/metrics/histogram_collector.h> + +#include <library/cpp/threading/light_rw_lock/lightrwlock.h> +#include <library/cpp/containers/stack_vector/stack_vec.h> + +#include <util/generic/cast.h> +#include <util/generic/map.h> +#include <util/generic/ptr.h> +#include <util/string/cast.h> +#include <util/system/rwlock.h> + +#include <functional> + +namespace NMonitoring { + struct TCounterForPtr; + struct TDynamicCounters; + struct ICountableConsumer; + + + struct TCountableBase: public TAtomicRefCount<TCountableBase> { + // Private means that the object must not be serialized unless the consumer + // has explicitly specified this by setting its Visibility to Private. + // + // Works only for the methods that accept ICountableConsumer + enum class EVisibility: ui8 { + Unspecified, + Public, + Private, + }; + + virtual ~TCountableBase() { + } + + virtual void Accept( + const TString& labelName, const TString& labelValue, + ICountableConsumer& consumer) const = 0; + + virtual EVisibility Visibility() const { + return Visibility_; + } + + protected: + EVisibility Visibility_{EVisibility::Unspecified}; + }; + + inline bool IsVisible(TCountableBase::EVisibility myLevel, TCountableBase::EVisibility consumerLevel) { + if (myLevel == TCountableBase::EVisibility::Private + && consumerLevel != TCountableBase::EVisibility::Private) { + + return false; + } + + return true; + } + + struct ICountableConsumer { + virtual ~ICountableConsumer() { + } + + virtual void OnCounter( + const TString& labelName, const TString& labelValue, + const TCounterForPtr* counter) = 0; + + virtual void OnHistogram( + const TString& labelName, const TString& labelValue, + IHistogramSnapshotPtr snapshot, bool derivative) = 0; + + virtual void OnGroupBegin( + const TString& labelName, const TString& labelValue, + const TDynamicCounters* group) = 0; + + virtual void OnGroupEnd( + const TString& labelName, const TString& labelValue, + const TDynamicCounters* group) = 0; + + virtual TCountableBase::EVisibility Visibility() const { + return TCountableBase::EVisibility::Unspecified; + } + }; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4522) // multiple assignment operators specified +#endif // _MSC_VER + + struct TCounterForPtr: public TDeprecatedCounter, public TCountableBase { + TCounterForPtr(bool derivative = false, EVisibility vis = EVisibility::Public) + : TDeprecatedCounter(0ULL, derivative) + { + Visibility_ = vis; + } + + TCounterForPtr(const TCounterForPtr&) = delete; + TCounterForPtr& operator=(const TCounterForPtr& other) = delete; + + void Accept( + const TString& labelName, const TString& labelValue, + ICountableConsumer& consumer) const override { + if (IsVisible(Visibility(), consumer.Visibility())) { + consumer.OnCounter(labelName, labelValue, this); + } + } + + TCountableBase::EVisibility Visibility() const override { + return Visibility_; + } + + using TDeprecatedCounter::operator++; + using TDeprecatedCounter::operator--; + using TDeprecatedCounter::operator+=; + using TDeprecatedCounter::operator-=; + using TDeprecatedCounter::operator=; + using TDeprecatedCounter::operator!; + }; + + struct TExpiringCounter: public TCounterForPtr { + explicit TExpiringCounter(bool derivative = false, EVisibility vis = EVisibility::Public) + : TCounterForPtr{derivative} + { + Visibility_ = vis; + } + + void Reset() { + TDeprecatedCounter::operator=(0); + } + }; + + struct THistogramCounter: public TCountableBase { + explicit THistogramCounter( + IHistogramCollectorPtr collector, bool derivative = true, EVisibility vis = EVisibility::Public) + : Collector_(std::move(collector)) + , Derivative_(derivative) + { + Visibility_ = vis; + } + + void Collect(i64 value) { + Collector_->Collect(value); + } + + void Collect(i64 value, ui32 count) { + Collector_->Collect(value, count); + } + + void Collect(double value, ui32 count) { + Collector_->Collect(value, count); + } + + void Collect(const IHistogramSnapshot& snapshot) { + Collector_->Collect(snapshot); + } + + void Accept( + const TString& labelName, const TString& labelValue, + ICountableConsumer& consumer) const override + { + if (IsVisible(Visibility(), consumer.Visibility())) { + consumer.OnHistogram(labelName, labelValue, Collector_->Snapshot(), Derivative_); + } + } + + void Reset() { + Collector_->Reset(); + } + + IHistogramSnapshotPtr Snapshot() const { + return Collector_->Snapshot(); + } + + private: + IHistogramCollectorPtr Collector_; + bool Derivative_; + }; + + struct TExpiringHistogramCounter: public THistogramCounter { + using THistogramCounter::THistogramCounter; + }; + + using THistogramPtr = TIntrusivePtr<THistogramCounter>; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + struct TDynamicCounters; + + typedef TIntrusivePtr<TDynamicCounters> TDynamicCounterPtr; + struct TDynamicCounters: public TCountableBase { + public: + using TCounterPtr = TIntrusivePtr<TCounterForPtr>; + using TOnLookupPtr = void (*)(const char *methodName, const TString &name, const TString &value); + + private: + TRWMutex Lock; + TCounterPtr LookupCounter; // Counts lookups by name + TOnLookupPtr OnLookup = nullptr; // Called on each lookup if not nullptr, intended for lightweight tracing. + + typedef TIntrusivePtr<TCountableBase> TCountablePtr; + + struct TChildId { + TString LabelName; + TString LabelValue; + TChildId() { + } + TChildId(const TString& labelName, const TString& labelValue) + : LabelName(labelName) + , LabelValue(labelValue) + { + } + auto AsTuple() const { + return std::make_tuple(std::cref(LabelName), std::cref(LabelValue)); + } + friend bool operator <(const TChildId& x, const TChildId& y) { + return x.AsTuple() < y.AsTuple(); + } + friend bool operator ==(const TChildId& x, const TChildId& y) { + return x.AsTuple() == y.AsTuple(); + } + friend bool operator !=(const TChildId& x, const TChildId& y) { + return x.AsTuple() != y.AsTuple(); + } + }; + + using TCounters = TMap<TChildId, TCountablePtr>; + using TLabels = TVector<TChildId>; + + /// XXX: hack for deferred removal of expired counters. Remove once Output* functions are not used for serialization + mutable TCounters Counters; + mutable TAtomic ExpiringCount = 0; + + public: + TDynamicCounters(TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + TDynamicCounters(const TDynamicCounters *origin) + : LookupCounter(origin->LookupCounter) + , OnLookup(origin->OnLookup) + {} + + ~TDynamicCounters() override; + + // This counter allows to track lookups by name within the whole subtree + void SetLookupCounter(TCounterPtr lookupCounter) { + TWriteGuard g(Lock); + LookupCounter = lookupCounter; + } + + void SetOnLookup(TOnLookupPtr onLookup) { + TWriteGuard g(Lock); + OnLookup = onLookup; + } + + TWriteGuard LockForUpdate(const char *method, const TString& name, const TString& value) { + auto res = TWriteGuard(Lock); + if (LookupCounter) { + ++*LookupCounter; + } + if (OnLookup) { + OnLookup(method, name, value); + } + return res; + } + + TStackVec<TCounters::value_type, 256> ReadSnapshot() const { + RemoveExpired(); + TReadGuard g(Lock); + TStackVec<TCounters::value_type, 256> items(Counters.begin(), Counters.end()); + return items; + } + + TCounterPtr GetCounter( + const TString& value, + bool derivative = false, + TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + TCounterPtr GetNamedCounter( + const TString& name, + const TString& value, + bool derivative = false, + TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + THistogramPtr GetHistogram( + const TString& value, + IHistogramCollectorPtr collector, + bool derivative = true, + TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + THistogramPtr GetNamedHistogram( + const TString& name, + const TString& value, + IHistogramCollectorPtr collector, + bool derivative = true, + TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + // These counters will be automatically removed from the registry + // when last reference to the counter expires. + TCounterPtr GetExpiringCounter( + const TString& value, + bool derivative = false, + TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + TCounterPtr GetExpiringNamedCounter( + const TString& name, + const TString& value, + bool derivative = false, + TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + THistogramPtr GetExpiringHistogram( + const TString& value, + IHistogramCollectorPtr collector, + bool derivative = true, + TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + THistogramPtr GetExpiringNamedHistogram( + const TString& name, + const TString& value, + IHistogramCollectorPtr collector, + bool derivative = true, + TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public); + + TCounterPtr FindCounter(const TString& value) const; + TCounterPtr FindNamedCounter(const TString& name, const TString& value) const; + + THistogramPtr FindHistogram(const TString& value) const; + THistogramPtr FindNamedHistogram(const TString& name,const TString& value) const; + + void RemoveCounter(const TString &value); + void RemoveNamedCounter(const TString& name, const TString &value); + + TIntrusivePtr<TDynamicCounters> GetSubgroup(const TString& name, const TString& value); + TIntrusivePtr<TDynamicCounters> FindSubgroup(const TString& name, const TString& value) const; + void RemoveSubgroup(const TString& name, const TString& value); + void ReplaceSubgroup(const TString& name, const TString& value, TIntrusivePtr<TDynamicCounters> subgroup); + + // Move all counters from specified subgroup and remove the subgroup. + void MergeWithSubgroup(const TString& name, const TString& value); + // Recursively reset all/deriv counters to 0. + void ResetCounters(bool derivOnly = false); + + void RegisterSubgroup(const TString& name, + const TString& value, + TIntrusivePtr<TDynamicCounters> subgroup); + + void OutputHtml(IOutputStream& os) const; + void EnumerateSubgroups(const std::function<void(const TString& name, const TString& value)>& output) const; + + // mostly for debugging purposes -- use accept with encoder instead + void OutputPlainText(IOutputStream& os, const TString& indent = "") const; + + void Accept( + const TString& labelName, const TString& labelValue, + ICountableConsumer& consumer) const override; + + private: + TCounters Resign() { + TCounters counters; + TWriteGuard g(Lock); + Counters.swap(counters); + return counters; + } + + void RegisterCountable(const TString& name, const TString& value, TCountablePtr countable); + void RemoveExpired() const; + + template <bool expiring, class TCounterType, class... TArgs> + TCountablePtr GetNamedCounterImpl(const TString& name, const TString& value, TArgs&&... args); + + template <class TCounterType> + TCountablePtr FindNamedCounterImpl(const TString& name, const TString& value) const; + }; + +} |