diff options
| author | ivanzhukov <[email protected]> | 2022-02-10 16:49:40 +0300 | 
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:49:40 +0300 | 
| commit | 0892d79ab411592ad25175c4bdadbcb09b466cf5 (patch) | |
| tree | 98dfdd45463c9bd747101748a9ca25d2917390fd /library/cpp/monlib/encode/json | |
| parent | 1b7466cb957659079ebebbb5d76e64e51f3306f0 (diff) | |
Restoring authorship annotation for <[email protected]>. 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 21530f20c37..b76900b8abb 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 d44ff5fd286..7f0d83e018f 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 4464e1d26a4..1f9513664a4 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 20d2bb6283f..db39a2a910e 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 09e79092890..5de8470fcf0 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 fbaa840c4bf..8da50217f08 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 1d27efacb06..cdcca789fe8 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 f8a17c8831c..7fb99fe768f 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 65f0c5c6e21..d127981c97f 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 e50c4f4903b..bfa12d159e8 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 a50fc412a99..9229ff12923 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  ) | 
