counters.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. #pragma once
  2. #include <library/cpp/monlib/counters/counters.h>
  3. #include <library/cpp/monlib/metrics/histogram_collector.h>
  4. #include <library/cpp/threading/light_rw_lock/lightrwlock.h>
  5. #include <library/cpp/containers/stack_vector/stack_vec.h>
  6. #include <util/generic/cast.h>
  7. #include <util/generic/map.h>
  8. #include <util/generic/ptr.h>
  9. #include <util/string/cast.h>
  10. #include <util/system/rwlock.h>
  11. #include <functional>
  12. namespace NMonitoring {
  13. struct TCounterForPtr;
  14. struct TDynamicCounters;
  15. struct ICountableConsumer;
  16. struct TCountableBase: public TAtomicRefCount<TCountableBase> {
  17. // Private means that the object must not be serialized unless the consumer
  18. // has explicitly specified this by setting its Visibility to Private.
  19. //
  20. // Works only for the methods that accept ICountableConsumer
  21. enum class EVisibility: ui8 {
  22. Unspecified,
  23. Public,
  24. Private,
  25. };
  26. virtual ~TCountableBase() {
  27. }
  28. virtual void Accept(
  29. const TString& labelName, const TString& labelValue,
  30. ICountableConsumer& consumer) const = 0;
  31. virtual EVisibility Visibility() const {
  32. return Visibility_;
  33. }
  34. protected:
  35. EVisibility Visibility_{EVisibility::Unspecified};
  36. };
  37. inline bool IsVisible(TCountableBase::EVisibility myLevel, TCountableBase::EVisibility consumerLevel) {
  38. if (myLevel == TCountableBase::EVisibility::Private
  39. && consumerLevel != TCountableBase::EVisibility::Private) {
  40. return false;
  41. }
  42. return true;
  43. }
  44. struct ICountableConsumer {
  45. virtual ~ICountableConsumer() {
  46. }
  47. virtual void OnCounter(
  48. const TString& labelName, const TString& labelValue,
  49. const TCounterForPtr* counter) = 0;
  50. virtual void OnHistogram(
  51. const TString& labelName, const TString& labelValue,
  52. IHistogramSnapshotPtr snapshot, bool derivative) = 0;
  53. virtual void OnGroupBegin(
  54. const TString& labelName, const TString& labelValue,
  55. const TDynamicCounters* group) = 0;
  56. virtual void OnGroupEnd(
  57. const TString& labelName, const TString& labelValue,
  58. const TDynamicCounters* group) = 0;
  59. virtual TCountableBase::EVisibility Visibility() const {
  60. return TCountableBase::EVisibility::Unspecified;
  61. }
  62. };
  63. #ifdef _MSC_VER
  64. #pragma warning(push)
  65. #pragma warning(disable : 4522) // multiple assignment operators specified
  66. #endif // _MSC_VER
  67. struct TCounterForPtr: public TDeprecatedCounter, public TCountableBase {
  68. TCounterForPtr(bool derivative = false, EVisibility vis = EVisibility::Public)
  69. : TDeprecatedCounter(0ULL, derivative)
  70. {
  71. Visibility_ = vis;
  72. }
  73. TCounterForPtr(const TCounterForPtr&) = delete;
  74. TCounterForPtr& operator=(const TCounterForPtr& other) = delete;
  75. void Accept(
  76. const TString& labelName, const TString& labelValue,
  77. ICountableConsumer& consumer) const override {
  78. if (IsVisible(Visibility(), consumer.Visibility())) {
  79. consumer.OnCounter(labelName, labelValue, this);
  80. }
  81. }
  82. TCountableBase::EVisibility Visibility() const override {
  83. return Visibility_;
  84. }
  85. using TDeprecatedCounter::operator++;
  86. using TDeprecatedCounter::operator--;
  87. using TDeprecatedCounter::operator+=;
  88. using TDeprecatedCounter::operator-=;
  89. using TDeprecatedCounter::operator=;
  90. using TDeprecatedCounter::operator!;
  91. };
  92. struct TExpiringCounter: public TCounterForPtr {
  93. explicit TExpiringCounter(bool derivative = false, EVisibility vis = EVisibility::Public)
  94. : TCounterForPtr{derivative}
  95. {
  96. Visibility_ = vis;
  97. }
  98. void Reset() {
  99. TDeprecatedCounter::operator=(0);
  100. }
  101. };
  102. struct THistogramCounter: public TCountableBase {
  103. explicit THistogramCounter(
  104. IHistogramCollectorPtr collector, bool derivative = true, EVisibility vis = EVisibility::Public)
  105. : Collector_(std::move(collector))
  106. , Derivative_(derivative)
  107. {
  108. Visibility_ = vis;
  109. }
  110. void Collect(i64 value) {
  111. Collector_->Collect(value);
  112. }
  113. void Collect(i64 value, ui64 count) {
  114. Collector_->Collect(value, count);
  115. }
  116. void Collect(double value, ui64 count) {
  117. Collector_->Collect(value, count);
  118. }
  119. void Collect(const IHistogramSnapshot& snapshot) {
  120. Collector_->Collect(snapshot);
  121. }
  122. void Accept(
  123. const TString& labelName, const TString& labelValue,
  124. ICountableConsumer& consumer) const override
  125. {
  126. if (IsVisible(Visibility(), consumer.Visibility())) {
  127. consumer.OnHistogram(labelName, labelValue, Collector_->Snapshot(), Derivative_);
  128. }
  129. }
  130. void Reset() {
  131. Collector_->Reset();
  132. }
  133. IHistogramSnapshotPtr Snapshot() const {
  134. return Collector_->Snapshot();
  135. }
  136. private:
  137. IHistogramCollectorPtr Collector_;
  138. bool Derivative_;
  139. };
  140. struct TExpiringHistogramCounter: public THistogramCounter {
  141. using THistogramCounter::THistogramCounter;
  142. };
  143. using THistogramPtr = TIntrusivePtr<THistogramCounter>;
  144. #ifdef _MSC_VER
  145. #pragma warning(pop)
  146. #endif
  147. struct TDynamicCounters;
  148. typedef TIntrusivePtr<TDynamicCounters> TDynamicCounterPtr;
  149. struct TDynamicCounters: public TCountableBase {
  150. public:
  151. using TCounterPtr = TIntrusivePtr<TCounterForPtr>;
  152. using TOnLookupPtr = void (*)(const char *methodName, const TString &name, const TString &value);
  153. private:
  154. TRWMutex Lock;
  155. TCounterPtr LookupCounter; // Counts lookups by name
  156. TOnLookupPtr OnLookup = nullptr; // Called on each lookup if not nullptr, intended for lightweight tracing.
  157. typedef TIntrusivePtr<TCountableBase> TCountablePtr;
  158. struct TChildId {
  159. TString LabelName;
  160. TString LabelValue;
  161. TChildId() {
  162. }
  163. TChildId(const TString& labelName, const TString& labelValue)
  164. : LabelName(labelName)
  165. , LabelValue(labelValue)
  166. {
  167. }
  168. auto AsTuple() const {
  169. return std::make_tuple(std::cref(LabelName), std::cref(LabelValue));
  170. }
  171. friend bool operator <(const TChildId& x, const TChildId& y) {
  172. return x.AsTuple() < y.AsTuple();
  173. }
  174. friend bool operator ==(const TChildId& x, const TChildId& y) {
  175. return x.AsTuple() == y.AsTuple();
  176. }
  177. friend bool operator !=(const TChildId& x, const TChildId& y) {
  178. return x.AsTuple() != y.AsTuple();
  179. }
  180. };
  181. using TCounters = TMap<TChildId, TCountablePtr>;
  182. using TLabels = TVector<TChildId>;
  183. /// XXX: hack for deferred removal of expired counters. Remove once Output* functions are not used for serialization
  184. mutable TCounters Counters;
  185. mutable TAtomic ExpiringCount = 0;
  186. public:
  187. TDynamicCounters(TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  188. TDynamicCounters(const TDynamicCounters *origin)
  189. : LookupCounter(origin->LookupCounter)
  190. , OnLookup(origin->OnLookup)
  191. {}
  192. ~TDynamicCounters() override;
  193. // This counter allows to track lookups by name within the whole subtree
  194. void SetLookupCounter(TCounterPtr lookupCounter) {
  195. TWriteGuard g(Lock);
  196. LookupCounter = lookupCounter;
  197. }
  198. void SetOnLookup(TOnLookupPtr onLookup) {
  199. TWriteGuard g(Lock);
  200. OnLookup = onLookup;
  201. }
  202. TWriteGuard LockForUpdate(const char *method, const TString& name, const TString& value) {
  203. auto res = TWriteGuard(Lock);
  204. if (LookupCounter) {
  205. ++*LookupCounter;
  206. }
  207. if (OnLookup) {
  208. OnLookup(method, name, value);
  209. }
  210. return res;
  211. }
  212. TStackVec<TCounters::value_type, 256> ReadSnapshot() const {
  213. RemoveExpired();
  214. TReadGuard g(Lock);
  215. TStackVec<TCounters::value_type, 256> items(Counters.begin(), Counters.end());
  216. return items;
  217. }
  218. TCounterPtr GetCounter(
  219. const TString& value,
  220. bool derivative = false,
  221. TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  222. TCounterPtr GetNamedCounter(
  223. const TString& name,
  224. const TString& value,
  225. bool derivative = false,
  226. TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  227. THistogramPtr GetHistogram(
  228. const TString& value,
  229. IHistogramCollectorPtr collector,
  230. bool derivative = true,
  231. TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  232. THistogramPtr GetNamedHistogram(
  233. const TString& name,
  234. const TString& value,
  235. IHistogramCollectorPtr collector,
  236. bool derivative = true,
  237. TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  238. // These counters will be automatically removed from the registry
  239. // when last reference to the counter expires.
  240. TCounterPtr GetExpiringCounter(
  241. const TString& value,
  242. bool derivative = false,
  243. TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  244. TCounterPtr GetExpiringNamedCounter(
  245. const TString& name,
  246. const TString& value,
  247. bool derivative = false,
  248. TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  249. THistogramPtr GetExpiringHistogram(
  250. const TString& value,
  251. IHistogramCollectorPtr collector,
  252. bool derivative = true,
  253. TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  254. THistogramPtr GetExpiringNamedHistogram(
  255. const TString& name,
  256. const TString& value,
  257. IHistogramCollectorPtr collector,
  258. bool derivative = true,
  259. TCountableBase::EVisibility visibility = TCountableBase::EVisibility::Public);
  260. TCounterPtr FindCounter(const TString& value) const;
  261. TCounterPtr FindNamedCounter(const TString& name, const TString& value) const;
  262. THistogramPtr FindHistogram(const TString& value) const;
  263. THistogramPtr FindNamedHistogram(const TString& name,const TString& value) const;
  264. void RemoveCounter(const TString &value);
  265. bool RemoveNamedCounter(const TString& name, const TString &value);
  266. void RemoveSubgroupChain(const std::vector<std::pair<TString, TString>>& chain);
  267. TIntrusivePtr<TDynamicCounters> GetSubgroup(const TString& name, const TString& value);
  268. TIntrusivePtr<TDynamicCounters> FindSubgroup(const TString& name, const TString& value) const;
  269. bool RemoveSubgroup(const TString& name, const TString& value);
  270. void ReplaceSubgroup(const TString& name, const TString& value, TIntrusivePtr<TDynamicCounters> subgroup);
  271. // Move all counters from specified subgroup and remove the subgroup.
  272. void MergeWithSubgroup(const TString& name, const TString& value);
  273. // Recursively reset all/deriv counters to 0.
  274. void ResetCounters(bool derivOnly = false);
  275. void RegisterSubgroup(const TString& name,
  276. const TString& value,
  277. TIntrusivePtr<TDynamicCounters> subgroup);
  278. void OutputHtml(IOutputStream& os) const;
  279. void EnumerateSubgroups(const std::function<void(const TString& name, const TString& value)>& output) const;
  280. // mostly for debugging purposes -- use accept with encoder instead
  281. void OutputPlainText(IOutputStream& os, const TString& indent = "") const;
  282. void Accept(
  283. const TString& labelName, const TString& labelValue,
  284. ICountableConsumer& consumer) const override;
  285. private:
  286. TCounters Resign() {
  287. TCounters counters;
  288. TWriteGuard g(Lock);
  289. Counters.swap(counters);
  290. return counters;
  291. }
  292. void RegisterCountable(const TString& name, const TString& value, TCountablePtr countable);
  293. void RemoveExpired() const;
  294. template <bool expiring, class TCounterType, class... TArgs>
  295. TCountablePtr GetNamedCounterImpl(const TString& name, const TString& value, TArgs&&... args);
  296. template <class TCounterType>
  297. TCountablePtr FindNamedCounterImpl(const TString& name, const TString& value) const;
  298. };
  299. }