diff options
author | msherbakov <msherbakov@yandex-team.ru> | 2022-02-10 16:49:17 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:49:17 +0300 |
commit | a0ffafe83b7d6229709a32fa942c71d672ac989c (patch) | |
tree | 5d5cb817648f650d76cf1076100726fd9b8448e8 /library/cpp/monlib/encode | |
parent | c224a621661ddd69699f9476922eb316607ef57e (diff) | |
download | ydb-a0ffafe83b7d6229709a32fa942c71d672ac989c.tar.gz |
Restoring authorship annotation for <msherbakov@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/monlib/encode')
47 files changed, 2337 insertions, 2337 deletions
diff --git a/library/cpp/monlib/encode/buffered/buffered_encoder_base.cpp b/library/cpp/monlib/encode/buffered/buffered_encoder_base.cpp index 022e025fa7..87c832d642 100644 --- a/library/cpp/monlib/encode/buffered/buffered_encoder_base.cpp +++ b/library/cpp/monlib/encode/buffered/buffered_encoder_base.cpp @@ -1,29 +1,29 @@ -#include "buffered_encoder_base.h" - +#include "buffered_encoder_base.h" + #include <util/string/join.h> #include <util/string/builder.h> -namespace NMonitoring { - -void TBufferedEncoderBase::OnStreamBegin() { +namespace NMonitoring { + +void TBufferedEncoderBase::OnStreamBegin() { State_.Expect(TEncoderState::EState::ROOT); -} - -void TBufferedEncoderBase::OnStreamEnd() { +} + +void TBufferedEncoderBase::OnStreamEnd() { State_.Expect(TEncoderState::EState::ROOT); -} - -void TBufferedEncoderBase::OnCommonTime(TInstant time) { +} + +void TBufferedEncoderBase::OnCommonTime(TInstant time) { State_.Expect(TEncoderState::EState::ROOT); - CommonTime_ = time; -} - + CommonTime_ = time; +} + void TBufferedEncoderBase::OnMetricBegin(EMetricType type) { State_.Switch(TEncoderState::EState::ROOT, TEncoderState::EState::METRIC); Metrics_.emplace_back(); Metrics_.back().MetricType = type; -} - +} + void TBufferedEncoderBase::OnMetricEnd() { State_.Switch(TEncoderState::EState::METRIC, TEncoderState::EState::ROOT); @@ -41,7 +41,7 @@ void TBufferedEncoderBase::OnMetricEnd() { auto& existing = Metrics_[it->second].TimeSeries; Y_ENSURE(existing.GetValueType() == metric.TimeSeries.GetValueType(), - "Time series point type mismatch: expected " << existing.GetValueType() + "Time series point type mismatch: expected " << existing.GetValueType() << " but found " << metric.TimeSeries.GetValueType() << ", labels '" << FormatLabels(metric.Labels) << "'"); @@ -54,41 +54,41 @@ void TBufferedEncoderBase::OnMetricEnd() { case EMetricsMergingMode::DEFAULT: break; } -} - -void TBufferedEncoderBase::OnLabelsBegin() { +} + +void TBufferedEncoderBase::OnLabelsBegin() { if (State_ == TEncoderState::EState::METRIC) { State_ = TEncoderState::EState::METRIC_LABELS; } else if (State_ == TEncoderState::EState::ROOT) { State_ = TEncoderState::EState::COMMON_LABELS; - } else { + } else { State_.ThrowInvalid("expected METRIC or ROOT"); - } -} - -void TBufferedEncoderBase::OnLabelsEnd() { + } +} + +void TBufferedEncoderBase::OnLabelsEnd() { if (State_ == TEncoderState::EState::METRIC_LABELS) { State_ = TEncoderState::EState::METRIC; } else if (State_ == TEncoderState::EState::COMMON_LABELS) { State_ = TEncoderState::EState::ROOT; - } else { - State_.ThrowInvalid("expected LABELS or COMMON_LABELS"); - } -} - + } else { + State_.ThrowInvalid("expected LABELS or COMMON_LABELS"); + } +} + void TBufferedEncoderBase::OnLabel(TStringBuf name, TStringBuf value) { - TPooledLabels* labels; + TPooledLabels* labels; if (State_ == TEncoderState::EState::METRIC_LABELS) { labels = &Metrics_.back().Labels; } else if (State_ == TEncoderState::EState::COMMON_LABELS) { - labels = &CommonLabels_; - } else { - State_.ThrowInvalid("expected LABELS or COMMON_LABELS"); - } - - labels->emplace_back(LabelNamesPool_.PutIfAbsent(name), LabelValuesPool_.PutIfAbsent(value)); -} - + labels = &CommonLabels_; + } else { + State_.ThrowInvalid("expected LABELS or COMMON_LABELS"); + } + + labels->emplace_back(LabelNamesPool_.PutIfAbsent(name), LabelValuesPool_.PutIfAbsent(value)); +} + void TBufferedEncoderBase::OnLabel(ui32 name, ui32 value) { TPooledLabels* labels; if (State_ == TEncoderState::EState::METRIC_LABELS) { @@ -108,24 +108,24 @@ std::pair<ui32, ui32> TBufferedEncoderBase::PrepareLabel(TStringBuf name, TStrin return std::make_pair(nameLabel->Index, valueLabel->Index); } -void TBufferedEncoderBase::OnDouble(TInstant time, double value) { +void TBufferedEncoderBase::OnDouble(TInstant time, double value) { State_.Expect(TEncoderState::EState::METRIC); TMetric& metric = Metrics_.back(); metric.TimeSeries.Add(time, value); -} - +} + void TBufferedEncoderBase::OnInt64(TInstant time, i64 value) { State_.Expect(TEncoderState::EState::METRIC); TMetric& metric = Metrics_.back(); metric.TimeSeries.Add(time, value); } -void TBufferedEncoderBase::OnUint64(TInstant time, ui64 value) { +void TBufferedEncoderBase::OnUint64(TInstant time, ui64 value) { State_.Expect(TEncoderState::EState::METRIC); TMetric& metric = Metrics_.back(); metric.TimeSeries.Add(time, value); -} - +} + void TBufferedEncoderBase::OnHistogram(TInstant time, IHistogramSnapshotPtr s) { State_.Expect(TEncoderState::EState::METRIC); TMetric& metric = Metrics_.back(); @@ -167,4 +167,4 @@ TString TBufferedEncoderBase::FormatLabels(const TPooledLabels& labels) const { return TStringBuilder() << "{" << JoinSeq(", ", formattedLabels) << "}"; } -} // namespace NMonitoring +} // namespace NMonitoring diff --git a/library/cpp/monlib/encode/buffered/buffered_encoder_base.h b/library/cpp/monlib/encode/buffered/buffered_encoder_base.h index 38f63eac1d..fe3714e58f 100644 --- a/library/cpp/monlib/encode/buffered/buffered_encoder_base.h +++ b/library/cpp/monlib/encode/buffered/buffered_encoder_base.h @@ -1,100 +1,100 @@ -#pragma once - -#include "string_pool.h" - +#pragma once + +#include "string_pool.h" + #include <library/cpp/monlib/encode/encoder.h> #include <library/cpp/monlib/encode/encoder_state.h> #include <library/cpp/monlib/encode/format.h> #include <library/cpp/monlib/metrics/metric_value.h> - -#include <util/datetime/base.h> -#include <util/digest/numeric.h> - - -namespace NMonitoring { - + +#include <util/datetime/base.h> +#include <util/digest/numeric.h> + + +namespace NMonitoring { + class TBufferedEncoderBase : public IMetricEncoder { -public: - void OnStreamBegin() override; - void OnStreamEnd() override; - - void OnCommonTime(TInstant time) override; - +public: + void OnStreamBegin() override; + void OnStreamEnd() override; + + void OnCommonTime(TInstant time) override; + void OnMetricBegin(EMetricType type) override; void OnMetricEnd() override; - - void OnLabelsBegin() override; - void OnLabelsEnd() override; + + void OnLabelsBegin() override; + void OnLabelsEnd() override; void OnLabel(TStringBuf name, TStringBuf value) override; void OnLabel(ui32 name, ui32 value) override; std::pair<ui32, ui32> PrepareLabel(TStringBuf name, TStringBuf value) override; - - void OnDouble(TInstant time, double value) override; + + void OnDouble(TInstant time, double value) override; void OnInt64(TInstant time, i64 value) override; - void OnUint64(TInstant time, ui64 value) override; - + void OnUint64(TInstant time, ui64 value) override; + void OnHistogram(TInstant time, IHistogramSnapshotPtr snapshot) override; void OnSummaryDouble(TInstant time, ISummaryDoubleSnapshotPtr snapshot) override; void OnLogHistogram(TInstant, TLogHistogramSnapshotPtr) override; -protected: - using TPooledStr = TStringPoolBuilder::TValue; - - struct TPooledLabel { - TPooledLabel(const TPooledStr* key, const TPooledStr* value) - : Key{key} - , Value{value} - { - } - - bool operator==(const TPooledLabel& other) const { - return std::tie(Key, Value) == std::tie(other.Key, other.Value); - } - - bool operator!=(const TPooledLabel& other) const { - return !(*this == other); - } - - const TPooledStr* Key; - const TPooledStr* Value; - }; - - using TPooledLabels = TVector<TPooledLabel>; - - struct TPooledLabelsHash { - size_t operator()(const TPooledLabels& val) const { - size_t hash{0}; - - for (auto v : val) { - hash = CombineHashes<size_t>(hash, reinterpret_cast<size_t>(v.Key)); - hash = CombineHashes<size_t>(hash, reinterpret_cast<size_t>(v.Value)); - } - - return hash; - } - }; - +protected: + using TPooledStr = TStringPoolBuilder::TValue; + + struct TPooledLabel { + TPooledLabel(const TPooledStr* key, const TPooledStr* value) + : Key{key} + , Value{value} + { + } + + bool operator==(const TPooledLabel& other) const { + return std::tie(Key, Value) == std::tie(other.Key, other.Value); + } + + bool operator!=(const TPooledLabel& other) const { + return !(*this == other); + } + + const TPooledStr* Key; + const TPooledStr* Value; + }; + + using TPooledLabels = TVector<TPooledLabel>; + + struct TPooledLabelsHash { + size_t operator()(const TPooledLabels& val) const { + size_t hash{0}; + + for (auto v : val) { + hash = CombineHashes<size_t>(hash, reinterpret_cast<size_t>(v.Key)); + hash = CombineHashes<size_t>(hash, reinterpret_cast<size_t>(v.Value)); + } + + return hash; + } + }; + using TMetricMap = THashMap<TPooledLabels, size_t, TPooledLabelsHash>; - + struct TMetric { EMetricType MetricType = EMetricType::UNKNOWN; - TPooledLabels Labels; + TPooledLabels Labels; TMetricTimeSeries TimeSeries; - }; - + }; + protected: TString FormatLabels(const TPooledLabels& labels) const; protected: - TEncoderState State_; - - TStringPoolBuilder LabelNamesPool_; - TStringPoolBuilder LabelValuesPool_; - TInstant CommonTime_ = TInstant::Zero(); - TPooledLabels CommonLabels_; + TEncoderState State_; + + TStringPoolBuilder LabelNamesPool_; + TStringPoolBuilder LabelValuesPool_; + TInstant CommonTime_ = TInstant::Zero(); + TPooledLabels CommonLabels_; TVector<TMetric> Metrics_; TMetricMap MetricMap_; EMetricsMergingMode MetricsMergingMode_ = EMetricsMergingMode::DEFAULT; -}; - -} +}; + +} diff --git a/library/cpp/monlib/encode/buffered/string_pool.cpp b/library/cpp/monlib/encode/buffered/string_pool.cpp index 3c274f27f7..b4c7988ba3 100644 --- a/library/cpp/monlib/encode/buffered/string_pool.cpp +++ b/library/cpp/monlib/encode/buffered/string_pool.cpp @@ -5,16 +5,16 @@ namespace NMonitoring { // TStringPoolBuilder //////////////////////////////////////////////////////////////////////////////// const TStringPoolBuilder::TValue* TStringPoolBuilder::PutIfAbsent(TStringBuf str) { - Y_ENSURE(!IsBuilt_, "Cannot add more values after string has been built"); + Y_ENSURE(!IsBuilt_, "Cannot add more values after string has been built"); - auto [it, isInserted] = StrMap_.try_emplace(str, Max<ui32>(), 0); - if (isInserted) { + auto [it, isInserted] = StrMap_.try_emplace(str, Max<ui32>(), 0); + if (isInserted) { BytesSize_ += str.size(); it->second.Index = StrVector_.size(); StrVector_.emplace_back(it->first, &it->second); } - - TValue* value = &it->second; + + TValue* value = &it->second; ++value->Frequency; return value; } @@ -23,12 +23,12 @@ namespace NMonitoring { return StrVector_.at(index).second; } - TStringPoolBuilder& TStringPoolBuilder::Build() { - if (RequiresSorting_) { - // sort in reversed order - std::sort(StrVector_.begin(), StrVector_.end(), [](auto& a, auto& b) { - return a.second->Frequency > b.second->Frequency; - }); + TStringPoolBuilder& TStringPoolBuilder::Build() { + if (RequiresSorting_) { + // sort in reversed order + std::sort(StrVector_.begin(), StrVector_.end(), [](auto& a, auto& b) { + return a.second->Frequency > b.second->Frequency; + }); ui32 i = 0; for (auto& value : StrVector_) { @@ -36,9 +36,9 @@ namespace NMonitoring { } } - IsBuilt_ = true; - - return *this; + IsBuilt_ = true; + + return *this; } //////////////////////////////////////////////////////////////////////////////// diff --git a/library/cpp/monlib/encode/buffered/string_pool.h b/library/cpp/monlib/encode/buffered/string_pool.h index 39fab1673f..00e5644608 100644 --- a/library/cpp/monlib/encode/buffered/string_pool.h +++ b/library/cpp/monlib/encode/buffered/string_pool.h @@ -9,13 +9,13 @@ namespace NMonitoring { //////////////////////////////////////////////////////////////////////////////// class TStringPoolBuilder { public: - struct TValue: TNonCopyable { - TValue(ui32 idx, ui32 freq) - : Index{idx} - , Frequency{freq} - { - } - + struct TValue: TNonCopyable { + TValue(ui32 idx, ui32 freq) + : Index{idx} + , Frequency{freq} + { + } + ui32 Index; ui32 Frequency; }; @@ -24,16 +24,16 @@ namespace NMonitoring { const TValue* PutIfAbsent(TStringBuf str); const TValue* GetByIndex(ui32 index) const; - /// Determines whether pool must be sorted by value frequencies - TStringPoolBuilder& SetSorted(bool sorted) { - RequiresSorting_ = sorted; - return *this; - } + /// Determines whether pool must be sorted by value frequencies + TStringPoolBuilder& SetSorted(bool sorted) { + RequiresSorting_ = sorted; + return *this; + } + + TStringPoolBuilder& Build(); - TStringPoolBuilder& Build(); - TStringBuf Get(ui32 index) const { - Y_ENSURE(IsBuilt_, "Pool must be sorted first"); + Y_ENSURE(IsBuilt_, "Pool must be sorted first"); return StrVector_.at(index).first; } @@ -43,7 +43,7 @@ namespace NMonitoring { template <typename TConsumer> void ForEach(TConsumer&& c) { - Y_ENSURE(IsBuilt_, "Pool must be sorted first"); + Y_ENSURE(IsBuilt_, "Pool must be sorted first"); for (const auto& value : StrVector_) { c(value.first, value.second->Index, value.second->Frequency); } @@ -60,8 +60,8 @@ namespace NMonitoring { private: THashMap<TString, TValue> StrMap_; TVector<std::pair<TStringBuf, TValue*>> StrVector_; - bool RequiresSorting_ = false; - bool IsBuilt_ = false; + bool RequiresSorting_ = false; + bool IsBuilt_ = false; size_t BytesSize_ = 0; }; diff --git a/library/cpp/monlib/encode/buffered/string_pool_ut.cpp b/library/cpp/monlib/encode/buffered/string_pool_ut.cpp index e597b0c23d..9fc3421d0b 100644 --- a/library/cpp/monlib/encode/buffered/string_pool_ut.cpp +++ b/library/cpp/monlib/encode/buffered/string_pool_ut.cpp @@ -7,8 +7,8 @@ using namespace NMonitoring; Y_UNIT_TEST_SUITE(TStringPoolTest) { Y_UNIT_TEST(PutIfAbsent) { TStringPoolBuilder strPool; - strPool.SetSorted(true); - + strPool.SetSorted(true); + auto* h1 = strPool.PutIfAbsent("one"); auto* h2 = strPool.PutIfAbsent("two"); auto* h3 = strPool.PutIfAbsent("two"); @@ -27,15 +27,15 @@ Y_UNIT_TEST_SUITE(TStringPoolTest) { Y_UNIT_TEST(SortByFrequency) { TStringPoolBuilder strPool; - strPool.SetSorted(true); - + strPool.SetSorted(true); + auto* h1 = strPool.PutIfAbsent("one"); auto* h2 = strPool.PutIfAbsent("two"); auto* h3 = strPool.PutIfAbsent("two"); UNIT_ASSERT(h1 != h2); UNIT_ASSERT(h2 == h3); - strPool.Build(); + strPool.Build(); UNIT_ASSERT_VALUES_EQUAL(h1->Frequency, 1); UNIT_ASSERT_VALUES_EQUAL(h1->Index, 1); @@ -61,7 +61,7 @@ Y_UNIT_TEST_SUITE(TStringPoolTest) { UNIT_ASSERT_VALUES_EQUAL(strPool.BytesSize(), 11); UNIT_ASSERT_VALUES_EQUAL(strPool.Count(), 3); - strPool.Build(); + strPool.Build(); TVector<TString> strings; TVector<ui32> indexes; diff --git a/library/cpp/monlib/encode/buffered/ut/ya.make b/library/cpp/monlib/encode/buffered/ut/ya.make index 3020c035d5..2157ac1490 100644 --- a/library/cpp/monlib/encode/buffered/ut/ya.make +++ b/library/cpp/monlib/encode/buffered/ut/ya.make @@ -1,12 +1,12 @@ UNITTEST_FOR(library/cpp/monlib/encode/buffered) - + OWNER( g:solomon jamel ) - -SRCS( - string_pool_ut.cpp -) - -END() + +SRCS( + string_pool_ut.cpp +) + +END() diff --git a/library/cpp/monlib/encode/buffered/ya.make b/library/cpp/monlib/encode/buffered/ya.make index ae749f5a16..81b6a78b93 100644 --- a/library/cpp/monlib/encode/buffered/ya.make +++ b/library/cpp/monlib/encode/buffered/ya.make @@ -1,19 +1,19 @@ -LIBRARY() - +LIBRARY() + OWNER( g:solomon jamel msherbakov ) - -SRCS( - buffered_encoder_base.cpp - string_pool.cpp -) - -PEERDIR( + +SRCS( + buffered_encoder_base.cpp + string_pool.cpp +) + +PEERDIR( library/cpp/monlib/encode library/cpp/monlib/metrics -) - -END() +) + +END() diff --git a/library/cpp/monlib/encode/fake/fake.cpp b/library/cpp/monlib/encode/fake/fake.cpp index e4d9f44835..69d691361a 100644 --- a/library/cpp/monlib/encode/fake/fake.cpp +++ b/library/cpp/monlib/encode/fake/fake.cpp @@ -1,51 +1,51 @@ -#include "fake.h" - -#include <util/datetime/base.h> - -namespace NMonitoring { +#include "fake.h" + +#include <util/datetime/base.h> + +namespace NMonitoring { class TFakeEncoder: public IMetricEncoder { - public: - void OnStreamBegin() override { - } - void OnStreamEnd() override { - } - - void OnCommonTime(TInstant) override { - } - + public: + void OnStreamBegin() override { + } + void OnStreamEnd() override { + } + + void OnCommonTime(TInstant) override { + } + void OnMetricBegin(EMetricType) override { - } + } void OnMetricEnd() override { - } - - void OnLabelsBegin() override { - } - void OnLabelsEnd() override { - } - void OnLabel(const TStringBuf, const TStringBuf) override { - } - - void OnDouble(TInstant, double) override { - } - void OnInt64(TInstant, i64) override { - } - void OnUint64(TInstant, ui64) override { - } - - void OnHistogram(TInstant, IHistogramSnapshotPtr) override { - } - + } + + void OnLabelsBegin() override { + } + void OnLabelsEnd() override { + } + void OnLabel(const TStringBuf, const TStringBuf) override { + } + + void OnDouble(TInstant, double) override { + } + void OnInt64(TInstant, i64) override { + } + void OnUint64(TInstant, ui64) override { + } + + void OnHistogram(TInstant, IHistogramSnapshotPtr) override { + } + void OnSummaryDouble(TInstant, ISummaryDoubleSnapshotPtr) override { } void OnLogHistogram(TInstant, TLogHistogramSnapshotPtr) override { } - void Close() override { - } - }; - + void Close() override { + } + }; + IMetricEncoderPtr EncoderFake() { return MakeHolder<TFakeEncoder>(); - } -} + } +} diff --git a/library/cpp/monlib/encode/fake/fake.h b/library/cpp/monlib/encode/fake/fake.h index 7874f9bb3e..8109326987 100644 --- a/library/cpp/monlib/encode/fake/fake.h +++ b/library/cpp/monlib/encode/fake/fake.h @@ -1,10 +1,10 @@ -#pragma once - +#pragma once + #include <library/cpp/monlib/encode/encoder.h> - -class IOutputStream; - -namespace NMonitoring { + +class IOutputStream; + +namespace NMonitoring { // Does nothing: just implements IMetricEncoder interface with stubs IMetricEncoderPtr EncoderFake(); -} +} diff --git a/library/cpp/monlib/encode/fake/ya.make b/library/cpp/monlib/encode/fake/ya.make index 0be0f851eb..ae96f45782 100644 --- a/library/cpp/monlib/encode/fake/ya.make +++ b/library/cpp/monlib/encode/fake/ya.make @@ -1,12 +1,12 @@ -LIBRARY() - +LIBRARY() + OWNER( g:solomon msherbakov ) - -SRCS( - fake.cpp -) - -END() + +SRCS( + fake.cpp +) + +END() diff --git a/library/cpp/monlib/encode/format.cpp b/library/cpp/monlib/encode/format.cpp index 8861e3dcc2..400ce5a643 100644 --- a/library/cpp/monlib/encode/format.cpp +++ b/library/cpp/monlib/encode/format.cpp @@ -7,65 +7,65 @@ #include <util/string/cast.h> namespace NMonitoring { - static ECompression CompressionFromHeader(TStringBuf value) { - if (value.empty()) { - return ECompression::UNKNOWN; - } - - for (const auto& it : StringSplitter(value).Split(',').SkipEmpty()) { - TStringBuf token = StripString(it.Token()); - - if (AsciiEqualsIgnoreCase(token, NFormatContentEncoding::IDENTITY)) { - return ECompression::IDENTITY; - } else if (AsciiEqualsIgnoreCase(token, NFormatContentEncoding::ZLIB)) { - return ECompression::ZLIB; - } else if (AsciiEqualsIgnoreCase(token, NFormatContentEncoding::LZ4)) { - return ECompression::LZ4; - } else if (AsciiEqualsIgnoreCase(token, NFormatContentEncoding::ZSTD)) { - return ECompression::ZSTD; - } - } - - return ECompression::UNKNOWN; - } - - static EFormat FormatFromHttpMedia(TStringBuf value) { - if (AsciiEqualsIgnoreCase(value, NFormatContenType::SPACK)) { - return EFormat::SPACK; - } else if (AsciiEqualsIgnoreCase(value, NFormatContenType::JSON)) { - return EFormat::JSON; - } else if (AsciiEqualsIgnoreCase(value, NFormatContenType::PROTOBUF)) { - return EFormat::PROTOBUF; - } else if (AsciiEqualsIgnoreCase(value, NFormatContenType::TEXT)) { - return EFormat::TEXT; + static ECompression CompressionFromHeader(TStringBuf value) { + if (value.empty()) { + return ECompression::UNKNOWN; + } + + for (const auto& it : StringSplitter(value).Split(',').SkipEmpty()) { + TStringBuf token = StripString(it.Token()); + + if (AsciiEqualsIgnoreCase(token, NFormatContentEncoding::IDENTITY)) { + return ECompression::IDENTITY; + } else if (AsciiEqualsIgnoreCase(token, NFormatContentEncoding::ZLIB)) { + return ECompression::ZLIB; + } else if (AsciiEqualsIgnoreCase(token, NFormatContentEncoding::LZ4)) { + return ECompression::LZ4; + } else if (AsciiEqualsIgnoreCase(token, NFormatContentEncoding::ZSTD)) { + return ECompression::ZSTD; + } + } + + return ECompression::UNKNOWN; + } + + static EFormat FormatFromHttpMedia(TStringBuf value) { + if (AsciiEqualsIgnoreCase(value, NFormatContenType::SPACK)) { + return EFormat::SPACK; + } else if (AsciiEqualsIgnoreCase(value, NFormatContenType::JSON)) { + return EFormat::JSON; + } else if (AsciiEqualsIgnoreCase(value, NFormatContenType::PROTOBUF)) { + return EFormat::PROTOBUF; + } else if (AsciiEqualsIgnoreCase(value, NFormatContenType::TEXT)) { + return EFormat::TEXT; } else if (AsciiEqualsIgnoreCase(value, NFormatContenType::PROMETHEUS)) { return EFormat::PROMETHEUS; } - return EFormat::UNKNOWN; - } - - EFormat FormatFromAcceptHeader(TStringBuf value) { - EFormat result{EFormat::UNKNOWN}; - + return EFormat::UNKNOWN; + } + + EFormat FormatFromAcceptHeader(TStringBuf value) { + EFormat result{EFormat::UNKNOWN}; + for (const auto& it : StringSplitter(value).Split(',').SkipEmpty()) { TStringBuf token = StripString(it.Token()); - result = FormatFromHttpMedia(token); - if (result != EFormat::UNKNOWN) { - break; + result = FormatFromHttpMedia(token); + if (result != EFormat::UNKNOWN) { + break; } } - return result; + return result; + } + + EFormat FormatFromContentType(TStringBuf value) { + value = value.NextTok(';'); + + return FormatFromHttpMedia(value); } - EFormat FormatFromContentType(TStringBuf value) { - value = value.NextTok(';'); - - return FormatFromHttpMedia(value); - } - TStringBuf ContentTypeByFormat(EFormat format) { switch (format) { case EFormat::SPACK: @@ -86,11 +86,11 @@ namespace NMonitoring { } ECompression CompressionFromAcceptEncodingHeader(TStringBuf value) { - return CompressionFromHeader(value); - } + return CompressionFromHeader(value); + } - ECompression CompressionFromContentEncodingHeader(TStringBuf value) { - return CompressionFromHeader(value); + ECompression CompressionFromContentEncodingHeader(TStringBuf value) { + return CompressionFromHeader(value); } TStringBuf ContentEncodingByCompression(ECompression compression) { diff --git a/library/cpp/monlib/encode/format.h b/library/cpp/monlib/encode/format.h index e7e5313af6..495d42d786 100644 --- a/library/cpp/monlib/encode/format.h +++ b/library/cpp/monlib/encode/format.h @@ -117,17 +117,17 @@ namespace NMonitoring { * @param value value of the "Accept" header. * @return most preffered serialization format type */ - EFormat FormatFromAcceptHeader(TStringBuf value); + EFormat FormatFromAcceptHeader(TStringBuf value); + + /** + * Matches serialization format by the given "Content-Type" header value + * + * @param value value of the "Content-Type" header + * @return message format + */ + EFormat FormatFromContentType(TStringBuf value); /** - * Matches serialization format by the given "Content-Type" header value - * - * @param value value of the "Content-Type" header - * @return message format - */ - EFormat FormatFromContentType(TStringBuf value); - - /** * Returns value for "Content-Type" header determined by the given * format type. * @@ -146,14 +146,14 @@ namespace NMonitoring { ECompression CompressionFromAcceptEncodingHeader(TStringBuf value); /** - * Matches compression algorithm by the given "Content-Encoding" header value. - * - * @param value value of the "Accept-Encoding" header. - * @return most preffered compression algorithm - */ - ECompression CompressionFromContentEncodingHeader(TStringBuf value); - - /** + * Matches compression algorithm by the given "Content-Encoding" header value. + * + * @param value value of the "Accept-Encoding" header. + * @return most preffered compression algorithm + */ + ECompression CompressionFromContentEncodingHeader(TStringBuf value); + + /** * Returns value for "Content-Encoding" header determined by the given * compression algorithm. * diff --git a/library/cpp/monlib/encode/format_ut.cpp b/library/cpp/monlib/encode/format_ut.cpp index f92f886c31..22a0e30c03 100644 --- a/library/cpp/monlib/encode/format_ut.cpp +++ b/library/cpp/monlib/encode/format_ut.cpp @@ -10,32 +10,32 @@ using namespace NMonitoring; Y_UNIT_TEST_SUITE(TFormatTest) { - Y_UNIT_TEST(ContentTypeHeader) { - UNIT_ASSERT_EQUAL(FormatFromContentType(""), EFormat::UNKNOWN); - UNIT_ASSERT_EQUAL(FormatFromContentType("application/json;some=stuff"), EFormat::JSON); - UNIT_ASSERT_EQUAL(FormatFromContentType("application/x-solomon-spack"), EFormat::SPACK); - UNIT_ASSERT_EQUAL(FormatFromContentType("application/xml"), EFormat::UNKNOWN); - UNIT_ASSERT_EQUAL(FormatFromContentType(";application/xml"), EFormat::UNKNOWN); - } - + Y_UNIT_TEST(ContentTypeHeader) { + UNIT_ASSERT_EQUAL(FormatFromContentType(""), EFormat::UNKNOWN); + UNIT_ASSERT_EQUAL(FormatFromContentType("application/json;some=stuff"), EFormat::JSON); + UNIT_ASSERT_EQUAL(FormatFromContentType("application/x-solomon-spack"), EFormat::SPACK); + UNIT_ASSERT_EQUAL(FormatFromContentType("application/xml"), EFormat::UNKNOWN); + UNIT_ASSERT_EQUAL(FormatFromContentType(";application/xml"), EFormat::UNKNOWN); + } + Y_UNIT_TEST(AcceptHeader) { - UNIT_ASSERT_EQUAL(FormatFromAcceptHeader(""), EFormat::UNKNOWN); - UNIT_ASSERT_EQUAL(FormatFromAcceptHeader("*/*"), EFormat::UNKNOWN); + UNIT_ASSERT_EQUAL(FormatFromAcceptHeader(""), EFormat::UNKNOWN); + UNIT_ASSERT_EQUAL(FormatFromAcceptHeader("*/*"), EFormat::UNKNOWN); UNIT_ASSERT_EQUAL( - FormatFromAcceptHeader("application/xml"), + FormatFromAcceptHeader("application/xml"), EFormat::UNKNOWN); UNIT_ASSERT_EQUAL( - FormatFromAcceptHeader("application/json"), + FormatFromAcceptHeader("application/json"), EFormat::JSON); UNIT_ASSERT_EQUAL( - FormatFromAcceptHeader("application/x-solomon-spack"), + FormatFromAcceptHeader("application/x-solomon-spack"), EFormat::SPACK); UNIT_ASSERT_EQUAL( - FormatFromAcceptHeader("application/x-solomon-pb"), + FormatFromAcceptHeader("application/x-solomon-pb"), EFormat::PROTOBUF); UNIT_ASSERT_EQUAL( @@ -43,19 +43,19 @@ Y_UNIT_TEST_SUITE(TFormatTest) { EFormat::TEXT); UNIT_ASSERT_EQUAL( - FormatFromAcceptHeader("application/json, text/plain"), + FormatFromAcceptHeader("application/json, text/plain"), EFormat::JSON); UNIT_ASSERT_EQUAL( - FormatFromAcceptHeader("application/x-solomon-spack, application/json, text/plain"), + FormatFromAcceptHeader("application/x-solomon-spack, application/json, text/plain"), EFormat::SPACK); UNIT_ASSERT_EQUAL( - FormatFromAcceptHeader(" , application/x-solomon-spack ,, application/json , text/plain"), + FormatFromAcceptHeader(" , application/x-solomon-spack ,, application/json , text/plain"), EFormat::SPACK); UNIT_ASSERT_EQUAL( - FormatFromAcceptHeader("application/xml, application/x-solomon-spack, text/plain"), + FormatFromAcceptHeader("application/xml, application/x-solomon-spack, text/plain"), EFormat::SPACK); UNIT_ASSERT_EQUAL( diff --git a/library/cpp/monlib/encode/fuzz/ya.make b/library/cpp/monlib/encode/fuzz/ya.make index 19f98efb7b..d9ca172bae 100644 --- a/library/cpp/monlib/encode/fuzz/ya.make +++ b/library/cpp/monlib/encode/fuzz/ya.make @@ -1,5 +1,5 @@ -RECURSE_ROOT_RELATIVE( +RECURSE_ROOT_RELATIVE( library/cpp/monlib/encode/json/fuzz library/cpp/monlib/encode/prometheus/fuzz library/cpp/monlib/encode/spack/fuzz -) +) diff --git a/library/cpp/monlib/encode/json/fuzz/main.cpp b/library/cpp/monlib/encode/json/fuzz/main.cpp index b85a973a1b..4f40310e06 100644 --- a/library/cpp/monlib/encode/json/fuzz/main.cpp +++ b/library/cpp/monlib/encode/json/fuzz/main.cpp @@ -1,16 +1,16 @@ #include <library/cpp/monlib/encode/json/json.h> #include <library/cpp/monlib/encode/fake/fake.h> - -#include <util/generic/strbuf.h> - - -extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) { - auto encoder = NMonitoring::EncoderFake(); - - try { - NMonitoring::DecodeJson({reinterpret_cast<const char*>(data), size}, encoder.Get()); - } catch (...) { - } - - return 0; -} + +#include <util/generic/strbuf.h> + + +extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) { + auto encoder = NMonitoring::EncoderFake(); + + try { + NMonitoring::DecodeJson({reinterpret_cast<const char*>(data), size}, encoder.Get()); + } catch (...) { + } + + return 0; +} diff --git a/library/cpp/monlib/encode/json/fuzz/ya.make b/library/cpp/monlib/encode/json/fuzz/ya.make index 85a12a37f0..75baa77716 100644 --- a/library/cpp/monlib/encode/json/fuzz/ya.make +++ b/library/cpp/monlib/encode/json/fuzz/ya.make @@ -1,19 +1,19 @@ -FUZZ() - +FUZZ() + OWNER( g:solomon msherbakov ) - -PEERDIR( + +PEERDIR( library/cpp/monlib/encode/json library/cpp/monlib/encode/fake -) - -SIZE(MEDIUM) - +) + +SIZE(MEDIUM) + SRCS( main.cpp ) - -END() + +END() diff --git a/library/cpp/monlib/encode/json/json.h b/library/cpp/monlib/encode/json/json.h index 9f4db4a743..21530f20c3 100644 --- a/library/cpp/monlib/encode/json/json.h +++ b/library/cpp/monlib/encode/json/json.h @@ -13,9 +13,9 @@ namespace NMonitoring { IMetricEncoderPtr EncoderJson(IOutputStream* out, int indentation = 0); - /// Buffered encoder will merge series with same labels into one. + /// Buffered encoder will merge series with same labels into one. IMetricEncoderPtr BufferedEncoderJson(IOutputStream* out, int indentation = 0); - + IMetricEncoderPtr EncoderCloudJson(IOutputStream* out, int indentation = 0, TStringBuf metricNameLabel = "name"); diff --git a/library/cpp/monlib/encode/json/json_decoder.cpp b/library/cpp/monlib/encode/json/json_decoder.cpp index 9468ea6447..d44ff5fd28 100644 --- a/library/cpp/monlib/encode/json/json_decoder.cpp +++ b/library/cpp/monlib/encode/json/json_decoder.cpp @@ -879,7 +879,7 @@ if (Y_UNLIKELY(!(CONDITION))) { \ State_.ToNext(TState::METRIC_LOG_HIST); } break; - + case TState::METRIC_HIST: if (key == TStringBuf("bounds")) { State_.ToNext(TState::METRIC_HIST_BOUNDS); diff --git a/library/cpp/monlib/encode/json/json_encoder.cpp b/library/cpp/monlib/encode/json/json_encoder.cpp index 95c7b2949f..20d2bb6283 100644 --- a/library/cpp/monlib/encode/json/json_encoder.cpp +++ b/library/cpp/monlib/encode/json/json_encoder.cpp @@ -10,8 +10,8 @@ #include <library/cpp/json/writer/json.h> #include <util/charset/utf8.h> -#include <util/generic/algorithm.h> - +#include <util/generic/algorithm.h> + namespace NMonitoring { namespace { enum class EJsonStyle { @@ -22,7 +22,7 @@ namespace NMonitoring { /////////////////////////////////////////////////////////////////////// // TJsonWriter /////////////////////////////////////////////////////////////////////// - class TJsonWriter { + class TJsonWriter { public: TJsonWriter(IOutputStream* out, int indentation, EJsonStyle style, TStringBuf metricNameLabel) : Buf_(NJsonWriter::HEM_UNSAFE, out) @@ -34,32 +34,32 @@ namespace NMonitoring { Buf_.SetWriteNanAsString(); } - void WriteTime(TInstant time) { - if (time != TInstant::Zero()) { + void WriteTime(TInstant time) { + if (time != TInstant::Zero()) { Buf_.WriteKey(TStringBuf("ts")); if (Style_ == EJsonStyle::Solomon) { Buf_.WriteULongLong(time.Seconds()); } else { Buf_.WriteString(time.ToString()); } - } - } - - void WriteValue(double value) { + } + } + + void WriteValue(double value) { Buf_.WriteKey(TStringBuf("value")); - Buf_.WriteDouble(value); - } - + Buf_.WriteDouble(value); + } + void WriteValue(i64 value) { Buf_.WriteKey(TStringBuf("value")); Buf_.WriteLongLong(value); } - void WriteValue(ui64 value) { + void WriteValue(ui64 value) { Buf_.WriteKey(TStringBuf("value")); - Buf_.WriteULongLong(value); - } - + Buf_.WriteULongLong(value); + } + void WriteValue(IHistogramSnapshot* s) { Y_ENSURE(Style_ == EJsonStyle::Solomon); @@ -143,19 +143,19 @@ namespace NMonitoring { } void WriteValue(EMetricValueType type, TMetricValue value) { - switch (type) { + switch (type) { case EMetricValueType::DOUBLE: WriteValue(value.AsDouble()); - break; - + break; + case EMetricValueType::INT64: WriteValue(value.AsInt64()); break; case EMetricValueType::UINT64: WriteValue(value.AsUint64()); - break; - + break; + case EMetricValueType::HISTOGRAM: WriteValue(value.AsHistogram()); break; @@ -170,20 +170,20 @@ namespace NMonitoring { case EMetricValueType::UNKNOWN: ythrow yexception() << "unknown metric value type"; - } - } - - void WriteLabel(TStringBuf name, TStringBuf value) { - Y_ENSURE(IsUtf(name), "label name is not valid UTF-8 string"); - Y_ENSURE(IsUtf(value), "label value is not valid UTF-8 string"); + } + } + + void WriteLabel(TStringBuf name, TStringBuf value) { + Y_ENSURE(IsUtf(name), "label name is not valid UTF-8 string"); + Y_ENSURE(IsUtf(value), "label value is not valid UTF-8 string"); if (Style_ == EJsonStyle::Cloud && name == MetricNameLabel_) { CurrentMetricName_ = value; } else { Buf_.WriteKey(name); Buf_.WriteString(value); } - } - + } + void WriteMetricType(EMetricType type) { if (Style_ == EJsonStyle::Cloud) { Buf_.WriteKey("type"); @@ -222,23 +222,23 @@ namespace NMonitoring { } } - protected: - NJsonWriter::TBuf Buf_; + protected: + NJsonWriter::TBuf Buf_; EJsonStyle Style_; TString MetricNameLabel_; TString CurrentMetricName_; - }; - + }; + /////////////////////////////////////////////////////////////////////// // TEncoderJson /////////////////////////////////////////////////////////////////////// class TEncoderJson final: public IMetricEncoder, public TJsonWriter { - public: + public: TEncoderJson(IOutputStream* out, int indentation, EJsonStyle style, TStringBuf metricNameLabel) : TJsonWriter{out, indentation, style, metricNameLabel} - { - } - + { + } + ~TEncoderJson() override { Close(); } @@ -308,8 +308,8 @@ namespace NMonitoring { State_.ThrowInvalid("expected METRIC or ROOT"); } Buf_.BeginObject(); - - EmptyLabels_ = true; + + EmptyLabels_ = true; } void OnLabelsEnd() override { @@ -320,8 +320,8 @@ namespace NMonitoring { } else { State_.ThrowInvalid("expected LABELS or COMMON_LABELS"); } - - Y_ENSURE(!EmptyLabels_, "Labels cannot be empty"); + + Y_ENSURE(!EmptyLabels_, "Labels cannot be empty"); Buf_.EndObject(); if (State_ == TEncoderState::EState::METRIC) { WriteName(); @@ -330,12 +330,12 @@ namespace NMonitoring { void OnLabel(TStringBuf name, TStringBuf value) override { if (State_ == TEncoderState::EState::METRIC_LABELS || State_ == TEncoderState::EState::COMMON_LABELS) { - WriteLabel(name, value); + WriteLabel(name, value); } else { State_.ThrowInvalid("expected LABELS or COMMON_LABELS"); } - - EmptyLabels_ = false; + + EmptyLabels_ = false; } void OnDouble(TInstant time, double value) override { @@ -385,7 +385,7 @@ namespace NMonitoring { Buf_.BeginList(); Buf_.BeginObject(); Y_ENSURE(LastPoint_.GetTime() != TInstant::Zero(), - "time cannot be empty or zero in a timeseries point"); + "time cannot be empty or zero in a timeseries point"); WriteTime(LastPoint_.GetTime()); WriteValue(LastPoint_.GetValueType(), LastPoint_.GetValue()); Buf_.EndObject(); @@ -394,8 +394,8 @@ namespace NMonitoring { if (TimeSeries_) { Buf_.BeginObject(); - Y_ENSURE(time != TInstant::Zero(), - "time cannot be empty or zero in a timeseries point"); + Y_ENSURE(time != TInstant::Zero(), + "time cannot be empty or zero in a timeseries point"); WriteTime(time); WriteValue(value); @@ -408,26 +408,26 @@ namespace NMonitoring { LastPoint_ = {}; } - private: - TEncoderState State_; + private: + TEncoderState State_; TTypedPoint LastPoint_; - bool TimeSeries_ = false; - bool EmptyLabels_ = false; - }; - + bool TimeSeries_ = false; + bool EmptyLabels_ = false; + }; + /////////////////////////////////////////////////////////////////////// // TBufferedJsonEncoder /////////////////////////////////////////////////////////////////////// - class TBufferedJsonEncoder : public TBufferedEncoderBase, public TJsonWriter { - public: + class TBufferedJsonEncoder : public TBufferedEncoderBase, public TJsonWriter { + public: TBufferedJsonEncoder(IOutputStream* out, int indentation, EJsonStyle style, TStringBuf metricNameLabel) : TJsonWriter{out, indentation, style, metricNameLabel} - { + { MetricsMergingMode_ = EMetricsMergingMode::MERGE_METRICS; } ~TBufferedJsonEncoder() override { - Close(); + Close(); } void OnLabelsBegin() override { @@ -445,54 +445,54 @@ namespace NMonitoring { EmptyLabels_ = false; } - void OnLabelsEnd() override { - TBufferedEncoderBase::OnLabelsEnd(); + void OnLabelsEnd() override { + TBufferedEncoderBase::OnLabelsEnd(); Y_ENSURE(!EmptyLabels_, "Labels cannot be empty"); - } - + } + void Close() final { - if (Closed_) { - return; - } - - Closed_ = true; + if (Closed_) { + return; + } - LabelValuesPool_.Build(); - LabelNamesPool_.Build(); + Closed_ = true; - Buf_.BeginObject(); + LabelValuesPool_.Build(); + LabelNamesPool_.Build(); + + Buf_.BeginObject(); - WriteTime(CommonTime_); - if (CommonLabels_.size() > 0) { + WriteTime(CommonTime_); + if (CommonLabels_.size() > 0) { Buf_.WriteKey(TStringBuf(Style_ == EJsonStyle::Solomon ? "commonLabels": "labels")); WriteLabels(CommonLabels_, true); } - + if (Metrics_.size() > 0) { Buf_.WriteKey(TStringBuf(Style_ == EJsonStyle::Solomon ? "sensors" : "metrics")); WriteMetrics(); - } - - Buf_.EndObject(); + } + + Buf_.EndObject(); } private: void WriteMetrics() { - Buf_.BeginList(); + Buf_.BeginList(); for (auto&& metric : Metrics_) { WriteMetric(metric); - } - Buf_.EndList(); - } - + } + Buf_.EndList(); + } + void WriteMetric(TMetric& metric) { - Buf_.BeginObject(); - + Buf_.BeginObject(); + WriteMetricType(metric.MetricType); - + Buf_.WriteKey(TStringBuf("labels")); WriteLabels(metric.Labels, false); - + metric.TimeSeries.SortByTs(); if (metric.TimeSeries.Size() == 1) { const auto& point = metric.TimeSeries[0]; @@ -500,40 +500,40 @@ namespace NMonitoring { WriteValue(metric.TimeSeries.GetValueType(), point.GetValue()); } else if (metric.TimeSeries.Size() > 1) { Buf_.WriteKey(TStringBuf("timeseries")); - Buf_.BeginList(); + Buf_.BeginList(); metric.TimeSeries.ForEach([this](TInstant time, EMetricValueType type, TMetricValue value) { - Buf_.BeginObject(); - // make gcc 6.1 happy https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61636 + Buf_.BeginObject(); + // make gcc 6.1 happy https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61636 this->WriteTime(time); this->WriteValue(type, value); - Buf_.EndObject(); - }); - - Buf_.EndList(); - } - - Buf_.EndObject(); - } - + Buf_.EndObject(); + }); + + Buf_.EndList(); + } + + Buf_.EndObject(); + } + void WriteLabels(const TPooledLabels& labels, bool isCommon) { - Buf_.BeginObject(); - - for (auto i = 0u; i < labels.size(); ++i) { - TStringBuf name = LabelNamesPool_.Get(labels[i].Key->Index); - TStringBuf value = LabelValuesPool_.Get(labels[i].Value->Index); - - WriteLabel(name, value); - } - - Buf_.EndObject(); + Buf_.BeginObject(); + + for (auto i = 0u; i < labels.size(); ++i) { + TStringBuf name = LabelNamesPool_.Get(labels[i].Key->Index); + TStringBuf value = LabelValuesPool_.Get(labels[i].Value->Index); + + WriteLabel(name, value); + } + + Buf_.EndObject(); if (!isCommon) { WriteName(); } - } - - private: - bool Closed_{false}; + } + + private: + bool Closed_{false}; bool EmptyLabels_ = false; }; } @@ -544,7 +544,7 @@ namespace NMonitoring { IMetricEncoderPtr BufferedEncoderJson(IOutputStream* out, int indentation) { return MakeHolder<TBufferedJsonEncoder>(out, indentation, EJsonStyle::Solomon, ""); - } + } IMetricEncoderPtr EncoderCloudJson(IOutputStream* out, int indentation, TStringBuf metricNameLabel) { return MakeHolder<TEncoderJson>(out, indentation, EJsonStyle::Cloud, metricNameLabel); diff --git a/library/cpp/monlib/encode/json/json_ut.cpp b/library/cpp/monlib/encode/json/json_ut.cpp index b3c3b879d4..09e7909289 100644 --- a/library/cpp/monlib/encode/json/json_ut.cpp +++ b/library/cpp/monlib/encode/json/json_ut.cpp @@ -14,93 +14,93 @@ using namespace NMonitoring; -namespace NMonitoring { - bool operator<(const TLabel& lhs, const TLabel& rhs) { - return lhs.Name() < rhs.Name() || - (lhs.Name() == rhs.Name() && lhs.Value() < rhs.Value()); - } -} -namespace { - void AssertLabels(const NProto::TMultiSample& actual, const TLabels& expected) { - UNIT_ASSERT_EQUAL(actual.LabelsSize(), expected.Size()); - - TSet<TLabel> actualSet; - TSet<TLabel> expectedSet; - Transform(expected.begin(), expected.end(), std::inserter(expectedSet, expectedSet.end()), [] (auto&& l) { - return TLabel{l.Name(), l.Value()}; - }); - - const auto& l = actual.GetLabels(); - Transform(std::begin(l), std::end(l), std::inserter(actualSet, std::begin(actualSet)), - [](auto&& elem) -> TLabel { - return {elem.GetName(), elem.GetValue()}; - }); - - TVector<TLabel> diff; - SetSymmetricDifference(std::begin(expectedSet), std::end(expectedSet), - std::begin(actualSet), std::end(actualSet), std::back_inserter(diff)); - - if (diff.size() > 0) { - for (auto&& l : diff) { - Cerr << l << Endl; - } - - UNIT_FAIL("Labels don't match"); - } - } - - void AssertLabelEqual(const NProto::TLabel& l, TStringBuf name, TStringBuf value) { - UNIT_ASSERT_STRINGS_EQUAL(l.GetName(), name); - UNIT_ASSERT_STRINGS_EQUAL(l.GetValue(), value); - } - - void AssertPointEqual(const NProto::TPoint& p, TInstant time, double value) { - UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); - UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64); - UNIT_ASSERT_DOUBLES_EQUAL(p.GetFloat64(), value, std::numeric_limits<double>::epsilon()); - } - - void AssertPointEqualNan(const NProto::TPoint& p, TInstant time) { - UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); - UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64); - UNIT_ASSERT(std::isnan(p.GetFloat64())); - } - - void AssertPointEqualInf(const NProto::TPoint& p, TInstant time, int sign) { - UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); - UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64); - UNIT_ASSERT(std::isinf(p.GetFloat64())); - if (sign < 0) { - UNIT_ASSERT(p.GetFloat64() < 0); - } - } - - void AssertPointEqual(const NProto::TPoint& p, TInstant time, ui64 value) { - UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); - UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kUint64); - UNIT_ASSERT_VALUES_EQUAL(p.GetUint64(), value); - } - - void AssertPointEqual(const NProto::TPoint& p, TInstant time, i64 value) { - UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); - UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kInt64); - UNIT_ASSERT_VALUES_EQUAL(p.GetInt64(), value); - } - - void AssertPointEqual(const NProto::TPoint& p, TInstant time, const IHistogramSnapshot& expected) { - UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); - UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kHistogram); - - const NProto::THistogram& h = p.GetHistogram(); - UNIT_ASSERT_VALUES_EQUAL(h.BoundsSize(), expected.Count()); - UNIT_ASSERT_VALUES_EQUAL(h.ValuesSize(), expected.Count()); - - for (size_t i = 0; i < h.BoundsSize(); i++) { - UNIT_ASSERT_DOUBLES_EQUAL(h.GetBounds(i), expected.UpperBound(i), Min<double>()); - UNIT_ASSERT_VALUES_EQUAL(h.GetValues(i), expected.Value(i)); - } - } - +namespace NMonitoring { + bool operator<(const TLabel& lhs, const TLabel& rhs) { + return lhs.Name() < rhs.Name() || + (lhs.Name() == rhs.Name() && lhs.Value() < rhs.Value()); + } +} +namespace { + void AssertLabels(const NProto::TMultiSample& actual, const TLabels& expected) { + UNIT_ASSERT_EQUAL(actual.LabelsSize(), expected.Size()); + + TSet<TLabel> actualSet; + TSet<TLabel> expectedSet; + Transform(expected.begin(), expected.end(), std::inserter(expectedSet, expectedSet.end()), [] (auto&& l) { + return TLabel{l.Name(), l.Value()}; + }); + + const auto& l = actual.GetLabels(); + Transform(std::begin(l), std::end(l), std::inserter(actualSet, std::begin(actualSet)), + [](auto&& elem) -> TLabel { + return {elem.GetName(), elem.GetValue()}; + }); + + TVector<TLabel> diff; + SetSymmetricDifference(std::begin(expectedSet), std::end(expectedSet), + std::begin(actualSet), std::end(actualSet), std::back_inserter(diff)); + + if (diff.size() > 0) { + for (auto&& l : diff) { + Cerr << l << Endl; + } + + UNIT_FAIL("Labels don't match"); + } + } + + void AssertLabelEqual(const NProto::TLabel& l, TStringBuf name, TStringBuf value) { + UNIT_ASSERT_STRINGS_EQUAL(l.GetName(), name); + UNIT_ASSERT_STRINGS_EQUAL(l.GetValue(), value); + } + + void AssertPointEqual(const NProto::TPoint& p, TInstant time, double value) { + UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); + UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64); + UNIT_ASSERT_DOUBLES_EQUAL(p.GetFloat64(), value, std::numeric_limits<double>::epsilon()); + } + + void AssertPointEqualNan(const NProto::TPoint& p, TInstant time) { + UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); + UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64); + UNIT_ASSERT(std::isnan(p.GetFloat64())); + } + + void AssertPointEqualInf(const NProto::TPoint& p, TInstant time, int sign) { + UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); + UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64); + UNIT_ASSERT(std::isinf(p.GetFloat64())); + if (sign < 0) { + UNIT_ASSERT(p.GetFloat64() < 0); + } + } + + void AssertPointEqual(const NProto::TPoint& p, TInstant time, ui64 value) { + UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); + UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kUint64); + UNIT_ASSERT_VALUES_EQUAL(p.GetUint64(), value); + } + + void AssertPointEqual(const NProto::TPoint& p, TInstant time, i64 value) { + UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); + UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kInt64); + UNIT_ASSERT_VALUES_EQUAL(p.GetInt64(), value); + } + + void AssertPointEqual(const NProto::TPoint& p, TInstant time, const IHistogramSnapshot& expected) { + UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); + UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kHistogram); + + const NProto::THistogram& h = p.GetHistogram(); + UNIT_ASSERT_VALUES_EQUAL(h.BoundsSize(), expected.Count()); + UNIT_ASSERT_VALUES_EQUAL(h.ValuesSize(), expected.Count()); + + for (size_t i = 0; i < h.BoundsSize(); i++) { + UNIT_ASSERT_DOUBLES_EQUAL(h.GetBounds(i), expected.UpperBound(i), Min<double>()); + UNIT_ASSERT_VALUES_EQUAL(h.GetValues(i), expected.Value(i)); + } + } + void AssertPointEqual(const NProto::TPoint& p, TInstant time, const TLogHistogramSnapshot& expected) { UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds()); UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kLogHistogram); @@ -129,9 +129,9 @@ namespace { UNIT_ASSERT_VALUES_EQUAL(actual.GetCount(), expected.GetCount()); } -} // namespace - - +} // namespace + + Y_UNIT_TEST_SUITE(TJsonTest) { const TInstant now = TInstant::ParseIso8601Deprecated("2017-11-05T01:02:03Z"); @@ -304,53 +304,53 @@ Y_UNIT_TEST_SUITE(TJsonTest) { } Y_UNIT_TEST(MetricsWithDifferentLabelOrderGetMerged) { - TString json; - TStringOutput out(json); - auto e = BufferedEncoderJson(&out, 2); + TString json; + TStringOutput out(json); + auto e = BufferedEncoderJson(&out, 2); - e->OnStreamBegin(); - { + e->OnStreamBegin(); + { e->OnMetricBegin(EMetricType::RATE); - { - e->OnLabelsBegin(); + { + e->OnLabelsBegin(); e->OnLabel("metric", "hello"); - e->OnLabel("label", "world"); - e->OnLabelsEnd(); - } - e->OnUint64(TInstant::Zero(), 0); + e->OnLabel("label", "world"); + e->OnLabelsEnd(); + } + e->OnUint64(TInstant::Zero(), 0); e->OnMetricEnd(); } - { + { e->OnMetricBegin(EMetricType::RATE); - { - e->OnLabelsBegin(); - e->OnLabel("label", "world"); + { + e->OnLabelsBegin(); + e->OnLabel("label", "world"); e->OnLabel("metric", "hello"); - e->OnLabelsEnd(); - } - e->OnUint64(TInstant::Zero(), 1); + e->OnLabelsEnd(); + } + e->OnUint64(TInstant::Zero(), 1); e->OnMetricEnd(); - } - e->OnStreamEnd(); - e->Close(); - json += "\n"; + } + e->OnStreamEnd(); + e->Close(); + json += "\n"; - TString expectedJson = NResource::Find("/merged.json"); - // we cannot be sure regarding the label order in the result, - // so we'll have to parse the expected value and then compare it with actual + TString expectedJson = NResource::Find("/merged.json"); + // we cannot be sure regarding the label order in the result, + // so we'll have to parse the expected value and then compare it with actual - NProto::TMultiSamplesList samples; + NProto::TMultiSamplesList samples; IMetricEncoderPtr d = EncoderProtobuf(&samples); - DecodeJson(expectedJson, d.Get()); + DecodeJson(expectedJson, d.Get()); - UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); - { - const NProto::TMultiSample& s = samples.GetSamples(0); + UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); + { + const NProto::TMultiSample& s = samples.GetSamples(0); UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::RATE); AssertLabels(s, TLabels{{"metric", "hello"}, {"label", "world"}}); - UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1); - AssertPointEqual(s.GetPoints(0), TInstant::Zero(), ui64(1)); + UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1); + AssertPointEqual(s.GetPoints(0), TInstant::Zero(), ui64(1)); } } Y_UNIT_TEST(Decode1) { @@ -453,7 +453,7 @@ Y_UNIT_TEST_SUITE(TJsonTest) { AssertLabelEqual(samples.GetCommonLabels(1), "cluster", "man"); AssertLabelEqual(samples.GetCommonLabels(2), "service", "stockpile"); - UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 4); + UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 4); { const NProto::TMultiSample& s = samples.GetSamples(0); UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE); @@ -484,7 +484,7 @@ Y_UNIT_TEST_SUITE(TJsonTest) { AssertPointEqual(s.GetPoints(0), ts, 3.14159); } { - const NProto::TMultiSample& s = samples.GetSamples(3); + const NProto::TMultiSample& s = samples.GetSamples(3); UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE); UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1); AssertLabelEqual(s.GetLabels(0), "metric", "Writes"); @@ -558,7 +558,7 @@ Y_UNIT_TEST_SUITE(TJsonTest) { AssertPointEqual(s.GetPoints(1), ts2, 20.0); } } - + Y_UNIT_TEST(DecodeToEncoder) { auto testJson = NResource::Find("/test_decode_to_encode.json"); @@ -575,154 +575,154 @@ Y_UNIT_TEST_SUITE(TJsonTest) { } void WriteEmptySeries(const IMetricEncoderPtr& e) { - e->OnStreamBegin(); - { + e->OnStreamBegin(); + { e->OnMetricBegin(EMetricType::COUNTER); - { - e->OnLabelsBegin(); - e->OnLabel("foo", "bar"); - e->OnLabelsEnd(); - } + { + e->OnLabelsBegin(); + e->OnLabel("foo", "bar"); + e->OnLabelsEnd(); + } e->OnMetricEnd(); - } - - e->OnStreamEnd(); - e->Close(); - } - - Y_UNIT_TEST(EncodeEmptySeries) { - TString json; - TStringOutput out(json); - - auto e = EncoderJson(&out, 2); - WriteEmptySeries(e); - json += "\n"; - - TString expectedJson = NResource::Find("/empty_series.json"); - UNIT_ASSERT_NO_DIFF(json, expectedJson); - } - + } + + e->OnStreamEnd(); + e->Close(); + } + + Y_UNIT_TEST(EncodeEmptySeries) { + TString json; + TStringOutput out(json); + + auto e = EncoderJson(&out, 2); + WriteEmptySeries(e); + json += "\n"; + + TString expectedJson = NResource::Find("/empty_series.json"); + UNIT_ASSERT_NO_DIFF(json, expectedJson); + } + void WriteEmptyLabels(IMetricEncoderPtr& e) { - e->OnStreamBegin(); + e->OnStreamBegin(); e->OnMetricBegin(EMetricType::COUNTER); - - e->OnLabelsBegin(); - UNIT_ASSERT_EXCEPTION(e->OnLabelsEnd(), yexception); - } - - Y_UNIT_TEST(LabelsCannotBeEmpty) { - TString json; - TStringOutput out(json); - - auto e = EncoderJson(&out, 2); - WriteEmptyLabels(e); - } - - Y_UNIT_TEST(LabelsCannotBeEmptyBuffered) { - TString json; - TStringOutput out(json); - - auto e = BufferedEncoderJson(&out, 2); - WriteEmptyLabels(e); - } - - Y_UNIT_TEST(EncodeEmptySeriesBuffered) { - TString json; - TStringOutput out(json); - - auto e = BufferedEncoderJson(&out, 2); - WriteEmptySeries(e); - json += "\n"; - - TString expectedJson = NResource::Find("/empty_series.json"); - UNIT_ASSERT_NO_DIFF(json, expectedJson); - } - + + e->OnLabelsBegin(); + UNIT_ASSERT_EXCEPTION(e->OnLabelsEnd(), yexception); + } + + Y_UNIT_TEST(LabelsCannotBeEmpty) { + TString json; + TStringOutput out(json); + + auto e = EncoderJson(&out, 2); + WriteEmptyLabels(e); + } + + Y_UNIT_TEST(LabelsCannotBeEmptyBuffered) { + TString json; + TStringOutput out(json); + + auto e = BufferedEncoderJson(&out, 2); + WriteEmptyLabels(e); + } + + Y_UNIT_TEST(EncodeEmptySeriesBuffered) { + TString json; + TStringOutput out(json); + + auto e = BufferedEncoderJson(&out, 2); + WriteEmptySeries(e); + json += "\n"; + + TString expectedJson = NResource::Find("/empty_series.json"); + UNIT_ASSERT_NO_DIFF(json, expectedJson); + } + Y_UNIT_TEST(BufferedEncoderMergesMetrics) { - TString json; - TStringOutput out(json); - - auto e = BufferedEncoderJson(&out, 2); - auto ts = 1; - + TString json; + TStringOutput out(json); + + auto e = BufferedEncoderJson(&out, 2); + auto ts = 1; + auto writeMetric = [&] (const TString& val) { e->OnMetricBegin(EMetricType::COUNTER); - - e->OnLabelsBegin(); - e->OnLabel("foo", val); - e->OnLabelsEnd(); - e->OnUint64(TInstant::Seconds(ts++), 42); - + + e->OnLabelsBegin(); + e->OnLabel("foo", val); + e->OnLabelsEnd(); + e->OnUint64(TInstant::Seconds(ts++), 42); + e->OnMetricEnd(); - }; - - e->OnStreamBegin(); + }; + + e->OnStreamBegin(); writeMetric("bar"); writeMetric("bar"); writeMetric("baz"); writeMetric("bar"); - e->OnStreamEnd(); - e->Close(); - - json += "\n"; - - TString expectedJson = NResource::Find("/buffered_test.json"); - UNIT_ASSERT_NO_DIFF(json, expectedJson); - } - - Y_UNIT_TEST(JsonEncoderDisallowsValuesInTimeseriesWithoutTs) { - TStringStream out; - - auto e = EncoderJson(&out); - auto writePreamble = [&] { - e->OnStreamBegin(); + e->OnStreamEnd(); + e->Close(); + + json += "\n"; + + TString expectedJson = NResource::Find("/buffered_test.json"); + UNIT_ASSERT_NO_DIFF(json, expectedJson); + } + + Y_UNIT_TEST(JsonEncoderDisallowsValuesInTimeseriesWithoutTs) { + TStringStream out; + + auto e = EncoderJson(&out); + auto writePreamble = [&] { + e->OnStreamBegin(); e->OnMetricBegin(EMetricType::COUNTER); - e->OnLabelsBegin(); - e->OnLabel("foo", "bar"); - e->OnLabelsEnd(); - }; - + e->OnLabelsBegin(); + e->OnLabel("foo", "bar"); + e->OnLabelsEnd(); + }; + // writing two values for a metric in a row will trigger - // timeseries object construction - writePreamble(); - e->OnUint64(TInstant::Zero(), 42); - UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Zero(), 42), yexception); - - e = EncoderJson(&out); - writePreamble(); - e->OnUint64(TInstant::Zero(), 42); - UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Now(), 42), yexception); - - e = EncoderJson(&out); - writePreamble(); - e->OnUint64(TInstant::Now(), 42); - UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Zero(), 42), yexception); - } - - Y_UNIT_TEST(BufferedJsonEncoderMergesTimeseriesWithoutTs) { - TStringStream out; - - { - auto e = BufferedEncoderJson(&out, 2); - e->OnStreamBegin(); + // timeseries object construction + writePreamble(); + e->OnUint64(TInstant::Zero(), 42); + UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Zero(), 42), yexception); + + e = EncoderJson(&out); + writePreamble(); + e->OnUint64(TInstant::Zero(), 42); + UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Now(), 42), yexception); + + e = EncoderJson(&out); + writePreamble(); + e->OnUint64(TInstant::Now(), 42); + UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Zero(), 42), yexception); + } + + Y_UNIT_TEST(BufferedJsonEncoderMergesTimeseriesWithoutTs) { + TStringStream out; + + { + auto e = BufferedEncoderJson(&out, 2); + e->OnStreamBegin(); e->OnMetricBegin(EMetricType::COUNTER); - e->OnLabelsBegin(); - e->OnLabel("foo", "bar"); - e->OnLabelsEnd(); - // in buffered mode we are able to find values with same (in this case zero) - // timestamp and discard duplicates - e->OnUint64(TInstant::Zero(), 42); - e->OnUint64(TInstant::Zero(), 43); - e->OnUint64(TInstant::Zero(), 44); - e->OnUint64(TInstant::Zero(), 45); + e->OnLabelsBegin(); + e->OnLabel("foo", "bar"); + e->OnLabelsEnd(); + // in buffered mode we are able to find values with same (in this case zero) + // timestamp and discard duplicates + e->OnUint64(TInstant::Zero(), 42); + e->OnUint64(TInstant::Zero(), 43); + e->OnUint64(TInstant::Zero(), 44); + e->OnUint64(TInstant::Zero(), 45); e->OnMetricEnd(); - e->OnStreamEnd(); - } - - out << "\n"; - UNIT_ASSERT_NO_DIFF(out.Str(), NResource::Find("/buffered_ts_merge.json")); + e->OnStreamEnd(); + } + + out << "\n"; + UNIT_ASSERT_NO_DIFF(out.Str(), NResource::Find("/buffered_ts_merge.json")); } - + template <typename TFactory, typename TConsumer> TString EncodeToString(TFactory factory, TConsumer consumer) { TStringStream out; @@ -732,7 +732,7 @@ Y_UNIT_TEST_SUITE(TJsonTest) { } out << '\n'; return out.Str(); - } + } Y_UNIT_TEST(SummaryValueEncode) { auto writeDocument = [](IMetricEncoder* e) { @@ -1235,35 +1235,35 @@ Y_UNIT_TEST_SUITE(TJsonTest) { AssertPointEqual(s.GetPoints(2), now + TDuration::Seconds(2), i64(0)); AssertPointEqual(s.GetPoints(3), now + TDuration::Seconds(3), Max<i64>()); } - - Y_UNIT_TEST(FuzzerRegression) { - NProto::TMultiSamplesList samples; - { + + Y_UNIT_TEST(FuzzerRegression) { + NProto::TMultiSamplesList samples; + { IMetricEncoderPtr e = EncoderProtobuf(&samples); - - for (auto f : { "/hist_crash.json", "/crash.json" }) { - TString testJson = NResource::Find(f); - UNIT_ASSERT_EXCEPTION(DecodeJson(testJson, e.Get()), yexception); - } - } - } - - Y_UNIT_TEST(LegacyNegativeRateThrows) { - const auto input = R"({ - "sensors": [ - { - "mode": "deriv", - "value": -1, + + for (auto f : { "/hist_crash.json", "/crash.json" }) { + TString testJson = NResource::Find(f); + UNIT_ASSERT_EXCEPTION(DecodeJson(testJson, e.Get()), yexception); + } + } + } + + Y_UNIT_TEST(LegacyNegativeRateThrows) { + const auto input = R"({ + "sensors": [ + { + "mode": "deriv", + "value": -1, "labels": { "metric": "SystemTime" } - }, - } - ]}")"; - - NProto::TMultiSamplesList samples; + }, + } + ]}")"; + + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - UNIT_ASSERT_EXCEPTION(DecodeJson(input, e.Get()), yexception); - } - + UNIT_ASSERT_EXCEPTION(DecodeJson(input, e.Get()), yexception); + } + Y_UNIT_TEST(DecodeNamedMetrics) { NProto::TMultiSamplesList samples; { diff --git a/library/cpp/monlib/encode/json/ut/buffered_test.json b/library/cpp/monlib/encode/json/ut/buffered_test.json index 580b929de0..53212cf8e1 100644 --- a/library/cpp/monlib/encode/json/ut/buffered_test.json +++ b/library/cpp/monlib/encode/json/ut/buffered_test.json @@ -1,36 +1,36 @@ -{ - "sensors": - [ - { - "kind":"COUNTER", - "labels": - { - "foo":"bar" - }, - "timeseries": - [ - { - "ts":1, - "value":42 - }, - { - "ts":2, - "value":42 - }, - { - "ts":4, - "value":42 - } - ] - }, - { - "kind":"COUNTER", - "labels": - { - "foo":"baz" - }, - "ts":3, - "value":42 - } - ] -} +{ + "sensors": + [ + { + "kind":"COUNTER", + "labels": + { + "foo":"bar" + }, + "timeseries": + [ + { + "ts":1, + "value":42 + }, + { + "ts":2, + "value":42 + }, + { + "ts":4, + "value":42 + } + ] + }, + { + "kind":"COUNTER", + "labels": + { + "foo":"baz" + }, + "ts":3, + "value":42 + } + ] +} diff --git a/library/cpp/monlib/encode/json/ut/buffered_ts_merge.json b/library/cpp/monlib/encode/json/ut/buffered_ts_merge.json index e71c9dd206..1d27efacb0 100644 --- a/library/cpp/monlib/encode/json/ut/buffered_ts_merge.json +++ b/library/cpp/monlib/encode/json/ut/buffered_ts_merge.json @@ -1,13 +1,13 @@ -{ - "sensors": - [ - { - "kind":"COUNTER", - "labels": - { - "foo":"bar" - }, +{ + "sensors": + [ + { + "kind":"COUNTER", + "labels": + { + "foo":"bar" + }, "value":45 - } - ] -} + } + ] +} diff --git a/library/cpp/monlib/encode/json/ut/empty_series.json b/library/cpp/monlib/encode/json/ut/empty_series.json index 877c957cab..641e10cdea 100644 --- a/library/cpp/monlib/encode/json/ut/empty_series.json +++ b/library/cpp/monlib/encode/json/ut/empty_series.json @@ -1,12 +1,12 @@ -{ - "sensors": - [ - { - "kind":"COUNTER", - "labels": - { - "foo":"bar" - } - } - ] -} +{ + "sensors": + [ + { + "kind":"COUNTER", + "labels": + { + "foo":"bar" + } + } + ] +} diff --git a/library/cpp/monlib/encode/json/ut/merged.json b/library/cpp/monlib/encode/json/ut/merged.json index fe39861f95..ea2c99a33c 100644 --- a/library/cpp/monlib/encode/json/ut/merged.json +++ b/library/cpp/monlib/encode/json/ut/merged.json @@ -1,14 +1,14 @@ -{ - "sensors": - [ - { - "kind":"RATE", - "labels": - { +{ + "sensors": + [ + { + "kind":"RATE", + "labels": + { "metric":"hello", - "label":"world" - }, - "value":1 - } - ] -} + "label":"world" + }, + "value":1 + } + ] +} diff --git a/library/cpp/monlib/encode/json/ut/ya.make b/library/cpp/monlib/encode/json/ut/ya.make index 96b4cef0c5..e50c4f4903 100644 --- a/library/cpp/monlib/encode/json/ut/ya.make +++ b/library/cpp/monlib/encode/json/ut/ya.make @@ -11,14 +11,14 @@ SRCS( ) RESOURCE( - buffered_test.json /buffered_test.json - buffered_ts_merge.json /buffered_ts_merge.json + buffered_test.json /buffered_test.json + buffered_ts_merge.json /buffered_ts_merge.json empty_series.json /empty_series.json expected.json /expected.json expected_buffered.json /expected_buffered.json expected_cloud.json /expected_cloud.json expected_cloud_buffered.json /expected_cloud_buffered.json - merged.json /merged.json + merged.json /merged.json histogram_timeseries.json /histogram_timeseries.json histogram_value.json /histogram_value.json histogram_value_inf_before_bounds.json /histogram_value_inf_before_bounds.json @@ -27,8 +27,8 @@ RESOURCE( metrics.json /metrics.json named_metrics.json /named_metrics.json test_decode_to_encode.json /test_decode_to_encode.json - crash.json /crash.json - hist_crash.json /hist_crash.json + crash.json /crash.json + hist_crash.json /hist_crash.json summary_value.json /summary_value.json summary_inf.json /summary_inf.json summary_timeseries.json /summary_timeseries.json diff --git a/library/cpp/monlib/encode/legacy_protobuf/legacy_proto_decoder.cpp b/library/cpp/monlib/encode/legacy_protobuf/legacy_proto_decoder.cpp index 4eba48619c..f87a2d7e8f 100644 --- a/library/cpp/monlib/encode/legacy_protobuf/legacy_proto_decoder.cpp +++ b/library/cpp/monlib/encode/legacy_protobuf/legacy_proto_decoder.cpp @@ -1,527 +1,527 @@ -#include "legacy_protobuf.h" - +#include "legacy_protobuf.h" + #include <library/cpp/monlib/encode/legacy_protobuf/protos/metric_meta.pb.h> #include <library/cpp/monlib/metrics/metric_consumer.h> #include <library/cpp/monlib/metrics/labels.h> - -#include <util/generic/yexception.h> -#include <util/generic/maybe.h> -#include <util/datetime/base.h> + +#include <util/generic/yexception.h> +#include <util/generic/maybe.h> +#include <util/datetime/base.h> #include <util/string/split.h> - + #include <google/protobuf/reflection.h> - -#include <algorithm> - -#ifdef LEGACY_PB_TRACE -#define TRACE(msg) \ - Cerr << msg << Endl -#else -#define TRACE(...) ; -#endif - -namespace NMonitoring { - namespace { + +#include <algorithm> + +#ifdef LEGACY_PB_TRACE +#define TRACE(msg) \ + Cerr << msg << Endl +#else +#define TRACE(...) ; +#endif + +namespace NMonitoring { + namespace { using TMaybeMeta = TMaybe<NMonProto::TMetricMeta>; - - TString ReadLabelValue(const NProtoBuf::Message& msg, const NProtoBuf::FieldDescriptor* d, const NProtoBuf::Reflection& r) { - using namespace NProtoBuf; - - switch (d->type()) { - case FieldDescriptor::TYPE_UINT32: - return ::ToString(r.GetUInt32(msg, d)); - case FieldDescriptor::TYPE_UINT64: - return ::ToString(r.GetUInt64(msg, d)); - case FieldDescriptor::TYPE_STRING: - return r.GetString(msg, d); - case FieldDescriptor::TYPE_ENUM: { - auto val = r.GetEnumValue(msg, d); - auto* valDesc = d->enum_type()->FindValueByNumber(val); - return valDesc->name(); - } - - default: - ythrow yexception() << "type " << d->type_name() << " cannot be used as a field value"; - } - - return {}; - } - - double ReadFieldAsDouble(const NProtoBuf::Message& msg, const NProtoBuf::FieldDescriptor* d, const NProtoBuf::Reflection& r) { - using namespace NProtoBuf; - - switch (d->type()) { - case FieldDescriptor::TYPE_DOUBLE: - return r.GetDouble(msg, d); - case FieldDescriptor::TYPE_BOOL: - return r.GetBool(msg, d) ? 1 : 0; - case FieldDescriptor::TYPE_INT32: - return r.GetInt32(msg, d); - case FieldDescriptor::TYPE_INT64: - return r.GetInt64(msg, d); - case FieldDescriptor::TYPE_UINT32: - return r.GetUInt32(msg, d); - case FieldDescriptor::TYPE_UINT64: - return r.GetUInt64(msg, d); - case FieldDescriptor::TYPE_SINT32: - return r.GetInt32(msg, d); - case FieldDescriptor::TYPE_SINT64: - return r.GetInt64(msg, d); - case FieldDescriptor::TYPE_FIXED32: - return r.GetUInt32(msg, d); - case FieldDescriptor::TYPE_FIXED64: - return r.GetUInt64(msg, d); - case FieldDescriptor::TYPE_SFIXED32: - return r.GetInt32(msg, d); - case FieldDescriptor::TYPE_SFIXED64: - return r.GetInt64(msg, d); - case FieldDescriptor::TYPE_FLOAT: - return r.GetFloat(msg, d); - case FieldDescriptor::TYPE_ENUM: - return r.GetEnumValue(msg, d); - default: - ythrow yexception() << "type " << d->type_name() << " cannot be used as a field value"; - } - - return std::numeric_limits<double>::quiet_NaN(); - } - - double ReadRepeatedAsDouble(const NProtoBuf::Message& msg, const NProtoBuf::FieldDescriptor* d, const NProtoBuf::Reflection& r, size_t i) { - using namespace NProtoBuf; - - switch (d->type()) { - case FieldDescriptor::TYPE_DOUBLE: - return r.GetRepeatedDouble(msg, d, i); - case FieldDescriptor::TYPE_BOOL: - return r.GetRepeatedBool(msg, d, i) ? 1 : 0; - case FieldDescriptor::TYPE_INT32: - return r.GetRepeatedInt32(msg, d, i); - case FieldDescriptor::TYPE_INT64: - return r.GetRepeatedInt64(msg, d, i); - case FieldDescriptor::TYPE_UINT32: - return r.GetRepeatedUInt32(msg, d, i); - case FieldDescriptor::TYPE_UINT64: - return r.GetRepeatedUInt64(msg, d, i); - case FieldDescriptor::TYPE_SINT32: - return r.GetRepeatedInt32(msg, d, i); - case FieldDescriptor::TYPE_SINT64: - return r.GetRepeatedInt64(msg, d, i); - case FieldDescriptor::TYPE_FIXED32: - return r.GetRepeatedUInt32(msg, d, i); - case FieldDescriptor::TYPE_FIXED64: - return r.GetRepeatedUInt64(msg, d, i); - case FieldDescriptor::TYPE_SFIXED32: - return r.GetRepeatedInt32(msg, d, i); - case FieldDescriptor::TYPE_SFIXED64: - return r.GetRepeatedInt64(msg, d, i); - case FieldDescriptor::TYPE_FLOAT: - return r.GetRepeatedFloat(msg, d, i); - case FieldDescriptor::TYPE_ENUM: - return r.GetRepeatedEnumValue(msg, d, i); - default: - ythrow yexception() << "type " << d->type_name() << " cannot be used as a field value"; - } - - return std::numeric_limits<double>::quiet_NaN(); - } - - TString LabelFromField(const NProtoBuf::Message& msg, const TString& name) { - const auto* fieldDesc = msg.GetDescriptor()->FindFieldByName(name); - const auto* reflection = msg.GetReflection(); - Y_ENSURE(fieldDesc && reflection, "Unable to get meta for field " << name); - - auto s = ReadLabelValue(msg, fieldDesc, *reflection); - std::replace(std::begin(s), s.vend(), ' ', '_'); - - return s; - } - - TMaybeMeta MaybeGetMeta(const NProtoBuf::FieldOptions& opts) { + + TString ReadLabelValue(const NProtoBuf::Message& msg, const NProtoBuf::FieldDescriptor* d, const NProtoBuf::Reflection& r) { + using namespace NProtoBuf; + + switch (d->type()) { + case FieldDescriptor::TYPE_UINT32: + return ::ToString(r.GetUInt32(msg, d)); + case FieldDescriptor::TYPE_UINT64: + return ::ToString(r.GetUInt64(msg, d)); + case FieldDescriptor::TYPE_STRING: + return r.GetString(msg, d); + case FieldDescriptor::TYPE_ENUM: { + auto val = r.GetEnumValue(msg, d); + auto* valDesc = d->enum_type()->FindValueByNumber(val); + return valDesc->name(); + } + + default: + ythrow yexception() << "type " << d->type_name() << " cannot be used as a field value"; + } + + return {}; + } + + double ReadFieldAsDouble(const NProtoBuf::Message& msg, const NProtoBuf::FieldDescriptor* d, const NProtoBuf::Reflection& r) { + using namespace NProtoBuf; + + switch (d->type()) { + case FieldDescriptor::TYPE_DOUBLE: + return r.GetDouble(msg, d); + case FieldDescriptor::TYPE_BOOL: + return r.GetBool(msg, d) ? 1 : 0; + case FieldDescriptor::TYPE_INT32: + return r.GetInt32(msg, d); + case FieldDescriptor::TYPE_INT64: + return r.GetInt64(msg, d); + case FieldDescriptor::TYPE_UINT32: + return r.GetUInt32(msg, d); + case FieldDescriptor::TYPE_UINT64: + return r.GetUInt64(msg, d); + case FieldDescriptor::TYPE_SINT32: + return r.GetInt32(msg, d); + case FieldDescriptor::TYPE_SINT64: + return r.GetInt64(msg, d); + case FieldDescriptor::TYPE_FIXED32: + return r.GetUInt32(msg, d); + case FieldDescriptor::TYPE_FIXED64: + return r.GetUInt64(msg, d); + case FieldDescriptor::TYPE_SFIXED32: + return r.GetInt32(msg, d); + case FieldDescriptor::TYPE_SFIXED64: + return r.GetInt64(msg, d); + case FieldDescriptor::TYPE_FLOAT: + return r.GetFloat(msg, d); + case FieldDescriptor::TYPE_ENUM: + return r.GetEnumValue(msg, d); + default: + ythrow yexception() << "type " << d->type_name() << " cannot be used as a field value"; + } + + return std::numeric_limits<double>::quiet_NaN(); + } + + double ReadRepeatedAsDouble(const NProtoBuf::Message& msg, const NProtoBuf::FieldDescriptor* d, const NProtoBuf::Reflection& r, size_t i) { + using namespace NProtoBuf; + + switch (d->type()) { + case FieldDescriptor::TYPE_DOUBLE: + return r.GetRepeatedDouble(msg, d, i); + case FieldDescriptor::TYPE_BOOL: + return r.GetRepeatedBool(msg, d, i) ? 1 : 0; + case FieldDescriptor::TYPE_INT32: + return r.GetRepeatedInt32(msg, d, i); + case FieldDescriptor::TYPE_INT64: + return r.GetRepeatedInt64(msg, d, i); + case FieldDescriptor::TYPE_UINT32: + return r.GetRepeatedUInt32(msg, d, i); + case FieldDescriptor::TYPE_UINT64: + return r.GetRepeatedUInt64(msg, d, i); + case FieldDescriptor::TYPE_SINT32: + return r.GetRepeatedInt32(msg, d, i); + case FieldDescriptor::TYPE_SINT64: + return r.GetRepeatedInt64(msg, d, i); + case FieldDescriptor::TYPE_FIXED32: + return r.GetRepeatedUInt32(msg, d, i); + case FieldDescriptor::TYPE_FIXED64: + return r.GetRepeatedUInt64(msg, d, i); + case FieldDescriptor::TYPE_SFIXED32: + return r.GetRepeatedInt32(msg, d, i); + case FieldDescriptor::TYPE_SFIXED64: + return r.GetRepeatedInt64(msg, d, i); + case FieldDescriptor::TYPE_FLOAT: + return r.GetRepeatedFloat(msg, d, i); + case FieldDescriptor::TYPE_ENUM: + return r.GetRepeatedEnumValue(msg, d, i); + default: + ythrow yexception() << "type " << d->type_name() << " cannot be used as a field value"; + } + + return std::numeric_limits<double>::quiet_NaN(); + } + + TString LabelFromField(const NProtoBuf::Message& msg, const TString& name) { + const auto* fieldDesc = msg.GetDescriptor()->FindFieldByName(name); + const auto* reflection = msg.GetReflection(); + Y_ENSURE(fieldDesc && reflection, "Unable to get meta for field " << name); + + auto s = ReadLabelValue(msg, fieldDesc, *reflection); + std::replace(std::begin(s), s.vend(), ' ', '_'); + + return s; + } + + TMaybeMeta MaybeGetMeta(const NProtoBuf::FieldOptions& opts) { if (opts.HasExtension(NMonProto::Metric)) { return opts.GetExtension(NMonProto::Metric); - } - - return Nothing(); - } - - class ILabelGetter: public TThrRefBase { - public: - enum class EType { - Fixed = 1, - Lazy = 2, - }; - - virtual TLabel Get(const NProtoBuf::Message&) = 0; - virtual EType Type() const = 0; - }; - - class TFixedLabel: public ILabelGetter { - public: - explicit TFixedLabel(TLabel&& l) - : Label_{std::move(l)} - { - TRACE("found fixed label " << l); - } - + } + + return Nothing(); + } + + class ILabelGetter: public TThrRefBase { + public: + enum class EType { + Fixed = 1, + Lazy = 2, + }; + + virtual TLabel Get(const NProtoBuf::Message&) = 0; + virtual EType Type() const = 0; + }; + + class TFixedLabel: public ILabelGetter { + public: + explicit TFixedLabel(TLabel&& l) + : Label_{std::move(l)} + { + TRACE("found fixed label " << l); + } + EType Type() const override { - return EType::Fixed; - } + return EType::Fixed; + } TLabel Get(const NProtoBuf::Message&) override { - return Label_; - } - - private: - TLabel Label_; - }; - - using TFunction = std::function<TLabel(const NProtoBuf::Message&)>; - - class TLazyLabel: public ILabelGetter { - public: - TLazyLabel(TFunction&& fn) - : Fn_{std::move(fn)} - { - TRACE("found lazy label"); - } - + return Label_; + } + + private: + TLabel Label_; + }; + + using TFunction = std::function<TLabel(const NProtoBuf::Message&)>; + + class TLazyLabel: public ILabelGetter { + public: + TLazyLabel(TFunction&& fn) + : Fn_{std::move(fn)} + { + TRACE("found lazy label"); + } + EType Type() const override { - return EType::Lazy; - } + return EType::Lazy; + } TLabel Get(const NProtoBuf::Message& msg) override { - return Fn_(msg); - } - - private: - TFunction Fn_; - }; - - class TDecoderContext { - public: - void Init(const NProtoBuf::Message* msg) { - Message_ = msg; - Y_ENSURE(Message_); - Reflection_ = msg->GetReflection(); - Y_ENSURE(Reflection_); - - for (auto it = Labels_.begin(); it != Labels_.end(); ++it) { - if ((*it)->Type() == ILabelGetter::EType::Lazy) { - auto l = (*it)->Get(Message()); - *it = ::MakeIntrusive<TFixedLabel>(std::move(l)); - } else { - auto l = (*it)->Get(Message()); - } - } - } - - void Clear() noexcept { - Message_ = nullptr; - Reflection_ = nullptr; - } - + return Fn_(msg); + } + + private: + TFunction Fn_; + }; + + class TDecoderContext { + public: + void Init(const NProtoBuf::Message* msg) { + Message_ = msg; + Y_ENSURE(Message_); + Reflection_ = msg->GetReflection(); + Y_ENSURE(Reflection_); + + for (auto it = Labels_.begin(); it != Labels_.end(); ++it) { + if ((*it)->Type() == ILabelGetter::EType::Lazy) { + auto l = (*it)->Get(Message()); + *it = ::MakeIntrusive<TFixedLabel>(std::move(l)); + } else { + auto l = (*it)->Get(Message()); + } + } + } + + void Clear() noexcept { + Message_ = nullptr; + Reflection_ = nullptr; + } + TDecoderContext CreateChildFromMeta(const NMonProto::TMetricMeta& metricMeta, const TString& name, i64 repeatedIdx = -1) { - TDecoderContext child{*this}; - child.Clear(); - + TDecoderContext child{*this}; + child.Clear(); + if (metricMeta.HasCustomPath()) { if (const auto& nodePath = metricMeta.GetCustomPath()) { child.AppendPath(nodePath); } } else if (metricMeta.GetPath()) { - child.AppendPath(name); - } - + child.AppendPath(name); + } + if (metricMeta.HasKeys()) { child.ParseKeys(metricMeta.GetKeys(), repeatedIdx); - } - - return child; - } - + } + + return child; + } + TDecoderContext CreateChildFromRepeatedScalar(const NMonProto::TMetricMeta& metricMeta, i64 repeatedIdx = -1) { - TDecoderContext child{*this}; - child.Clear(); - + TDecoderContext child{*this}; + child.Clear(); + if (metricMeta.HasKeys()) { child.ParseKeys(metricMeta.GetKeys(), repeatedIdx); - } - - return child; - } - + } + + return child; + } + TDecoderContext CreateChildFromEls(const TString& name, const NMonProto::TExtraLabelMetrics& metrics, size_t idx, TMaybeMeta maybeMeta) { - TDecoderContext child{*this}; - child.Clear(); - - auto usePath = [&maybeMeta] { - return !maybeMeta->HasPath() || maybeMeta->GetPath(); - }; - + TDecoderContext child{*this}; + child.Clear(); + + auto usePath = [&maybeMeta] { + return !maybeMeta->HasPath() || maybeMeta->GetPath(); + }; + if (!name.empty() && (!maybeMeta || usePath())) { - child.AppendPath(name); - } - - child.Labels_.push_back(::MakeIntrusive<TLazyLabel>( + child.AppendPath(name); + } + + child.Labels_.push_back(::MakeIntrusive<TLazyLabel>( [ labelName = metrics.GetlabelName(), idx, &metrics ](const auto&) { const auto& val = metrics.Getvalues(idx); - TString labelVal; - const auto uintLabel = val.GetlabelValueUint(); - - if (uintLabel) { - labelVal = ::ToString(uintLabel); - } else { - labelVal = val.GetlabelValue(); - } - - return TLabel{labelName, labelVal}; - })); - - return child; - } - - void ParseKeys(TStringBuf keys, i64 repeatedIdx = -1) { - auto parts = StringSplitter(keys) - .Split(' ') - .SkipEmpty(); - - for (auto part : parts) { - auto str = part.Token(); - - TStringBuf lhs, rhs; - - const bool isDynamic = str.TrySplit(':', lhs, rhs); + TString labelVal; + const auto uintLabel = val.GetlabelValueUint(); + + if (uintLabel) { + labelVal = ::ToString(uintLabel); + } else { + labelVal = val.GetlabelValue(); + } + + return TLabel{labelName, labelVal}; + })); + + return child; + } + + void ParseKeys(TStringBuf keys, i64 repeatedIdx = -1) { + auto parts = StringSplitter(keys) + .Split(' ') + .SkipEmpty(); + + for (auto part : parts) { + auto str = part.Token(); + + TStringBuf lhs, rhs; + + const bool isDynamic = str.TrySplit(':', lhs, rhs); const bool isIndexing = isDynamic && rhs == TStringBuf("#"); - - if (isIndexing) { - TRACE("parsed index labels"); - - // <label_name>:# means that we should use index of the repeated - // field as label value - Y_ENSURE(repeatedIdx != -1); - Labels_.push_back(::MakeIntrusive<TLazyLabel>([=](const auto&) { - return TLabel{lhs, ::ToString(repeatedIdx)}; - })); - } else if (isDynamic) { - TRACE("parsed dynamic labels"); - - // <label_name>:<field_name> means that we need to take label value - // later from message's field - Labels_.push_back(::MakeIntrusive<TLazyLabel>([=](const auto& msg) { - return TLabel{lhs, LabelFromField(msg, TString{rhs})}; - })); - } else if (str.TrySplit('=', lhs, rhs)) { - TRACE("parsed static labels"); - - // <label_name>=<label_value> stands for constant label - Labels_.push_back(::MakeIntrusive<TFixedLabel>(TLabel{lhs, rhs})); - } else { - ythrow yexception() << "Incorrect Keys format"; - } - } - } - - void AppendPath(TStringBuf fieldName) { - Path_ += '/'; - Path_ += fieldName; - } - - const TString& Path() const { - return Path_; - } - - TLabels Labels() const { - TLabels result; - for (auto&& l : Labels_) { - result.Add(l->Get(Message())); - } - - return result; - } - - const NProtoBuf::Message& Message() const { - Y_VERIFY_DEBUG(Message_); - return *Message_; - } - - const NProtoBuf::Reflection& Reflection() const { - return *Reflection_; - } - - private: - const NProtoBuf::Message* Message_{nullptr}; - const NProtoBuf::Reflection* Reflection_{nullptr}; - - TString Path_; - TVector<TIntrusivePtr<ILabelGetter>> Labels_; - }; - - class TDecoder { - public: + + if (isIndexing) { + TRACE("parsed index labels"); + + // <label_name>:# means that we should use index of the repeated + // field as label value + Y_ENSURE(repeatedIdx != -1); + Labels_.push_back(::MakeIntrusive<TLazyLabel>([=](const auto&) { + return TLabel{lhs, ::ToString(repeatedIdx)}; + })); + } else if (isDynamic) { + TRACE("parsed dynamic labels"); + + // <label_name>:<field_name> means that we need to take label value + // later from message's field + Labels_.push_back(::MakeIntrusive<TLazyLabel>([=](const auto& msg) { + return TLabel{lhs, LabelFromField(msg, TString{rhs})}; + })); + } else if (str.TrySplit('=', lhs, rhs)) { + TRACE("parsed static labels"); + + // <label_name>=<label_value> stands for constant label + Labels_.push_back(::MakeIntrusive<TFixedLabel>(TLabel{lhs, rhs})); + } else { + ythrow yexception() << "Incorrect Keys format"; + } + } + } + + void AppendPath(TStringBuf fieldName) { + Path_ += '/'; + Path_ += fieldName; + } + + const TString& Path() const { + return Path_; + } + + TLabels Labels() const { + TLabels result; + for (auto&& l : Labels_) { + result.Add(l->Get(Message())); + } + + return result; + } + + const NProtoBuf::Message& Message() const { + Y_VERIFY_DEBUG(Message_); + return *Message_; + } + + const NProtoBuf::Reflection& Reflection() const { + return *Reflection_; + } + + private: + const NProtoBuf::Message* Message_{nullptr}; + const NProtoBuf::Reflection* Reflection_{nullptr}; + + TString Path_; + TVector<TIntrusivePtr<ILabelGetter>> Labels_; + }; + + class TDecoder { + public: TDecoder(IMetricConsumer* consumer, const NProtoBuf::Message& message, TInstant timestamp) - : Consumer_{consumer} - , Message_{message} - , Timestamp_{timestamp} - { - } - - void Decode() const { - Consumer_->OnStreamBegin(); - DecodeToStream(); - Consumer_->OnStreamEnd(); - } - - void DecodeToStream() const { - DecodeImpl(Message_, {}); - } - - private: + : Consumer_{consumer} + , Message_{message} + , Timestamp_{timestamp} + { + } + + void Decode() const { + Consumer_->OnStreamBegin(); + DecodeToStream(); + Consumer_->OnStreamEnd(); + } + + void DecodeToStream() const { + DecodeImpl(Message_, {}); + } + + private: static const NMonProto::TExtraLabelMetrics& ExtractExtraMetrics(TDecoderContext& ctx, const NProtoBuf::FieldDescriptor& f) { - const auto& parent = ctx.Message(); - const auto& reflection = ctx.Reflection(); - auto& subMessage = reflection.GetMessage(parent, &f); - + const auto& parent = ctx.Message(); + const auto& reflection = ctx.Reflection(); + auto& subMessage = reflection.GetMessage(parent, &f); + return dynamic_cast<const NMonProto::TExtraLabelMetrics&>(subMessage); - } - - void DecodeImpl(const NProtoBuf::Message& msg, TDecoderContext ctx) const { - std::vector<const NProtoBuf::FieldDescriptor*> fields; - - ctx.Init(&msg); - - ctx.Reflection().ListFields(msg, &fields); - - for (const auto* f : fields) { - Y_ENSURE(f); - - const auto& opts = f->options(); - const auto isMessage = f->type() == NProtoBuf::FieldDescriptor::TYPE_MESSAGE; + } + + void DecodeImpl(const NProtoBuf::Message& msg, TDecoderContext ctx) const { + std::vector<const NProtoBuf::FieldDescriptor*> fields; + + ctx.Init(&msg); + + ctx.Reflection().ListFields(msg, &fields); + + for (const auto* f : fields) { + Y_ENSURE(f); + + const auto& opts = f->options(); + const auto isMessage = f->type() == NProtoBuf::FieldDescriptor::TYPE_MESSAGE; const auto isExtraLabelMetrics = isMessage && f->message_type()->full_name() == "NMonProto.TExtraLabelMetrics"; - const auto maybeMeta = MaybeGetMeta(opts); - + const auto maybeMeta = MaybeGetMeta(opts); + if (!(maybeMeta || isExtraLabelMetrics)) { - continue; - } - + continue; + } + if (isExtraLabelMetrics) { const auto& extra = ExtractExtraMetrics(ctx, *f); RecurseExtraLabelMetrics(ctx, extra, f->name(), maybeMeta); - } else if (isMessage) { - RecurseMessage(ctx, *maybeMeta, *f); - } else if (f->is_repeated()) { - RecurseRepeatedScalar(ctx, *maybeMeta, *f); + } else if (isMessage) { + RecurseMessage(ctx, *maybeMeta, *f); + } else if (f->is_repeated()) { + RecurseRepeatedScalar(ctx, *maybeMeta, *f); } else if (maybeMeta->HasType()) { - const auto val = ReadFieldAsDouble(msg, f, ctx.Reflection()); + const auto val = ReadFieldAsDouble(msg, f, ctx.Reflection()); const bool isRate = maybeMeta->GetType() == NMonProto::EMetricType::RATE; WriteMetric(val, ctx, f->name(), isRate); - } - } - } - + } + } + } + void RecurseRepeatedScalar(TDecoderContext ctx, const NMonProto::TMetricMeta& meta, const NProtoBuf::FieldDescriptor& f) const { - auto&& msg = ctx.Message(); - auto&& reflection = ctx.Reflection(); + auto&& msg = ctx.Message(); + auto&& reflection = ctx.Reflection(); const bool isRate = meta.GetType() == NMonProto::EMetricType::RATE; - + // this is a repeated scalar field, which makes metric only if it's indexing - for (auto i = 0; i < reflection.FieldSize(msg, &f); ++i) { - auto subCtx = ctx.CreateChildFromRepeatedScalar(meta, i); - subCtx.Init(&msg); - auto val = ReadRepeatedAsDouble(msg, &f, reflection, i); + for (auto i = 0; i < reflection.FieldSize(msg, &f); ++i) { + auto subCtx = ctx.CreateChildFromRepeatedScalar(meta, i); + subCtx.Init(&msg); + auto val = ReadRepeatedAsDouble(msg, &f, reflection, i); WriteMetric(val, subCtx, f.name(), isRate); - } - } - + } + } + void RecurseExtraLabelMetrics(TDecoderContext ctx, const NMonProto::TExtraLabelMetrics& msg, const TString& name, const TMaybeMeta& meta) const { - auto i = 0; - for (const auto& val : msg.Getvalues()) { - auto subCtx = ctx.CreateChildFromEls(name, msg, i++, meta); - subCtx.Init(&val); - + auto i = 0; + for (const auto& val : msg.Getvalues()) { + auto subCtx = ctx.CreateChildFromEls(name, msg, i++, meta); + subCtx.Init(&val); + const bool isRate = val.Hastype() ? val.Gettype() == NMonProto::EMetricType::RATE : meta->GetType() == NMonProto::EMetricType::RATE; - + double metricVal{0}; if (isRate) { metricVal = val.GetlongValue(); - } else { + } else { metricVal = val.GetdoubleValue(); - } - + } + WriteMetric(metricVal, subCtx, "", isRate); - - for (const auto& child : val.Getchildren()) { + + for (const auto& child : val.Getchildren()) { RecurseExtraLabelMetrics(subCtx, child, "", meta); - } - } - } - + } + } + } + void RecurseMessage(TDecoderContext ctx, const NMonProto::TMetricMeta& metricMeta, const NProtoBuf::FieldDescriptor& f) const { - const auto& msg = ctx.Message(); - const auto& reflection = ctx.Reflection(); - - if (f.is_repeated()) { - TRACE("recurse into repeated message " << f.name()); - for (auto i = 0; i < reflection.FieldSize(msg, &f); ++i) { - auto& subMessage = reflection.GetRepeatedMessage(msg, &f, i); + const auto& msg = ctx.Message(); + const auto& reflection = ctx.Reflection(); + + if (f.is_repeated()) { + TRACE("recurse into repeated message " << f.name()); + for (auto i = 0; i < reflection.FieldSize(msg, &f); ++i) { + auto& subMessage = reflection.GetRepeatedMessage(msg, &f, i); DecodeImpl(subMessage, ctx.CreateChildFromMeta(metricMeta, f.name(), i)); - } - } else { - TRACE("recurse into message " << f.name()); - auto& subMessage = reflection.GetMessage(msg, &f); + } + } else { + TRACE("recurse into message " << f.name()); + auto& subMessage = reflection.GetMessage(msg, &f); DecodeImpl(subMessage, ctx.CreateChildFromMeta(metricMeta, f.name())); - } - } - - inline void WriteValue(ui64 value) const { - Consumer_->OnUint64(Timestamp_, value); - } - - inline void WriteValue(double value) const { - Consumer_->OnDouble(Timestamp_, value); - } - + } + } + + inline void WriteValue(ui64 value) const { + Consumer_->OnUint64(Timestamp_, value); + } + + inline void WriteValue(double value) const { + Consumer_->OnDouble(Timestamp_, value); + } + void WriteMetric(double value, const TDecoderContext& ctx, const TString& name, bool isRate) const { if (isRate) { Consumer_->OnMetricBegin(EMetricType::RATE); - WriteValue(static_cast<ui64>(value)); - } else { + WriteValue(static_cast<ui64>(value)); + } else { Consumer_->OnMetricBegin(EMetricType::GAUGE); - WriteValue(static_cast<double>(value)); - } - - Consumer_->OnLabelsBegin(); - - for (const auto& label : ctx.Labels()) { - Consumer_->OnLabel(label.Name(), label.Value()); - } - + WriteValue(static_cast<double>(value)); + } + + Consumer_->OnLabelsBegin(); + + for (const auto& label : ctx.Labels()) { + Consumer_->OnLabel(label.Name(), label.Value()); + } + const auto fullPath = name.empty() - ? ctx.Path() - : ctx.Path() + '/' + name; - - if (fullPath) { - Consumer_->OnLabel("path", fullPath); - } - - Consumer_->OnLabelsEnd(); + ? ctx.Path() + : ctx.Path() + '/' + name; + + if (fullPath) { + Consumer_->OnLabel("path", fullPath); + } + + Consumer_->OnLabelsEnd(); Consumer_->OnMetricEnd(); - } - - private: + } + + private: IMetricConsumer* Consumer_{nullptr}; - const NProtoBuf::Message& Message_; - TInstant Timestamp_; - }; - - } - + const NProtoBuf::Message& Message_; + TInstant Timestamp_; + }; + + } + void DecodeLegacyProto(const NProtoBuf::Message& data, IMetricConsumer* consumer, TInstant ts) { - Y_ENSURE(consumer); - TDecoder(consumer, data, ts).Decode(); - } - + Y_ENSURE(consumer); + TDecoder(consumer, data, ts).Decode(); + } + void DecodeLegacyProtoToStream(const NProtoBuf::Message& data, IMetricConsumer* consumer, TInstant ts) { - Y_ENSURE(consumer); - TDecoder(consumer, data, ts).DecodeToStream(); - } -} + Y_ENSURE(consumer); + TDecoder(consumer, data, ts).DecodeToStream(); + } +} diff --git a/library/cpp/monlib/encode/legacy_protobuf/legacy_protobuf.h b/library/cpp/monlib/encode/legacy_protobuf/legacy_protobuf.h index c1bd7cd436..7cf8985d65 100644 --- a/library/cpp/monlib/encode/legacy_protobuf/legacy_protobuf.h +++ b/library/cpp/monlib/encode/legacy_protobuf/legacy_protobuf.h @@ -1,16 +1,16 @@ -#pragma once - +#pragma once + #include <google/protobuf/message.h> -#include <util/datetime/base.h> - -namespace NMonitoring { - // Unsupported features of the original format: - // - histograms; - // - memOnly; - // - dropHost/ignorePath - +#include <util/datetime/base.h> + +namespace NMonitoring { + // Unsupported features of the original format: + // - histograms; + // - memOnly; + // - dropHost/ignorePath + void DecodeLegacyProto(const NProtoBuf::Message& data, class IMetricConsumer* c, TInstant ts = TInstant::Zero()); - - /// Does not open/close consumer stream unlike the above function. + + /// Does not open/close consumer stream unlike the above function. void DecodeLegacyProtoToStream(const NProtoBuf::Message& data, class IMetricConsumer* c, TInstant ts = TInstant::Zero()); -} +} diff --git a/library/cpp/monlib/encode/legacy_protobuf/legacy_protobuf_ut.cpp b/library/cpp/monlib/encode/legacy_protobuf/legacy_protobuf_ut.cpp index 140ef1ef58..53683cb39c 100644 --- a/library/cpp/monlib/encode/legacy_protobuf/legacy_protobuf_ut.cpp +++ b/library/cpp/monlib/encode/legacy_protobuf/legacy_protobuf_ut.cpp @@ -1,422 +1,422 @@ -#include "legacy_protobuf.h" - +#include "legacy_protobuf.h" + #include <library/cpp/testing/unittest/registar.h> - + #include <library/cpp/monlib/encode/legacy_protobuf/ut/test_cases.pb.h> #include <library/cpp/monlib/encode/legacy_protobuf/protos/metric_meta.pb.h> - + #include <library/cpp/monlib/encode/protobuf/protobuf.h> #include <library/cpp/monlib/encode/text/text.h> #include <library/cpp/monlib/metrics/labels.h> - -#include <util/generic/algorithm.h> -#include <util/generic/hash_set.h> - -using namespace NMonitoring; - -TSimple MakeSimpleMessage() { - TSimple msg; - - msg.SetFoo(1); - msg.SetBar(2.); - msg.SetBaz(42.); - - return msg; -} - + +#include <util/generic/algorithm.h> +#include <util/generic/hash_set.h> + +using namespace NMonitoring; + +TSimple MakeSimpleMessage() { + TSimple msg; + + msg.SetFoo(1); + msg.SetBar(2.); + msg.SetBaz(42.); + + return msg; +} + IMetricEncoderPtr debugPrinter = EncoderText(&Cerr); - -namespace NMonitoring { - inline bool operator<(const TLabel& lhs, const TLabel& rhs) { - return lhs.Name() < rhs.Name() || - (lhs.Name() == rhs.Name() && lhs.Value() < rhs.Value()); - } - -} - + +namespace NMonitoring { + inline bool operator<(const TLabel& lhs, const TLabel& rhs) { + return lhs.Name() < rhs.Name() || + (lhs.Name() == rhs.Name() && lhs.Value() < rhs.Value()); + } + +} + void SetLabelValue(NMonProto::TExtraLabelMetrics::TValue& val, TString s) { - val.SetlabelValue(s); -} - + val.SetlabelValue(s); +} + void SetLabelValue(NMonProto::TExtraLabelMetrics::TValue& val, ui64 u) { - val.SetlabelValueUint(u); -} - -template <typename T, typename V> + val.SetlabelValueUint(u); +} + +template <typename T, typename V> NMonProto::TExtraLabelMetrics MakeExtra(TString labelName, V labelValue, T value, bool isDeriv) { NMonProto::TExtraLabelMetrics metric; auto* val = metric.Addvalues(); - + metric.SetlabelName(labelName); - SetLabelValue(*val, labelValue); - - if (isDeriv) { - val->SetlongValue(value); - } else { - val->SetdoubleValue(value); - } - + SetLabelValue(*val, labelValue); + + if (isDeriv) { + val->SetlongValue(value); + } else { + val->SetdoubleValue(value); + } + return metric; -} - -void AssertLabels(const TLabels& expected, const NProto::TMultiSample& actual) { - UNIT_ASSERT_EQUAL(actual.LabelsSize(), expected.Size()); - - TSet<TLabel> actualSet; - TSet<TLabel> expectedSet; - Transform(expected.begin(), expected.end(), std::inserter(expectedSet, expectedSet.end()), [] (auto&& l) { - return TLabel{l.Name(), l.Value()}; - }); - - const auto& l = actual.GetLabels(); - Transform(std::begin(l), std::end(l), std::inserter(actualSet, std::begin(actualSet)), - [](auto&& elem) -> TLabel { - return {elem.GetName(), elem.GetValue()}; - }); - - TVector<TLabel> diff; - SetSymmetricDifference(std::begin(expectedSet), std::end(expectedSet), - std::begin(actualSet), std::end(actualSet), std::back_inserter(diff)); - - if (diff.size() > 0) { - for (auto&& l : diff) { - Cerr << l << Endl; - } - - UNIT_FAIL("Labels don't match"); - } -} - -void AssertSimpleMessage(const NProto::TMultiSamplesList& samples, TString pathPrefix = "/") { - UNIT_ASSERT_EQUAL(samples.SamplesSize(), 3); - - THashSet<TString> expectedValues{pathPrefix + "Foo", pathPrefix + "Bar", pathPrefix + "Baz"}; - - for (const auto& s : samples.GetSamples()) { - UNIT_ASSERT_EQUAL(s.LabelsSize(), 1); - UNIT_ASSERT_EQUAL(s.PointsSize(), 1); - - const auto labelVal = s.GetLabels(0).GetValue(); +} + +void AssertLabels(const TLabels& expected, const NProto::TMultiSample& actual) { + UNIT_ASSERT_EQUAL(actual.LabelsSize(), expected.Size()); + + TSet<TLabel> actualSet; + TSet<TLabel> expectedSet; + Transform(expected.begin(), expected.end(), std::inserter(expectedSet, expectedSet.end()), [] (auto&& l) { + return TLabel{l.Name(), l.Value()}; + }); + + const auto& l = actual.GetLabels(); + Transform(std::begin(l), std::end(l), std::inserter(actualSet, std::begin(actualSet)), + [](auto&& elem) -> TLabel { + return {elem.GetName(), elem.GetValue()}; + }); + + TVector<TLabel> diff; + SetSymmetricDifference(std::begin(expectedSet), std::end(expectedSet), + std::begin(actualSet), std::end(actualSet), std::back_inserter(diff)); + + if (diff.size() > 0) { + for (auto&& l : diff) { + Cerr << l << Endl; + } + + UNIT_FAIL("Labels don't match"); + } +} + +void AssertSimpleMessage(const NProto::TMultiSamplesList& samples, TString pathPrefix = "/") { + UNIT_ASSERT_EQUAL(samples.SamplesSize(), 3); + + THashSet<TString> expectedValues{pathPrefix + "Foo", pathPrefix + "Bar", pathPrefix + "Baz"}; + + for (const auto& s : samples.GetSamples()) { + UNIT_ASSERT_EQUAL(s.LabelsSize(), 1); + UNIT_ASSERT_EQUAL(s.PointsSize(), 1); + + const auto labelVal = s.GetLabels(0).GetValue(); UNIT_ASSERT(expectedValues.contains(labelVal)); - - if (labelVal == pathPrefix + "Foo") { + + if (labelVal == pathPrefix + "Foo") { UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE); - UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 1, 1e-6); - } else if (labelVal == pathPrefix + "Bar") { + UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 1, 1e-6); + } else if (labelVal == pathPrefix + "Bar") { UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE); - UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 2, 1e-6); - } else if (labelVal == pathPrefix + "Baz") { + UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 2, 1e-6); + } else if (labelVal == pathPrefix + "Baz") { UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::RATE); - UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 42); - } - } -} - -Y_UNIT_TEST_SUITE(TLegacyProtoDecoderTest) { - Y_UNIT_TEST(SimpleProto) { - NProto::TMultiSamplesList samples; + UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 42); + } + } +} + +Y_UNIT_TEST_SUITE(TLegacyProtoDecoderTest) { + Y_UNIT_TEST(SimpleProto) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - auto msg = MakeSimpleMessage(); - DecodeLegacyProto(msg, e.Get()); - - AssertSimpleMessage(samples); - }; - - Y_UNIT_TEST(RepeatedProto) { - NProto::TMultiSamplesList samples; + + auto msg = MakeSimpleMessage(); + DecodeLegacyProto(msg, e.Get()); + + AssertSimpleMessage(samples); + }; + + Y_UNIT_TEST(RepeatedProto) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - auto simple = MakeSimpleMessage(); - TRepeated msg; - msg.AddMessages()->CopyFrom(simple); - - DecodeLegacyProto(msg, e.Get()); - - AssertSimpleMessage(samples); - } - - Y_UNIT_TEST(RepeatedProtoWithPath) { - NProto::TMultiSamplesList samples; + + auto simple = MakeSimpleMessage(); + TRepeated msg; + msg.AddMessages()->CopyFrom(simple); + + DecodeLegacyProto(msg, e.Get()); + + AssertSimpleMessage(samples); + } + + Y_UNIT_TEST(RepeatedProtoWithPath) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - auto simple = MakeSimpleMessage(); - TRepeatedWithPath msg; - msg.AddNamespace()->CopyFrom(simple); - - DecodeLegacyProto(msg, e.Get()); - - AssertSimpleMessage(samples, "/Namespace/"); - } - - Y_UNIT_TEST(DeepNesting) { - NProto::TMultiSamplesList samples; + + auto simple = MakeSimpleMessage(); + TRepeatedWithPath msg; + msg.AddNamespace()->CopyFrom(simple); + + DecodeLegacyProto(msg, e.Get()); + + AssertSimpleMessage(samples, "/Namespace/"); + } + + Y_UNIT_TEST(DeepNesting) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - auto simple = MakeSimpleMessage(); - TRepeatedWithPath internal; - internal.AddNamespace()->CopyFrom(simple); - - TDeepNesting msg; - msg.MutableNested()->CopyFrom(internal); - - DecodeLegacyProto(msg, e.Get()); - - AssertSimpleMessage(samples, "/Namespace/"); - } - - Y_UNIT_TEST(Keys) { - NProto::TMultiSamplesList samples; + + auto simple = MakeSimpleMessage(); + TRepeatedWithPath internal; + internal.AddNamespace()->CopyFrom(simple); + + TDeepNesting msg; + msg.MutableNested()->CopyFrom(internal); + + DecodeLegacyProto(msg, e.Get()); + + AssertSimpleMessage(samples, "/Namespace/"); + } + + Y_UNIT_TEST(Keys) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - auto simple = MakeSimpleMessage(); - simple.SetLabel("my_label_value"); - - TNestedWithKeys msg; - msg.AddNamespace()->CopyFrom(simple); - - DecodeLegacyProto(msg, e.Get()); - - auto i = 0; - for (const auto& s : samples.GetSamples()) { - UNIT_ASSERT_EQUAL(s.LabelsSize(), 4); - - bool foundLabel = false; - bool foundFixed = false; - bool foundNumbered = false; - - for (const auto& label : s.GetLabels()) { - if (label.GetName() == "my_label") { - foundLabel = true; - UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "my_label_value"); - } else if (label.GetName() == "fixed_label") { - foundFixed = true; - UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "fixed_value"); - } else if (label.GetName() == "numbered") { - foundNumbered = true; - UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), ::ToString(i)); - } - } - - UNIT_ASSERT(foundLabel); - UNIT_ASSERT(foundFixed); - UNIT_ASSERT(foundNumbered); - } - } - - Y_UNIT_TEST(NonStringKeys) { - NProto::TMultiSamplesList samples; + + auto simple = MakeSimpleMessage(); + simple.SetLabel("my_label_value"); + + TNestedWithKeys msg; + msg.AddNamespace()->CopyFrom(simple); + + DecodeLegacyProto(msg, e.Get()); + + auto i = 0; + for (const auto& s : samples.GetSamples()) { + UNIT_ASSERT_EQUAL(s.LabelsSize(), 4); + + bool foundLabel = false; + bool foundFixed = false; + bool foundNumbered = false; + + for (const auto& label : s.GetLabels()) { + if (label.GetName() == "my_label") { + foundLabel = true; + UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "my_label_value"); + } else if (label.GetName() == "fixed_label") { + foundFixed = true; + UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "fixed_value"); + } else if (label.GetName() == "numbered") { + foundNumbered = true; + UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), ::ToString(i)); + } + } + + UNIT_ASSERT(foundLabel); + UNIT_ASSERT(foundFixed); + UNIT_ASSERT(foundNumbered); + } + } + + Y_UNIT_TEST(NonStringKeys) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - TNonStringKeys msg; - msg.SetFoo(42); - msg.SetEnum(ENUM); - msg.SetInt(43); - - TRepeatedNonStringKeys msgs; - msgs.AddNested()->CopyFrom(msg); - - DecodeLegacyProto(msgs, e.Get()); - - for (const auto& s : samples.GetSamples()) { - bool foundEnum = false; - bool foundInt = false; - - for (const auto& label : s.GetLabels()) { - if (label.GetName() == "enum") { - foundEnum = true; - UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "ENUM"); - } else if (label.GetName() == "int") { - foundInt = true; - UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "43"); - } - } - - UNIT_ASSERT(foundEnum); - UNIT_ASSERT(foundInt); - - UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 42, 1e-6); - } - } - - Y_UNIT_TEST(KeysFromNonLeafNodes) { - NProto::TMultiSamplesList samples; + + TNonStringKeys msg; + msg.SetFoo(42); + msg.SetEnum(ENUM); + msg.SetInt(43); + + TRepeatedNonStringKeys msgs; + msgs.AddNested()->CopyFrom(msg); + + DecodeLegacyProto(msgs, e.Get()); + + for (const auto& s : samples.GetSamples()) { + bool foundEnum = false; + bool foundInt = false; + + for (const auto& label : s.GetLabels()) { + if (label.GetName() == "enum") { + foundEnum = true; + UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "ENUM"); + } else if (label.GetName() == "int") { + foundInt = true; + UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "43"); + } + } + + UNIT_ASSERT(foundEnum); + UNIT_ASSERT(foundInt); + + UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 42, 1e-6); + } + } + + Y_UNIT_TEST(KeysFromNonLeafNodes) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - auto simple = MakeSimpleMessage(); - simple.SetLabel("label_value"); - - TRepeatedWithName nested; - nested.SetName("my_name"); - nested.AddNested()->CopyFrom(simple); - - TKeysFromNonLeaf msg; - msg.AddNested()->CopyFrom(nested); - - DecodeLegacyProto(msg, e.Get()); - - AssertLabels({{"my_label", "label_value"}, {"path", "/Nested/Nested/Foo"}, {"name", "my_name"}}, samples.GetSamples(0)); - } - - Y_UNIT_TEST(SpacesAreGetReplaced) { - NProto::TMultiSamplesList samples; + + auto simple = MakeSimpleMessage(); + simple.SetLabel("label_value"); + + TRepeatedWithName nested; + nested.SetName("my_name"); + nested.AddNested()->CopyFrom(simple); + + TKeysFromNonLeaf msg; + msg.AddNested()->CopyFrom(nested); + + DecodeLegacyProto(msg, e.Get()); + + AssertLabels({{"my_label", "label_value"}, {"path", "/Nested/Nested/Foo"}, {"name", "my_name"}}, samples.GetSamples(0)); + } + + Y_UNIT_TEST(SpacesAreGetReplaced) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - auto simple = MakeSimpleMessage(); - simple.SetLabel("my label_value"); - - TNestedWithKeys msg; - msg.AddNamespace()->CopyFrom(simple); - - DecodeLegacyProto(msg, e.Get()); - - for (const auto& s : samples.GetSamples()) { - UNIT_ASSERT_EQUAL(s.LabelsSize(), 4); - - bool foundLabel = false; - - for (const auto& label : s.GetLabels()) { - if (label.GetName() == "my_label") { - foundLabel = true; - UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "my_label_value"); - } - } - - UNIT_ASSERT(foundLabel); - } - } - - Y_UNIT_TEST(ExtraLabels) { - NProto::TMultiSamplesList samples; + + auto simple = MakeSimpleMessage(); + simple.SetLabel("my label_value"); + + TNestedWithKeys msg; + msg.AddNamespace()->CopyFrom(simple); + + DecodeLegacyProto(msg, e.Get()); + + for (const auto& s : samples.GetSamples()) { + UNIT_ASSERT_EQUAL(s.LabelsSize(), 4); + + bool foundLabel = false; + + for (const auto& label : s.GetLabels()) { + if (label.GetName() == "my_label") { + foundLabel = true; + UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "my_label_value"); + } + } + + UNIT_ASSERT(foundLabel); + } + } + + Y_UNIT_TEST(ExtraLabels) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - TExtraLabels msg; - msg.MutableExtraAsIs()->CopyFrom(MakeExtra("label", "foo", 42, false)); - msg.MutableExtraDeriv()->CopyFrom(MakeExtra("deriv_label", "deriv_foo", 43, true)); - - DecodeLegacyProto(msg, e.Get()); - - UNIT_ASSERT_EQUAL(samples.SamplesSize(), 2); - { - auto s = samples.GetSamples(0); - AssertLabels({{"label", "foo"}, {"path", "/ExtraAsIs"}}, s); - - UNIT_ASSERT_EQUAL(s.PointsSize(), 1); - auto point = s.GetPoints(0); - UNIT_ASSERT_DOUBLES_EQUAL(point.GetFloat64(), 42, 1e-6); - } - - { - auto s = samples.GetSamples(1); - AssertLabels({{"deriv_label", "deriv_foo"}, {"path", "/ExtraDeriv"}}, s); - - UNIT_ASSERT_EQUAL(s.PointsSize(), 1); - auto point = s.GetPoints(0); - UNIT_ASSERT_EQUAL(point.GetUint64(), 43); - } - } - - Y_UNIT_TEST(NestedExtraLabels) { - NProto::TMultiSamplesList samples; + + TExtraLabels msg; + msg.MutableExtraAsIs()->CopyFrom(MakeExtra("label", "foo", 42, false)); + msg.MutableExtraDeriv()->CopyFrom(MakeExtra("deriv_label", "deriv_foo", 43, true)); + + DecodeLegacyProto(msg, e.Get()); + + UNIT_ASSERT_EQUAL(samples.SamplesSize(), 2); + { + auto s = samples.GetSamples(0); + AssertLabels({{"label", "foo"}, {"path", "/ExtraAsIs"}}, s); + + UNIT_ASSERT_EQUAL(s.PointsSize(), 1); + auto point = s.GetPoints(0); + UNIT_ASSERT_DOUBLES_EQUAL(point.GetFloat64(), 42, 1e-6); + } + + { + auto s = samples.GetSamples(1); + AssertLabels({{"deriv_label", "deriv_foo"}, {"path", "/ExtraDeriv"}}, s); + + UNIT_ASSERT_EQUAL(s.PointsSize(), 1); + auto point = s.GetPoints(0); + UNIT_ASSERT_EQUAL(point.GetUint64(), 43); + } + } + + Y_UNIT_TEST(NestedExtraLabels) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - TExtraLabels msg; - auto extra = MakeExtra("label", "foo", 42, false); - auto* val = extra.Mutablevalues(0); - { - auto child = MakeExtra("child1", "label1", 24, true); + + TExtraLabels msg; + auto extra = MakeExtra("label", "foo", 42, false); + auto* val = extra.Mutablevalues(0); + { + auto child = MakeExtra("child1", "label1", 24, true); child.Mutablevalues(0)->Settype(NMonProto::EMetricType::RATE); - val->Addchildren()->CopyFrom(child); - } - - { - auto child = MakeExtra("child2", 34, 23, false); - val->Addchildren()->CopyFrom(child); - } - msg.MutableExtraAsIs()->CopyFrom(extra); - - DecodeLegacyProto(msg, e.Get()); - - UNIT_ASSERT_EQUAL(samples.SamplesSize(), 3); - { - auto s = samples.GetSamples(0); - AssertLabels({{"label", "foo"}, {"path", "/ExtraAsIs"}}, s); - - UNIT_ASSERT_EQUAL(s.PointsSize(), 1); - auto point = s.GetPoints(0); - UNIT_ASSERT_DOUBLES_EQUAL(point.GetFloat64(), 42, 1e-6); - } - - { - auto s = samples.GetSamples(1); - AssertLabels({{"label", "foo"}, {"child1", "label1"}, {"path", "/ExtraAsIs"}}, s); - - UNIT_ASSERT_EQUAL(s.PointsSize(), 1); - auto point = s.GetPoints(0); - UNIT_ASSERT_EQUAL(point.GetUint64(), 24); - } - - { - auto s = samples.GetSamples(2); - AssertLabels({{"label", "foo"}, {"child2", "34"}, {"path", "/ExtraAsIs"}}, s); - - UNIT_ASSERT_EQUAL(s.PointsSize(), 1); - auto point = s.GetPoints(0); - UNIT_ASSERT_EQUAL(point.GetFloat64(), 23); - } - } - - Y_UNIT_TEST(RobotLabels) { - NProto::TMultiSamplesList samples; + val->Addchildren()->CopyFrom(child); + } + + { + auto child = MakeExtra("child2", 34, 23, false); + val->Addchildren()->CopyFrom(child); + } + msg.MutableExtraAsIs()->CopyFrom(extra); + + DecodeLegacyProto(msg, e.Get()); + + UNIT_ASSERT_EQUAL(samples.SamplesSize(), 3); + { + auto s = samples.GetSamples(0); + AssertLabels({{"label", "foo"}, {"path", "/ExtraAsIs"}}, s); + + UNIT_ASSERT_EQUAL(s.PointsSize(), 1); + auto point = s.GetPoints(0); + UNIT_ASSERT_DOUBLES_EQUAL(point.GetFloat64(), 42, 1e-6); + } + + { + auto s = samples.GetSamples(1); + AssertLabels({{"label", "foo"}, {"child1", "label1"}, {"path", "/ExtraAsIs"}}, s); + + UNIT_ASSERT_EQUAL(s.PointsSize(), 1); + auto point = s.GetPoints(0); + UNIT_ASSERT_EQUAL(point.GetUint64(), 24); + } + + { + auto s = samples.GetSamples(2); + AssertLabels({{"label", "foo"}, {"child2", "34"}, {"path", "/ExtraAsIs"}}, s); + + UNIT_ASSERT_EQUAL(s.PointsSize(), 1); + auto point = s.GetPoints(0); + UNIT_ASSERT_EQUAL(point.GetFloat64(), 23); + } + } + + Y_UNIT_TEST(RobotLabels) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - TNamedCounter responses; - responses.SetName("responses"); - responses.SetCount(42); - - TCrawlerCounters::TStatusCounters statusCounters; - statusCounters.AddZoraResponses()->CopyFrom(responses); - - TCrawlerCounters::TPolicyCounters policyCounters; - policyCounters.SetSubComponent("mySubComponent"); - policyCounters.SetName("myComponentName"); - policyCounters.SetZone("myComponentZone"); - policyCounters.MutableStatusCounters()->CopyFrom(statusCounters); - - TCrawlerCounters counters; - counters.SetComponent("myComponent"); - counters.AddPoliciesCounters()->CopyFrom(policyCounters); - - DecodeLegacyProto(counters, e.Get()); - UNIT_ASSERT_EQUAL(samples.SamplesSize(), 1); - auto s = samples.GetSamples(0); - AssertLabels({ - {"SubComponent", "mySubComponent"}, {"Policy", "myComponentName"}, {"Zone", "myComponentZone"}, - {"ZoraResponse", "responses"}, {"path", "/PoliciesCounters/StatusCounters/ZoraResponses/Count"}}, s); - } - - Y_UNIT_TEST(ZoraLabels) { - NProto::TMultiSamplesList samples; + + TNamedCounter responses; + responses.SetName("responses"); + responses.SetCount(42); + + TCrawlerCounters::TStatusCounters statusCounters; + statusCounters.AddZoraResponses()->CopyFrom(responses); + + TCrawlerCounters::TPolicyCounters policyCounters; + policyCounters.SetSubComponent("mySubComponent"); + policyCounters.SetName("myComponentName"); + policyCounters.SetZone("myComponentZone"); + policyCounters.MutableStatusCounters()->CopyFrom(statusCounters); + + TCrawlerCounters counters; + counters.SetComponent("myComponent"); + counters.AddPoliciesCounters()->CopyFrom(policyCounters); + + DecodeLegacyProto(counters, e.Get()); + UNIT_ASSERT_EQUAL(samples.SamplesSize(), 1); + auto s = samples.GetSamples(0); + AssertLabels({ + {"SubComponent", "mySubComponent"}, {"Policy", "myComponentName"}, {"Zone", "myComponentZone"}, + {"ZoraResponse", "responses"}, {"path", "/PoliciesCounters/StatusCounters/ZoraResponses/Count"}}, s); + } + + Y_UNIT_TEST(ZoraLabels) { + NProto::TMultiSamplesList samples; IMetricEncoderPtr e = EncoderProtobuf(&samples); - - TTimeLogHist hist; - hist.AddBuckets(42); - hist.AddBuckets(0); - - TKiwiCounters counters; - counters.MutableTimes()->CopyFrom(hist); - - DecodeLegacyProto(counters, e.Get()); - - UNIT_ASSERT_EQUAL(samples.SamplesSize(), 2); - - auto s = samples.GetSamples(0); - AssertLabels({{"slot", "0"}, {"path", "/Times/Buckets"}}, s); - UNIT_ASSERT_EQUAL(s.PointsSize(), 1); - UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 42); - - s = samples.GetSamples(1); - AssertLabels({{"slot", "1"}, {"path", "/Times/Buckets"}}, s); - UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 0); - } -} + + TTimeLogHist hist; + hist.AddBuckets(42); + hist.AddBuckets(0); + + TKiwiCounters counters; + counters.MutableTimes()->CopyFrom(hist); + + DecodeLegacyProto(counters, e.Get()); + + UNIT_ASSERT_EQUAL(samples.SamplesSize(), 2); + + auto s = samples.GetSamples(0); + AssertLabels({{"slot", "0"}, {"path", "/Times/Buckets"}}, s); + UNIT_ASSERT_EQUAL(s.PointsSize(), 1); + UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 42); + + s = samples.GetSamples(1); + AssertLabels({{"slot", "1"}, {"path", "/Times/Buckets"}}, s); + UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 0); + } +} diff --git a/library/cpp/monlib/encode/legacy_protobuf/protos/ya.make b/library/cpp/monlib/encode/legacy_protobuf/protos/ya.make index 01505f61ca..489f361ab1 100644 --- a/library/cpp/monlib/encode/legacy_protobuf/protos/ya.make +++ b/library/cpp/monlib/encode/legacy_protobuf/protos/ya.make @@ -1,13 +1,13 @@ -PROTO_LIBRARY() - -OWNER(g:solomon) - -SRCS( +PROTO_LIBRARY() + +OWNER(g:solomon) + +SRCS( metric_meta.proto -) - +) + IF (NOT PY_PROTOS_FOR) EXCLUDE_TAGS(GO_PROTO) ENDIF() -END() +END() diff --git a/library/cpp/monlib/encode/legacy_protobuf/ut/test_cases.proto b/library/cpp/monlib/encode/legacy_protobuf/ut/test_cases.proto index de870cb9e2..37e901de48 100644 --- a/library/cpp/monlib/encode/legacy_protobuf/ut/test_cases.proto +++ b/library/cpp/monlib/encode/legacy_protobuf/ut/test_cases.proto @@ -1,90 +1,90 @@ import "library/cpp/monlib/encode/legacy_protobuf/protos/metric_meta.proto"; - -message TSimple { + +message TSimple { optional uint64 Foo = 1 [ (NMonProto.Metric).Type = GAUGE ]; optional double Bar = 2 [ (NMonProto.Metric).Type = GAUGE ]; optional double Baz = 3 [ (NMonProto.Metric).Type = RATE ]; - optional string Label = 4; -} - -message TRepeated { + optional string Label = 4; +} + +message TRepeated { repeated TSimple Messages = 1 [ (NMonProto.Metric).Path = false ]; -}; - -message TRepeatedWithPath { +}; + +message TRepeatedWithPath { repeated TSimple Namespace = 1 [ (NMonProto.Metric).Path = true ]; -}; - -message TNestedWithKeys { +}; + +message TNestedWithKeys { repeated TSimple Namespace = 1 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "my_label:Label fixed_label=fixed_value numbered:#" ]; -}; - -message TDeepNesting { +}; + +message TDeepNesting { optional TRepeatedWithPath Nested = 1 [ (NMonProto.Metric).Path = false ]; -}; - -enum EEnum { - MY = 1; - ENUM = 2; -}; - -message TNonStringKeys { +}; + +enum EEnum { + MY = 1; + ENUM = 2; +}; + +message TNonStringKeys { optional uint32 Foo = 1 [ (NMonProto.Metric).Type = GAUGE ]; - optional EEnum Enum = 2; - optional uint32 Int = 3; -}; - -message TRepeatedNonStringKeys { + optional EEnum Enum = 2; + optional uint32 Int = 3; +}; + +message TRepeatedNonStringKeys { repeated TNonStringKeys Nested = 1 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "enum:Enum int:Int" ]; -}; - -message TExtraLabels { +}; + +message TExtraLabels { optional NMonProto.TExtraLabelMetrics ExtraAsIs = 1 [ (NMonProto.Metric).Type = GAUGE ]; optional NMonProto.TExtraLabelMetrics ExtraDeriv = 2 [ (NMonProto.Metric).Type = RATE ]; -}; - -message TRepeatedWithName { - optional string Name = 1; +}; + +message TRepeatedWithName { + optional string Name = 1; repeated TSimple Nested = 2 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "my_label:Label" ]; -}; - -message TKeysFromNonLeaf { +}; + +message TKeysFromNonLeaf { repeated TRepeatedWithName Nested = 1 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "name:Name" ]; -}; - - -message TNamedCounter { - optional string Name = 1; +}; + + +message TNamedCounter { + optional string Name = 1; optional uint64 Count = 2 [ (NMonProto.Metric).Type = RATE ]; -} - -message TCrawlerCounters { - message TStatusCounters { +} + +message TCrawlerCounters { + message TStatusCounters { repeated TNamedCounter ZoraResponses = 3 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "ZoraResponse:Name" ]; repeated TNamedCounter FetcherResponses = 4 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "SpiderResponse:Name" ]; repeated TNamedCounter RotorResponses = 5 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "SpiderResponse:Name" ]; repeated TNamedCounter PDFetchResponses = 6 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "PDFetchResponse:Name" ]; repeated TNamedCounter CalcResponses = 7 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "CalcResponse:Name" ]; repeated TNamedCounter Responses = 8 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "AggregatedResponse:Name" ]; - } - - message TPolicyCounters { - optional string SubComponent = 1; - optional string Name = 2; - optional string Zone = 3; - + } + + message TPolicyCounters { + optional string SubComponent = 1; + optional string Name = 2; + optional string Zone = 3; + optional TStatusCounters StatusCounters = 4 [ (NMonProto.Metric).Path = true ]; - } - - optional string Component = 1; + } + + optional string Component = 1; repeated TPolicyCounters PoliciesCounters = 3 [ (NMonProto.Metric).Path = true, (NMonProto.Metric).Keys = "SubComponent:SubComponent Policy:Name Zone:Zone" ]; -} - -message TTimeLogHist { - optional uint32 MinBucketMillisec = 1; +} + +message TTimeLogHist { + optional uint32 MinBucketMillisec = 1; repeated uint64 Buckets = 2 [ (NMonProto.Metric).Type = RATE, (NMonProto.Metric).Keys = "slot:#" ]; -} - -message TKiwiCounters { +} + +message TKiwiCounters { optional TTimeLogHist Times = 22 [ (NMonProto.Metric).Path = true ]; -} +} diff --git a/library/cpp/monlib/encode/legacy_protobuf/ut/ya.make b/library/cpp/monlib/encode/legacy_protobuf/ut/ya.make index f066b6c327..479a0c46c9 100644 --- a/library/cpp/monlib/encode/legacy_protobuf/ut/ya.make +++ b/library/cpp/monlib/encode/legacy_protobuf/ut/ya.make @@ -1,18 +1,18 @@ UNITTEST_FOR(library/cpp/monlib/encode/legacy_protobuf) - + OWNER( g:solomon msherbakov ) - -SRCS( - legacy_protobuf_ut.cpp - test_cases.proto -) - + +SRCS( + legacy_protobuf_ut.cpp + test_cases.proto +) + PEERDIR( library/cpp/monlib/encode/protobuf library/cpp/monlib/encode/text ) - -END() + +END() diff --git a/library/cpp/monlib/encode/legacy_protobuf/ya.make b/library/cpp/monlib/encode/legacy_protobuf/ya.make index 16a8ebb1f3..74c82aac93 100644 --- a/library/cpp/monlib/encode/legacy_protobuf/ya.make +++ b/library/cpp/monlib/encode/legacy_protobuf/ya.make @@ -1,16 +1,16 @@ -LIBRARY() - +LIBRARY() + OWNER( g:solomon msherbakov ) - -SRCS( - legacy_proto_decoder.cpp -) - -PEERDIR( + +SRCS( + legacy_proto_decoder.cpp +) + +PEERDIR( library/cpp/monlib/encode/legacy_protobuf/protos -) - -END() +) + +END() diff --git a/library/cpp/monlib/encode/prometheus/prometheus_decoder.cpp b/library/cpp/monlib/encode/prometheus/prometheus_decoder.cpp index 2195d9e125..7e81357dbd 100644 --- a/library/cpp/monlib/encode/prometheus/prometheus_decoder.cpp +++ b/library/cpp/monlib/encode/prometheus/prometheus_decoder.cpp @@ -46,24 +46,24 @@ namespace NMonitoring { return sb; } - template <typename T, typename U> - bool TryStaticCast(U val, T& out) { - static_assert(std::is_arithmetic_v<U>); + template <typename T, typename U> + bool TryStaticCast(U val, T& out) { + static_assert(std::is_arithmetic_v<U>); if constexpr (std::is_floating_point_v<T> || std::is_floating_point_v<U>) { if (val > MaxFloor<T>() || val < -MaxFloor<T>()) { - return false; - } - - } else { - if (val > Max<T>() || val < Min<T>()) { - return false; - } - } - - out = static_cast<T>(val); - return true; - } - + return false; + } + + } else { + if (val > Max<T>() || val < Min<T>()) { + return false; + } + } + + out = static_cast<T>(val); + return true; + } + /////////////////////////////////////////////////////////////////////// // THistogramBuilder /////////////////////////////////////////////////////////////////////// @@ -298,9 +298,9 @@ namespace NMonitoring { HistogramBuilder_.SetName(baseName); } - TBucketValue bucketVal; - Y_PARSER_ENSURE(TryStaticCast(value, bucketVal), "Cannot convert " << value << " to bucket value type"); - HistogramBuilder_.AddBucket(bound, bucketVal); + TBucketValue bucketVal; + Y_PARSER_ENSURE(TryStaticCast(value, bucketVal), "Cannot convert " << value << " to bucket value type"); + HistogramBuilder_.AddBucket(bound, bucketVal); HistogramBuilder_.SetTime(time); HistogramBuilder_.SetLabels(std::move(labels)); } else if (NPrometheus::IsCount(name)) { @@ -398,7 +398,7 @@ namespace NMonitoring { CurrentByte_ = Data_[CurrentPos_++]; } - Y_FORCE_INLINE bool IsSpace(char ch) { + Y_FORCE_INLINE bool IsSpace(char ch) { return ch == ' ' || ch == '\t'; } @@ -414,7 +414,7 @@ namespace NMonitoring { } void SkipSpaces() { - while (HasRemaining() && IsSpace(CurrentByte_)) { + while (HasRemaining() && IsSpace(CurrentByte_)) { ReadNextByteUnsafe(); } } @@ -428,7 +428,7 @@ namespace NMonitoring { TStringBuf ReadToken() { Y_VERIFY_DEBUG(CurrentPos_ > 0); size_t begin = CurrentPos_ - 1; // read first byte again - while (HasRemaining() && !IsSpace(CurrentByte_) && CurrentByte_ != '\n') { + while (HasRemaining() && !IsSpace(CurrentByte_) && CurrentByte_ != '\n') { ReadNextByteUnsafe(); } return TokenFromPos(begin); @@ -529,11 +529,11 @@ namespace NMonitoring { } void ConsumeCounter(TStringBuf name, const TLabelsMap& labels, TInstant time, double value) { - i64 intValue{0}; - // not nan - if (value == value) { - Y_PARSER_ENSURE(TryStaticCast(value, intValue), "value " << value << " is out of range"); - } + i64 intValue{0}; + // not nan + if (value == value) { + Y_PARSER_ENSURE(TryStaticCast(value, intValue), "value " << value << " is out of range"); + } // see https://st.yandex-team.ru/SOLOMON-4142 for more details // why we convert Prometheus COUNTER into Solomon RATE diff --git a/library/cpp/monlib/encode/prometheus/prometheus_encoder.cpp b/library/cpp/monlib/encode/prometheus/prometheus_encoder.cpp index db7f76978c..15efeb8c03 100644 --- a/library/cpp/monlib/encode/prometheus/prometheus_encoder.cpp +++ b/library/cpp/monlib/encode/prometheus/prometheus_encoder.cpp @@ -126,7 +126,7 @@ namespace NMonitoring { void WriteLabels(const TLabels& labels, TStringBuf addLabelKey, TStringBuf addLabelValue) { Out_->Write('{'); - for (auto&& l: labels) { + for (auto&& l: labels) { Out_->Write(l.Name()); Out_->Write('='); WriteLabelValue(l.Value()); @@ -354,7 +354,7 @@ namespace NMonitoring { } // XXX: poor performace - for (auto&& l: CommonLabels_) { + for (auto&& l: CommonLabels_) { MetricState_.Labels.Add(l.Name(), l.Value()); } @@ -363,7 +363,7 @@ namespace NMonitoring { "labels " << MetricState_.Labels << " does not contain label '" << MetricNameLabel_ << '\''); - const TString& metricName = ToString(nameLabel->Value()); + const TString& metricName = ToString(nameLabel->Value()); if (MetricState_.Type != EMetricType::DSUMMARY) { Writer_.WriteType(MetricState_.Type, metricName); } diff --git a/library/cpp/monlib/encode/protobuf/protobuf_encoder.cpp b/library/cpp/monlib/encode/protobuf/protobuf_encoder.cpp index 9ed5136efa..2d11b9d5ba 100644 --- a/library/cpp/monlib/encode/protobuf/protobuf_encoder.cpp +++ b/library/cpp/monlib/encode/protobuf/protobuf_encoder.cpp @@ -15,9 +15,9 @@ namespace NMonitoring { case EMetricType::IGAUGE: return NProto::IGAUGE; case EMetricType::HIST: - return NProto::HISTOGRAM; + return NProto::HISTOGRAM; case EMetricType::HIST_RATE: - return NProto::HIST_RATE; + return NProto::HIST_RATE; case EMetricType::DSUMMARY: return NProto::DSUMMARY; case EMetricType::LOGHIST: diff --git a/library/cpp/monlib/encode/protobuf/protos/samples.proto b/library/cpp/monlib/encode/protobuf/protos/samples.proto index 8653d0a06e..371f4181d2 100644 --- a/library/cpp/monlib/encode/protobuf/protos/samples.proto +++ b/library/cpp/monlib/encode/protobuf/protos/samples.proto @@ -18,7 +18,7 @@ enum EMetricType { COUNTER = 3; RATE = 4; HISTOGRAM = 5; - HIST_RATE = 6; + HIST_RATE = 6; DSUMMARY = 7; LOGHISTOGRAM = 8; } diff --git a/library/cpp/monlib/encode/spack/compression.cpp b/library/cpp/monlib/encode/spack/compression.cpp index 922e11d6ad..0d2152fc85 100644 --- a/library/cpp/monlib/encode/spack/compression.cpp +++ b/library/cpp/monlib/encode/spack/compression.cpp @@ -1,12 +1,12 @@ #include "compression.h" -#include <util/generic/buffer.h> +#include <util/generic/buffer.h> #include <util/generic/cast.h> #include <util/generic/ptr.h> #include <util/generic/scope.h> -#include <util/generic/size_literals.h> -#include <util/stream/format.h> -#include <util/stream/output.h> +#include <util/generic/size_literals.h> +#include <util/stream/format.h> +#include <util/stream/output.h> #include <util/stream/walk.h> #include <contrib/libs/lz4/lz4.h> @@ -24,10 +24,10 @@ namespace NMonitoring { using TUncompressedSize = ui32; using TCheckSum = ui32; - constexpr size_t COMPRESSED_FRAME_SIZE_LIMIT = 512_KB; - constexpr size_t UNCOMPRESSED_FRAME_SIZE_LIMIT = COMPRESSED_FRAME_SIZE_LIMIT; - constexpr size_t FRAME_SIZE_LIMIT = 2_MB; - constexpr size_t DEFAULT_FRAME_LEN = 64_KB; + constexpr size_t COMPRESSED_FRAME_SIZE_LIMIT = 512_KB; + constexpr size_t UNCOMPRESSED_FRAME_SIZE_LIMIT = COMPRESSED_FRAME_SIZE_LIMIT; + constexpr size_t FRAME_SIZE_LIMIT = 2_MB; + constexpr size_t DEFAULT_FRAME_LEN = 64_KB; struct Y_PACKED TFrameHeader { TCompressedSize CompressedSize; @@ -46,7 +46,7 @@ namespace NMonitoring { TBlock(T&& t) : TStringBuf(t.data(), t.size()) { - Y_ENSURE(t.data() != nullptr); + Y_ENSURE(t.data() != nullptr); } char* data() noexcept { @@ -208,14 +208,14 @@ namespace NMonitoring { return 0; } - Y_ENSURE(header.CompressedSize <= COMPRESSED_FRAME_SIZE_LIMIT, "Compressed frame size is limited to " - << HumanReadableSize(COMPRESSED_FRAME_SIZE_LIMIT, SF_BYTES) - << " but is " << HumanReadableSize(header.CompressedSize, SF_BYTES)); - - Y_ENSURE(header.UncompressedSize <= UNCOMPRESSED_FRAME_SIZE_LIMIT, "Uncompressed frame size is limited to " - << HumanReadableSize(UNCOMPRESSED_FRAME_SIZE_LIMIT, SF_BYTES) - << " but is " << HumanReadableSize(header.UncompressedSize, SF_BYTES)); - + Y_ENSURE(header.CompressedSize <= COMPRESSED_FRAME_SIZE_LIMIT, "Compressed frame size is limited to " + << HumanReadableSize(COMPRESSED_FRAME_SIZE_LIMIT, SF_BYTES) + << " but is " << HumanReadableSize(header.CompressedSize, SF_BYTES)); + + Y_ENSURE(header.UncompressedSize <= UNCOMPRESSED_FRAME_SIZE_LIMIT, "Uncompressed frame size is limited to " + << HumanReadableSize(UNCOMPRESSED_FRAME_SIZE_LIMIT, SF_BYTES) + << " but is " << HumanReadableSize(header.UncompressedSize, SF_BYTES)); + Compressed_.Resize(header.CompressedSize); In_->LoadOrFail(Compressed_.Data(), header.CompressedSize); @@ -307,13 +307,13 @@ namespace NMonitoring { void WriteCompressedFrame() { static const auto framePayload = sizeof(TFrameHeader) + sizeof(TFrameFooter); - const auto maxFrameSize = ui64(TCodecAlg::MaxCompressedLength(Uncompressed_.Size())) + framePayload; - Y_ENSURE(maxFrameSize <= FRAME_SIZE_LIMIT, "Frame size in encoder is limited to " - << HumanReadableSize(FRAME_SIZE_LIMIT, SF_BYTES) - << " but is " << HumanReadableSize(maxFrameSize, SF_BYTES)); + const auto maxFrameSize = ui64(TCodecAlg::MaxCompressedLength(Uncompressed_.Size())) + framePayload; + Y_ENSURE(maxFrameSize <= FRAME_SIZE_LIMIT, "Frame size in encoder is limited to " + << HumanReadableSize(FRAME_SIZE_LIMIT, SF_BYTES) + << " but is " << HumanReadableSize(maxFrameSize, SF_BYTES)); + + Frame_.Resize(maxFrameSize); - Frame_.Resize(maxFrameSize); - // compress TBlock compressedBlock = Frame_; compressedBlock.Skip(sizeof(TFrameHeader)); diff --git a/library/cpp/monlib/encode/spack/fuzz/main.cpp b/library/cpp/monlib/encode/spack/fuzz/main.cpp index c546e392cb..6a14afe71c 100644 --- a/library/cpp/monlib/encode/spack/fuzz/main.cpp +++ b/library/cpp/monlib/encode/spack/fuzz/main.cpp @@ -1,20 +1,20 @@ #include <library/cpp/monlib/encode/spack/spack_v1.h> #include <library/cpp/monlib/encode/fake/fake.h> - -#include <util/stream/mem.h> - - -extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) { - using namespace NMonitoring; - - TMemoryInput min{data, size}; - - auto encoder = EncoderFake(); - - try { - DecodeSpackV1(&min, encoder.Get()); - } catch (...) { - } - - return 0; -} + +#include <util/stream/mem.h> + + +extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) { + using namespace NMonitoring; + + TMemoryInput min{data, size}; + + auto encoder = EncoderFake(); + + try { + DecodeSpackV1(&min, encoder.Get()); + } catch (...) { + } + + return 0; +} diff --git a/library/cpp/monlib/encode/spack/fuzz/ya.make b/library/cpp/monlib/encode/spack/fuzz/ya.make index fc41465df3..99b63eadd5 100644 --- a/library/cpp/monlib/encode/spack/fuzz/ya.make +++ b/library/cpp/monlib/encode/spack/fuzz/ya.make @@ -1,21 +1,21 @@ -FUZZ() - +FUZZ() + OWNER( g:solomon msherbakov -) - +) + FUZZ_OPTS(-rss_limit_mb=1024) -SIZE(MEDIUM) - -PEERDIR( +SIZE(MEDIUM) + +PEERDIR( library/cpp/monlib/encode/spack library/cpp/monlib/encode/fake -) - +) + SRCS( main.cpp ) - -END() + +END() diff --git a/library/cpp/monlib/encode/spack/spack_v1_decoder.cpp b/library/cpp/monlib/encode/spack/spack_v1_decoder.cpp index b3be13f77c..1f445fc80d 100644 --- a/library/cpp/monlib/encode/spack/spack_v1_decoder.cpp +++ b/library/cpp/monlib/encode/spack/spack_v1_decoder.cpp @@ -9,8 +9,8 @@ #include <util/generic/yexception.h> #include <util/generic/buffer.h> -#include <util/generic/size_literals.h> -#include <util/stream/format.h> +#include <util/generic/size_literals.h> +#include <util/stream/format.h> #ifndef _little_endian_ #error Unsupported platform @@ -20,8 +20,8 @@ namespace NMonitoring { namespace { #define DECODE_ENSURE(COND, ...) MONLIB_ENSURE_EX(COND, TSpackDecodeError() << __VA_ARGS__) - constexpr ui64 LABEL_SIZE_LIMIT = 128_MB; - + constexpr ui64 LABEL_SIZE_LIMIT = 128_MB; + /////////////////////////////////////////////////////////////////////// // TDecoderSpackV1 /////////////////////////////////////////////////////////////////////// @@ -63,20 +63,20 @@ namespace NMonitoring { TimePrecision_ = DecodeTimePrecision(Header_.TimePrecision); const ui64 labelSizeTotal = ui64(Header_.LabelNamesSize) + Header_.LabelValuesSize; - + DECODE_ENSURE(labelSizeTotal <= LABEL_SIZE_LIMIT, "Label names & values size of " << HumanReadableSize(labelSizeTotal, SF_BYTES) - << " exceeds the limit which is " << HumanReadableSize(LABEL_SIZE_LIMIT, SF_BYTES)); - + << " exceeds the limit which is " << HumanReadableSize(LABEL_SIZE_LIMIT, SF_BYTES)); + // (2) read string pools - TVector<char> namesBuf(Header_.LabelNamesSize); - readBytes = In_->Load(namesBuf.data(), namesBuf.size()); + TVector<char> namesBuf(Header_.LabelNamesSize); + readBytes = In_->Load(namesBuf.data(), namesBuf.size()); DECODE_ENSURE(readBytes == Header_.LabelNamesSize, "not enough data to read label names pool"); - TStringPool labelNames(namesBuf.data(), namesBuf.size()); + TStringPool labelNames(namesBuf.data(), namesBuf.size()); - TVector<char> valuesBuf(Header_.LabelValuesSize); - readBytes = In_->Load(valuesBuf.data(), valuesBuf.size()); + TVector<char> valuesBuf(Header_.LabelValuesSize); + readBytes = In_->Load(valuesBuf.data(), valuesBuf.size()); DECODE_ENSURE(readBytes == Header_.LabelValuesSize, "not enough data to read label values pool"); - TStringPool labelValues(valuesBuf.data(), valuesBuf.size()); + TStringPool labelValues(valuesBuf.data(), valuesBuf.size()); // (3) read common time c->OnCommonTime(ReadTime()); diff --git a/library/cpp/monlib/encode/spack/spack_v1_encoder.cpp b/library/cpp/monlib/encode/spack/spack_v1_encoder.cpp index d7c6e1d123..a2b0bb5f50 100644 --- a/library/cpp/monlib/encode/spack/spack_v1_encoder.cpp +++ b/library/cpp/monlib/encode/spack/spack_v1_encoder.cpp @@ -17,7 +17,7 @@ namespace NMonitoring { /////////////////////////////////////////////////////////////////////// // TEncoderSpackV1 /////////////////////////////////////////////////////////////////////// - class TEncoderSpackV1 final: public TBufferedEncoderBase { + class TEncoderSpackV1 final: public TBufferedEncoderBase { public: TEncoderSpackV1( IOutputStream* out, @@ -35,8 +35,8 @@ namespace NMonitoring { { MetricsMergingMode_ = mergingMode; - LabelNamesPool_.SetSorted(true); - LabelValuesPool_.SetSorted(true); + LabelNamesPool_.SetSorted(true); + LabelValuesPool_.SetSorted(true); } ~TEncoderSpackV1() override { @@ -45,7 +45,7 @@ namespace NMonitoring { private: void OnDouble(TInstant time, double value) override { - TBufferedEncoderBase::OnDouble(time, value); + TBufferedEncoderBase::OnDouble(time, value); } void OnInt64(TInstant time, i64 value) override { @@ -53,7 +53,7 @@ namespace NMonitoring { } void OnUint64(TInstant time, ui64 value) override { - TBufferedEncoderBase::OnUint64(time, value); + TBufferedEncoderBase::OnUint64(time, value); } void OnHistogram(TInstant time, IHistogramSnapshotPtr snapshot) override { @@ -74,8 +74,8 @@ namespace NMonitoring { } Closed_ = true; - LabelNamesPool_.Build(); - LabelValuesPool_.Build(); + LabelNamesPool_.Build(); + LabelValuesPool_.Build(); // Sort all points uniquely by ts -- the size can decrease ui64 pointsCount = 0; @@ -192,12 +192,12 @@ namespace NMonitoring { void WriteLabels(const TPooledLabels& labels, const TPooledStr* skipKey) { WriteVarUInt32(Out_, static_cast<ui32>(skipKey ? labels.size() - 1 : labels.size())); - for (auto&& label : labels) { + for (auto&& label : labels) { if (label.Key == skipKey) { continue; } - WriteVarUInt32(Out_, label.Key->Index); - WriteVarUInt32(Out_, label.Value->Index); + WriteVarUInt32(Out_, label.Key->Index); + WriteVarUInt32(Out_, label.Value->Index); } } diff --git a/library/cpp/monlib/encode/text/text_encoder.cpp b/library/cpp/monlib/encode/text/text_encoder.cpp index 8917152f56..10336261f0 100644 --- a/library/cpp/monlib/encode/text/text_encoder.cpp +++ b/library/cpp/monlib/encode/text/text_encoder.cpp @@ -99,9 +99,9 @@ namespace NMonitoring { TimeSeries_.Add(time, snapshot.Get()); } - void OnLogHistogram(TInstant ts, TLogHistogramSnapshotPtr snapshot) override { + void OnLogHistogram(TInstant ts, TLogHistogramSnapshotPtr snapshot) override { State_.Expect(TEncoderState::EState::METRIC); - TimeSeries_.Add(ts, snapshot.Get()); + TimeSeries_.Add(ts, snapshot.Get()); } void Close() override { @@ -135,7 +135,7 @@ namespace NMonitoring { (*Out_) << *value.AsSummaryDouble(); break; case EMetricValueType::LOGHISTOGRAM: - (*Out_) << *value.AsLogHistogram(); + (*Out_) << *value.AsLogHistogram(); break; case EMetricValueType::UNKNOWN: ythrow yexception() << "unknown metric value type"; @@ -143,21 +143,21 @@ namespace NMonitoring { } void WriteLabels() { - auto& out = *Out_; - const auto size = Labels_.Size(); - size_t i = 0; - - out << '{'; - for (auto&& l : Labels_) { + auto& out = *Out_; + const auto size = Labels_.Size(); + size_t i = 0; + + out << '{'; + for (auto&& l : Labels_) { out << l.Name() << TStringBuf("='") << l.Value() << '\''; - - ++i; - if (i < size) { + + ++i; + if (i < size) { out << TStringBuf(", "); } - }; - - out << '}'; + }; + + out << '}'; } void WriteMetric() { diff --git a/library/cpp/monlib/encode/unistat/unistat.h b/library/cpp/monlib/encode/unistat/unistat.h index 460141b5bc..1c43b7fa1b 100644 --- a/library/cpp/monlib/encode/unistat/unistat.h +++ b/library/cpp/monlib/encode/unistat/unistat.h @@ -1,13 +1,13 @@ -#pragma once - -#include <util/generic/fwd.h> -#include <util/datetime/base.h> - -namespace NMonitoring { - /// Decodes unistat-style metrics - /// https://wiki.yandex-team.ru/golovan/stat-handle +#pragma once + +#include <util/generic/fwd.h> +#include <util/datetime/base.h> + +namespace NMonitoring { + /// Decodes unistat-style metrics + /// https://wiki.yandex-team.ru/golovan/stat-handle void DecodeUnistat(TStringBuf data, class IMetricConsumer* c, TInstant ts = TInstant::Zero()); - - /// Assumes consumer's stream is open by the caller + + /// Assumes consumer's stream is open by the caller void DecodeUnistatToStream(TStringBuf data, class IMetricConsumer* c, TInstant = TInstant::Zero()); -} +} diff --git a/library/cpp/monlib/encode/unistat/unistat_decoder.cpp b/library/cpp/monlib/encode/unistat/unistat_decoder.cpp index 8006d34070..b2344b0905 100644 --- a/library/cpp/monlib/encode/unistat/unistat_decoder.cpp +++ b/library/cpp/monlib/encode/unistat/unistat_decoder.cpp @@ -1,253 +1,253 @@ -#include "unistat.h" - +#include "unistat.h" + #include <library/cpp/monlib/metrics/histogram_collector.h> #include <library/cpp/monlib/metrics/labels.h> #include <library/cpp/monlib/metrics/metric_type.h> #include <library/cpp/monlib/metrics/metric_value.h> #include <library/cpp/monlib/metrics/metric_consumer.h> - + #include <library/cpp/json/json_reader.h> - -#include <util/datetime/base.h> + +#include <util/datetime/base.h> #include <util/string/split.h> - -#include <contrib/libs/re2/re2/re2.h> - -using namespace NJson; - + +#include <contrib/libs/re2/re2/re2.h> + +using namespace NJson; + const re2::RE2 NAME_RE{R"((?:[a-zA-Z0-9\.\-/@_]+_)+(?:[ad][vehmntx]{3}|summ|hgram|max))"}; - -namespace NMonitoring { - namespace { - bool IsNumber(const NJson::TJsonValue& j) { - switch (j.GetType()) { - case EJsonValueType::JSON_INTEGER: - case EJsonValueType::JSON_UINTEGER: - case EJsonValueType::JSON_DOUBLE: - return true; - - default: - return false; - } - } - - template <typename T> - T ExtractNumber(const TJsonValue& val) { - switch (val.GetType()) { - case EJsonValueType::JSON_INTEGER: - return static_cast<T>(val.GetInteger()); - case EJsonValueType::JSON_UINTEGER: - return static_cast<T>(val.GetUInteger()); - case EJsonValueType::JSON_DOUBLE: - return static_cast<T>(val.GetDouble()); - - default: - ythrow yexception() << "Expected number, but found " << val.GetType(); - } - } - - auto ExtractDouble = ExtractNumber<double>; - auto ExtractUi64 = ExtractNumber<ui64>; - + +namespace NMonitoring { + namespace { + bool IsNumber(const NJson::TJsonValue& j) { + switch (j.GetType()) { + case EJsonValueType::JSON_INTEGER: + case EJsonValueType::JSON_UINTEGER: + case EJsonValueType::JSON_DOUBLE: + return true; + + default: + return false; + } + } + + template <typename T> + T ExtractNumber(const TJsonValue& val) { + switch (val.GetType()) { + case EJsonValueType::JSON_INTEGER: + return static_cast<T>(val.GetInteger()); + case EJsonValueType::JSON_UINTEGER: + return static_cast<T>(val.GetUInteger()); + case EJsonValueType::JSON_DOUBLE: + return static_cast<T>(val.GetDouble()); + + default: + ythrow yexception() << "Expected number, but found " << val.GetType(); + } + } + + auto ExtractDouble = ExtractNumber<double>; + auto ExtractUi64 = ExtractNumber<ui64>; + class THistogramBuilder { - public: - void Add(TBucketBound bound, TBucketValue value) { - /// XXX: yasm uses left-closed intervals, while in monlib we use right-closed ones, - /// so (-inf; 0) [0, 100) [100; +inf) - /// becomes (-inf; 0] (0, 100] (100; +inf) - /// but since we've already lost some information these no way to avoid this kind of error here - Bounds_.push_back(bound); - - /// this will always be 0 for the first bucket, - /// since there's no way to make (-inf; N) bucket in yasm - Values_.push_back(NextValue_); - - /// we will write this value into the next bucket so that [[0, 10], [100, 20], [200, 50]] - /// becomes (-inf; 0] -> 0; (0; 100] -> 10; (100; 200] -> 20; (200; +inf) -> 50 - NextValue_ = value; - } - + public: + void Add(TBucketBound bound, TBucketValue value) { + /// XXX: yasm uses left-closed intervals, while in monlib we use right-closed ones, + /// so (-inf; 0) [0, 100) [100; +inf) + /// becomes (-inf; 0] (0, 100] (100; +inf) + /// but since we've already lost some information these no way to avoid this kind of error here + Bounds_.push_back(bound); + + /// this will always be 0 for the first bucket, + /// since there's no way to make (-inf; N) bucket in yasm + Values_.push_back(NextValue_); + + /// we will write this value into the next bucket so that [[0, 10], [100, 20], [200, 50]] + /// becomes (-inf; 0] -> 0; (0; 100] -> 10; (100; 200] -> 20; (200; +inf) -> 50 + NextValue_ = value; + } + IHistogramSnapshotPtr Finalize() { - Bounds_.push_back(std::numeric_limits<TBucketBound>::max()); - Values_.push_back(NextValue_); - + Bounds_.push_back(std::numeric_limits<TBucketBound>::max()); + Values_.push_back(NextValue_); + Y_ENSURE(Bounds_.size() <= HISTOGRAM_MAX_BUCKETS_COUNT, "Histogram is only allowed to have " << HISTOGRAM_MAX_BUCKETS_COUNT << " buckets, but has " << Bounds_.size()); - + return ExplicitHistogramSnapshot(Bounds_, Values_); - } - - public: - TBucketValue NextValue_ {0}; - TBucketBounds Bounds_; - TBucketValues Values_; - }; - - class TDecoderUnistat { - private: - public: + } + + public: + TBucketValue NextValue_ {0}; + TBucketBounds Bounds_; + TBucketValues Values_; + }; + + class TDecoderUnistat { + private: + public: explicit TDecoderUnistat(IMetricConsumer* consumer, IInputStream* is, TInstant ts) - : Consumer_{consumer} - , Timestamp_{ts} { - ReadJsonTree(is, &Json_, /* throw */ true); - } - - void Decode() { - Y_ENSURE(Json_.IsArray(), "Expected array at the top level, but found " << Json_.GetType()); - - for (auto&& metric : Json_.GetArray()) { - Y_ENSURE(metric.IsArray(), "Metric must be an array"); - auto&& arr = metric.GetArray(); - Y_ENSURE(arr.size() == 2, "Metric must be an array of 2 elements"); - auto&& name = arr[0]; - auto&& value = arr[1]; - MetricContext_ = {}; - - ParseName(name.GetString()); - - if (value.IsArray()) { - OnHistogram(value); - } else if (IsNumber(value)) { - OnScalar(value); - } else { - ythrow yexception() << "Expected list or number, but found " << value.GetType(); - } - - WriteValue(); - } - } - - private: - void OnScalar(const TJsonValue& jsonValue) { - if (MetricContext_.IsDeriv) { + : Consumer_{consumer} + , Timestamp_{ts} { + ReadJsonTree(is, &Json_, /* throw */ true); + } + + void Decode() { + Y_ENSURE(Json_.IsArray(), "Expected array at the top level, but found " << Json_.GetType()); + + for (auto&& metric : Json_.GetArray()) { + Y_ENSURE(metric.IsArray(), "Metric must be an array"); + auto&& arr = metric.GetArray(); + Y_ENSURE(arr.size() == 2, "Metric must be an array of 2 elements"); + auto&& name = arr[0]; + auto&& value = arr[1]; + MetricContext_ = {}; + + ParseName(name.GetString()); + + if (value.IsArray()) { + OnHistogram(value); + } else if (IsNumber(value)) { + OnScalar(value); + } else { + ythrow yexception() << "Expected list or number, but found " << value.GetType(); + } + + WriteValue(); + } + } + + private: + void OnScalar(const TJsonValue& jsonValue) { + if (MetricContext_.IsDeriv) { MetricContext_.Type = EMetricType::RATE; MetricContext_.Value = TMetricValue{ExtractUi64(jsonValue)}; - } else { + } else { MetricContext_.Type = EMetricType::GAUGE; MetricContext_.Value = TMetricValue{ExtractDouble(jsonValue)}; - } - } - - void OnHistogram(const TJsonValue& jsonHist) { - if (MetricContext_.IsDeriv) { + } + } + + void OnHistogram(const TJsonValue& jsonHist) { + if (MetricContext_.IsDeriv) { MetricContext_.Type = EMetricType::HIST_RATE; - } else { + } else { MetricContext_.Type = EMetricType::HIST; - } - + } + auto histogramBuilder = THistogramBuilder(); - - for (auto&& bucket : jsonHist.GetArray()) { - Y_ENSURE(bucket.IsArray(), "Expected an array, but found " << bucket.GetType()); - auto&& arr = bucket.GetArray(); - Y_ENSURE(arr.size() == 2, "Histogram bucket must be an array of 2 elements"); - const auto bound = ExtractDouble(arr[0]); - const auto weight = ExtractUi64(arr[1]); + + for (auto&& bucket : jsonHist.GetArray()) { + Y_ENSURE(bucket.IsArray(), "Expected an array, but found " << bucket.GetType()); + auto&& arr = bucket.GetArray(); + Y_ENSURE(arr.size() == 2, "Histogram bucket must be an array of 2 elements"); + const auto bound = ExtractDouble(arr[0]); + const auto weight = ExtractUi64(arr[1]); histogramBuilder.Add(bound, weight); - } - + } + MetricContext_.Histogram = histogramBuilder.Finalize(); MetricContext_.Value = TMetricValue{MetricContext_.Histogram.Get()}; - } - - bool IsDeriv(TStringBuf name) { - TStringBuf ignore, suffix; - name.RSplit('_', ignore, suffix); - - Y_ENSURE(suffix.size() >= 3 && suffix.size() <= 5, "Disallowed suffix value: " << suffix); - + } + + bool IsDeriv(TStringBuf name) { + TStringBuf ignore, suffix; + name.RSplit('_', ignore, suffix); + + Y_ENSURE(suffix.size() >= 3 && suffix.size() <= 5, "Disallowed suffix value: " << suffix); + if (suffix == TStringBuf("summ") || suffix == TStringBuf("hgram")) { - return true; + return true; } else if (suffix == TStringBuf("max")) { - return false; - } - - return suffix[0] == 'd'; - } - - void ParseName(TStringBuf value) { - TVector<TStringBuf> parts; - StringSplitter(value).Split(';').SkipEmpty().Collect(&parts); - - Y_ENSURE(parts.size() >= 1 && parts.size() <= 16); - - TStringBuf name = parts.back(); - parts.pop_back(); - + return false; + } + + return suffix[0] == 'd'; + } + + void ParseName(TStringBuf value) { + TVector<TStringBuf> parts; + StringSplitter(value).Split(';').SkipEmpty().Collect(&parts); + + Y_ENSURE(parts.size() >= 1 && parts.size() <= 16); + + TStringBuf name = parts.back(); + parts.pop_back(); + Y_ENSURE(RE2::FullMatch(re2::StringPiece{name.data(), name.size()}, NAME_RE), - "Metric name " << name << " doesn't match regex " << NAME_RE.pattern()); - - MetricContext_.Name = name; - MetricContext_.IsDeriv = IsDeriv(MetricContext_.Name); - - for (auto tag : parts) { - TStringBuf n, v; - tag.Split('=', n, v); - Y_ENSURE(n && v, "Unexpected tag format in " << tag); - MetricContext_.Labels.Add(n, v); - } - } - - private: - void WriteValue() { + "Metric name " << name << " doesn't match regex " << NAME_RE.pattern()); + + MetricContext_.Name = name; + MetricContext_.IsDeriv = IsDeriv(MetricContext_.Name); + + for (auto tag : parts) { + TStringBuf n, v; + tag.Split('=', n, v); + Y_ENSURE(n && v, "Unexpected tag format in " << tag); + MetricContext_.Labels.Add(n, v); + } + } + + private: + void WriteValue() { Consumer_->OnMetricBegin(MetricContext_.Type); - - Consumer_->OnLabelsBegin(); - Consumer_->OnLabel("sensor", TString{MetricContext_.Name}); - for (auto&& l : MetricContext_.Labels) { - Consumer_->OnLabel(l.Name(), l.Value()); - } - - Consumer_->OnLabelsEnd(); - + + Consumer_->OnLabelsBegin(); + Consumer_->OnLabel("sensor", TString{MetricContext_.Name}); + for (auto&& l : MetricContext_.Labels) { + Consumer_->OnLabel(l.Name(), l.Value()); + } + + Consumer_->OnLabelsEnd(); + switch (MetricContext_.Type) { case EMetricType::GAUGE: - Consumer_->OnDouble(Timestamp_, MetricContext_.Value.AsDouble()); - break; + Consumer_->OnDouble(Timestamp_, MetricContext_.Value.AsDouble()); + break; case EMetricType::RATE: - Consumer_->OnUint64(Timestamp_, MetricContext_.Value.AsUint64()); - break; + Consumer_->OnUint64(Timestamp_, MetricContext_.Value.AsUint64()); + break; case EMetricType::HIST: case EMetricType::HIST_RATE: - Consumer_->OnHistogram(Timestamp_, MetricContext_.Value.AsHistogram()); - break; + Consumer_->OnHistogram(Timestamp_, MetricContext_.Value.AsHistogram()); + break; case EMetricType::LOGHIST: case EMetricType::DSUMMARY: case EMetricType::IGAUGE: case EMetricType::COUNTER: case EMetricType::UNKNOWN: ythrow yexception() << "Unexpected metric type: " << MetricContext_.Type; - } - + } + Consumer_->OnMetricEnd(); - } - - private: + } + + private: IMetricConsumer* Consumer_; - NJson::TJsonValue Json_; - TInstant Timestamp_; - - struct { - TStringBuf Name; + NJson::TJsonValue Json_; + TInstant Timestamp_; + + struct { + TStringBuf Name; EMetricType Type{EMetricType::UNKNOWN}; TMetricValue Value; - bool IsDeriv{false}; - TLabels Labels; + bool IsDeriv{false}; + TLabels Labels; IHistogramSnapshotPtr Histogram; - } MetricContext_; - }; - - } - + } MetricContext_; + }; + + } + void DecodeUnistat(TStringBuf data, IMetricConsumer* c, TInstant ts) { - c->OnStreamBegin(); - DecodeUnistatToStream(data, c, ts); - c->OnStreamEnd(); - } - + c->OnStreamBegin(); + DecodeUnistatToStream(data, c, ts); + c->OnStreamEnd(); + } + void DecodeUnistatToStream(TStringBuf data, IMetricConsumer* c, TInstant ts) { TMemoryInput in{data.data(), data.size()}; - TDecoderUnistat decoder(c, &in, ts); - decoder.Decode(); - } -} + TDecoderUnistat decoder(c, &in, ts); + decoder.Decode(); + } +} diff --git a/library/cpp/monlib/encode/unistat/unistat_ut.cpp b/library/cpp/monlib/encode/unistat/unistat_ut.cpp index e55d41eec3..dbbc238bf3 100644 --- a/library/cpp/monlib/encode/unistat/unistat_ut.cpp +++ b/library/cpp/monlib/encode/unistat/unistat_ut.cpp @@ -1,124 +1,124 @@ -#include "unistat.h" - +#include "unistat.h" + #include <library/cpp/monlib/encode/protobuf/protobuf.h> #include <library/cpp/monlib/metrics/labels.h> - + #include <library/cpp/testing/unittest/registar.h> - -using namespace NMonitoring; - -Y_UNIT_TEST_SUITE(TUnistatDecoderTest) { - Y_UNIT_TEST(ScalarMetric) { + +using namespace NMonitoring; + +Y_UNIT_TEST_SUITE(TUnistatDecoderTest) { + Y_UNIT_TEST(ScalarMetric) { constexpr auto input = TStringBuf(R"([["something_axxx", 42]])"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - - DecodeUnistat(input, encoder.Get()); - - UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); - auto sample = samples.GetSamples(0); + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + + DecodeUnistat(input, encoder.Get()); + + UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); + auto sample = samples.GetSamples(0); UNIT_ASSERT_EQUAL(sample.GetMetricType(), NProto::GAUGE); - UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); - UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); - - auto label = sample.GetLabels(0); - auto point = sample.GetPoints(0); - UNIT_ASSERT_VALUES_EQUAL(point.GetFloat64(), 42.); - UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); - UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_axxx"); - } - - Y_UNIT_TEST(OverriddenTags) { + UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); + UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); + + auto label = sample.GetLabels(0); + auto point = sample.GetPoints(0); + UNIT_ASSERT_VALUES_EQUAL(point.GetFloat64(), 42.); + UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); + UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_axxx"); + } + + Y_UNIT_TEST(OverriddenTags) { constexpr auto input = TStringBuf(R"([["ctype=foo;prj=bar;custom_tag=qwe;something_axxx", 42]])"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - - DecodeUnistat(input, encoder.Get()); - - UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); - auto sample = samples.GetSamples(0); - UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + + DecodeUnistat(input, encoder.Get()); + + UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); + auto sample = samples.GetSamples(0); + UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 4); - - const auto& labels = sample.GetLabels(); - TLabels actual; - for (auto&& l : labels) { - actual.Add(l.GetName(), l.GetValue()); - } - + + const auto& labels = sample.GetLabels(); + TLabels actual; + for (auto&& l : labels) { + actual.Add(l.GetName(), l.GetValue()); + } + TLabels expected{{"ctype", "foo"}, {"prj", "bar"}, {"custom_tag", "qwe"}, {"sensor", "something_axxx"}}; - - UNIT_ASSERT_VALUES_EQUAL(actual.size(), expected.size()); - for (auto&& l : actual) { - UNIT_ASSERT(expected.Extract(l.Name())->Value() == l.Value()); - } - } - - Y_UNIT_TEST(ThrowsOnTopLevelObject) { + + UNIT_ASSERT_VALUES_EQUAL(actual.size(), expected.size()); + for (auto&& l : actual) { + UNIT_ASSERT(expected.Extract(l.Name())->Value() == l.Value()); + } + } + + Y_UNIT_TEST(ThrowsOnTopLevelObject) { constexpr auto input = TStringBuf(R"({["something_axxx", 42]})"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - - UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); - } - - Y_UNIT_TEST(ThrowsOnUnwrappedMetric) { + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + + UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); + } + + Y_UNIT_TEST(ThrowsOnUnwrappedMetric) { constexpr auto input = TStringBuf(R"(["something_axxx", 42])"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - - UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); - } - - Y_UNIT_TEST(HistogramMetric) { + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + + UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); + } + + Y_UNIT_TEST(HistogramMetric) { constexpr auto input = TStringBuf(R"([["something_hgram", [[0, 1], [200, 2], [500, 3]] ]])"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - - DecodeUnistat(input, encoder.Get()); - - auto sample = samples.GetSamples(0); + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + + DecodeUnistat(input, encoder.Get()); + + auto sample = samples.GetSamples(0); UNIT_ASSERT_EQUAL(sample.GetMetricType(), NProto::HIST_RATE); - UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); - UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); - - auto label = sample.GetLabels(0); - const auto point = sample.GetPoints(0); - const auto histogram = point.GetHistogram(); - const auto size = histogram.BoundsSize(); - UNIT_ASSERT_VALUES_EQUAL(size, 4); - - const TVector<double> expectedBounds {0, 200, 500, std::numeric_limits<double>::max()}; - const TVector<ui64> expectedValues {0, 1, 2, 3}; - - for (auto i = 0; i < 4; ++i) { - UNIT_ASSERT_VALUES_EQUAL(histogram.GetBounds(i), expectedBounds[i]); - UNIT_ASSERT_VALUES_EQUAL(histogram.GetValues(i), expectedValues[i]); - } - - UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); - UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_hgram"); - } - - Y_UNIT_TEST(AbsoluteHistogram) { + UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); + UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); + + auto label = sample.GetLabels(0); + const auto point = sample.GetPoints(0); + const auto histogram = point.GetHistogram(); + const auto size = histogram.BoundsSize(); + UNIT_ASSERT_VALUES_EQUAL(size, 4); + + const TVector<double> expectedBounds {0, 200, 500, std::numeric_limits<double>::max()}; + const TVector<ui64> expectedValues {0, 1, 2, 3}; + + for (auto i = 0; i < 4; ++i) { + UNIT_ASSERT_VALUES_EQUAL(histogram.GetBounds(i), expectedBounds[i]); + UNIT_ASSERT_VALUES_EQUAL(histogram.GetValues(i), expectedValues[i]); + } + + UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); + UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_hgram"); + } + + Y_UNIT_TEST(AbsoluteHistogram) { constexpr auto input = TStringBuf(R"([["something_ahhh", [[0, 1], [200, 2], [500, 3]] ]])"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - - DecodeUnistat(input, encoder.Get()); - - auto sample = samples.GetSamples(0); + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + + DecodeUnistat(input, encoder.Get()); + + auto sample = samples.GetSamples(0); UNIT_ASSERT_EQUAL(sample.GetMetricType(), NProto::HISTOGRAM); - UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); - UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); - } - + UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); + UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); + } + Y_UNIT_TEST(AllowedMetricNames) { NProto::TMultiSamplesList samples; auto encoder = EncoderProtobuf(&samples); @@ -129,95 +129,95 @@ Y_UNIT_TEST_SUITE(TUnistatDecoderTest) { } } - Y_UNIT_TEST(DisallowedMetricNames) { - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - - { + Y_UNIT_TEST(DisallowedMetricNames) { + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + + { constexpr auto input = TStringBuf(R"([["someth!ng_ahhh", [[0, 1], [200, 2], [500, 3]] ]])"); - UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); - } - - { + UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); + } + + { constexpr auto input = TStringBuf(R"([["foo_a", [[0, 1], [200, 2], [500, 3]] ]])"); - UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); - } - - { + UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); + } + + { constexpr auto input = TStringBuf(R"([["foo_ahhh;tag=value", [[0, 1], [200, 2], [500, 3]] ]])"); - UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); - } - } - - Y_UNIT_TEST(MultipleMetrics) { + UNIT_ASSERT_EXCEPTION(DecodeUnistat(input, encoder.Get()), yexception); + } + } + + Y_UNIT_TEST(MultipleMetrics) { constexpr auto input = TStringBuf(R"([["something_axxx", 42], ["some-other_dhhh", 53]])"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - - DecodeUnistat(input, encoder.Get()); - - UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 2); - auto sample = samples.GetSamples(0); + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + + DecodeUnistat(input, encoder.Get()); + + UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 2); + auto sample = samples.GetSamples(0); UNIT_ASSERT_EQUAL(sample.GetMetricType(), NProto::GAUGE); - UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); - UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); - - auto label = sample.GetLabels(0); - auto point = sample.GetPoints(0); - UNIT_ASSERT_VALUES_EQUAL(point.GetFloat64(), 42.); - UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); - UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_axxx"); - - sample = samples.GetSamples(1); + UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); + UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); + + auto label = sample.GetLabels(0); + auto point = sample.GetPoints(0); + UNIT_ASSERT_VALUES_EQUAL(point.GetFloat64(), 42.); + UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); + UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_axxx"); + + sample = samples.GetSamples(1); UNIT_ASSERT_EQUAL(sample.GetMetricType(), NProto::RATE); - UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); - UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); - - label = sample.GetLabels(0); - point = sample.GetPoints(0); - UNIT_ASSERT_VALUES_EQUAL(point.GetUint64(), 53); - UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); - UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "some-other_dhhh"); - } - - Y_UNIT_TEST(UnderscoreName) { + UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); + UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); + + label = sample.GetLabels(0); + point = sample.GetPoints(0); + UNIT_ASSERT_VALUES_EQUAL(point.GetUint64(), 53); + UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); + UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "some-other_dhhh"); + } + + Y_UNIT_TEST(UnderscoreName) { constexpr auto input = TStringBuf(R"([["something_anything_dmmm", 42]])"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - DecodeUnistat(input, encoder.Get()); - - UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); - auto sample = samples.GetSamples(0); + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + DecodeUnistat(input, encoder.Get()); + + UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); + auto sample = samples.GetSamples(0); UNIT_ASSERT_EQUAL(sample.GetMetricType(), NProto::RATE); - UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); - UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); - - auto label = sample.GetLabels(0); - auto point = sample.GetPoints(0); - UNIT_ASSERT_VALUES_EQUAL(point.GetUint64(), 42); - UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); - UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_anything_dmmm"); - } - - Y_UNIT_TEST(MaxAggr) { + UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); + UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); + + auto label = sample.GetLabels(0); + auto point = sample.GetPoints(0); + UNIT_ASSERT_VALUES_EQUAL(point.GetUint64(), 42); + UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); + UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_anything_dmmm"); + } + + Y_UNIT_TEST(MaxAggr) { constexpr auto input = TStringBuf(R"([["something_anything_max", 42]])"); - - NProto::TMultiSamplesList samples; - auto encoder = EncoderProtobuf(&samples); - DecodeUnistat(input, encoder.Get()); - - UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); - auto sample = samples.GetSamples(0); + + NProto::TMultiSamplesList samples; + auto encoder = EncoderProtobuf(&samples); + DecodeUnistat(input, encoder.Get()); + + UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1); + auto sample = samples.GetSamples(0); UNIT_ASSERT_EQUAL(sample.GetMetricType(), NProto::GAUGE); - UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); - UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); - - auto label = sample.GetLabels(0); - auto point = sample.GetPoints(0); - UNIT_ASSERT_VALUES_EQUAL(point.GetFloat64(), 42.); - UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); - UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_anything_max"); - } -} + UNIT_ASSERT_VALUES_EQUAL(sample.PointsSize(), 1); + UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1); + + auto label = sample.GetLabels(0); + auto point = sample.GetPoints(0); + UNIT_ASSERT_VALUES_EQUAL(point.GetFloat64(), 42.); + UNIT_ASSERT_VALUES_EQUAL(label.GetName(), "sensor"); + UNIT_ASSERT_VALUES_EQUAL(label.GetValue(), "something_anything_max"); + } +} diff --git a/library/cpp/monlib/encode/unistat/ut/ya.make b/library/cpp/monlib/encode/unistat/ut/ya.make index 4beba98863..a652139f45 100644 --- a/library/cpp/monlib/encode/unistat/ut/ya.make +++ b/library/cpp/monlib/encode/unistat/ut/ya.make @@ -1,16 +1,16 @@ UNITTEST_FOR(library/cpp/monlib/encode/unistat) - -OWNER( - msherbakov - g:solomon -) - -SRCS( - unistat_ut.cpp -) - -PEERDIR( + +OWNER( + msherbakov + g:solomon +) + +SRCS( + unistat_ut.cpp +) + +PEERDIR( library/cpp/monlib/encode/protobuf -) - -END() +) + +END() diff --git a/library/cpp/monlib/encode/unistat/ya.make b/library/cpp/monlib/encode/unistat/ya.make index c6ec66ca40..4ac2edadf4 100644 --- a/library/cpp/monlib/encode/unistat/ya.make +++ b/library/cpp/monlib/encode/unistat/ya.make @@ -1,18 +1,18 @@ -LIBRARY() - -OWNER( - msherbakov - g:solomon -) - -PEERDIR( - contrib/libs/re2 +LIBRARY() + +OWNER( + msherbakov + g:solomon +) + +PEERDIR( + contrib/libs/re2 library/cpp/json library/cpp/monlib/metrics -) - -SRCS( - unistat_decoder.cpp -) - -END() +) + +SRCS( + unistat_decoder.cpp +) + +END() |