aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/monlib/counters/counters.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/monlib/counters/counters.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/monlib/counters/counters.h')
-rw-r--r--library/cpp/monlib/counters/counters.h350
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;
+}