aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/monlib/metrics/labels.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/metrics/labels.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/monlib/metrics/labels.h')
-rw-r--r--library/cpp/monlib/metrics/labels.h483
1 files changed, 483 insertions, 0 deletions
diff --git a/library/cpp/monlib/metrics/labels.h b/library/cpp/monlib/metrics/labels.h
new file mode 100644
index 0000000000..63dc997c28
--- /dev/null
+++ b/library/cpp/monlib/metrics/labels.h
@@ -0,0 +1,483 @@
+#pragma once
+
+#include <util/digest/multi.h>
+#include <util/digest/sequence.h>
+#include <util/generic/algorithm.h>
+#include <util/generic/maybe.h>
+#include <util/generic/string.h>
+#include <util/generic/vector.h>
+#include <util/stream/output.h>
+#include <util/string/builder.h>
+#include <util/string/strip.h>
+
+#include <optional>
+#include <type_traits>
+
+namespace NMonitoring {
+ struct ILabel {
+ virtual ~ILabel() = default;
+
+ virtual TStringBuf Name() const noexcept = 0;
+ virtual TStringBuf Value() const noexcept = 0;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // TLabel
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename TStringBackend>
+ class TLabelImpl: public ILabel {
+ public:
+ using TStringType = TStringBackend;
+
+ TLabelImpl() = default;
+
+ inline TLabelImpl(TStringBuf name, TStringBuf value)
+ : Name_{name}
+ , Value_{value}
+ {
+ }
+
+ inline bool operator==(const TLabelImpl& rhs) const noexcept {
+ return Name_ == rhs.Name_ && Value_ == rhs.Value_;
+ }
+
+ inline bool operator!=(const TLabelImpl& rhs) const noexcept {
+ return !(*this == rhs);
+ }
+
+ inline TStringBuf Name() const noexcept {
+ return Name_;
+ }
+
+ inline TStringBuf Value() const noexcept {
+ return Value_;
+ }
+
+ inline const TStringBackend& NameStr() const {
+ return Name_;
+ }
+
+ inline const TStringBackend& ValueStr() const {
+ return Value_;
+ }
+
+ inline size_t Hash() const noexcept {
+ return MultiHash(Name_, Value_);
+ }
+
+ TStringBackend ToString() const {
+ TStringBackend buf = Name_;
+ buf += '=';
+ buf += Value_;
+
+ return buf;
+ }
+
+ static TLabelImpl FromString(TStringBuf str) {
+ TStringBuf name, value;
+ Y_ENSURE(str.TrySplit('=', name, value),
+ "invalid label string format: '" << str << '\'');
+
+ TStringBuf nameStripped = StripString(name);
+ Y_ENSURE(!nameStripped.empty(), "label name cannot be empty");
+
+ TStringBuf valueStripped = StripString(value);
+ Y_ENSURE(!valueStripped.empty(), "label value cannot be empty");
+
+ return {nameStripped, valueStripped};
+ }
+
+ static bool TryFromString(TStringBuf str, TLabelImpl& label) {
+ TStringBuf name, value;
+ if (!str.TrySplit('=', name, value)) {
+ return false;
+ }
+
+ TStringBuf nameStripped = StripString(name);
+ if (nameStripped.empty()) {
+ return false;
+ }
+
+ TStringBuf valueStripped = StripString(value);
+ if (valueStripped.empty()) {
+ return false;
+ }
+
+ label = {nameStripped, valueStripped};
+ return true;
+ }
+
+ private:
+ TStringBackend Name_;
+ TStringBackend Value_;
+ };
+
+ using TLabel = TLabelImpl<TString>;
+
+ struct ILabels {
+ struct TIterator {
+ TIterator() = default;
+ TIterator(const ILabels* labels, size_t idx = 0)
+ : Labels_{labels}
+ , Idx_{idx}
+ {
+ }
+
+ TIterator& operator++() noexcept {
+ Idx_++;
+ return *this;
+ }
+
+ void operator+=(size_t i) noexcept {
+ Idx_ += i;
+ }
+
+ bool operator==(const TIterator& other) const noexcept {
+ return Idx_ == other.Idx_;
+ }
+
+ bool operator!=(const TIterator& other) const noexcept {
+ return !(*this == other);
+ }
+
+ const ILabel* operator->() const noexcept {
+ Y_VERIFY_DEBUG(Labels_);
+ return Labels_->Get(Idx_);
+ }
+
+ const ILabel& operator*() const noexcept {
+ Y_VERIFY_DEBUG(Labels_);
+ return *Labels_->Get(Idx_);
+ }
+
+
+ private:
+ const ILabels* Labels_{nullptr};
+ size_t Idx_{0};
+ };
+
+ virtual ~ILabels() = default;
+
+ virtual bool Add(TStringBuf name, TStringBuf value) noexcept = 0;
+ virtual bool Add(const ILabel& label) noexcept {
+ return Add(label.Name(), label.Value());
+ }
+
+ virtual bool Has(TStringBuf name) const noexcept = 0;
+
+ virtual size_t Size() const noexcept = 0;
+ virtual bool Empty() const noexcept = 0;
+ virtual void Clear() noexcept = 0;
+
+ virtual size_t Hash() const noexcept = 0;
+
+ virtual std::optional<const ILabel*> Get(TStringBuf name) const = 0;
+
+ // NB: there's no guarantee that indices are preserved after any object modification
+ virtual const ILabel* Get(size_t idx) const = 0;
+
+ TIterator begin() const {
+ return TIterator{this};
+ }
+
+ TIterator end() const {
+ return TIterator{this, Size()};
+ }
+ };
+
+ bool TryLoadLabelsFromString(TStringBuf sb, ILabels& labels);
+ bool TryLoadLabelsFromString(IInputStream& is, ILabels& labels);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // TLabels
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename TStringBackend>
+ class TLabelsImpl: public ILabels {
+ public:
+ using value_type = TLabelImpl<TStringBackend>;
+
+ TLabelsImpl() = default;
+
+ explicit TLabelsImpl(::NDetail::TReserveTag rt)
+ : Labels_(std::move(rt))
+ {}
+
+ explicit TLabelsImpl(size_t count)
+ : Labels_(count)
+ {}
+
+ explicit TLabelsImpl(size_t count, const value_type& label)
+ : Labels_(count, label)
+ {}
+
+ TLabelsImpl(std::initializer_list<value_type> il)
+ : Labels_(std::move(il))
+ {}
+
+ TLabelsImpl(const TLabelsImpl&) = default;
+ TLabelsImpl& operator=(const TLabelsImpl&) = default;
+
+ TLabelsImpl(TLabelsImpl&&) noexcept = default;
+ TLabelsImpl& operator=(TLabelsImpl&&) noexcept = default;
+
+ inline bool operator==(const TLabelsImpl& rhs) const {
+ return Labels_ == rhs.Labels_;
+ }
+
+ inline bool operator!=(const TLabelsImpl& rhs) const {
+ return Labels_ != rhs.Labels_;
+ }
+
+ bool Add(TStringBuf name, TStringBuf value) noexcept override {
+ if (Has(name)) {
+ return false;
+ }
+
+ Labels_.emplace_back(name, value);
+ return true;
+ }
+
+ using ILabels::Add;
+
+ bool Has(TStringBuf name) const noexcept override {
+ auto it = FindIf(Labels_, [name](const TLabelImpl<TStringBackend>& label) {
+ return name == TStringBuf{label.Name()};
+ });
+ return it != Labels_.end();
+ }
+
+ bool Has(const TString& name) const noexcept {
+ auto it = FindIf(Labels_, [name](const TLabelImpl<TStringBackend>& label) {
+ return name == TStringBuf{label.Name()};
+ });
+ return it != Labels_.end();
+ }
+
+ // XXX for backward compatibility
+ TMaybe<TLabelImpl<TStringBackend>> Find(TStringBuf name) const {
+ auto it = FindIf(Labels_, [name](const TLabelImpl<TStringBackend>& label) {
+ return name == TStringBuf{label.Name()};
+ });
+ if (it == Labels_.end()) {
+ return Nothing();
+ }
+ return *it;
+ }
+
+ std::optional<const ILabel*> Get(TStringBuf name) const override {
+ auto it = FindIf(Labels_, [name] (auto&& l) {
+ return name == l.Name();
+ });
+
+ if (it == Labels_.end()) {
+ return {};
+ }
+
+ return &*it;
+ }
+
+ const ILabel* Get(size_t idx) const noexcept override {
+ return &(*this)[idx];
+ }
+
+ TMaybe<TLabelImpl<TStringBackend>> Extract(TStringBuf name) {
+ auto it = FindIf(Labels_, [name](const TLabelImpl<TStringBackend>& label) {
+ return name == TStringBuf{label.Name()};
+ });
+ if (it == Labels_.end()) {
+ return Nothing();
+ }
+ TLabel tmp = *it;
+ Labels_.erase(it);
+ return tmp;
+ }
+
+ void SortByName() {
+ std::sort(Labels_.begin(), Labels_.end(), [](const auto& lhs, const auto& rhs) {
+ return lhs.Name() < rhs.Name();
+ });
+ }
+
+ inline size_t Hash() const noexcept override {
+ return TSimpleRangeHash()(Labels_);
+ }
+
+ inline TLabel* Data() const noexcept {
+ return const_cast<TLabel*>(Labels_.data());
+ }
+
+ inline size_t Size() const noexcept override {
+ return Labels_.size();
+ }
+
+ inline bool Empty() const noexcept override {
+ return Labels_.empty();
+ }
+
+ inline void Clear() noexcept override {
+ Labels_.clear();
+ };
+
+ TLabelImpl<TStringBackend>& front() {
+ return Labels_.front();
+ }
+
+ const TLabelImpl<TStringBackend>& front() const {
+ return Labels_.front();
+ }
+
+ TLabelImpl<TStringBackend>& back() {
+ return Labels_.back();
+ }
+
+ const TLabelImpl<TStringBackend>& back() const {
+ return Labels_.back();
+ }
+
+ TLabelImpl<TStringBackend>& operator[](size_t index) {
+ return Labels_[index];
+ }
+
+ const TLabelImpl<TStringBackend>& operator[](size_t index) const {
+ return Labels_[index];
+ }
+
+ TLabelImpl<TStringBackend>& at(size_t index) {
+ return Labels_.at(index);
+ }
+
+ const TLabelImpl<TStringBackend>& at(size_t index) const {
+ return Labels_.at(index);
+ }
+
+ size_t capacity() const {
+ return Labels_.capacity();
+ }
+
+ TLabelImpl<TStringBackend>* data() {
+ return Labels_.data();
+ }
+
+ const TLabelImpl<TStringBackend>* data() const {
+ return Labels_.data();
+ }
+
+ size_t size() const {
+ return Labels_.size();
+ }
+
+ bool empty() const {
+ return Labels_.empty();
+ }
+
+ void clear() {
+ Labels_.clear();
+ }
+
+ using ILabels::begin;
+ using ILabels::end;
+
+ using iterator = ILabels::TIterator;
+ using const_iterator = iterator;
+
+ protected:
+ TVector<TLabelImpl<TStringBackend>>& AsVector() {
+ return Labels_;
+ }
+
+ const TVector<TLabelImpl<TStringBackend>>& AsVector() const {
+ return Labels_;
+ }
+
+ private:
+ TVector<TLabelImpl<TStringBackend>> Labels_;
+ };
+
+ using TLabels = TLabelsImpl<TString>;
+ using ILabelsPtr = THolder<ILabels>;
+
+ template <typename T>
+ ILabelsPtr MakeLabels() {
+ return MakeHolder<TLabelsImpl<T>>();
+ }
+
+ template <typename T>
+ ILabelsPtr MakeLabels(std::initializer_list<TLabelImpl<T>> labels) {
+ return MakeHolder<TLabelsImpl<T>>(labels);
+ }
+
+ inline ILabelsPtr MakeLabels(TLabels&& labels) {
+ return MakeHolder<TLabels>(std::move(labels));
+ }
+}
+
+template<>
+struct THash<NMonitoring::ILabelsPtr> {
+ size_t operator()(const NMonitoring::ILabelsPtr& labels) const noexcept {
+ return labels->Hash();
+ }
+
+ size_t operator()(const NMonitoring::ILabels& labels) const noexcept {
+ return labels.Hash();
+ }
+};
+
+template<typename TStringBackend>
+struct THash<NMonitoring::TLabelsImpl<TStringBackend>> {
+ size_t operator()(const NMonitoring::TLabelsImpl<TStringBackend>& labels) const noexcept {
+ return labels.Hash();
+ }
+};
+
+template <typename TStringBackend>
+struct THash<NMonitoring::TLabelImpl<TStringBackend>> {
+ inline size_t operator()(const NMonitoring::TLabelImpl<TStringBackend>& label) const noexcept {
+ return label.Hash();
+ }
+};
+
+inline bool operator==(const NMonitoring::ILabels& lhs, const NMonitoring::ILabels& rhs) {
+ if (lhs.Size() != rhs.Size()) {
+ return false;
+ }
+
+ for (auto&& l : lhs) {
+ auto rl = rhs.Get(l.Name());
+ if (!rl || (*rl)->Value() != l.Value()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool operator==(const NMonitoring::ILabelsPtr& lhs, const NMonitoring::ILabelsPtr& rhs) = delete;
+bool operator==(const NMonitoring::ILabels& lhs, const NMonitoring::ILabelsPtr& rhs) = delete;
+bool operator==(const NMonitoring::ILabelsPtr& lhs, const NMonitoring::ILabels& rhs) = delete;
+
+template<>
+struct TEqualTo<NMonitoring::ILabelsPtr> {
+ bool operator()(const NMonitoring::ILabelsPtr& lhs, const NMonitoring::ILabelsPtr& rhs) {
+ return *lhs == *rhs;
+ }
+
+ bool operator()(const NMonitoring::ILabelsPtr& lhs, const NMonitoring::ILabels& rhs) {
+ return *lhs == rhs;
+ }
+
+ bool operator()(const NMonitoring::ILabels& lhs, const NMonitoring::ILabelsPtr& rhs) {
+ return lhs == *rhs;
+ }
+};
+
+#define Y_MONLIB_DEFINE_LABELS_OUT(T) \
+template <> \
+void Out<T>(IOutputStream& out, const T& labels) { \
+ Out<NMonitoring::ILabels>(out, labels); \
+}
+
+#define Y_MONLIB_DEFINE_LABEL_OUT(T) \
+template <> \
+void Out<T>(IOutputStream& out, const T& label) { \
+ Out<NMonitoring::ILabel>(out, label); \
+}