counters.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #pragma once
  2. #include <util/datetime/base.h>
  3. #include <util/generic/algorithm.h>
  4. #include <util/generic/list.h>
  5. #include <util/generic/map.h>
  6. #include <util/generic/ptr.h>
  7. #include <util/generic/singleton.h>
  8. #include <util/generic/vector.h>
  9. #include <util/str_stl.h>
  10. #include <util/stream/output.h>
  11. #include <util/string/util.h>
  12. #include <library/cpp/deprecated/atomic/atomic.h>
  13. #include <util/system/defaults.h>
  14. #include <util/system/guard.h>
  15. #include <util/system/sem.h>
  16. #include <util/system/spinlock.h>
  17. #include <array>
  18. namespace NMonitoring {
  19. #define BEGIN_OUTPUT_COUNTERS \
  20. void OutputImpl(IOutputStream& out) { \
  21. char prettyBuf[32];
  22. #define END_OUTPUT_COUNTERS \
  23. out.Flush(); \
  24. }
  25. #define OUTPUT_NAMED_COUNTER(var, name) out << name << ": \t" << var << NMonitoring::PrettyNum(var, prettyBuf, 32) << '\n'
  26. #define OUTPUT_COUNTER(var) OUTPUT_NAMED_COUNTER(var, #var);
  27. char* PrettyNumShort(i64 val, char* buf, size_t size);
  28. char* PrettyNum(i64 val, char* buf, size_t size);
  29. // This class is deprecated. Please consider to use
  30. // library/cpp/monlib/metrics instead. See more info at
  31. // https://wiki.yandex-team.ru/solomon/libs/monlib_cpp/
  32. class TDeprecatedCounter {
  33. public:
  34. using TValue = TAtomic;
  35. using TValueBase = TAtomicBase;
  36. TDeprecatedCounter()
  37. : Value()
  38. , Derivative(false)
  39. {
  40. }
  41. TDeprecatedCounter(TValueBase value, bool derivative = false)
  42. : Value(value)
  43. , Derivative(derivative)
  44. {
  45. }
  46. bool ForDerivative() const {
  47. return Derivative;
  48. }
  49. operator TValueBase() const {
  50. return AtomicGet(Value);
  51. }
  52. TValueBase Val() const {
  53. return AtomicGet(Value);
  54. }
  55. void Set(TValueBase val) {
  56. AtomicSet(Value, val);
  57. }
  58. TValueBase Inc() {
  59. return AtomicIncrement(Value);
  60. }
  61. TValueBase Dec() {
  62. return AtomicDecrement(Value);
  63. }
  64. TValueBase Add(const TValueBase val) {
  65. return AtomicAdd(Value, val);
  66. }
  67. TValueBase Sub(const TValueBase val) {
  68. return AtomicAdd(Value, -val);
  69. }
  70. // operator overloads convinient
  71. void operator++() {
  72. Inc();
  73. }
  74. void operator++(int) {
  75. Inc();
  76. }
  77. void operator--() {
  78. Dec();
  79. }
  80. void operator--(int) {
  81. Dec();
  82. }
  83. void operator+=(TValueBase rhs) {
  84. Add(rhs);
  85. }
  86. void operator-=(TValueBase rhs) {
  87. Sub(rhs);
  88. }
  89. TValueBase operator=(TValueBase rhs) {
  90. AtomicSwap(&Value, rhs);
  91. return rhs;
  92. }
  93. bool operator!() const {
  94. return AtomicGet(Value) == 0;
  95. }
  96. TAtomic& GetAtomic() {
  97. return Value;
  98. }
  99. private:
  100. TAtomic Value;
  101. bool Derivative;
  102. };
  103. template <typename T>
  104. struct TDeprecatedCountersBase {
  105. virtual ~TDeprecatedCountersBase() {
  106. }
  107. virtual void OutputImpl(IOutputStream&) = 0;
  108. static T& Instance() {
  109. return *Singleton<T>();
  110. }
  111. static void Output(IOutputStream& out) {
  112. Instance().OutputImpl(out);
  113. }
  114. };
  115. // This class is deprecated. Please consider to use
  116. // library/cpp/monlib/metrics instead. See more info at
  117. // https://wiki.yandex-team.ru/solomon/libs/monlib_cpp/
  118. //
  119. // Groups of G counters, defined by T type.
  120. // Less(a,b) returns true, if a < b.
  121. // It's threadsafe.
  122. template <typename T, typename G, typename TL = TLess<T>>
  123. class TDeprecatedCounterGroups {
  124. public:
  125. typedef TMap<T, G*> TGroups;
  126. typedef TVector<T> TGroupsNames;
  127. typedef THolder<TGroupsNames> TGroupsNamesPtr;
  128. private:
  129. class TCollection {
  130. struct TElement {
  131. T* Name;
  132. G* Counters;
  133. public:
  134. static bool Compare(const TElement& a, const TElement& b) {
  135. return Less(*(a.Name), *(b.Name));
  136. }
  137. }; // TElement
  138. private:
  139. TArrayHolder<TElement> Elements;
  140. size_t Size;
  141. public:
  142. TCollection()
  143. : Size(0)
  144. {
  145. }
  146. TCollection(const TCollection& collection)
  147. : Elements(new TElement[collection.Size])
  148. , Size(collection.Size)
  149. {
  150. for (int i = 0; i < Size; ++i) {
  151. Elements[i] = collection.Elements[i];
  152. }
  153. }
  154. TCollection(const TCollection& collection, T* name, G* counters)
  155. : Elements(new TElement[collection.Size + 1])
  156. , Size(collection.Size + 1)
  157. {
  158. for (size_t i = 0; i < Size - 1; ++i) {
  159. Elements[i] = collection.Elements[i];
  160. }
  161. Elements[Size - 1].Name = name;
  162. Elements[Size - 1].Counters = counters;
  163. for (size_t i = 1; i < Size; ++i) {
  164. size_t j = i;
  165. while (j > 0 &&
  166. TElement::Compare(Elements[j], Elements[j - 1])) {
  167. std::swap(Elements[j], Elements[j - 1]);
  168. --j;
  169. }
  170. }
  171. }
  172. G* Find(const T& name) const {
  173. G* result = nullptr;
  174. if (Size == 0) {
  175. return nullptr;
  176. }
  177. size_t l = 0;
  178. size_t r = Size - 1;
  179. while (l < r) {
  180. size_t m = (l + r) / 2;
  181. if (Less(*(Elements[m].Name), name)) {
  182. l = m + 1;
  183. } else {
  184. r = m;
  185. }
  186. }
  187. if (!Less(*(Elements[l].Name), name) && !Less(name, *(Elements[l].Name))) {
  188. result = Elements[l].Counters;
  189. }
  190. return result;
  191. }
  192. void Free() {
  193. for (size_t i = 0; i < Size; ++i) {
  194. T* name = Elements[i].Name;
  195. G* counters = Elements[i].Counters;
  196. Elements[i].Name = nullptr;
  197. Elements[i].Counters = nullptr;
  198. delete name;
  199. delete counters;
  200. }
  201. Size = 0;
  202. }
  203. TGroupsNamesPtr GetNames() const {
  204. TGroupsNamesPtr result(new TGroupsNames());
  205. for (size_t i = 0; i < Size; ++i) {
  206. result->push_back(*(Elements[i].Name));
  207. }
  208. return result;
  209. }
  210. }; // TCollection
  211. struct TOldGroup {
  212. TCollection* Collection;
  213. ui64 Time;
  214. };
  215. private:
  216. TCollection* Groups;
  217. TList<TOldGroup> OldGroups;
  218. TSpinLock AddMutex;
  219. ui64 Timeout;
  220. static TL Less;
  221. private:
  222. G* Add(const T& name) {
  223. TGuard<TSpinLock> guard(AddMutex);
  224. G* result = Groups->Find(name);
  225. if (result == nullptr) {
  226. T* newName = new T(name);
  227. G* newCounters = new G();
  228. TCollection* newGroups =
  229. new TCollection(*Groups, newName, newCounters);
  230. ui64 now = ::Now().MicroSeconds();
  231. TOldGroup group;
  232. group.Collection = Groups;
  233. group.Time = now;
  234. OldGroups.push_back(group);
  235. for (ui32 i = 0; i < 5; ++i) {
  236. if (OldGroups.front().Time + Timeout < now) {
  237. delete OldGroups.front().Collection;
  238. OldGroups.front().Collection = nullptr;
  239. OldGroups.pop_front();
  240. } else {
  241. break;
  242. }
  243. }
  244. Groups = newGroups;
  245. result = Groups->Find(name);
  246. }
  247. return result;
  248. }
  249. public:
  250. TDeprecatedCounterGroups(ui64 timeout = 5 * 1000000L) {
  251. Groups = new TCollection();
  252. Timeout = timeout;
  253. }
  254. virtual ~TDeprecatedCounterGroups() {
  255. TGuard<TSpinLock> guard(AddMutex);
  256. Groups->Free();
  257. delete Groups;
  258. Groups = nullptr;
  259. typename TList<TOldGroup>::iterator i;
  260. for (i = OldGroups.begin(); i != OldGroups.end(); ++i) {
  261. delete i->Collection;
  262. i->Collection = nullptr;
  263. }
  264. OldGroups.clear();
  265. }
  266. bool Has(const T& name) const {
  267. TCollection* groups = Groups;
  268. return groups->Find(name) != nullptr;
  269. }
  270. G* Find(const T& name) const {
  271. TCollection* groups = Groups;
  272. return groups->Find(name);
  273. }
  274. // Get group with the name, if it exists.
  275. // If there is no group with the name, add new group.
  276. G& Get(const T& name) {
  277. G* result = Find(name);
  278. if (result == nullptr) {
  279. result = Add(name);
  280. Y_ASSERT(result != nullptr);
  281. }
  282. return *result;
  283. }
  284. // Get copy of groups names array.
  285. TGroupsNamesPtr GetGroupsNames() const {
  286. TCollection* groups = Groups;
  287. TGroupsNamesPtr result = groups->GetNames();
  288. return result;
  289. }
  290. }; // TDeprecatedCounterGroups
  291. template <typename T, typename G, typename TL>
  292. TL TDeprecatedCounterGroups<T, G, TL>::Less;
  293. }
  294. static inline IOutputStream& operator<<(IOutputStream& o, const NMonitoring::TDeprecatedCounter& rhs) {
  295. return o << rhs.Val();
  296. }
  297. template <size_t N>
  298. static inline IOutputStream& operator<<(IOutputStream& o, const std::array<NMonitoring::TDeprecatedCounter, N>& rhs) {
  299. for (typename std::array<NMonitoring::TDeprecatedCounter, N>::const_iterator it = rhs.begin(); it != rhs.end(); ++it) {
  300. if (!!*it)
  301. o << *it << Endl;
  302. }
  303. return o;
  304. }