labels.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. #pragma once
  2. #include <util/digest/multi.h>
  3. #include <util/digest/sequence.h>
  4. #include <util/generic/algorithm.h>
  5. #include <util/generic/maybe.h>
  6. #include <util/generic/string.h>
  7. #include <util/generic/vector.h>
  8. #include <util/stream/output.h>
  9. #include <util/string/builder.h>
  10. #include <util/string/strip.h>
  11. #include <optional>
  12. #include <type_traits>
  13. namespace NMonitoring {
  14. struct ILabel {
  15. virtual ~ILabel() = default;
  16. virtual TStringBuf Name() const noexcept = 0;
  17. virtual TStringBuf Value() const noexcept = 0;
  18. };
  19. ///////////////////////////////////////////////////////////////////////////
  20. // TLabel
  21. ///////////////////////////////////////////////////////////////////////////
  22. template <typename TStringBackend>
  23. class TLabelImpl: public ILabel {
  24. public:
  25. using TStringType = TStringBackend;
  26. TLabelImpl() = default;
  27. inline TLabelImpl(TStringBuf name, TStringBuf value)
  28. : Name_{name}
  29. , Value_{value}
  30. {
  31. }
  32. inline bool operator==(const TLabelImpl& rhs) const noexcept {
  33. return Name_ == rhs.Name_ && Value_ == rhs.Value_;
  34. }
  35. inline bool operator!=(const TLabelImpl& rhs) const noexcept {
  36. return !(*this == rhs);
  37. }
  38. inline TStringBuf Name() const noexcept {
  39. return Name_;
  40. }
  41. inline TStringBuf Value() const noexcept {
  42. return Value_;
  43. }
  44. inline const TStringBackend& NameStr() const {
  45. return Name_;
  46. }
  47. inline const TStringBackend& ValueStr() const {
  48. return Value_;
  49. }
  50. inline size_t Hash() const noexcept {
  51. return MultiHash(Name_, Value_);
  52. }
  53. TStringBackend ToString() const {
  54. TStringBackend buf = Name_;
  55. buf += '=';
  56. buf += Value_;
  57. return buf;
  58. }
  59. static TLabelImpl FromString(TStringBuf str) {
  60. TStringBuf name, value;
  61. Y_ENSURE(str.TrySplit('=', name, value),
  62. "invalid label string format: '" << str << '\'');
  63. TStringBuf nameStripped = StripString(name);
  64. Y_ENSURE(!nameStripped.empty(), "label name cannot be empty");
  65. TStringBuf valueStripped = StripString(value);
  66. Y_ENSURE(!valueStripped.empty(), "label value cannot be empty");
  67. return {nameStripped, valueStripped};
  68. }
  69. static bool TryFromString(TStringBuf str, TLabelImpl& label) {
  70. TStringBuf name, value;
  71. if (!str.TrySplit('=', name, value)) {
  72. return false;
  73. }
  74. TStringBuf nameStripped = StripString(name);
  75. if (nameStripped.empty()) {
  76. return false;
  77. }
  78. TStringBuf valueStripped = StripString(value);
  79. if (valueStripped.empty()) {
  80. return false;
  81. }
  82. label = {nameStripped, valueStripped};
  83. return true;
  84. }
  85. private:
  86. TStringBackend Name_;
  87. TStringBackend Value_;
  88. };
  89. using TLabel = TLabelImpl<TString>;
  90. struct ILabels : public TThrRefBase {
  91. struct TIterator {
  92. TIterator() = default;
  93. TIterator(const ILabels* labels, size_t idx = 0)
  94. : Labels_{labels}
  95. , Idx_{idx}
  96. {
  97. }
  98. TIterator& operator++() noexcept {
  99. Idx_++;
  100. return *this;
  101. }
  102. void operator+=(size_t i) noexcept {
  103. Idx_ += i;
  104. }
  105. bool operator==(const TIterator& other) const noexcept {
  106. return Idx_ == other.Idx_;
  107. }
  108. bool operator!=(const TIterator& other) const noexcept {
  109. return !(*this == other);
  110. }
  111. const ILabel* operator->() const noexcept {
  112. Y_DEBUG_ABORT_UNLESS(Labels_);
  113. return Labels_->Get(Idx_);
  114. }
  115. const ILabel& operator*() const noexcept {
  116. Y_DEBUG_ABORT_UNLESS(Labels_);
  117. return *Labels_->Get(Idx_);
  118. }
  119. private:
  120. const ILabels* Labels_{nullptr};
  121. size_t Idx_{0};
  122. };
  123. virtual ~ILabels() = default;
  124. virtual bool Add(TStringBuf name, TStringBuf value) noexcept = 0;
  125. virtual bool Add(const ILabel& label) noexcept {
  126. return Add(label.Name(), label.Value());
  127. }
  128. virtual bool Has(TStringBuf name) const noexcept = 0;
  129. virtual size_t Size() const noexcept = 0;
  130. virtual bool Empty() const noexcept = 0;
  131. virtual void Clear() noexcept = 0;
  132. virtual size_t Hash() const noexcept = 0;
  133. virtual std::optional<const ILabel*> Get(TStringBuf name) const = 0;
  134. // NB: there's no guarantee that indices are preserved after any object modification
  135. virtual const ILabel* Get(size_t idx) const = 0;
  136. TIterator begin() const {
  137. return TIterator{this};
  138. }
  139. TIterator end() const {
  140. return TIterator{this, Size()};
  141. }
  142. };
  143. bool TryLoadLabelsFromString(TStringBuf sb, ILabels& labels);
  144. bool TryLoadLabelsFromString(IInputStream& is, ILabels& labels);
  145. ///////////////////////////////////////////////////////////////////////////
  146. // TLabels
  147. ///////////////////////////////////////////////////////////////////////////
  148. template <typename TStringBackend>
  149. class TLabelsImpl: public ILabels {
  150. public:
  151. using value_type = TLabelImpl<TStringBackend>;
  152. TLabelsImpl() = default;
  153. explicit TLabelsImpl(::NDetail::TReserveTag rt)
  154. : Labels_(std::move(rt))
  155. {}
  156. explicit TLabelsImpl(size_t count)
  157. : Labels_(count)
  158. {}
  159. explicit TLabelsImpl(size_t count, const value_type& label)
  160. : Labels_(count, label)
  161. {}
  162. TLabelsImpl(std::initializer_list<value_type> il)
  163. : Labels_(std::move(il))
  164. {}
  165. TLabelsImpl(const TLabelsImpl&) = default;
  166. TLabelsImpl& operator=(const TLabelsImpl&) = default;
  167. TLabelsImpl(TLabelsImpl&&) noexcept = default;
  168. TLabelsImpl& operator=(TLabelsImpl&&) noexcept = default;
  169. inline bool operator==(const TLabelsImpl& rhs) const {
  170. return Labels_ == rhs.Labels_;
  171. }
  172. inline bool operator!=(const TLabelsImpl& rhs) const {
  173. return Labels_ != rhs.Labels_;
  174. }
  175. bool Add(TStringBuf name, TStringBuf value) noexcept override {
  176. if (Has(name)) {
  177. return false;
  178. }
  179. Labels_.emplace_back(name, value);
  180. return true;
  181. }
  182. using ILabels::Add;
  183. bool Has(TStringBuf name) const noexcept override {
  184. auto it = FindIf(Labels_, [name](const TLabelImpl<TStringBackend>& label) {
  185. return name == TStringBuf{label.Name()};
  186. });
  187. return it != Labels_.end();
  188. }
  189. bool Has(const TString& name) const noexcept {
  190. auto it = FindIf(Labels_, [name](const TLabelImpl<TStringBackend>& label) {
  191. return name == TStringBuf{label.Name()};
  192. });
  193. return it != Labels_.end();
  194. }
  195. // XXX for backward compatibility
  196. TMaybe<TLabelImpl<TStringBackend>> Find(TStringBuf name) const {
  197. auto it = FindIf(Labels_, [name](const TLabelImpl<TStringBackend>& label) {
  198. return name == TStringBuf{label.Name()};
  199. });
  200. if (it == Labels_.end()) {
  201. return Nothing();
  202. }
  203. return *it;
  204. }
  205. std::optional<const ILabel*> Get(TStringBuf name) const override {
  206. auto it = FindIf(Labels_, [name] (auto&& l) {
  207. return name == l.Name();
  208. });
  209. if (it == Labels_.end()) {
  210. return {};
  211. }
  212. return &*it;
  213. }
  214. const ILabel* Get(size_t idx) const noexcept override {
  215. return &(*this)[idx];
  216. }
  217. TMaybe<TLabelImpl<TStringBackend>> Extract(TStringBuf name) {
  218. auto it = FindIf(Labels_, [name](const TLabelImpl<TStringBackend>& label) {
  219. return name == TStringBuf{label.Name()};
  220. });
  221. if (it == Labels_.end()) {
  222. return Nothing();
  223. }
  224. TLabel tmp = *it;
  225. Labels_.erase(it);
  226. return tmp;
  227. }
  228. void SortByName() {
  229. std::sort(Labels_.begin(), Labels_.end(), [](const auto& lhs, const auto& rhs) {
  230. return lhs.Name() < rhs.Name();
  231. });
  232. }
  233. inline size_t Hash() const noexcept override {
  234. return TSimpleRangeHash()(Labels_);
  235. }
  236. inline TLabel* Data() const noexcept {
  237. return const_cast<TLabel*>(Labels_.data());
  238. }
  239. inline size_t Size() const noexcept override {
  240. return Labels_.size();
  241. }
  242. inline bool Empty() const noexcept override {
  243. return Labels_.empty();
  244. }
  245. inline void Clear() noexcept override {
  246. Labels_.clear();
  247. }
  248. TLabelImpl<TStringBackend>& front() {
  249. return Labels_.front();
  250. }
  251. const TLabelImpl<TStringBackend>& front() const {
  252. return Labels_.front();
  253. }
  254. TLabelImpl<TStringBackend>& back() {
  255. return Labels_.back();
  256. }
  257. const TLabelImpl<TStringBackend>& back() const {
  258. return Labels_.back();
  259. }
  260. TLabelImpl<TStringBackend>& operator[](size_t index) {
  261. return Labels_[index];
  262. }
  263. const TLabelImpl<TStringBackend>& operator[](size_t index) const {
  264. return Labels_[index];
  265. }
  266. TLabelImpl<TStringBackend>& at(size_t index) {
  267. return Labels_.at(index);
  268. }
  269. const TLabelImpl<TStringBackend>& at(size_t index) const {
  270. return Labels_.at(index);
  271. }
  272. size_t capacity() const {
  273. return Labels_.capacity();
  274. }
  275. TLabelImpl<TStringBackend>* data() {
  276. return Labels_.data();
  277. }
  278. const TLabelImpl<TStringBackend>* data() const {
  279. return Labels_.data();
  280. }
  281. size_t size() const {
  282. return Labels_.size();
  283. }
  284. bool empty() const {
  285. return Labels_.empty();
  286. }
  287. void clear() {
  288. Labels_.clear();
  289. }
  290. using ILabels::begin;
  291. using ILabels::end;
  292. using iterator = ILabels::TIterator;
  293. using const_iterator = iterator;
  294. protected:
  295. TVector<TLabelImpl<TStringBackend>>& AsVector() {
  296. return Labels_;
  297. }
  298. const TVector<TLabelImpl<TStringBackend>>& AsVector() const {
  299. return Labels_;
  300. }
  301. private:
  302. TVector<TLabelImpl<TStringBackend>> Labels_;
  303. };
  304. using TLabels = TLabelsImpl<TString>;
  305. using ILabelsPtr = TIntrusivePtr<ILabels>;
  306. template <typename T>
  307. ILabelsPtr MakeLabels() {
  308. return MakeIntrusive<TLabelsImpl<T>>();
  309. }
  310. template <typename T>
  311. ILabelsPtr MakeLabels(std::initializer_list<TLabelImpl<T>> labels) {
  312. return MakeIntrusive<TLabelsImpl<T>>(labels);
  313. }
  314. inline ILabelsPtr MakeLabels(TLabels&& labels) {
  315. return MakeIntrusive<TLabels>(std::move(labels));
  316. }
  317. }
  318. template<>
  319. struct THash<NMonitoring::ILabelsPtr> {
  320. size_t operator()(const NMonitoring::ILabelsPtr& labels) const noexcept {
  321. return labels->Hash();
  322. }
  323. size_t operator()(const NMonitoring::ILabels& labels) const noexcept {
  324. return labels.Hash();
  325. }
  326. };
  327. template<typename TStringBackend>
  328. struct THash<NMonitoring::TLabelsImpl<TStringBackend>> {
  329. size_t operator()(const NMonitoring::TLabelsImpl<TStringBackend>& labels) const noexcept {
  330. return labels.Hash();
  331. }
  332. };
  333. template <typename TStringBackend>
  334. struct THash<NMonitoring::TLabelImpl<TStringBackend>> {
  335. inline size_t operator()(const NMonitoring::TLabelImpl<TStringBackend>& label) const noexcept {
  336. return label.Hash();
  337. }
  338. };
  339. inline bool operator==(const NMonitoring::ILabels& lhs, const NMonitoring::ILabels& rhs) {
  340. if (lhs.Size() != rhs.Size()) {
  341. return false;
  342. }
  343. for (auto&& l : lhs) {
  344. auto rl = rhs.Get(l.Name());
  345. if (!rl || (*rl)->Value() != l.Value()) {
  346. return false;
  347. }
  348. }
  349. return true;
  350. }
  351. bool operator==(const NMonitoring::ILabelsPtr& lhs, const NMonitoring::ILabelsPtr& rhs) = delete;
  352. bool operator==(const NMonitoring::ILabels& lhs, const NMonitoring::ILabelsPtr& rhs) = delete;
  353. bool operator==(const NMonitoring::ILabelsPtr& lhs, const NMonitoring::ILabels& rhs) = delete;
  354. template<>
  355. struct TEqualTo<NMonitoring::ILabelsPtr> {
  356. bool operator()(const NMonitoring::ILabelsPtr& lhs, const NMonitoring::ILabelsPtr& rhs) {
  357. return *lhs == *rhs;
  358. }
  359. bool operator()(const NMonitoring::ILabelsPtr& lhs, const NMonitoring::ILabels& rhs) {
  360. return *lhs == rhs;
  361. }
  362. bool operator()(const NMonitoring::ILabels& lhs, const NMonitoring::ILabelsPtr& rhs) {
  363. return lhs == *rhs;
  364. }
  365. };
  366. #define Y_MONLIB_DEFINE_LABELS_OUT(T) \
  367. template <> \
  368. void Out<T>(IOutputStream& out, const T& labels) { \
  369. Out<NMonitoring::ILabels>(out, labels); \
  370. }
  371. #define Y_MONLIB_DEFINE_LABEL_OUT(T) \
  372. template <> \
  373. void Out<T>(IOutputStream& out, const T& label) { \
  374. Out<NMonitoring::ILabel>(out, label); \
  375. }