diff options
author | ivanzhukov <ivanzhukov@yandex-team.ru> | 2022-02-10 16:49:40 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:49:40 +0300 |
commit | 0892d79ab411592ad25175c4bdadbcb09b466cf5 (patch) | |
tree | 98dfdd45463c9bd747101748a9ca25d2917390fd /library/cpp/monlib/encode/json | |
parent | 1b7466cb957659079ebebbb5d76e64e51f3306f0 (diff) | |
download | ydb-0892d79ab411592ad25175c4bdadbcb09b466cf5.tar.gz |
Restoring authorship annotation for <ivanzhukov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/monlib/encode/json')
-rw-r--r-- | library/cpp/monlib/encode/json/json.h | 10 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/json_decoder.cpp | 2142 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/json_decoder_ut.cpp | 228 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/json_encoder.cpp | 40 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/json_ut.cpp | 44 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/typed_point.h | 4 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/ut/buffered_ts_merge.json | 2 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/ut/histogram_value_inf_before_bounds.json | 64 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/ut/test_decode_to_encode.json | 30 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/ut/ya.make | 8 | ||||
-rw-r--r-- | library/cpp/monlib/encode/json/ya.make | 6 |
11 files changed, 1289 insertions, 1289 deletions
diff --git a/library/cpp/monlib/encode/json/json.h b/library/cpp/monlib/encode/json/json.h index 21530f20c3..b76900b8ab 100644 --- a/library/cpp/monlib/encode/json/json.h +++ b/library/cpp/monlib/encode/json/json.h @@ -3,14 +3,14 @@ #include <library/cpp/monlib/encode/encoder.h> #include <library/cpp/monlib/encode/format.h> - + class IOutputStream; namespace NMonitoring { - - class TJsonDecodeError: public yexception { - }; - + + class TJsonDecodeError: public yexception { + }; + IMetricEncoderPtr EncoderJson(IOutputStream* out, int indentation = 0); /// Buffered encoder will merge series with same labels into one. diff --git a/library/cpp/monlib/encode/json/json_decoder.cpp b/library/cpp/monlib/encode/json/json_decoder.cpp index d44ff5fd28..7f0d83e018 100644 --- a/library/cpp/monlib/encode/json/json_decoder.cpp +++ b/library/cpp/monlib/encode/json/json_decoder.cpp @@ -1,8 +1,8 @@ #include "json.h" #include "typed_point.h" - -#include <library/cpp/monlib/exception/exception.h> + +#include <library/cpp/monlib/exception/exception.h> #include <library/cpp/monlib/metrics/labels.h> #include <library/cpp/monlib/metrics/metric_value.h> @@ -14,1149 +14,1149 @@ #include <limits> namespace NMonitoring { - -#define DECODE_ENSURE(COND, ...) MONLIB_ENSURE_EX(COND, TJsonDecodeError() << __VA_ARGS__) - -namespace { - -/////////////////////////////////////////////////////////////////////// -// THistogramBuilder -/////////////////////////////////////////////////////////////////////// -class THistogramBuilder { -public: - void AddBound(TBucketBound bound) { - if (!Bounds_.empty()) { - DECODE_ENSURE(Bounds_.back() < bound, - "non sorted bounds, " << Bounds_.back() << - " >= " << bound); - } - Bounds_.push_back(bound); - } - - void AddValue(TBucketValue value) { - Values_.push_back(value); - } - - void AddInf(TBucketValue value) { - InfPresented_ = true; - InfValue_ = value; - } - - IHistogramSnapshotPtr Build() { - if (InfPresented_) { - Bounds_.push_back(Max<TBucketBound>()); - Values_.push_back(InfValue_); - } - - auto snapshot = ExplicitHistogramSnapshot(Bounds_, Values_); - - Bounds_.clear(); - Values_.clear(); + +#define DECODE_ENSURE(COND, ...) MONLIB_ENSURE_EX(COND, TJsonDecodeError() << __VA_ARGS__) + +namespace { + +/////////////////////////////////////////////////////////////////////// +// THistogramBuilder +/////////////////////////////////////////////////////////////////////// +class THistogramBuilder { +public: + void AddBound(TBucketBound bound) { + if (!Bounds_.empty()) { + DECODE_ENSURE(Bounds_.back() < bound, + "non sorted bounds, " << Bounds_.back() << + " >= " << bound); + } + Bounds_.push_back(bound); + } + + void AddValue(TBucketValue value) { + Values_.push_back(value); + } + + void AddInf(TBucketValue value) { + InfPresented_ = true; + InfValue_ = value; + } + + IHistogramSnapshotPtr Build() { + if (InfPresented_) { + Bounds_.push_back(Max<TBucketBound>()); + Values_.push_back(InfValue_); + } + + auto snapshot = ExplicitHistogramSnapshot(Bounds_, Values_); + + Bounds_.clear(); + Values_.clear(); InfPresented_ = false; - return snapshot; - } - - bool Empty() const noexcept { - return Bounds_.empty() && Values_.empty(); - } - - void Clear() { - Bounds_.clear(); - Values_.clear(); - } - -private: - TBucketBounds Bounds_; - TBucketValues Values_; - - bool InfPresented_ = false; - TBucketValue InfValue_; -}; - -class TSummaryDoubleBuilder { -public: - ISummaryDoubleSnapshotPtr Build() const { - return MakeIntrusive<TSummaryDoubleSnapshot>(Sum_, Min_, Max_, Last_, Count_); - } - - void SetSum(double sum) { - Empty_ = false; - Sum_ = sum; - } - - void SetMin(double min) { - Empty_ = false; - Min_ = min; - } - - void SetMax(double max) { - Empty_ = false; - Max_ = max; - } - - void SetLast(double last) { - Empty_ = false; - Last_ = last; - } - - void SetCount(ui64 count) { - Empty_ = false; - Count_ = count; - } - - void Clear() { - Empty_ = true; - Sum_ = 0; - Min_ = 0; - Max_ = 0; - Last_ = 0; - Count_ = 0; - } - - bool Empty() const { - return Empty_; - } - -private: - double Sum_ = 0; - double Min_ = 0; - double Max_ = 0; - double Last_ = 0; - ui64 Count_ = 0; - bool Empty_ = true; -}; - -class TLogHistogramBuilder { -public: - void SetBase(double base) { - DECODE_ENSURE(base > 0, "base must be positive"); - Base_ = base; - } - - void SetZerosCount(ui64 zerosCount) { - DECODE_ENSURE(zerosCount >= 0, "zeros count must be positive"); - ZerosCount_ = zerosCount; - } - - void SetStartPower(int startPower) { - StartPower_ = startPower; - } - - void AddBucketValue(double value) { - DECODE_ENSURE(value > 0.0, "bucket values must be positive"); - DECODE_ENSURE(value < std::numeric_limits<double>::max(), "bucket values must be finite"); - Buckets_.push_back(value); - } - - void Clear() { - Buckets_.clear(); - Base_ = 1.5; - ZerosCount_ = 0; - StartPower_ = 0; - } - - bool Empty() const { - return Buckets_.empty() && ZerosCount_ == 0; - } - - TLogHistogramSnapshotPtr Build() { - return MakeIntrusive<TLogHistogramSnapshot>(Base_, ZerosCount_, StartPower_, std::move(Buckets_)); - } - -private: - double Base_ = 1.5; - ui64 ZerosCount_ = 0; - int StartPower_ = 0; - TVector<double> Buckets_; -}; - -std::pair<double, bool> ParseSpecDouble(TStringBuf string) { + return snapshot; + } + + bool Empty() const noexcept { + return Bounds_.empty() && Values_.empty(); + } + + void Clear() { + Bounds_.clear(); + Values_.clear(); + } + +private: + TBucketBounds Bounds_; + TBucketValues Values_; + + bool InfPresented_ = false; + TBucketValue InfValue_; +}; + +class TSummaryDoubleBuilder { +public: + ISummaryDoubleSnapshotPtr Build() const { + return MakeIntrusive<TSummaryDoubleSnapshot>(Sum_, Min_, Max_, Last_, Count_); + } + + void SetSum(double sum) { + Empty_ = false; + Sum_ = sum; + } + + void SetMin(double min) { + Empty_ = false; + Min_ = min; + } + + void SetMax(double max) { + Empty_ = false; + Max_ = max; + } + + void SetLast(double last) { + Empty_ = false; + Last_ = last; + } + + void SetCount(ui64 count) { + Empty_ = false; + Count_ = count; + } + + void Clear() { + Empty_ = true; + Sum_ = 0; + Min_ = 0; + Max_ = 0; + Last_ = 0; + Count_ = 0; + } + + bool Empty() const { + return Empty_; + } + +private: + double Sum_ = 0; + double Min_ = 0; + double Max_ = 0; + double Last_ = 0; + ui64 Count_ = 0; + bool Empty_ = true; +}; + +class TLogHistogramBuilder { +public: + void SetBase(double base) { + DECODE_ENSURE(base > 0, "base must be positive"); + Base_ = base; + } + + void SetZerosCount(ui64 zerosCount) { + DECODE_ENSURE(zerosCount >= 0, "zeros count must be positive"); + ZerosCount_ = zerosCount; + } + + void SetStartPower(int startPower) { + StartPower_ = startPower; + } + + void AddBucketValue(double value) { + DECODE_ENSURE(value > 0.0, "bucket values must be positive"); + DECODE_ENSURE(value < std::numeric_limits<double>::max(), "bucket values must be finite"); + Buckets_.push_back(value); + } + + void Clear() { + Buckets_.clear(); + Base_ = 1.5; + ZerosCount_ = 0; + StartPower_ = 0; + } + + bool Empty() const { + return Buckets_.empty() && ZerosCount_ == 0; + } + + TLogHistogramSnapshotPtr Build() { + return MakeIntrusive<TLogHistogramSnapshot>(Base_, ZerosCount_, StartPower_, std::move(Buckets_)); + } + +private: + double Base_ = 1.5; + ui64 ZerosCount_ = 0; + int StartPower_ = 0; + TVector<double> Buckets_; +}; + +std::pair<double, bool> ParseSpecDouble(TStringBuf string) { if (string == TStringBuf("nan") || string == TStringBuf("NaN")) { - return {std::numeric_limits<double>::quiet_NaN(), true}; + return {std::numeric_limits<double>::quiet_NaN(), true}; } else if (string == TStringBuf("inf") || string == TStringBuf("Infinity")) { - return {std::numeric_limits<double>::infinity(), true}; + return {std::numeric_limits<double>::infinity(), true}; } else if (string == TStringBuf("-inf") || string == TStringBuf("-Infinity")) { - return {-std::numeric_limits<double>::infinity(), true}; - } else { - return {0, false}; - } -} - -/////////////////////////////////////////////////////////////////////// -// TMetricCollector -/////////////////////////////////////////////////////////////////////// -struct TMetricCollector { - EMetricType Type = EMetricType::UNKNOWN; - TLabels Labels; - THistogramBuilder HistogramBuilder; - TSummaryDoubleBuilder SummaryBuilder; - TLogHistogramBuilder LogHistBuilder; - TTypedPoint LastPoint; - TVector<TTypedPoint> TimeSeries; - - bool SeenTsOrValue = false; - bool SeenTimeseries = false; - - void Clear() { - Type = EMetricType::UNKNOWN; - Labels.Clear(); - SeenTsOrValue = false; - SeenTimeseries = false; - TimeSeries.clear(); - LastPoint = {}; - HistogramBuilder.Clear(); - SummaryBuilder.Clear(); - LogHistBuilder.Clear(); - } - - void AddLabel(const TLabel& label) { - Labels.Add(label.Name(), label.Value()); - } - - void SetLastTime(TInstant time) { - LastPoint.SetTime(time); - } - - template <typename T> - void SetLastValue(T value) { - LastPoint.SetValue(value); - } - - void SaveLastPoint() { - DECODE_ENSURE(LastPoint.GetTime() != TInstant::Zero(), - "cannot add point without or zero timestamp"); - if (!HistogramBuilder.Empty()) { - auto histogram = HistogramBuilder.Build(); - TimeSeries.emplace_back(LastPoint.GetTime(), histogram.Get()); - } else if (!SummaryBuilder.Empty()) { - auto summary = SummaryBuilder.Build(); - TimeSeries.emplace_back(LastPoint.GetTime(), summary.Get()); - } else if (!LogHistBuilder.Empty()) { - auto logHist = LogHistBuilder.Build(); - TimeSeries.emplace_back(LastPoint.GetTime(), logHist.Get()); - } else { - TimeSeries.push_back(std::move(LastPoint)); - } - } - - template <typename TConsumer> - void Consume(TConsumer&& consumer) { - if (TimeSeries.empty()) { - const auto& p = LastPoint; - consumer(p.GetTime(), p.GetValueType(), p.GetValue()); - } else { - for (const auto& p: TimeSeries) { - consumer(p.GetTime(), p.GetValueType(), p.GetValue()); + return {-std::numeric_limits<double>::infinity(), true}; + } else { + return {0, false}; + } +} + +/////////////////////////////////////////////////////////////////////// +// TMetricCollector +/////////////////////////////////////////////////////////////////////// +struct TMetricCollector { + EMetricType Type = EMetricType::UNKNOWN; + TLabels Labels; + THistogramBuilder HistogramBuilder; + TSummaryDoubleBuilder SummaryBuilder; + TLogHistogramBuilder LogHistBuilder; + TTypedPoint LastPoint; + TVector<TTypedPoint> TimeSeries; + + bool SeenTsOrValue = false; + bool SeenTimeseries = false; + + void Clear() { + Type = EMetricType::UNKNOWN; + Labels.Clear(); + SeenTsOrValue = false; + SeenTimeseries = false; + TimeSeries.clear(); + LastPoint = {}; + HistogramBuilder.Clear(); + SummaryBuilder.Clear(); + LogHistBuilder.Clear(); + } + + void AddLabel(const TLabel& label) { + Labels.Add(label.Name(), label.Value()); + } + + void SetLastTime(TInstant time) { + LastPoint.SetTime(time); + } + + template <typename T> + void SetLastValue(T value) { + LastPoint.SetValue(value); + } + + void SaveLastPoint() { + DECODE_ENSURE(LastPoint.GetTime() != TInstant::Zero(), + "cannot add point without or zero timestamp"); + if (!HistogramBuilder.Empty()) { + auto histogram = HistogramBuilder.Build(); + TimeSeries.emplace_back(LastPoint.GetTime(), histogram.Get()); + } else if (!SummaryBuilder.Empty()) { + auto summary = SummaryBuilder.Build(); + TimeSeries.emplace_back(LastPoint.GetTime(), summary.Get()); + } else if (!LogHistBuilder.Empty()) { + auto logHist = LogHistBuilder.Build(); + TimeSeries.emplace_back(LastPoint.GetTime(), logHist.Get()); + } else { + TimeSeries.push_back(std::move(LastPoint)); + } + } + + template <typename TConsumer> + void Consume(TConsumer&& consumer) { + if (TimeSeries.empty()) { + const auto& p = LastPoint; + consumer(p.GetTime(), p.GetValueType(), p.GetValue()); + } else { + for (const auto& p: TimeSeries) { + consumer(p.GetTime(), p.GetValueType(), p.GetValue()); } - } - } -}; - -struct TCommonParts { - TInstant CommonTime; - TLabels CommonLabels; -}; - -class IHaltableMetricConsumer: public IMetricConsumer { -public: - virtual bool NeedToStop() const = 0; -}; - -// TODO(ivanzhukov@): check all states for cases when a json document is invalid -// e.g. "metrics" or "commonLabels" keys are specified multiple times -class TCommonPartsCollector: public IHaltableMetricConsumer { -public: - TCommonParts&& CommonParts() { - return std::move(CommonParts_); - } - -private: - bool NeedToStop() const override { - return TInstant::Zero() != CommonParts_.CommonTime && !CommonParts_.CommonLabels.Empty(); - } - - void OnStreamBegin() override { - } - - void OnStreamEnd() override { - } - - void OnCommonTime(TInstant time) override { - CommonParts_.CommonTime = time; - } - - void OnMetricBegin(EMetricType) override { - IsMetric_ = true; - } - - void OnMetricEnd() override { - IsMetric_ = false; - } - - void OnLabelsBegin() override { - } - - void OnLabelsEnd() override { - } - - void OnLabel(TStringBuf name, TStringBuf value) override { - if (!IsMetric_) { - CommonParts_.CommonLabels.Add(std::move(name), std::move(value)); - } - } - - void OnDouble(TInstant, double) override { - } - - void OnInt64(TInstant, i64) override { - } - - void OnUint64(TInstant, ui64) override { - } - - void OnHistogram(TInstant, IHistogramSnapshotPtr) override { - } - - void OnLogHistogram(TInstant, TLogHistogramSnapshotPtr) override { - } - - void OnSummaryDouble(TInstant, ISummaryDoubleSnapshotPtr) override { - } - -private: - TCommonParts CommonParts_; - bool IsMetric_{false}; -}; - -class TCommonPartsProxy: public IHaltableMetricConsumer { -public: - TCommonPartsProxy(TCommonParts&& commonParts, IMetricConsumer* c) - : CommonParts_{std::move(commonParts)} - , Consumer_{c} - {} - -private: - bool NeedToStop() const override { - return false; - } - - void OnStreamBegin() override { - Consumer_->OnStreamBegin(); - - if (!CommonParts_.CommonLabels.Empty()) { - Consumer_->OnLabelsBegin(); - - for (auto&& label : CommonParts_.CommonLabels) { - Consumer_->OnLabel(label.Name(), label.Value()); - } - - Consumer_->OnLabelsEnd(); - } - - if (TInstant::Zero() != CommonParts_.CommonTime) { - Consumer_->OnCommonTime(CommonParts_.CommonTime); - } - } - - void OnStreamEnd() override { - Consumer_->OnStreamEnd(); - } - - void OnCommonTime(TInstant) override { - } - - void OnMetricBegin(EMetricType type) override { - IsMetric_ = true; - - Consumer_->OnMetricBegin(type); - } - - void OnMetricEnd() override { - IsMetric_ = false; - - Consumer_->OnMetricEnd(); - } - - void OnLabelsBegin() override { - if (IsMetric_) { - Consumer_->OnLabelsBegin(); - } - } - - void OnLabelsEnd() override { - if (IsMetric_) { - Consumer_->OnLabelsEnd(); - } - } - - void OnLabel(TStringBuf name, TStringBuf value) override { - if (IsMetric_) { - Consumer_->OnLabel(std::move(name), std::move(value)); - } - } - - void OnDouble(TInstant time, double value) override { - Consumer_->OnDouble(time, value); - } - - void OnInt64(TInstant time, i64 value) override { - Consumer_->OnInt64(time, value); - } - - void OnUint64(TInstant time, ui64 value) override { - Consumer_->OnUint64(time, value); - } - - void OnHistogram(TInstant time, IHistogramSnapshotPtr snapshot) override { - Consumer_->OnHistogram(time, std::move(snapshot)); - } - - void OnLogHistogram(TInstant time, TLogHistogramSnapshotPtr snapshot) override { - Consumer_->OnLogHistogram(time, std::move(snapshot)); - } - - void OnSummaryDouble(TInstant time, ISummaryDoubleSnapshotPtr snapshot) override { - Consumer_->OnSummaryDouble(time, std::move(snapshot)); - } - -private: - const TCommonParts CommonParts_; - IMetricConsumer* Consumer_; - bool IsMetric_{false}; -}; - -/////////////////////////////////////////////////////////////////////// -// TDecoderJson -/////////////////////////////////////////////////////////////////////// -class TDecoderJson final: public NJson::TJsonCallbacks { - struct TState { - enum EState { - ROOT_OBJECT = 0x01, - - COMMON_LABELS, - COMMON_TS, - METRICS_ARRAY, - - METRIC_OBJECT, + } + } +}; + +struct TCommonParts { + TInstant CommonTime; + TLabels CommonLabels; +}; + +class IHaltableMetricConsumer: public IMetricConsumer { +public: + virtual bool NeedToStop() const = 0; +}; + +// TODO(ivanzhukov@): check all states for cases when a json document is invalid +// e.g. "metrics" or "commonLabels" keys are specified multiple times +class TCommonPartsCollector: public IHaltableMetricConsumer { +public: + TCommonParts&& CommonParts() { + return std::move(CommonParts_); + } + +private: + bool NeedToStop() const override { + return TInstant::Zero() != CommonParts_.CommonTime && !CommonParts_.CommonLabels.Empty(); + } + + void OnStreamBegin() override { + } + + void OnStreamEnd() override { + } + + void OnCommonTime(TInstant time) override { + CommonParts_.CommonTime = time; + } + + void OnMetricBegin(EMetricType) override { + IsMetric_ = true; + } + + void OnMetricEnd() override { + IsMetric_ = false; + } + + void OnLabelsBegin() override { + } + + void OnLabelsEnd() override { + } + + void OnLabel(TStringBuf name, TStringBuf value) override { + if (!IsMetric_) { + CommonParts_.CommonLabels.Add(std::move(name), std::move(value)); + } + } + + void OnDouble(TInstant, double) override { + } + + void OnInt64(TInstant, i64) override { + } + + void OnUint64(TInstant, ui64) override { + } + + void OnHistogram(TInstant, IHistogramSnapshotPtr) override { + } + + void OnLogHistogram(TInstant, TLogHistogramSnapshotPtr) override { + } + + void OnSummaryDouble(TInstant, ISummaryDoubleSnapshotPtr) override { + } + +private: + TCommonParts CommonParts_; + bool IsMetric_{false}; +}; + +class TCommonPartsProxy: public IHaltableMetricConsumer { +public: + TCommonPartsProxy(TCommonParts&& commonParts, IMetricConsumer* c) + : CommonParts_{std::move(commonParts)} + , Consumer_{c} + {} + +private: + bool NeedToStop() const override { + return false; + } + + void OnStreamBegin() override { + Consumer_->OnStreamBegin(); + + if (!CommonParts_.CommonLabels.Empty()) { + Consumer_->OnLabelsBegin(); + + for (auto&& label : CommonParts_.CommonLabels) { + Consumer_->OnLabel(label.Name(), label.Value()); + } + + Consumer_->OnLabelsEnd(); + } + + if (TInstant::Zero() != CommonParts_.CommonTime) { + Consumer_->OnCommonTime(CommonParts_.CommonTime); + } + } + + void OnStreamEnd() override { + Consumer_->OnStreamEnd(); + } + + void OnCommonTime(TInstant) override { + } + + void OnMetricBegin(EMetricType type) override { + IsMetric_ = true; + + Consumer_->OnMetricBegin(type); + } + + void OnMetricEnd() override { + IsMetric_ = false; + + Consumer_->OnMetricEnd(); + } + + void OnLabelsBegin() override { + if (IsMetric_) { + Consumer_->OnLabelsBegin(); + } + } + + void OnLabelsEnd() override { + if (IsMetric_) { + Consumer_->OnLabelsEnd(); + } + } + + void OnLabel(TStringBuf name, TStringBuf value) override { + if (IsMetric_) { + Consumer_->OnLabel(std::move(name), std::move(value)); + } + } + + void OnDouble(TInstant time, double value) override { + Consumer_->OnDouble(time, value); + } + + void OnInt64(TInstant time, i64 value) override { + Consumer_->OnInt64(time, value); + } + + void OnUint64(TInstant time, ui64 value) override { + Consumer_->OnUint64(time, value); + } + + void OnHistogram(TInstant time, IHistogramSnapshotPtr snapshot) override { + Consumer_->OnHistogram(time, std::move(snapshot)); + } + + void OnLogHistogram(TInstant time, TLogHistogramSnapshotPtr snapshot) override { + Consumer_->OnLogHistogram(time, std::move(snapshot)); + } + + void OnSummaryDouble(TInstant time, ISummaryDoubleSnapshotPtr snapshot) override { + Consumer_->OnSummaryDouble(time, std::move(snapshot)); + } + +private: + const TCommonParts CommonParts_; + IMetricConsumer* Consumer_; + bool IsMetric_{false}; +}; + +/////////////////////////////////////////////////////////////////////// +// TDecoderJson +/////////////////////////////////////////////////////////////////////// +class TDecoderJson final: public NJson::TJsonCallbacks { + struct TState { + enum EState { + ROOT_OBJECT = 0x01, + + COMMON_LABELS, + COMMON_TS, + METRICS_ARRAY, + + METRIC_OBJECT, METRIC_NAME, - METRIC_LABELS, - METRIC_TYPE, - METRIC_MODE, // TODO: must be deleted - METRIC_TIMESERIES, - METRIC_TS, - METRIC_VALUE, - METRIC_HIST, - METRIC_HIST_BOUNDS, - METRIC_HIST_BUCKETS, - METRIC_HIST_INF, - METRIC_DSUMMARY, - METRIC_DSUMMARY_SUM, - METRIC_DSUMMARY_MIN, - METRIC_DSUMMARY_MAX, - METRIC_DSUMMARY_LAST, - METRIC_DSUMMARY_COUNT, - METRIC_LOG_HIST, - METRIC_LOG_HIST_BASE, - METRIC_LOG_HIST_ZEROS, - METRIC_LOG_HIST_START_POWER, - METRIC_LOG_HIST_BUCKETS, - }; - - constexpr EState Current() const noexcept { - return static_cast<EState>(State_ & 0xFF); - } - - void ToNext(EState state) noexcept { - constexpr auto bitSize = 8 * sizeof(ui8); - State_ = (State_ << bitSize) | static_cast<ui8>(state); - } - - void ToPrev() noexcept { - constexpr auto bitSize = 8 * sizeof(ui8); - State_ = State_ >> bitSize; - } - - private: - ui64 State_ = static_cast<ui64>(ROOT_OBJECT); - }; - -public: + METRIC_LABELS, + METRIC_TYPE, + METRIC_MODE, // TODO: must be deleted + METRIC_TIMESERIES, + METRIC_TS, + METRIC_VALUE, + METRIC_HIST, + METRIC_HIST_BOUNDS, + METRIC_HIST_BUCKETS, + METRIC_HIST_INF, + METRIC_DSUMMARY, + METRIC_DSUMMARY_SUM, + METRIC_DSUMMARY_MIN, + METRIC_DSUMMARY_MAX, + METRIC_DSUMMARY_LAST, + METRIC_DSUMMARY_COUNT, + METRIC_LOG_HIST, + METRIC_LOG_HIST_BASE, + METRIC_LOG_HIST_ZEROS, + METRIC_LOG_HIST_START_POWER, + METRIC_LOG_HIST_BUCKETS, + }; + + constexpr EState Current() const noexcept { + return static_cast<EState>(State_ & 0xFF); + } + + void ToNext(EState state) noexcept { + constexpr auto bitSize = 8 * sizeof(ui8); + State_ = (State_ << bitSize) | static_cast<ui8>(state); + } + + void ToPrev() noexcept { + constexpr auto bitSize = 8 * sizeof(ui8); + State_ = State_ >> bitSize; + } + + private: + ui64 State_ = static_cast<ui64>(ROOT_OBJECT); + }; + +public: TDecoderJson(TStringBuf data, IHaltableMetricConsumer* metricConsumer, TStringBuf metricNameLabel) - : Data_(data) - , MetricConsumer_(metricConsumer) + : Data_(data) + , MetricConsumer_(metricConsumer) , MetricNameLabel_(metricNameLabel) - { - } - -private: -#define PARSE_ENSURE(CONDITION, ...) \ -do { \ -if (Y_UNLIKELY(!(CONDITION))) { \ - ErrorMsg_ = TStringBuilder() << __VA_ARGS__; \ - return false; \ -} \ -} while (false) - - bool OnInteger(long long value) override { - switch (State_.Current()) { - case TState::COMMON_TS: - PARSE_ENSURE(value >= 0, "unexpected negative number in a common timestamp: " << value); - MetricConsumer_->OnCommonTime(TInstant::Seconds(value)); - State_.ToPrev(); - - if (MetricConsumer_->NeedToStop()) { - IsIntentionallyHalted_ = true; - return false; - } - - break; - - case TState::METRIC_TS: - PARSE_ENSURE(value >= 0, "unexpected negative number in a metric timestamp: " << value); - LastMetric_.SetLastTime(TInstant::Seconds(value)); - State_.ToPrev(); - break; - - case TState::METRIC_VALUE: - LastMetric_.SetLastValue(static_cast<i64>(value)); - State_.ToPrev(); - break; - - case TState::METRIC_HIST_BOUNDS: - LastMetric_.HistogramBuilder.AddBound(static_cast<double>(value)); - break; - - case TState::METRIC_HIST_BUCKETS: - PARSE_ENSURE(value >= 0 && static_cast<ui64>(value) <= Max<TBucketValues::value_type>(), "value is out of bounds " << value); - LastMetric_.HistogramBuilder.AddValue(value); - break; - - case TState::METRIC_HIST_INF: - PARSE_ENSURE(value >= 0, "unexpected negative number in histogram inf: " << value); - LastMetric_.HistogramBuilder.AddInf(value); - State_.ToPrev(); - break; - - case TState::METRIC_DSUMMARY_COUNT: - LastMetric_.SummaryBuilder.SetCount(value); - State_.ToPrev(); - break; - - case TState::METRIC_DSUMMARY_SUM: - LastMetric_.SummaryBuilder.SetSum(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_MIN: - LastMetric_.SummaryBuilder.SetMin(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_MAX: - LastMetric_.SummaryBuilder.SetMax(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_LAST: - LastMetric_.SummaryBuilder.SetLast(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_BASE: - LastMetric_.LogHistBuilder.SetBase(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_ZEROS: - LastMetric_.LogHistBuilder.SetZerosCount(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_START_POWER: - LastMetric_.LogHistBuilder.SetStartPower(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_BUCKETS: - LastMetric_.LogHistBuilder.AddBucketValue(value); - break; - - default: - return false; - } - return true; - } - - bool OnUInteger(unsigned long long value) override { - switch (State_.Current()) { - case TState::COMMON_TS: - MetricConsumer_->OnCommonTime(TInstant::Seconds(value)); - State_.ToPrev(); - - if (MetricConsumer_->NeedToStop()) { - IsIntentionallyHalted_ = true; - return false; - } - - break; - - case TState::METRIC_TS: - LastMetric_.SetLastTime(TInstant::Seconds(value)); - State_.ToPrev(); - break; - - case TState::METRIC_VALUE: - PARSE_ENSURE(value <= Max<ui64>(), "Metric value is out of bounds: " << value); - LastMetric_.SetLastValue(static_cast<ui64>(value)); - State_.ToPrev(); - break; - - case TState::METRIC_HIST_BOUNDS: - LastMetric_.HistogramBuilder.AddBound(static_cast<double>(value)); - break; - - case TState::METRIC_HIST_BUCKETS: - PARSE_ENSURE(value <= Max<TBucketValues::value_type>(), "Histogram bucket value is out of bounds: " << value); - LastMetric_.HistogramBuilder.AddValue(value); - break; - - case TState::METRIC_HIST_INF: - LastMetric_.HistogramBuilder.AddInf(value); - State_.ToPrev(); - break; - - case TState::METRIC_DSUMMARY_COUNT: - LastMetric_.SummaryBuilder.SetCount(value); - State_.ToPrev(); - break; - - case TState::METRIC_DSUMMARY_SUM: - LastMetric_.SummaryBuilder.SetSum(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_MIN: - LastMetric_.SummaryBuilder.SetMin(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_MAX: - LastMetric_.SummaryBuilder.SetMax(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_LAST: - LastMetric_.SummaryBuilder.SetLast(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_BASE: - LastMetric_.LogHistBuilder.SetBase(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_ZEROS: - LastMetric_.LogHistBuilder.SetZerosCount(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_START_POWER: - LastMetric_.LogHistBuilder.SetStartPower(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_BUCKETS: - LastMetric_.LogHistBuilder.AddBucketValue(value); - break; - - default: - return false; - } - return true; - } - - bool OnDouble(double value) override { - switch (State_.Current()) { - case TState::METRIC_VALUE: - LastMetric_.SetLastValue(value); - State_.ToPrev(); - break; - - case TState::METRIC_HIST_BOUNDS: - LastMetric_.HistogramBuilder.AddBound(value); - break; - - case TState::METRIC_DSUMMARY_SUM: - LastMetric_.SummaryBuilder.SetSum(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_MIN: - LastMetric_.SummaryBuilder.SetMin(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_MAX: - LastMetric_.SummaryBuilder.SetMax(value); - State_.ToPrev(); - break; - case TState::METRIC_DSUMMARY_LAST: - LastMetric_.SummaryBuilder.SetLast(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_BASE: - LastMetric_.LogHistBuilder.SetBase(value); - State_.ToPrev(); - break; - - case TState::METRIC_LOG_HIST_BUCKETS: - LastMetric_.LogHistBuilder.AddBucketValue(value); - break; - - default: - return false; - } - return true; - } - - bool OnString(const TStringBuf& value) override { - switch (State_.Current()) { - case TState::COMMON_LABELS: - PARSE_ENSURE(!LastLabelName_.empty(), "empty label name in common labels"); - MetricConsumer_->OnLabel(LastLabelName_, TString{value}); - break; - - case TState::METRIC_LABELS: - PARSE_ENSURE(!LastLabelName_.empty(), "empty label name in metric labels"); - LastMetric_.Labels.Add(LastLabelName_, TString{value}); - break; - + { + } + +private: +#define PARSE_ENSURE(CONDITION, ...) \ +do { \ +if (Y_UNLIKELY(!(CONDITION))) { \ + ErrorMsg_ = TStringBuilder() << __VA_ARGS__; \ + return false; \ +} \ +} while (false) + + bool OnInteger(long long value) override { + switch (State_.Current()) { + case TState::COMMON_TS: + PARSE_ENSURE(value >= 0, "unexpected negative number in a common timestamp: " << value); + MetricConsumer_->OnCommonTime(TInstant::Seconds(value)); + State_.ToPrev(); + + if (MetricConsumer_->NeedToStop()) { + IsIntentionallyHalted_ = true; + return false; + } + + break; + + case TState::METRIC_TS: + PARSE_ENSURE(value >= 0, "unexpected negative number in a metric timestamp: " << value); + LastMetric_.SetLastTime(TInstant::Seconds(value)); + State_.ToPrev(); + break; + + case TState::METRIC_VALUE: + LastMetric_.SetLastValue(static_cast<i64>(value)); + State_.ToPrev(); + break; + + case TState::METRIC_HIST_BOUNDS: + LastMetric_.HistogramBuilder.AddBound(static_cast<double>(value)); + break; + + case TState::METRIC_HIST_BUCKETS: + PARSE_ENSURE(value >= 0 && static_cast<ui64>(value) <= Max<TBucketValues::value_type>(), "value is out of bounds " << value); + LastMetric_.HistogramBuilder.AddValue(value); + break; + + case TState::METRIC_HIST_INF: + PARSE_ENSURE(value >= 0, "unexpected negative number in histogram inf: " << value); + LastMetric_.HistogramBuilder.AddInf(value); + State_.ToPrev(); + break; + + case TState::METRIC_DSUMMARY_COUNT: + LastMetric_.SummaryBuilder.SetCount(value); + State_.ToPrev(); + break; + + case TState::METRIC_DSUMMARY_SUM: + LastMetric_.SummaryBuilder.SetSum(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_MIN: + LastMetric_.SummaryBuilder.SetMin(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_MAX: + LastMetric_.SummaryBuilder.SetMax(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_LAST: + LastMetric_.SummaryBuilder.SetLast(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_BASE: + LastMetric_.LogHistBuilder.SetBase(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_ZEROS: + LastMetric_.LogHistBuilder.SetZerosCount(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_START_POWER: + LastMetric_.LogHistBuilder.SetStartPower(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_BUCKETS: + LastMetric_.LogHistBuilder.AddBucketValue(value); + break; + + default: + return false; + } + return true; + } + + bool OnUInteger(unsigned long long value) override { + switch (State_.Current()) { + case TState::COMMON_TS: + MetricConsumer_->OnCommonTime(TInstant::Seconds(value)); + State_.ToPrev(); + + if (MetricConsumer_->NeedToStop()) { + IsIntentionallyHalted_ = true; + return false; + } + + break; + + case TState::METRIC_TS: + LastMetric_.SetLastTime(TInstant::Seconds(value)); + State_.ToPrev(); + break; + + case TState::METRIC_VALUE: + PARSE_ENSURE(value <= Max<ui64>(), "Metric value is out of bounds: " << value); + LastMetric_.SetLastValue(static_cast<ui64>(value)); + State_.ToPrev(); + break; + + case TState::METRIC_HIST_BOUNDS: + LastMetric_.HistogramBuilder.AddBound(static_cast<double>(value)); + break; + + case TState::METRIC_HIST_BUCKETS: + PARSE_ENSURE(value <= Max<TBucketValues::value_type>(), "Histogram bucket value is out of bounds: " << value); + LastMetric_.HistogramBuilder.AddValue(value); + break; + + case TState::METRIC_HIST_INF: + LastMetric_.HistogramBuilder.AddInf(value); + State_.ToPrev(); + break; + + case TState::METRIC_DSUMMARY_COUNT: + LastMetric_.SummaryBuilder.SetCount(value); + State_.ToPrev(); + break; + + case TState::METRIC_DSUMMARY_SUM: + LastMetric_.SummaryBuilder.SetSum(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_MIN: + LastMetric_.SummaryBuilder.SetMin(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_MAX: + LastMetric_.SummaryBuilder.SetMax(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_LAST: + LastMetric_.SummaryBuilder.SetLast(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_BASE: + LastMetric_.LogHistBuilder.SetBase(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_ZEROS: + LastMetric_.LogHistBuilder.SetZerosCount(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_START_POWER: + LastMetric_.LogHistBuilder.SetStartPower(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_BUCKETS: + LastMetric_.LogHistBuilder.AddBucketValue(value); + break; + + default: + return false; + } + return true; + } + + bool OnDouble(double value) override { + switch (State_.Current()) { + case TState::METRIC_VALUE: + LastMetric_.SetLastValue(value); + State_.ToPrev(); + break; + + case TState::METRIC_HIST_BOUNDS: + LastMetric_.HistogramBuilder.AddBound(value); + break; + + case TState::METRIC_DSUMMARY_SUM: + LastMetric_.SummaryBuilder.SetSum(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_MIN: + LastMetric_.SummaryBuilder.SetMin(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_MAX: + LastMetric_.SummaryBuilder.SetMax(value); + State_.ToPrev(); + break; + case TState::METRIC_DSUMMARY_LAST: + LastMetric_.SummaryBuilder.SetLast(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_BASE: + LastMetric_.LogHistBuilder.SetBase(value); + State_.ToPrev(); + break; + + case TState::METRIC_LOG_HIST_BUCKETS: + LastMetric_.LogHistBuilder.AddBucketValue(value); + break; + + default: + return false; + } + return true; + } + + bool OnString(const TStringBuf& value) override { + switch (State_.Current()) { + case TState::COMMON_LABELS: + PARSE_ENSURE(!LastLabelName_.empty(), "empty label name in common labels"); + MetricConsumer_->OnLabel(LastLabelName_, TString{value}); + break; + + case TState::METRIC_LABELS: + PARSE_ENSURE(!LastLabelName_.empty(), "empty label name in metric labels"); + LastMetric_.Labels.Add(LastLabelName_, TString{value}); + break; + case TState::METRIC_NAME: PARSE_ENSURE(!value.empty(), "empty metric name"); LastMetric_.Labels.Add(MetricNameLabel_, TString{value}); State_.ToPrev(); break; - case TState::COMMON_TS: - MetricConsumer_->OnCommonTime(TInstant::ParseIso8601(value)); - State_.ToPrev(); - - if (MetricConsumer_->NeedToStop()) { - IsIntentionallyHalted_ = true; - return false; + case TState::COMMON_TS: + MetricConsumer_->OnCommonTime(TInstant::ParseIso8601(value)); + State_.ToPrev(); + + if (MetricConsumer_->NeedToStop()) { + IsIntentionallyHalted_ = true; + return false; + } + + break; + + case TState::METRIC_TS: + LastMetric_.SetLastTime(TInstant::ParseIso8601(value)); + State_.ToPrev(); + break; + + case TState::METRIC_VALUE: + if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { + LastMetric_.SetLastValue(doubleValue); + } else { + return false; } + State_.ToPrev(); + break; - break; - - case TState::METRIC_TS: - LastMetric_.SetLastTime(TInstant::ParseIso8601(value)); - State_.ToPrev(); - break; + case TState::METRIC_TYPE: + LastMetric_.Type = MetricTypeFromStr(value); + State_.ToPrev(); + break; - case TState::METRIC_VALUE: - if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { - LastMetric_.SetLastValue(doubleValue); - } else { - return false; - } - State_.ToPrev(); - break; - - case TState::METRIC_TYPE: - LastMetric_.Type = MetricTypeFromStr(value); - State_.ToPrev(); - break; - - case TState::METRIC_MODE: + case TState::METRIC_MODE: if (value == TStringBuf("deriv")) { - LastMetric_.Type = EMetricType::RATE; - } - State_.ToPrev(); - break; - - case TState::METRIC_DSUMMARY_SUM: - if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { - LastMetric_.SummaryBuilder.SetSum(doubleValue); - } else { - return false; - } - State_.ToPrev(); - break; - - case TState::METRIC_DSUMMARY_MIN: - if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { - LastMetric_.SummaryBuilder.SetMin(doubleValue); - } else { - return false; - } - State_.ToPrev(); - break; - - case TState::METRIC_DSUMMARY_MAX: - if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { - LastMetric_.SummaryBuilder.SetMax(doubleValue); - } else { - return false; - } - State_.ToPrev(); - break; - - case TState::METRIC_DSUMMARY_LAST: - if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { - LastMetric_.SummaryBuilder.SetLast(doubleValue); - } else { - return false; - } - State_.ToPrev(); - break; - - default: - return false; - } - - return true; - } - - bool OnMapKey(const TStringBuf& key) override { - switch (State_.Current()) { - case TState::ROOT_OBJECT: + LastMetric_.Type = EMetricType::RATE; + } + State_.ToPrev(); + break; + + case TState::METRIC_DSUMMARY_SUM: + if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { + LastMetric_.SummaryBuilder.SetSum(doubleValue); + } else { + return false; + } + State_.ToPrev(); + break; + + case TState::METRIC_DSUMMARY_MIN: + if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { + LastMetric_.SummaryBuilder.SetMin(doubleValue); + } else { + return false; + } + State_.ToPrev(); + break; + + case TState::METRIC_DSUMMARY_MAX: + if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { + LastMetric_.SummaryBuilder.SetMax(doubleValue); + } else { + return false; + } + State_.ToPrev(); + break; + + case TState::METRIC_DSUMMARY_LAST: + if (auto [doubleValue, ok] = ParseSpecDouble(value); ok) { + LastMetric_.SummaryBuilder.SetLast(doubleValue); + } else { + return false; + } + State_.ToPrev(); + break; + + default: + return false; + } + + return true; + } + + bool OnMapKey(const TStringBuf& key) override { + switch (State_.Current()) { + case TState::ROOT_OBJECT: if (key == TStringBuf("commonLabels") || key == TStringBuf("labels")) { - State_.ToNext(TState::COMMON_LABELS); + State_.ToNext(TState::COMMON_LABELS); } else if (key == TStringBuf("ts")) { - State_.ToNext(TState::COMMON_TS); + State_.ToNext(TState::COMMON_TS); } else if (key == TStringBuf("sensors") || key == TStringBuf("metrics")) { - State_.ToNext(TState::METRICS_ARRAY); - } - break; + State_.ToNext(TState::METRICS_ARRAY); + } + break; - case TState::COMMON_LABELS: - case TState::METRIC_LABELS: - LastLabelName_ = key; - break; + case TState::COMMON_LABELS: + case TState::METRIC_LABELS: + LastLabelName_ = key; + break; - case TState::METRIC_OBJECT: + case TState::METRIC_OBJECT: if (key == TStringBuf("labels")) { - State_.ToNext(TState::METRIC_LABELS); + State_.ToNext(TState::METRIC_LABELS); } else if (key == TStringBuf("name")) { State_.ToNext(TState::METRIC_NAME); } else if (key == TStringBuf("ts")) { - PARSE_ENSURE(!LastMetric_.SeenTimeseries, - "mixed timeseries and ts attributes"); - LastMetric_.SeenTsOrValue = true; - State_.ToNext(TState::METRIC_TS); + PARSE_ENSURE(!LastMetric_.SeenTimeseries, + "mixed timeseries and ts attributes"); + LastMetric_.SeenTsOrValue = true; + State_.ToNext(TState::METRIC_TS); } else if (key == TStringBuf("value")) { - PARSE_ENSURE(!LastMetric_.SeenTimeseries, - "mixed timeseries and value attributes"); - LastMetric_.SeenTsOrValue = true; - State_.ToNext(TState::METRIC_VALUE); + PARSE_ENSURE(!LastMetric_.SeenTimeseries, + "mixed timeseries and value attributes"); + LastMetric_.SeenTsOrValue = true; + State_.ToNext(TState::METRIC_VALUE); } else if (key == TStringBuf("timeseries")) { - PARSE_ENSURE(!LastMetric_.SeenTsOrValue, - "mixed timeseries and ts/value attributes"); - LastMetric_.SeenTimeseries = true; - State_.ToNext(TState::METRIC_TIMESERIES); + PARSE_ENSURE(!LastMetric_.SeenTsOrValue, + "mixed timeseries and ts/value attributes"); + LastMetric_.SeenTimeseries = true; + State_.ToNext(TState::METRIC_TIMESERIES); } else if (key == TStringBuf("mode")) { - State_.ToNext(TState::METRIC_MODE); + State_.ToNext(TState::METRIC_MODE); } else if (key == TStringBuf("kind") || key == TStringBuf("type")) { - State_.ToNext(TState::METRIC_TYPE); + State_.ToNext(TState::METRIC_TYPE); } else if (key == TStringBuf("hist")) { - State_.ToNext(TState::METRIC_HIST); + State_.ToNext(TState::METRIC_HIST); } else if (key == TStringBuf("summary")) { - State_.ToNext(TState::METRIC_DSUMMARY); + State_.ToNext(TState::METRIC_DSUMMARY); } else if (key == TStringBuf("log_hist")) { - State_.ToNext(TState::METRIC_LOG_HIST); + State_.ToNext(TState::METRIC_LOG_HIST); } else if (key == TStringBuf("memOnly")) { - // deprecated. Skip it without errors for backward compatibility - } else { - ErrorMsg_ = TStringBuilder() << "unexpected key \"" << key << "\" in a metric schema"; - return false; - } - break; - - case TState::METRIC_TIMESERIES: + // deprecated. Skip it without errors for backward compatibility + } else { + ErrorMsg_ = TStringBuilder() << "unexpected key \"" << key << "\" in a metric schema"; + return false; + } + break; + + case TState::METRIC_TIMESERIES: if (key == TStringBuf("ts")) { - State_.ToNext(TState::METRIC_TS); + State_.ToNext(TState::METRIC_TS); } else if (key == TStringBuf("value")) { - State_.ToNext(TState::METRIC_VALUE); + State_.ToNext(TState::METRIC_VALUE); } else if (key == TStringBuf("hist")) { - State_.ToNext(TState::METRIC_HIST); + State_.ToNext(TState::METRIC_HIST); } else if (key == TStringBuf("summary")) { - State_.ToNext(TState::METRIC_DSUMMARY); + State_.ToNext(TState::METRIC_DSUMMARY); } else if (key == TStringBuf("log_hist")) { - State_.ToNext(TState::METRIC_LOG_HIST); + State_.ToNext(TState::METRIC_LOG_HIST); } - break; + break; - case TState::METRIC_HIST: + case TState::METRIC_HIST: if (key == TStringBuf("bounds")) { - State_.ToNext(TState::METRIC_HIST_BOUNDS); + State_.ToNext(TState::METRIC_HIST_BOUNDS); } else if (key == TStringBuf("buckets")) { - State_.ToNext(TState::METRIC_HIST_BUCKETS); + State_.ToNext(TState::METRIC_HIST_BUCKETS); } else if (key == TStringBuf("inf")) { - State_.ToNext(TState::METRIC_HIST_INF); - } - break; + State_.ToNext(TState::METRIC_HIST_INF); + } + break; - case TState::METRIC_LOG_HIST: + case TState::METRIC_LOG_HIST: if (key == TStringBuf("base")) { - State_.ToNext(TState::METRIC_LOG_HIST_BASE); + State_.ToNext(TState::METRIC_LOG_HIST_BASE); } else if (key == TStringBuf("zeros_count")) { - State_.ToNext(TState::METRIC_LOG_HIST_ZEROS); + State_.ToNext(TState::METRIC_LOG_HIST_ZEROS); } else if (key == TStringBuf("start_power")) { - State_.ToNext(TState::METRIC_LOG_HIST_START_POWER); + State_.ToNext(TState::METRIC_LOG_HIST_START_POWER); } else if (key == TStringBuf("buckets")) { - State_.ToNext(TState::METRIC_LOG_HIST_BUCKETS); - } - break; + State_.ToNext(TState::METRIC_LOG_HIST_BUCKETS); + } + break; - case TState::METRIC_DSUMMARY: + case TState::METRIC_DSUMMARY: if (key == TStringBuf("sum")) { - State_.ToNext(TState::METRIC_DSUMMARY_SUM); + State_.ToNext(TState::METRIC_DSUMMARY_SUM); } else if (key == TStringBuf("min")) { - State_.ToNext(TState::METRIC_DSUMMARY_MIN); + State_.ToNext(TState::METRIC_DSUMMARY_MIN); } else if (key == TStringBuf("max")) { - State_.ToNext(TState::METRIC_DSUMMARY_MAX); + State_.ToNext(TState::METRIC_DSUMMARY_MAX); } else if (key == TStringBuf("last")) { - State_.ToNext(TState::METRIC_DSUMMARY_LAST); + State_.ToNext(TState::METRIC_DSUMMARY_LAST); } else if (key == TStringBuf("count")) { - State_.ToNext(TState::METRIC_DSUMMARY_COUNT); - } - - break; - - - default: - return false; - } - - return true; - } - - bool OnOpenMap() override { - switch (State_.Current()) { - case TState::ROOT_OBJECT: - MetricConsumer_->OnStreamBegin(); - break; - - case TState::COMMON_LABELS: - MetricConsumer_->OnLabelsBegin(); - break; - - case TState::METRICS_ARRAY: - State_.ToNext(TState::METRIC_OBJECT); - LastMetric_.Clear(); - break; - - default: - break; - } - return true; - } - - bool OnCloseMap() override { - switch (State_.Current()) { - case TState::ROOT_OBJECT: - MetricConsumer_->OnStreamEnd(); - break; - - case TState::METRIC_LABELS: - State_.ToPrev(); - break; - - case TState::COMMON_LABELS: - MetricConsumer_->OnLabelsEnd(); - State_.ToPrev(); - - if (MetricConsumer_->NeedToStop()) { - IsIntentionallyHalted_ = true; - return false; - } - - break; - - case TState::METRIC_OBJECT: - ConsumeMetric(); - State_.ToPrev(); - break; - - case TState::METRIC_TIMESERIES: - LastMetric_.SaveLastPoint(); - break; - - case TState::METRIC_HIST: - case TState::METRIC_DSUMMARY: - case TState::METRIC_LOG_HIST: - State_.ToPrev(); - break; - - default: - break; - } - return true; - } - - bool OnOpenArray() override { - auto currentState = State_.Current(); - PARSE_ENSURE( - currentState == TState::METRICS_ARRAY || - currentState == TState::METRIC_TIMESERIES || - currentState == TState::METRIC_HIST_BOUNDS || - currentState == TState::METRIC_HIST_BUCKETS || - currentState == TState::METRIC_LOG_HIST_BUCKETS, - "unexpected array begin"); - return true; - } - - bool OnCloseArray() override { - switch (State_.Current()) { - case TState::METRICS_ARRAY: - case TState::METRIC_TIMESERIES: - case TState::METRIC_HIST_BOUNDS: - case TState::METRIC_HIST_BUCKETS: - case TState::METRIC_LOG_HIST_BUCKETS: - State_.ToPrev(); - break; - - default: - return false; - } - return true; - } - - void OnError(size_t off, TStringBuf reason) override { - if (IsIntentionallyHalted_) { - return; - } - - size_t snippetBeg = (off < 20) ? 0 : (off - 20); - TStringBuf snippet = Data_.SubStr(snippetBeg, 40); - - throw TJsonDecodeError() - << "cannot parse JSON, error at: " << off - << ", reason: " << (ErrorMsg_.empty() ? reason : TStringBuf{ErrorMsg_}) - << "\nsnippet: ..." << snippet << "..."; - } - - bool OnEnd() override { - return true; - } - - void ConsumeMetric() { - // for backwad compatibility all unknown metrics treated as gauges - if (LastMetric_.Type == EMetricType::UNKNOWN) { - if (LastMetric_.HistogramBuilder.Empty()) { - LastMetric_.Type = EMetricType::GAUGE; - } else { - LastMetric_.Type = EMetricType::HIST; + State_.ToNext(TState::METRIC_DSUMMARY_COUNT); + } + + break; + + + default: + return false; + } + + return true; + } + + bool OnOpenMap() override { + switch (State_.Current()) { + case TState::ROOT_OBJECT: + MetricConsumer_->OnStreamBegin(); + break; + + case TState::COMMON_LABELS: + MetricConsumer_->OnLabelsBegin(); + break; + + case TState::METRICS_ARRAY: + State_.ToNext(TState::METRIC_OBJECT); + LastMetric_.Clear(); + break; + + default: + break; + } + return true; + } + + bool OnCloseMap() override { + switch (State_.Current()) { + case TState::ROOT_OBJECT: + MetricConsumer_->OnStreamEnd(); + break; + + case TState::METRIC_LABELS: + State_.ToPrev(); + break; + + case TState::COMMON_LABELS: + MetricConsumer_->OnLabelsEnd(); + State_.ToPrev(); + + if (MetricConsumer_->NeedToStop()) { + IsIntentionallyHalted_ = true; + return false; + } + + break; + + case TState::METRIC_OBJECT: + ConsumeMetric(); + State_.ToPrev(); + break; + + case TState::METRIC_TIMESERIES: + LastMetric_.SaveLastPoint(); + break; + + case TState::METRIC_HIST: + case TState::METRIC_DSUMMARY: + case TState::METRIC_LOG_HIST: + State_.ToPrev(); + break; + + default: + break; + } + return true; + } + + bool OnOpenArray() override { + auto currentState = State_.Current(); + PARSE_ENSURE( + currentState == TState::METRICS_ARRAY || + currentState == TState::METRIC_TIMESERIES || + currentState == TState::METRIC_HIST_BOUNDS || + currentState == TState::METRIC_HIST_BUCKETS || + currentState == TState::METRIC_LOG_HIST_BUCKETS, + "unexpected array begin"); + return true; + } + + bool OnCloseArray() override { + switch (State_.Current()) { + case TState::METRICS_ARRAY: + case TState::METRIC_TIMESERIES: + case TState::METRIC_HIST_BOUNDS: + case TState::METRIC_HIST_BUCKETS: + case TState::METRIC_LOG_HIST_BUCKETS: + State_.ToPrev(); + break; + + default: + return false; + } + return true; + } + + void OnError(size_t off, TStringBuf reason) override { + if (IsIntentionallyHalted_) { + return; + } + + size_t snippetBeg = (off < 20) ? 0 : (off - 20); + TStringBuf snippet = Data_.SubStr(snippetBeg, 40); + + throw TJsonDecodeError() + << "cannot parse JSON, error at: " << off + << ", reason: " << (ErrorMsg_.empty() ? reason : TStringBuf{ErrorMsg_}) + << "\nsnippet: ..." << snippet << "..."; + } + + bool OnEnd() override { + return true; + } + + void ConsumeMetric() { + // for backwad compatibility all unknown metrics treated as gauges + if (LastMetric_.Type == EMetricType::UNKNOWN) { + if (LastMetric_.HistogramBuilder.Empty()) { + LastMetric_.Type = EMetricType::GAUGE; + } else { + LastMetric_.Type = EMetricType::HIST; } - } + } - // (1) begin metric - MetricConsumer_->OnMetricBegin(LastMetric_.Type); + // (1) begin metric + MetricConsumer_->OnMetricBegin(LastMetric_.Type); - // (2) labels - if (!LastMetric_.Labels.empty()) { - MetricConsumer_->OnLabelsBegin(); - for (auto&& label : LastMetric_.Labels) { - MetricConsumer_->OnLabel(label.Name(), label.Value()); + // (2) labels + if (!LastMetric_.Labels.empty()) { + MetricConsumer_->OnLabelsBegin(); + for (auto&& label : LastMetric_.Labels) { + MetricConsumer_->OnLabel(label.Name(), label.Value()); } - MetricConsumer_->OnLabelsEnd(); - } - - // (3) values - switch (LastMetric_.Type) { - case EMetricType::GAUGE: - LastMetric_.Consume([this](TInstant time, EMetricValueType valueType, TMetricValue value) { - MetricConsumer_->OnDouble(time, value.AsDouble(valueType)); - }); - break; - - case EMetricType::IGAUGE: - LastMetric_.Consume([this](TInstant time, EMetricValueType valueType, TMetricValue value) { - MetricConsumer_->OnInt64(time, value.AsInt64(valueType)); - }); - break; - - case EMetricType::COUNTER: - case EMetricType::RATE: - LastMetric_.Consume([this](TInstant time, EMetricValueType valueType, TMetricValue value) { - MetricConsumer_->OnUint64(time, value.AsUint64(valueType)); - }); - break; - - case EMetricType::HIST: - case EMetricType::HIST_RATE: - if (LastMetric_.TimeSeries.empty()) { - auto time = LastMetric_.LastPoint.GetTime(); - auto histogram = LastMetric_.HistogramBuilder.Build(); - MetricConsumer_->OnHistogram(time, histogram); - } else { - for (const auto& p : LastMetric_.TimeSeries) { - DECODE_ENSURE(p.GetValueType() == EMetricValueType::HISTOGRAM, "Value is not a histogram"); - MetricConsumer_->OnHistogram(p.GetTime(), p.GetValue().AsHistogram()); + MetricConsumer_->OnLabelsEnd(); + } + + // (3) values + switch (LastMetric_.Type) { + case EMetricType::GAUGE: + LastMetric_.Consume([this](TInstant time, EMetricValueType valueType, TMetricValue value) { + MetricConsumer_->OnDouble(time, value.AsDouble(valueType)); + }); + break; + + case EMetricType::IGAUGE: + LastMetric_.Consume([this](TInstant time, EMetricValueType valueType, TMetricValue value) { + MetricConsumer_->OnInt64(time, value.AsInt64(valueType)); + }); + break; + + case EMetricType::COUNTER: + case EMetricType::RATE: + LastMetric_.Consume([this](TInstant time, EMetricValueType valueType, TMetricValue value) { + MetricConsumer_->OnUint64(time, value.AsUint64(valueType)); + }); + break; + + case EMetricType::HIST: + case EMetricType::HIST_RATE: + if (LastMetric_.TimeSeries.empty()) { + auto time = LastMetric_.LastPoint.GetTime(); + auto histogram = LastMetric_.HistogramBuilder.Build(); + MetricConsumer_->OnHistogram(time, histogram); + } else { + for (const auto& p : LastMetric_.TimeSeries) { + DECODE_ENSURE(p.GetValueType() == EMetricValueType::HISTOGRAM, "Value is not a histogram"); + MetricConsumer_->OnHistogram(p.GetTime(), p.GetValue().AsHistogram()); } } - break; - - case EMetricType::DSUMMARY: - if (LastMetric_.TimeSeries.empty()) { - auto time = LastMetric_.LastPoint.GetTime(); - auto summary = LastMetric_.SummaryBuilder.Build(); - MetricConsumer_->OnSummaryDouble(time, summary); - } else { - for (const auto& p : LastMetric_.TimeSeries) { - DECODE_ENSURE(p.GetValueType() == EMetricValueType::SUMMARY, "Value is not a summary"); - MetricConsumer_->OnSummaryDouble(p.GetTime(), p.GetValue().AsSummaryDouble()); + break; + + case EMetricType::DSUMMARY: + if (LastMetric_.TimeSeries.empty()) { + auto time = LastMetric_.LastPoint.GetTime(); + auto summary = LastMetric_.SummaryBuilder.Build(); + MetricConsumer_->OnSummaryDouble(time, summary); + } else { + for (const auto& p : LastMetric_.TimeSeries) { + DECODE_ENSURE(p.GetValueType() == EMetricValueType::SUMMARY, "Value is not a summary"); + MetricConsumer_->OnSummaryDouble(p.GetTime(), p.GetValue().AsSummaryDouble()); + } + } + break; + + case EMetricType::LOGHIST: + if (LastMetric_.TimeSeries.empty()) { + auto time = LastMetric_.LastPoint.GetTime(); + auto logHist = LastMetric_.LogHistBuilder.Build(); + MetricConsumer_->OnLogHistogram(time, logHist); + } else { + for (const auto& p : LastMetric_.TimeSeries) { + DECODE_ENSURE(p.GetValueType() == EMetricValueType::LOGHISTOGRAM, "Value is not a log_histogram"); + MetricConsumer_->OnLogHistogram(p.GetTime(), p.GetValue().AsLogHistogram()); } } - break; + break; - case EMetricType::LOGHIST: - if (LastMetric_.TimeSeries.empty()) { - auto time = LastMetric_.LastPoint.GetTime(); - auto logHist = LastMetric_.LogHistBuilder.Build(); - MetricConsumer_->OnLogHistogram(time, logHist); - } else { - for (const auto& p : LastMetric_.TimeSeries) { - DECODE_ENSURE(p.GetValueType() == EMetricValueType::LOGHISTOGRAM, "Value is not a log_histogram"); - MetricConsumer_->OnLogHistogram(p.GetTime(), p.GetValue().AsLogHistogram()); - } - } - break; + case EMetricType::UNKNOWN: + // TODO: output metric labels + ythrow yexception() << "unknown metric type"; + } - case EMetricType::UNKNOWN: - // TODO: output metric labels - ythrow yexception() << "unknown metric type"; - } + // (4) end metric + MetricConsumer_->OnMetricEnd(); + } - // (4) end metric - MetricConsumer_->OnMetricEnd(); - } - -private: - TStringBuf Data_; - IHaltableMetricConsumer* MetricConsumer_; +private: + TStringBuf Data_; + IHaltableMetricConsumer* MetricConsumer_; TString MetricNameLabel_; - TState State_; - TString LastLabelName_; - TMetricCollector LastMetric_; - TString ErrorMsg_; - bool IsIntentionallyHalted_{false}; -}; + TState State_; + TString LastLabelName_; + TMetricCollector LastMetric_; + TString ErrorMsg_; + bool IsIntentionallyHalted_{false}; +}; -} // namespace +} // namespace void DecodeJson(TStringBuf data, IMetricConsumer* c, TStringBuf metricNameLabel) { - TCommonPartsCollector commonPartsCollector; - { - TMemoryInput memIn(data); + TCommonPartsCollector commonPartsCollector; + { + TMemoryInput memIn(data); TDecoderJson decoder(data, &commonPartsCollector, metricNameLabel); - // no need to check a return value. If there is an error, a TJsonDecodeError is thrown - NJson::ReadJson(&memIn, &decoder); - } + // no need to check a return value. If there is an error, a TJsonDecodeError is thrown + NJson::ReadJson(&memIn, &decoder); + } - TCommonPartsProxy commonPartsProxy(std::move(commonPartsCollector.CommonParts()), c); - { - TMemoryInput memIn(data); + TCommonPartsProxy commonPartsProxy(std::move(commonPartsCollector.CommonParts()), c); + { + TMemoryInput memIn(data); TDecoderJson decoder(data, &commonPartsProxy, metricNameLabel); - // no need to check a return value. If there is an error, a TJsonDecodeError is thrown - NJson::ReadJson(&memIn, &decoder); - } -} - -#undef DECODE_ENSURE + // no need to check a return value. If there is an error, a TJsonDecodeError is thrown + NJson::ReadJson(&memIn, &decoder); + } +} +#undef DECODE_ENSURE + } diff --git a/library/cpp/monlib/encode/json/json_decoder_ut.cpp b/library/cpp/monlib/encode/json/json_decoder_ut.cpp index 4464e1d26a..1f9513664a 100644 --- a/library/cpp/monlib/encode/json/json_decoder_ut.cpp +++ b/library/cpp/monlib/encode/json/json_decoder_ut.cpp @@ -1,125 +1,125 @@ -#include "json_decoder.cpp" - -#include <library/cpp/monlib/consumers/collecting_consumer.h> -#include <library/cpp/testing/unittest/registar.h> - -#include <array> - - -using namespace NMonitoring; - -enum EJsonPart : ui8 { - METRICS = 0, - COMMON_TS = 1, - COMMON_LABELS = 2, -}; - -constexpr std::array<TStringBuf, 3> JSON_PARTS = { +#include "json_decoder.cpp" + +#include <library/cpp/monlib/consumers/collecting_consumer.h> +#include <library/cpp/testing/unittest/registar.h> + +#include <array> + + +using namespace NMonitoring; + +enum EJsonPart : ui8 { + METRICS = 0, + COMMON_TS = 1, + COMMON_LABELS = 2, +}; + +constexpr std::array<TStringBuf, 3> JSON_PARTS = { TStringBuf(R"("metrics": [{ - "labels": { "key": "value" }, - "type": "GAUGE", - "value": 123 - }])"), - + "labels": { "key": "value" }, + "type": "GAUGE", + "value": 123 + }])"), + TStringBuf(R"("ts": 1)"), - + TStringBuf(R"("commonLabels": { - "key1": "value1", - "key2": "value2" - })"), -}; - -TString BuildJson(std::initializer_list<EJsonPart> parts) { - TString data = "{"; - - for (auto it = parts.begin(); it != parts.end(); ++it) { - data += JSON_PARTS[*it]; - - if (it + 1 != parts.end()) { - data += ","; - } - } - - data += "}"; - return data; -} - -void ValidateCommonParts(TCommonParts&& commonParts, bool checkLabels, bool checkTs) { - if (checkTs) { - UNIT_ASSERT_VALUES_EQUAL(commonParts.CommonTime.MilliSeconds(), 1000); - } - - if (checkLabels) { - auto& labels = commonParts.CommonLabels; - UNIT_ASSERT_VALUES_EQUAL(labels.Size(), 2); + "key1": "value1", + "key2": "value2" + })"), +}; + +TString BuildJson(std::initializer_list<EJsonPart> parts) { + TString data = "{"; + + for (auto it = parts.begin(); it != parts.end(); ++it) { + data += JSON_PARTS[*it]; + + if (it + 1 != parts.end()) { + data += ","; + } + } + + data += "}"; + return data; +} + +void ValidateCommonParts(TCommonParts&& commonParts, bool checkLabels, bool checkTs) { + if (checkTs) { + UNIT_ASSERT_VALUES_EQUAL(commonParts.CommonTime.MilliSeconds(), 1000); + } + + if (checkLabels) { + auto& labels = commonParts.CommonLabels; + UNIT_ASSERT_VALUES_EQUAL(labels.Size(), 2); UNIT_ASSERT(labels.Has(TStringBuf("key1"))); UNIT_ASSERT(labels.Has(TStringBuf("key2"))); UNIT_ASSERT_VALUES_EQUAL(labels.Get(TStringBuf("key1")).value()->Value(), "value1"); UNIT_ASSERT_VALUES_EQUAL(labels.Get(TStringBuf("key2")).value()->Value(), "value2"); - } -} - -void ValidateMetrics(const TVector<TMetricData>& metrics) { - UNIT_ASSERT_VALUES_EQUAL(metrics.size(), 1); - - auto& m = metrics[0]; - UNIT_ASSERT_VALUES_EQUAL(m.Kind, EMetricType::GAUGE); - auto& l = m.Labels; - UNIT_ASSERT_VALUES_EQUAL(l.Size(), 1); - UNIT_ASSERT_VALUES_EQUAL(l.Get(0)->Name(), "key"); - UNIT_ASSERT_VALUES_EQUAL(l.Get(0)->Value(), "value"); - - UNIT_ASSERT_VALUES_EQUAL(m.Values->Size(), 1); - UNIT_ASSERT_VALUES_EQUAL((*m.Values)[0].GetValue().AsDouble(), 123); -} - + } +} + +void ValidateMetrics(const TVector<TMetricData>& metrics) { + UNIT_ASSERT_VALUES_EQUAL(metrics.size(), 1); + + auto& m = metrics[0]; + UNIT_ASSERT_VALUES_EQUAL(m.Kind, EMetricType::GAUGE); + auto& l = m.Labels; + UNIT_ASSERT_VALUES_EQUAL(l.Size(), 1); + UNIT_ASSERT_VALUES_EQUAL(l.Get(0)->Name(), "key"); + UNIT_ASSERT_VALUES_EQUAL(l.Get(0)->Value(), "value"); + + UNIT_ASSERT_VALUES_EQUAL(m.Values->Size(), 1); + UNIT_ASSERT_VALUES_EQUAL((*m.Values)[0].GetValue().AsDouble(), 123); +} + void CheckCommonPartsCollector(TString data, bool shouldBeStopped, bool checkLabels = true, bool checkTs = true, TStringBuf metricNameLabel = "name") { - TCommonPartsCollector commonPartsCollector; - TMemoryInput memIn(data); + TCommonPartsCollector commonPartsCollector; + TMemoryInput memIn(data); TDecoderJson decoder(data, &commonPartsCollector, metricNameLabel); - - bool isOk{false}; - UNIT_ASSERT_NO_EXCEPTION(isOk = NJson::ReadJson(&memIn, &decoder)); - UNIT_ASSERT_VALUES_EQUAL(isOk, !shouldBeStopped); - - ValidateCommonParts(commonPartsCollector.CommonParts(), checkLabels, checkTs); -} - -Y_UNIT_TEST_SUITE(TJsonDecoderTest) { - Y_UNIT_TEST(FullCommonParts) { - CheckCommonPartsCollector(BuildJson({COMMON_LABELS, COMMON_TS, METRICS}), true); - CheckCommonPartsCollector(BuildJson({COMMON_TS, COMMON_LABELS, METRICS}), true); - - CheckCommonPartsCollector(BuildJson({METRICS, COMMON_TS, COMMON_LABELS}), true); - CheckCommonPartsCollector(BuildJson({METRICS, COMMON_LABELS, COMMON_TS}), true); - - CheckCommonPartsCollector(BuildJson({COMMON_LABELS, METRICS, COMMON_TS}), true); - CheckCommonPartsCollector(BuildJson({COMMON_TS, METRICS, COMMON_LABELS}), true); - } - - Y_UNIT_TEST(PartialCommonParts) { - CheckCommonPartsCollector(BuildJson({COMMON_TS, METRICS}), false, false, true); - CheckCommonPartsCollector(BuildJson({COMMON_LABELS, METRICS}), false, true, false); - - CheckCommonPartsCollector(BuildJson({METRICS, COMMON_LABELS}), false, true, false); - CheckCommonPartsCollector(BuildJson({METRICS, COMMON_TS}), false, false, true); - - CheckCommonPartsCollector(BuildJson({METRICS}), false, false, false); - } - - Y_UNIT_TEST(CheckCommonPartsAndMetrics) { - auto data = BuildJson({COMMON_LABELS, COMMON_TS, METRICS}); - TCollectingConsumer collector; - - DecodeJson(data, &collector); - - TCommonParts commonParts; - commonParts.CommonTime = collector.CommonTime; - commonParts.CommonLabels = collector.CommonLabels; - - ValidateCommonParts(std::move(commonParts), true, true); - ValidateMetrics(collector.Metrics); - } + + bool isOk{false}; + UNIT_ASSERT_NO_EXCEPTION(isOk = NJson::ReadJson(&memIn, &decoder)); + UNIT_ASSERT_VALUES_EQUAL(isOk, !shouldBeStopped); + + ValidateCommonParts(commonPartsCollector.CommonParts(), checkLabels, checkTs); +} + +Y_UNIT_TEST_SUITE(TJsonDecoderTest) { + Y_UNIT_TEST(FullCommonParts) { + CheckCommonPartsCollector(BuildJson({COMMON_LABELS, COMMON_TS, METRICS}), true); + CheckCommonPartsCollector(BuildJson({COMMON_TS, COMMON_LABELS, METRICS}), true); + + CheckCommonPartsCollector(BuildJson({METRICS, COMMON_TS, COMMON_LABELS}), true); + CheckCommonPartsCollector(BuildJson({METRICS, COMMON_LABELS, COMMON_TS}), true); + + CheckCommonPartsCollector(BuildJson({COMMON_LABELS, METRICS, COMMON_TS}), true); + CheckCommonPartsCollector(BuildJson({COMMON_TS, METRICS, COMMON_LABELS}), true); + } + + Y_UNIT_TEST(PartialCommonParts) { + CheckCommonPartsCollector(BuildJson({COMMON_TS, METRICS}), false, false, true); + CheckCommonPartsCollector(BuildJson({COMMON_LABELS, METRICS}), false, true, false); + + CheckCommonPartsCollector(BuildJson({METRICS, COMMON_LABELS}), false, true, false); + CheckCommonPartsCollector(BuildJson({METRICS, COMMON_TS}), false, false, true); + + CheckCommonPartsCollector(BuildJson({METRICS}), false, false, false); + } + + Y_UNIT_TEST(CheckCommonPartsAndMetrics) { + auto data = BuildJson({COMMON_LABELS, COMMON_TS, METRICS}); + TCollectingConsumer collector; + + DecodeJson(data, &collector); + + TCommonParts commonParts; + commonParts.CommonTime = collector.CommonTime; + commonParts.CommonLabels = collector.CommonLabels; + + ValidateCommonParts(std::move(commonParts), true, true); + ValidateMetrics(collector.Metrics); + } Y_UNIT_TEST(CanParseHistogramsWithInf) { const char* metricsData = R"({ @@ -176,4 +176,4 @@ Y_UNIT_TEST_SUITE(TJsonDecoderTest) { UNIT_ASSERT_VALUES_EQUAL(histogram->Value(0), 21); } } -} +} diff --git a/library/cpp/monlib/encode/json/json_encoder.cpp b/library/cpp/monlib/encode/json/json_encoder.cpp index 20d2bb6283..db39a2a910 100644 --- a/library/cpp/monlib/encode/json/json_encoder.cpp +++ b/library/cpp/monlib/encode/json/json_encoder.cpp @@ -9,7 +9,7 @@ #include <library/cpp/json/writer/json.h> -#include <util/charset/utf8.h> +#include <util/charset/utf8.h> #include <util/generic/algorithm.h> namespace NMonitoring { @@ -245,12 +245,12 @@ namespace NMonitoring { private: void OnStreamBegin() override { - State_.Expect(TEncoderState::EState::ROOT); + State_.Expect(TEncoderState::EState::ROOT); Buf_.BeginObject(); } void OnStreamEnd() override { - State_.Expect(TEncoderState::EState::ROOT); + State_.Expect(TEncoderState::EState::ROOT); if (!Buf_.KeyExpected()) { // not closed metrics array Buf_.EndList(); @@ -259,7 +259,7 @@ namespace NMonitoring { } void OnCommonTime(TInstant time) override { - State_.Expect(TEncoderState::EState::ROOT); + State_.Expect(TEncoderState::EState::ROOT); WriteTime(time); } @@ -298,8 +298,8 @@ namespace NMonitoring { // not closed metrics or timeseries array if labels go after values Buf_.EndList(); } - if (State_ == TEncoderState::EState::ROOT) { - State_ = TEncoderState::EState::COMMON_LABELS; + if (State_ == TEncoderState::EState::ROOT) { + State_ = TEncoderState::EState::COMMON_LABELS; Buf_.WriteKey(TStringBuf(Style_ == EJsonStyle::Solomon ? "commonLabels" : "labels")); } else if (State_ == TEncoderState::EState::METRIC) { State_ = TEncoderState::EState::METRIC_LABELS; @@ -315,8 +315,8 @@ namespace NMonitoring { void OnLabelsEnd() override { if (State_ == TEncoderState::EState::METRIC_LABELS) { State_ = TEncoderState::EState::METRIC; - } else if (State_ == TEncoderState::EState::COMMON_LABELS) { - State_ = TEncoderState::EState::ROOT; + } else if (State_ == TEncoderState::EState::COMMON_LABELS) { + State_ = TEncoderState::EState::ROOT; } else { State_.ThrowInvalid("expected LABELS or COMMON_LABELS"); } @@ -430,16 +430,16 @@ namespace NMonitoring { Close(); } - void OnLabelsBegin() override { - TBufferedEncoderBase::OnLabelsBegin(); - EmptyLabels_ = true; - } - + void OnLabelsBegin() override { + TBufferedEncoderBase::OnLabelsBegin(); + EmptyLabels_ = true; + } + void OnLabel(TStringBuf name, TStringBuf value) override { - TBufferedEncoderBase::OnLabel(name, value); - EmptyLabels_ = false; - } - + TBufferedEncoderBase::OnLabel(name, value); + EmptyLabels_ = false; + } + void OnLabel(ui32 name, ui32 value) override { TBufferedEncoderBase::OnLabel(name, value); EmptyLabels_ = false; @@ -447,10 +447,10 @@ namespace NMonitoring { void OnLabelsEnd() override { TBufferedEncoderBase::OnLabelsEnd(); - Y_ENSURE(!EmptyLabels_, "Labels cannot be empty"); + Y_ENSURE(!EmptyLabels_, "Labels cannot be empty"); } - void Close() final { + void Close() final { if (Closed_) { return; } @@ -534,7 +534,7 @@ namespace NMonitoring { private: bool Closed_{false}; - bool EmptyLabels_ = false; + bool EmptyLabels_ = false; }; } diff --git a/library/cpp/monlib/encode/json/json_ut.cpp b/library/cpp/monlib/encode/json/json_ut.cpp index 09e7909289..5de8470fcf 100644 --- a/library/cpp/monlib/encode/json/json_ut.cpp +++ b/library/cpp/monlib/encode/json/json_ut.cpp @@ -559,21 +559,21 @@ Y_UNIT_TEST_SUITE(TJsonTest) { } } - Y_UNIT_TEST(DecodeToEncoder) { - auto testJson = NResource::Find("/test_decode_to_encode.json"); - - TStringStream Stream_; - auto encoder = BufferedEncoderJson(&Stream_, 4); - DecodeJson(testJson, encoder.Get()); - - encoder->Close(); - - auto val1 = NJson::ReadJsonFastTree(testJson, true); - auto val2 = NJson::ReadJsonFastTree(Stream_.Str(), true); - - UNIT_ASSERT_VALUES_EQUAL(val1, val2); - } - + Y_UNIT_TEST(DecodeToEncoder) { + auto testJson = NResource::Find("/test_decode_to_encode.json"); + + TStringStream Stream_; + auto encoder = BufferedEncoderJson(&Stream_, 4); + DecodeJson(testJson, encoder.Get()); + + encoder->Close(); + + auto val1 = NJson::ReadJsonFastTree(testJson, true); + auto val2 = NJson::ReadJsonFastTree(Stream_.Str(), true); + + UNIT_ASSERT_VALUES_EQUAL(val1, val2); + } + void WriteEmptySeries(const IMetricEncoderPtr& e) { e->OnStreamBegin(); { @@ -1033,12 +1033,12 @@ Y_UNIT_TEST_SUITE(TJsonTest) { AssertPointEqual(s.GetPoints(1), now + TDuration::Seconds(15), *logHist); } - void HistogramValueDecode(const TString& filePath) { + void HistogramValueDecode(const TString& filePath) { NProto::TMultiSamplesList samples; { IMetricEncoderPtr e = EncoderProtobuf(&samples); - TString testJson = NResource::Find(filePath); + TString testJson = NResource::Find(filePath); DecodeJson(testJson, e.Get()); } @@ -1059,11 +1059,11 @@ Y_UNIT_TEST_SUITE(TJsonTest) { AssertPointEqual(s.GetPoints(0), now, *h->Snapshot()); } - Y_UNIT_TEST(HistogramValueDecode) { - HistogramValueDecode("/histogram_value.json"); - HistogramValueDecode("/histogram_value_inf_before_bounds.json"); - } - + Y_UNIT_TEST(HistogramValueDecode) { + HistogramValueDecode("/histogram_value.json"); + HistogramValueDecode("/histogram_value_inf_before_bounds.json"); + } + Y_UNIT_TEST(HistogramTimeSeriesEncode) { auto writeDocument = [](IMetricEncoder* e) { e->OnStreamBegin(); diff --git a/library/cpp/monlib/encode/json/typed_point.h b/library/cpp/monlib/encode/json/typed_point.h index fbaa840c4b..8da50217f0 100644 --- a/library/cpp/monlib/encode/json/typed_point.h +++ b/library/cpp/monlib/encode/json/typed_point.h @@ -45,7 +45,7 @@ namespace NMonitoring { return *this; } - TTypedPoint(TTypedPoint&& rhs) noexcept + TTypedPoint(TTypedPoint&& rhs) noexcept : Time_(rhs.Time_) , ValueType_(rhs.ValueType_) , Value_(rhs.Value_) @@ -54,7 +54,7 @@ namespace NMonitoring { rhs.Value_ = {}; } - TTypedPoint& operator=(TTypedPoint&& rhs) noexcept { + TTypedPoint& operator=(TTypedPoint&& rhs) noexcept { UnRef(); Time_ = rhs.Time_; 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 1d27efacb0..cdcca789fe 100644 --- a/library/cpp/monlib/encode/json/ut/buffered_ts_merge.json +++ b/library/cpp/monlib/encode/json/ut/buffered_ts_merge.json @@ -7,7 +7,7 @@ { "foo":"bar" }, - "value":45 + "value":45 } ] } diff --git a/library/cpp/monlib/encode/json/ut/histogram_value_inf_before_bounds.json b/library/cpp/monlib/encode/json/ut/histogram_value_inf_before_bounds.json index f8a17c8831..7fb99fe768 100644 --- a/library/cpp/monlib/encode/json/ut/histogram_value_inf_before_bounds.json +++ b/library/cpp/monlib/encode/json/ut/histogram_value_inf_before_bounds.json @@ -1,33 +1,33 @@ -{ - "sensors": - [ - { - "kind":"HIST", - "labels": - { +{ + "sensors": + [ + { + "kind":"HIST", + "labels": + { "metric":"responseTimeMillis" - }, - "ts":1509843723, - "hist": - { - "inf":83, - "bounds": - [ - 1, - 2, - 4, - 8, - 16 - ], - "buckets": - [ - 1, - 1, - 2, - 4, - 8 - ] - } - } - ] -} + }, + "ts":1509843723, + "hist": + { + "inf":83, + "bounds": + [ + 1, + 2, + 4, + 8, + 16 + ], + "buckets": + [ + 1, + 1, + 2, + 4, + 8 + ] + } + } + ] +} diff --git a/library/cpp/monlib/encode/json/ut/test_decode_to_encode.json b/library/cpp/monlib/encode/json/ut/test_decode_to_encode.json index 65f0c5c6e2..d127981c97 100644 --- a/library/cpp/monlib/encode/json/ut/test_decode_to_encode.json +++ b/library/cpp/monlib/encode/json/ut/test_decode_to_encode.json @@ -1,16 +1,16 @@ -{ - "commonLabels": { - "project": "solomon", - "cluster": "man", - "service": "stockpile" - }, - "sensors": [ - { - "kind": "GAUGE", +{ + "commonLabels": { + "project": "solomon", + "cluster": "man", + "service": "stockpile" + }, + "sensors": [ + { + "kind": "GAUGE", "labels": { "export": "Oxygen", "metric": "QueueSize" }, - "ts": 1509885296, - "value": 3.14159 - } - ], - "ts": 1503837296 -} + "ts": 1509885296, + "value": 3.14159 + } + ], + "ts": 1503837296 +} diff --git a/library/cpp/monlib/encode/json/ut/ya.make b/library/cpp/monlib/encode/json/ut/ya.make index e50c4f4903..bfa12d159e 100644 --- a/library/cpp/monlib/encode/json/ut/ya.make +++ b/library/cpp/monlib/encode/json/ut/ya.make @@ -6,7 +6,7 @@ OWNER( ) SRCS( - json_decoder_ut.cpp + json_decoder_ut.cpp json_ut.cpp ) @@ -21,12 +21,12 @@ RESOURCE( 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 + histogram_value_inf_before_bounds.json /histogram_value_inf_before_bounds.json int_gauge.json /int_gauge.json sensors.json /sensors.json metrics.json /metrics.json named_metrics.json /named_metrics.json - test_decode_to_encode.json /test_decode_to_encode.json + test_decode_to_encode.json /test_decode_to_encode.json crash.json /crash.json hist_crash.json /hist_crash.json summary_value.json /summary_value.json @@ -38,7 +38,7 @@ RESOURCE( PEERDIR( library/cpp/json - library/cpp/monlib/consumers + library/cpp/monlib/consumers library/cpp/monlib/encode/protobuf library/cpp/resource ) diff --git a/library/cpp/monlib/encode/json/ya.make b/library/cpp/monlib/encode/json/ya.make index a50fc412a9..9229ff1292 100644 --- a/library/cpp/monlib/encode/json/ya.make +++ b/library/cpp/monlib/encode/json/ya.make @@ -11,9 +11,9 @@ SRCS( ) PEERDIR( - library/cpp/monlib/encode - library/cpp/monlib/encode/buffered - library/cpp/monlib/exception + library/cpp/monlib/encode + library/cpp/monlib/encode/buffered + library/cpp/monlib/exception library/cpp/json library/cpp/json/writer ) |