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/counters/counters.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/monlib/counters/counters.h')
-rw-r--r-- | library/cpp/monlib/counters/counters.h | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/library/cpp/monlib/counters/counters.h b/library/cpp/monlib/counters/counters.h new file mode 100644 index 0000000000..038b55f0c8 --- /dev/null +++ b/library/cpp/monlib/counters/counters.h @@ -0,0 +1,350 @@ +#pragma once + +#include <util/datetime/base.h> +#include <util/generic/algorithm.h> +#include <util/generic/list.h> +#include <util/generic/map.h> +#include <util/generic/ptr.h> +#include <util/generic/singleton.h> +#include <util/generic/vector.h> +#include <util/str_stl.h> +#include <util/stream/output.h> +#include <util/string/util.h> +#include <util/system/atomic.h> +#include <util/system/defaults.h> +#include <util/system/guard.h> +#include <util/system/sem.h> +#include <util/system/spinlock.h> + +#include <array> + +namespace NMonitoring { +#define BEGIN_OUTPUT_COUNTERS \ + void OutputImpl(IOutputStream& out) { \ + char prettyBuf[32]; +#define END_OUTPUT_COUNTERS \ + out.Flush(); \ + } + +#define OUTPUT_NAMED_COUNTER(var, name) out << name << ": \t" << var << NMonitoring::PrettyNum(var, prettyBuf, 32) << '\n' +#define OUTPUT_COUNTER(var) OUTPUT_NAMED_COUNTER(var, #var); + + char* PrettyNumShort(i64 val, char* buf, size_t size); + char* PrettyNum(i64 val, char* buf, size_t size); + + // This class is deprecated. Please consider to use + // library/cpp/monlib/metrics instead. See more info at + // https://wiki.yandex-team.ru/solomon/libs/monlib_cpp/ + class TDeprecatedCounter { + public: + using TValue = TAtomic; + using TValueBase = TAtomicBase; + + TDeprecatedCounter() + : Value() + , Derivative(false) + { + } + + TDeprecatedCounter(TValue value, bool derivative = false) + : Value(value) + , Derivative(derivative) + { + } + + bool ForDerivative() const { + return Derivative; + } + + operator TValueBase() const { + return AtomicGet(Value); + } + TValueBase Val() const { + return AtomicGet(Value); + } + + void Set(TValue val) { + AtomicSet(Value, val); + } + + TValueBase Inc() { + return AtomicIncrement(Value); + } + TValueBase Dec() { + return AtomicDecrement(Value); + } + + TValueBase Add(const TValue val) { + return AtomicAdd(Value, val); + } + TValueBase Sub(const TValue val) { + return AtomicAdd(Value, -val); + } + + // operator overloads convinient + void operator++() { + Inc(); + } + void operator++(int) { + Inc(); + } + + void operator--() { + Dec(); + } + void operator--(int) { + Dec(); + } + + void operator+=(TValue rhs) { + Add(rhs); + } + void operator-=(TValue rhs) { + Sub(rhs); + } + + TValueBase operator=(TValue rhs) { + AtomicSwap(&Value, rhs); + return rhs; + } + + bool operator!() const { + return AtomicGet(Value) == 0; + } + + TAtomic& GetAtomic() { + return Value; + } + + private: + TAtomic Value; + bool Derivative; + }; + + template <typename T> + struct TDeprecatedCountersBase { + virtual ~TDeprecatedCountersBase() { + } + + virtual void OutputImpl(IOutputStream&) = 0; + + static T& Instance() { + return *Singleton<T>(); + } + + static void Output(IOutputStream& out) { + Instance().OutputImpl(out); + } + }; + + // This class is deprecated. Please consider to use + // library/cpp/monlib/metrics instead. See more info at + // https://wiki.yandex-team.ru/solomon/libs/monlib_cpp/ + // + // Groups of G counters, defined by T type. + // Less(a,b) returns true, if a < b. + // It's threadsafe. + template <typename T, typename G, typename TL = TLess<T>> + class TDeprecatedCounterGroups { + public: + typedef TMap<T, G*> TGroups; + typedef TVector<T> TGroupsNames; + typedef THolder<TGroupsNames> TGroupsNamesPtr; + + private: + class TCollection { + struct TElement { + T* Name; + G* Counters; + + public: + static bool Compare(const TElement& a, const TElement& b) { + return Less(*(a.Name), *(b.Name)); + } + }; // TElement + private: + TArrayHolder<TElement> Elements; + size_t Size; + + public: + TCollection() + : Size(0) + { + } + + TCollection(const TCollection& collection) + : Elements(new TElement[collection.Size]) + , Size(collection.Size) + { + for (int i = 0; i < Size; ++i) { + Elements[i] = collection.Elements[i]; + } + } + + TCollection(const TCollection& collection, T* name, G* counters) + : Elements(new TElement[collection.Size + 1]) + , Size(collection.Size + 1) + { + for (size_t i = 0; i < Size - 1; ++i) { + Elements[i] = collection.Elements[i]; + } + Elements[Size - 1].Name = name; + Elements[Size - 1].Counters = counters; + for (size_t i = 1; i < Size; ++i) { + size_t j = i; + while (j > 0 && + TElement::Compare(Elements[j], Elements[j - 1])) { + std::swap(Elements[j], Elements[j - 1]); + --j; + } + } + } + + G* Find(const T& name) const { + G* result = nullptr; + if (Size == 0) { + return nullptr; + } + size_t l = 0; + size_t r = Size - 1; + while (l < r) { + size_t m = (l + r) / 2; + if (Less(*(Elements[m].Name), name)) { + l = m + 1; + } else { + r = m; + } + } + if (!Less(*(Elements[l].Name), name) && !Less(name, *(Elements[l].Name))) { + result = Elements[l].Counters; + } + return result; + } + + void Free() { + for (size_t i = 0; i < Size; ++i) { + T* name = Elements[i].Name; + G* counters = Elements[i].Counters; + Elements[i].Name = nullptr; + Elements[i].Counters = nullptr; + delete name; + delete counters; + } + Size = 0; + } + + TGroupsNamesPtr GetNames() const { + TGroupsNamesPtr result(new TGroupsNames()); + for (size_t i = 0; i < Size; ++i) { + result->push_back(*(Elements[i].Name)); + } + return result; + } + }; // TCollection + struct TOldGroup { + TCollection* Collection; + ui64 Time; + }; + + private: + TCollection* Groups; + TList<TOldGroup> OldGroups; + TSpinLock AddMutex; + + ui64 Timeout; + + static TL Less; + + private: + G* Add(const T& name) { + TGuard<TSpinLock> guard(AddMutex); + G* result = Groups->Find(name); + if (result == nullptr) { + T* newName = new T(name); + G* newCounters = new G(); + TCollection* newGroups = + new TCollection(*Groups, newName, newCounters); + ui64 now = ::Now().MicroSeconds(); + TOldGroup group; + group.Collection = Groups; + group.Time = now; + OldGroups.push_back(group); + for (ui32 i = 0; i < 5; ++i) { + if (OldGroups.front().Time + Timeout < now) { + delete OldGroups.front().Collection; + OldGroups.front().Collection = nullptr; + OldGroups.pop_front(); + } else { + break; + } + } + Groups = newGroups; + result = Groups->Find(name); + } + return result; + } + + public: + TDeprecatedCounterGroups(ui64 timeout = 5 * 1000000L) { + Groups = new TCollection(); + Timeout = timeout; + } + + virtual ~TDeprecatedCounterGroups() { + TGuard<TSpinLock> guard(AddMutex); + Groups->Free(); + delete Groups; + Groups = nullptr; + typename TList<TOldGroup>::iterator i; + for (i = OldGroups.begin(); i != OldGroups.end(); ++i) { + delete i->Collection; + i->Collection = nullptr; + } + OldGroups.clear(); + } + + bool Has(const T& name) const { + TCollection* groups = Groups; + return groups->Find(name) != nullptr; + } + + G* Find(const T& name) const { + TCollection* groups = Groups; + return groups->Find(name); + } + + // Get group with the name, if it exists. + // If there is no group with the name, add new group. + G& Get(const T& name) { + G* result = Find(name); + if (result == nullptr) { + result = Add(name); + Y_ASSERT(result != nullptr); + } + return *result; + } + + // Get copy of groups names array. + TGroupsNamesPtr GetGroupsNames() const { + TCollection* groups = Groups; + TGroupsNamesPtr result = groups->GetNames(); + return result; + } + }; // TDeprecatedCounterGroups + + template <typename T, typename G, typename TL> + TL TDeprecatedCounterGroups<T, G, TL>::Less; +} + +static inline IOutputStream& operator<<(IOutputStream& o, const NMonitoring::TDeprecatedCounter& rhs) { + return o << rhs.Val(); +} + +template <size_t N> +static inline IOutputStream& operator<<(IOutputStream& o, const std::array<NMonitoring::TDeprecatedCounter, N>& rhs) { + for (typename std::array<NMonitoring::TDeprecatedCounter, N>::const_iterator it = rhs.begin(); it != rhs.end(); ++it) { + if (!!*it) + o << *it << Endl; + } + return o; +} |