123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290 |
- #include "json.h"
- #include <library/cpp/monlib/encode/protobuf/protobuf.h>
- #include <library/cpp/monlib/metrics/labels.h>
- #include <library/cpp/json/json_reader.h>
- #include <library/cpp/resource/resource.h>
- #include <library/cpp/testing/unittest/registar.h>
- #include <util/stream/str.h>
- #include <util/string/builder.h>
- #include <limits>
- using namespace NMonitoring;
- namespace NMonitoring {
- bool operator<(const TLabel& lhs, const TLabel& rhs) {
- return lhs.Name() < rhs.Name() ||
- (lhs.Name() == rhs.Name() && lhs.Value() < rhs.Value());
- }
- }
- namespace {
- void AssertLabels(const NProto::TMultiSample& actual, const TLabels& expected) {
- UNIT_ASSERT_EQUAL(actual.LabelsSize(), expected.Size());
- TSet<TLabel> actualSet;
- TSet<TLabel> expectedSet;
- Transform(expected.begin(), expected.end(), std::inserter(expectedSet, expectedSet.end()), [] (auto&& l) {
- return TLabel{l.Name(), l.Value()};
- });
- const auto& l = actual.GetLabels();
- Transform(std::begin(l), std::end(l), std::inserter(actualSet, std::begin(actualSet)),
- [](auto&& elem) -> TLabel {
- return {elem.GetName(), elem.GetValue()};
- });
- TVector<TLabel> diff;
- SetSymmetricDifference(std::begin(expectedSet), std::end(expectedSet),
- std::begin(actualSet), std::end(actualSet), std::back_inserter(diff));
- if (diff.size() > 0) {
- for (auto&& l : diff) {
- Cerr << l << Endl;
- }
- UNIT_FAIL("Labels don't match");
- }
- }
- void AssertLabelEqual(const NProto::TLabel& l, TStringBuf name, TStringBuf value) {
- UNIT_ASSERT_STRINGS_EQUAL(l.GetName(), name);
- UNIT_ASSERT_STRINGS_EQUAL(l.GetValue(), value);
- }
- void AssertPointEqual(const NProto::TPoint& p, TInstant time, double value) {
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64);
- UNIT_ASSERT_DOUBLES_EQUAL(p.GetFloat64(), value, std::numeric_limits<double>::epsilon());
- }
- void AssertPointEqualNan(const NProto::TPoint& p, TInstant time) {
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64);
- UNIT_ASSERT(std::isnan(p.GetFloat64()));
- }
- void AssertPointEqualInf(const NProto::TPoint& p, TInstant time, int sign) {
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kFloat64);
- UNIT_ASSERT(std::isinf(p.GetFloat64()));
- if (sign < 0) {
- UNIT_ASSERT(p.GetFloat64() < 0);
- }
- }
- void AssertPointEqual(const NProto::TPoint& p, TInstant time, ui64 value) {
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kUint64);
- UNIT_ASSERT_VALUES_EQUAL(p.GetUint64(), value);
- }
- void AssertPointEqual(const NProto::TPoint& p, TInstant time, i64 value) {
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kInt64);
- UNIT_ASSERT_VALUES_EQUAL(p.GetInt64(), value);
- }
- void AssertPointEqual(const NProto::TPoint& p, TInstant time, const IHistogramSnapshot& expected) {
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kHistogram);
- const NProto::THistogram& h = p.GetHistogram();
- UNIT_ASSERT_VALUES_EQUAL(h.BoundsSize(), expected.Count());
- UNIT_ASSERT_VALUES_EQUAL(h.ValuesSize(), expected.Count());
- for (size_t i = 0; i < h.BoundsSize(); i++) {
- UNIT_ASSERT_DOUBLES_EQUAL(h.GetBounds(i), expected.UpperBound(i), Min<double>());
- UNIT_ASSERT_VALUES_EQUAL(h.GetValues(i), expected.Value(i));
- }
- }
- void AssertPointEqual(const NProto::TPoint& p, TInstant time, const TLogHistogramSnapshot& expected) {
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kLogHistogram);
- const double eps = 1e-10;
- const NProto::TLogHistogram& h = p.GetLogHistogram();
- UNIT_ASSERT_DOUBLES_EQUAL(h.GetBase(), expected.Base(), eps);
- UNIT_ASSERT_VALUES_EQUAL(h.GetZerosCount(), expected.ZerosCount());
- UNIT_ASSERT_VALUES_EQUAL(h.GetStartPower(), expected.StartPower());
- UNIT_ASSERT_VALUES_EQUAL(h.BucketsSize(), expected.Count());
- for (size_t i = 0; i < expected.Count(); ++i) {
- UNIT_ASSERT_DOUBLES_EQUAL(h.GetBuckets(i), expected.Bucket(i), eps);
- }
- }
- void AssertPointEqual(const NProto::TPoint& p, TInstant time, const ISummaryDoubleSnapshot& expected) {
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), time.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kSummaryDouble);
- auto actual = p.GetSummaryDouble();
- const double eps = 1e-10;
- UNIT_ASSERT_DOUBLES_EQUAL(actual.GetSum(), expected.GetSum(), eps);
- UNIT_ASSERT_DOUBLES_EQUAL(actual.GetMin(), expected.GetMin(), eps);
- UNIT_ASSERT_DOUBLES_EQUAL(actual.GetMax(), expected.GetMax(), eps);
- UNIT_ASSERT_DOUBLES_EQUAL(actual.GetLast(), expected.GetLast(), eps);
- UNIT_ASSERT_VALUES_EQUAL(actual.GetCount(), expected.GetCount());
- }
- } // namespace
- Y_UNIT_TEST_SUITE(TJsonTest) {
- const TInstant now = TInstant::ParseIso8601Deprecated("2017-11-05T01:02:03Z");
- Y_UNIT_TEST(Encode) {
- auto check = [](bool cloud, bool buffered, TStringBuf expectedResourceKey) {
- TString json;
- TStringOutput out(json);
- auto e = cloud
- ? (buffered ? BufferedEncoderCloudJson(&out, 2, "metric") : EncoderCloudJson(&out, 2, "metric"))
- : (buffered ? BufferedEncoderJson(&out, 2) : EncoderJson(&out, 2));
- e->OnStreamBegin();
- { // common time
- e->OnCommonTime(TInstant::Seconds(1500000000));
- }
- { // common labels
- e->OnLabelsBegin();
- e->OnLabel("project", "solomon");
- e->OnLabelsEnd();
- }
- { // metric #1
- e->OnMetricBegin(EMetricType::COUNTER);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "single");
- e->OnLabel("labels", "l1");
- e->OnLabelsEnd();
- }
- e->OnUint64(now, 17);
- e->OnMetricEnd();
- }
- { // metric #2
- e->OnMetricBegin(EMetricType::RATE);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "single");
- e->OnLabel("labels", "l2");
- e->OnLabelsEnd();
- }
- e->OnUint64(now, 17);
- e->OnMetricEnd();
- }
- { // metric #3
- e->OnMetricBegin(EMetricType::GAUGE);
- e->OnDouble(now, 3.14);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "single");
- e->OnLabel("labels", "l3");
- e->OnLabelsEnd();
- }
- e->OnMetricEnd();
- }
- { // metric #4
- e->OnMetricBegin(EMetricType::IGAUGE);
- e->OnInt64(now, 42);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "single_igauge");
- e->OnLabel("labels", "l4");
- e->OnLabelsEnd();
- }
- e->OnMetricEnd();
- }
- { // metric #5
- e->OnMetricBegin(EMetricType::GAUGE);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "multiple");
- e->OnLabel("labels", "l5");
- e->OnLabelsEnd();
- }
- e->OnDouble(now, std::numeric_limits<double>::quiet_NaN());
- e->OnDouble(now + TDuration::Seconds(15), std::numeric_limits<double>::infinity());
- e->OnDouble(now + TDuration::Seconds(30), -std::numeric_limits<double>::infinity());
- e->OnMetricEnd();
- }
- { // metric #6
- e->OnMetricBegin(EMetricType::COUNTER);
- e->OnUint64(now, 1337);
- e->OnUint64(now + TDuration::Seconds(15), 1338);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "multiple");
- e->OnLabel("labels", "l6");
- e->OnLabelsEnd();
- }
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- e->Close();
- json += "\n";
- auto parseJson = [] (auto buf) {
- NJson::TJsonValue value;
- NJson::ReadJsonTree(buf, &value, true);
- return value;
- };
- const auto expectedJson = NResource::Find(expectedResourceKey);
- UNIT_ASSERT_EQUAL(parseJson(json), parseJson(expectedJson));
- };
- check(false, false, "/expected.json");
- check(false, true, "/expected_buffered.json");
- check(true, false, "/expected_cloud.json");
- check(true, true, "/expected_cloud_buffered.json");
- }
- TLogHistogramSnapshotPtr TestLogHistogram(ui32 v = 1) {
- TVector<double> buckets{0.5 * v, 0.25 * v, 0.25 * v, 0.5 * v};
- return MakeIntrusive<TLogHistogramSnapshot>(1.5, 1u, 0, std::move(buckets));
- }
- Y_UNIT_TEST(HistogramAndSummaryMetricTypesAreNotSupportedByCloudJson) {
- const TInstant now = TInstant::ParseIso8601Deprecated("2017-11-05T01:02:03Z");
- auto emit = [&](IMetricEncoder* encoder, EMetricType metricType) {
- encoder->OnStreamBegin();
- {
- encoder->OnMetricBegin(metricType);
- {
- encoder->OnLabelsBegin();
- encoder->OnLabel("name", "m");
- encoder->OnLabelsEnd();
- }
- switch (metricType) {
- case EMetricType::HIST: {
- auto histogram = ExponentialHistogram(6, 2);
- encoder->OnHistogram(now, histogram->Snapshot());
- break;
- }
- case EMetricType::LOGHIST: {
- auto histogram = TestLogHistogram();
- encoder->OnLogHistogram(now, histogram);
- break;
- }
- case EMetricType::DSUMMARY: {
- auto summary = MakeIntrusive<TSummaryDoubleSnapshot>(10., -0.5, 0.5, 0.3, 30u);
- encoder->OnSummaryDouble(now, summary);
- break;
- }
- default:
- Y_ABORT("unexpected metric type [%s]", ToString(metricType).c_str());
- }
- encoder->OnMetricEnd();
- }
- encoder->OnStreamEnd();
- encoder->Close();
- };
- auto doTest = [&](bool buffered, EMetricType metricType) {
- TString json;
- TStringOutput out(json);
- auto encoder = buffered ? BufferedEncoderCloudJson(&out, 2) : EncoderCloudJson(&out, 2);
- const TString expectedMessage = TStringBuilder()
- << "metric type '" << metricType << "' is not supported by cloud json format";
- UNIT_ASSERT_EXCEPTION_CONTAINS_C(emit(encoder.Get(), metricType), yexception, expectedMessage,
- TString("buffered: ") + ToString(buffered));
- };
- doTest(false, EMetricType::HIST);
- doTest(false, EMetricType::LOGHIST);
- doTest(false, EMetricType::DSUMMARY);
- doTest(true, EMetricType::HIST);
- doTest(true, EMetricType::LOGHIST);
- doTest(true, EMetricType::DSUMMARY);
- }
- Y_UNIT_TEST(MetricsWithDifferentLabelOrderGetMerged) {
- TString json;
- TStringOutput out(json);
- auto e = BufferedEncoderJson(&out, 2);
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::RATE);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "hello");
- e->OnLabel("label", "world");
- e->OnLabelsEnd();
- }
- e->OnUint64(TInstant::Zero(), 0);
- e->OnMetricEnd();
- }
- {
- e->OnMetricBegin(EMetricType::RATE);
- {
- e->OnLabelsBegin();
- e->OnLabel("label", "world");
- e->OnLabel("metric", "hello");
- e->OnLabelsEnd();
- }
- e->OnUint64(TInstant::Zero(), 1);
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- e->Close();
- json += "\n";
- TString expectedJson = NResource::Find("/merged.json");
- // we cannot be sure regarding the label order in the result,
- // so we'll have to parse the expected value and then compare it with actual
- NProto::TMultiSamplesList samples;
- IMetricEncoderPtr d = EncoderProtobuf(&samples);
- DecodeJson(expectedJson, d.Get());
- UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1);
- {
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::RATE);
- AssertLabels(s, TLabels{{"metric", "hello"}, {"label", "world"}});
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), TInstant::Zero(), ui64(1));
- }
- }
- Y_UNIT_TEST(Decode1) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find("/expected.json");
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(
- TInstant::MilliSeconds(samples.GetCommonTime()),
- TInstant::Seconds(1500000000));
- UNIT_ASSERT_VALUES_EQUAL(samples.CommonLabelsSize(), 1);
- AssertLabelEqual(samples.GetCommonLabels(0), "project", "solomon");
- UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 6);
- {
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::COUNTER);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "metric", "single");
- AssertLabelEqual(s.GetLabels(1), "labels", "l1");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), now, ui64(17));
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(1);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::RATE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "metric", "single");
- AssertLabelEqual(s.GetLabels(1), "labels", "l2");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), now, ui64(17));
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(2);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "metric", "single");
- AssertLabelEqual(s.GetLabels(1), "labels", "l3");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), now, 3.14);
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(3);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::IGAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "metric", "single_igauge");
- AssertLabelEqual(s.GetLabels(1), "labels", "l4");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), now, i64(42));
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(4);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "metric", "multiple");
- AssertLabelEqual(s.GetLabels(1), "labels", "l5");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 3);
- AssertPointEqualNan(s.GetPoints(0), now);
- AssertPointEqualInf(s.GetPoints(1), now + TDuration::Seconds(15), 1);
- AssertPointEqualInf(s.GetPoints(2), now + TDuration::Seconds(30), -11);
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(5);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::COUNTER);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "metric", "multiple");
- AssertLabelEqual(s.GetLabels(1), "labels", "l6");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 2);
- AssertPointEqual(s.GetPoints(0), now, ui64(1337));
- AssertPointEqual(s.GetPoints(1), now + TDuration::Seconds(15), ui64(1338));
- }
- }
- Y_UNIT_TEST(DecodeMetrics) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString metricsJson = NResource::Find("/metrics.json");
- DecodeJson(metricsJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(
- TInstant::MilliSeconds(samples.GetCommonTime()),
- TInstant::ParseIso8601Deprecated("2017-08-27T12:34:56Z"));
- UNIT_ASSERT_VALUES_EQUAL(samples.CommonLabelsSize(), 3);
- AssertLabelEqual(samples.GetCommonLabels(0), "project", "solomon");
- AssertLabelEqual(samples.GetCommonLabels(1), "cluster", "man");
- AssertLabelEqual(samples.GetCommonLabels(2), "service", "stockpile");
- UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 4);
- {
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "Memory");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), TInstant::Zero(), 10.0);
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(1);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::RATE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "UserTime");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), TInstant::Zero(), ui64(1));
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(2);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "export", "Oxygen");
- AssertLabelEqual(s.GetLabels(1), "metric", "QueueSize");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- auto ts = TInstant::ParseIso8601Deprecated("2017-11-05T12:34:56.000Z");
- AssertPointEqual(s.GetPoints(0), ts, 3.14159);
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(3);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "Writes");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 2);
- auto ts1 = TInstant::ParseIso8601Deprecated("2017-08-28T12:32:11Z");
- AssertPointEqual(s.GetPoints(0), ts1, -10.0);
- auto ts2 = TInstant::Seconds(1503923187);
- AssertPointEqual(s.GetPoints(1), ts2, 20.0);
- }
- }
- Y_UNIT_TEST(DecodeSensors) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString sensorsJson = NResource::Find("/sensors.json");
- DecodeJson(sensorsJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(
- TInstant::MilliSeconds(samples.GetCommonTime()),
- TInstant::ParseIso8601Deprecated("2017-08-27T12:34:56Z"));
- UNIT_ASSERT_VALUES_EQUAL(samples.CommonLabelsSize(), 3);
- AssertLabelEqual(samples.GetCommonLabels(0), "project", "solomon");
- AssertLabelEqual(samples.GetCommonLabels(1), "cluster", "man");
- AssertLabelEqual(samples.GetCommonLabels(2), "service", "stockpile");
- UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 4);
- {
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "Memory");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), TInstant::Zero(), 10.0);
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(1);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::RATE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "UserTime");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), TInstant::Zero(), ui64(1));
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(2);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "export", "Oxygen");
- AssertLabelEqual(s.GetLabels(1), "metric", "QueueSize");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- auto ts = TInstant::ParseIso8601Deprecated("2017-11-05T12:34:56.000Z");
- AssertPointEqual(s.GetPoints(0), ts, 3.14159);
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(3);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "Writes");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 2);
- auto ts1 = TInstant::ParseIso8601Deprecated("2017-08-28T12:32:11Z");
- AssertPointEqual(s.GetPoints(0), ts1, -10.0);
- auto ts2 = TInstant::Seconds(1503923187);
- AssertPointEqual(s.GetPoints(1), ts2, 20.0);
- }
- }
- 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();
- {
- e->OnMetricBegin(EMetricType::COUNTER);
- {
- e->OnLabelsBegin();
- e->OnLabel("foo", "bar");
- e->OnLabelsEnd();
- }
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- e->Close();
- }
- Y_UNIT_TEST(EncodeEmptySeries) {
- TString json;
- TStringOutput out(json);
- auto e = EncoderJson(&out, 2);
- WriteEmptySeries(e);
- json += "\n";
- TString expectedJson = NResource::Find("/empty_series.json");
- UNIT_ASSERT_NO_DIFF(json, expectedJson);
- }
- void WriteEmptyLabels(IMetricEncoderPtr& e) {
- e->OnStreamBegin();
- e->OnMetricBegin(EMetricType::COUNTER);
- e->OnLabelsBegin();
- UNIT_ASSERT_EXCEPTION(e->OnLabelsEnd(), yexception);
- }
- Y_UNIT_TEST(LabelsCannotBeEmpty) {
- TString json;
- TStringOutput out(json);
- auto e = EncoderJson(&out, 2);
- WriteEmptyLabels(e);
- }
- Y_UNIT_TEST(LabelsCannotBeEmptyBuffered) {
- TString json;
- TStringOutput out(json);
- auto e = BufferedEncoderJson(&out, 2);
- WriteEmptyLabels(e);
- }
- Y_UNIT_TEST(EncodeEmptySeriesBuffered) {
- TString json;
- TStringOutput out(json);
- auto e = BufferedEncoderJson(&out, 2);
- WriteEmptySeries(e);
- json += "\n";
- TString expectedJson = NResource::Find("/empty_series.json");
- UNIT_ASSERT_NO_DIFF(json, expectedJson);
- }
- Y_UNIT_TEST(BufferedEncoderMergesMetrics) {
- TString json;
- TStringOutput out(json);
- auto e = BufferedEncoderJson(&out, 2);
- auto ts = 1;
- auto writeMetric = [&] (const TString& val) {
- e->OnMetricBegin(EMetricType::COUNTER);
- e->OnLabelsBegin();
- e->OnLabel("foo", val);
- e->OnLabelsEnd();
- e->OnUint64(TInstant::Seconds(ts++), 42);
- e->OnMetricEnd();
- };
- e->OnStreamBegin();
- writeMetric("bar");
- writeMetric("bar");
- writeMetric("baz");
- writeMetric("bar");
- e->OnStreamEnd();
- e->Close();
- json += "\n";
- TString expectedJson = NResource::Find("/buffered_test.json");
- UNIT_ASSERT_NO_DIFF(json, expectedJson);
- }
- Y_UNIT_TEST(JsonEncoderDisallowsValuesInTimeseriesWithoutTs) {
- TStringStream out;
- auto e = EncoderJson(&out);
- auto writePreamble = [&] {
- e->OnStreamBegin();
- e->OnMetricBegin(EMetricType::COUNTER);
- e->OnLabelsBegin();
- e->OnLabel("foo", "bar");
- e->OnLabelsEnd();
- };
- // writing two values for a metric in a row will trigger
- // timeseries object construction
- writePreamble();
- e->OnUint64(TInstant::Zero(), 42);
- UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Zero(), 42), yexception);
- e = EncoderJson(&out);
- writePreamble();
- e->OnUint64(TInstant::Zero(), 42);
- UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Now(), 42), yexception);
- e = EncoderJson(&out);
- writePreamble();
- e->OnUint64(TInstant::Now(), 42);
- UNIT_ASSERT_EXCEPTION(e->OnUint64(TInstant::Zero(), 42), yexception);
- }
- Y_UNIT_TEST(BufferedJsonEncoderMergesTimeseriesWithoutTs) {
- TStringStream out;
- {
- auto e = BufferedEncoderJson(&out, 2);
- e->OnStreamBegin();
- e->OnMetricBegin(EMetricType::COUNTER);
- e->OnLabelsBegin();
- e->OnLabel("foo", "bar");
- e->OnLabelsEnd();
- // in buffered mode we are able to find values with same (in this case zero)
- // timestamp and discard duplicates
- e->OnUint64(TInstant::Zero(), 42);
- e->OnUint64(TInstant::Zero(), 43);
- e->OnUint64(TInstant::Zero(), 44);
- e->OnUint64(TInstant::Zero(), 45);
- e->OnMetricEnd();
- e->OnStreamEnd();
- }
- out << "\n";
- UNIT_ASSERT_NO_DIFF(out.Str(), NResource::Find("/buffered_ts_merge.json"));
- }
- template <typename TFactory, typename TConsumer>
- TString EncodeToString(TFactory factory, TConsumer consumer) {
- TStringStream out;
- {
- IMetricEncoderPtr e = factory(&out, 2);
- consumer(e.Get());
- }
- out << '\n';
- return out.Str();
- }
- Y_UNIT_TEST(SummaryValueEncode) {
- auto writeDocument = [](IMetricEncoder* e) {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::DSUMMARY);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "temperature");
- e->OnLabelsEnd();
- }
- e->OnSummaryDouble(now, MakeIntrusive<TSummaryDoubleSnapshot>(10., -0.5, 0.5, 0.3, 30u));
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- };
- TString result1 = EncodeToString(EncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result1, NResource::Find("/summary_value.json"));
- TString result2 = EncodeToString(BufferedEncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result2, NResource::Find("/summary_value.json"));
- }
- ISummaryDoubleSnapshotPtr TestInfSummary() {
- return MakeIntrusive<TSummaryDoubleSnapshot>(
- std::numeric_limits<double>::quiet_NaN(),
- -std::numeric_limits<double>::infinity(),
- std::numeric_limits<double>::infinity(),
- 0.3,
- 30u);
- }
- Y_UNIT_TEST(SummaryInfEncode) {
- auto writeDocument = [](IMetricEncoder* e) {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::DSUMMARY);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "temperature");
- e->OnLabelsEnd();
- }
- e->OnSummaryDouble(now, TestInfSummary());
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- };
- TString result1 = EncodeToString(EncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result1, NResource::Find("/summary_inf.json"));
- TString result2 = EncodeToString(BufferedEncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result2, NResource::Find("/summary_inf.json"));
- }
- Y_UNIT_TEST(SummaryInfDecode) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find("/summary_inf.json");
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(1, samples.SamplesSize());
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::DSUMMARY);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "temperature");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- auto actual = s.GetPoints(0).GetSummaryDouble();
- UNIT_ASSERT(std::isnan(actual.GetSum()));
- UNIT_ASSERT(actual.GetMin() < 0);
- UNIT_ASSERT(std::isinf(actual.GetMin()));
- UNIT_ASSERT(actual.GetMax() > 0);
- UNIT_ASSERT(std::isinf(actual.GetMax()));
- }
- Y_UNIT_TEST(SummaryValueDecode) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find("/summary_value.json");
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(1, samples.SamplesSize());
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::DSUMMARY);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "temperature");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- auto snapshot = TSummaryDoubleSnapshot(10., -0.5, 0.5, 0.3, 30u);
- AssertPointEqual(s.GetPoints(0), now, snapshot);
- }
- Y_UNIT_TEST(SummaryTimeSeriesEncode) {
- auto writeDocument = [](IMetricEncoder* e) {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::DSUMMARY);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "temperature");
- e->OnLabelsEnd();
- }
- TSummaryDoubleCollector summary;
- summary.Collect(0.3);
- summary.Collect(-0.5);
- summary.Collect(1.);
- e->OnSummaryDouble(now, summary.Snapshot());
- summary.Collect(-1.5);
- summary.Collect(0.01);
- e->OnSummaryDouble(now + TDuration::Seconds(15), summary.Snapshot());
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- };
- TString result1 = EncodeToString(EncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result1, NResource::Find("/summary_timeseries.json"));
- TString result2 = EncodeToString(BufferedEncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result2, NResource::Find("/summary_timeseries.json"));
- }
- Y_UNIT_TEST(SummaryTimeSeriesDecode) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find("/summary_timeseries.json");
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(1, samples.SamplesSize());
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::DSUMMARY);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "temperature");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 2);
- TSummaryDoubleCollector summary;
- summary.Collect(0.3);
- summary.Collect(-0.5);
- summary.Collect(1.);
- AssertPointEqual(s.GetPoints(0), now, *summary.Snapshot());
- summary.Collect(-1.5);
- summary.Collect(0.01);
- AssertPointEqual(s.GetPoints(1), now + TDuration::Seconds(15), *summary.Snapshot());
- }
- Y_UNIT_TEST(LogHistogramValueEncode) {
- auto writeDocument = [](IMetricEncoder* e) {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::LOGHIST);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "ms");
- e->OnLabelsEnd();
- }
- e->OnLogHistogram(now, TestLogHistogram());
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- };
- TString result1 = EncodeToString(EncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result1, NResource::Find("/log_histogram_value.json"));
- TString result2 = EncodeToString(BufferedEncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result2, NResource::Find("/log_histogram_value.json"));
- }
- Y_UNIT_TEST(LogHistogramValueDecode) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find("/log_histogram_value.json");
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(1, samples.SamplesSize());
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::LOGHISTOGRAM);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "ms");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- auto snapshot = TestLogHistogram();
- AssertPointEqual(s.GetPoints(0), now, *snapshot);
- }
- Y_UNIT_TEST(HistogramValueEncode) {
- auto writeDocument = [](IMetricEncoder* e) {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::HIST);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "responseTimeMillis");
- e->OnLabelsEnd();
- }
- // {1: 1, 2: 1, 4: 2, 8: 4, 16: 8, inf: 83}
- auto h = ExponentialHistogram(6, 2);
- for (i64 i = 1; i < 100; i++) {
- h->Collect(i);
- }
- e->OnHistogram(now, h->Snapshot());
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- };
- TString result1 = EncodeToString(EncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result1, NResource::Find("/histogram_value.json"));
- TString result2 = EncodeToString(BufferedEncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result2, NResource::Find("/histogram_value.json"));
- }
- Y_UNIT_TEST(LogHistogramTimeSeriesEncode) {
- auto writeDocument = [](IMetricEncoder* e) {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::LOGHIST);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "ms");
- e->OnLabelsEnd();
- }
- e->OnLogHistogram(now, TestLogHistogram(1));;
- e->OnLogHistogram(now + TDuration::Seconds(15), TestLogHistogram(2));
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- };
- TString result1 = EncodeToString(EncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result1, NResource::Find("/log_histogram_timeseries.json"));
- TString result2 = EncodeToString(BufferedEncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result2, NResource::Find("/log_histogram_timeseries.json"));
- }
- Y_UNIT_TEST(LogHistogramTimeSeriesDecode) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find("/log_histogram_timeseries.json");
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(1, samples.SamplesSize());
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::LOGHISTOGRAM);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "ms");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 2);
- auto logHist = TestLogHistogram(1);
- AssertPointEqual(s.GetPoints(0), now, *logHist);
- logHist = TestLogHistogram(2);
- AssertPointEqual(s.GetPoints(1), now + TDuration::Seconds(15), *logHist);
- }
- void HistogramValueDecode(const TString& filePath) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find(filePath);
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(1, samples.SamplesSize());
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::HISTOGRAM);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "responseTimeMillis");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- auto h = ExponentialHistogram(6, 2);
- for (i64 i = 1; i < 100; i++) {
- h->Collect(i);
- }
- 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(HistogramTimeSeriesEncode) {
- auto writeDocument = [](IMetricEncoder* e) {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::HIST_RATE);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "responseTimeMillis");
- e->OnLabelsEnd();
- }
- // {1: 1, 2: 1, 4: 2, 8: 4, 16: 8, inf: 83}
- auto h = ExponentialHistogram(6, 2);
- for (i64 i = 1; i < 100; i++) {
- h->Collect(i);
- }
- e->OnHistogram(now, h->Snapshot());
- // {1: 2, 2: 2, 4: 4, 8: 8, 16: 16, inf: 166}
- for (i64 i = 1; i < 100; i++) {
- h->Collect(i);
- }
- e->OnHistogram(now + TDuration::Seconds(15), h->Snapshot());
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- };
- TString result1 = EncodeToString(EncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result1, NResource::Find("/histogram_timeseries.json"));
- TString result2 = EncodeToString(BufferedEncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result2, NResource::Find("/histogram_timeseries.json"));
- }
- Y_UNIT_TEST(HistogramTimeSeriesDecode) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find("/histogram_timeseries.json");
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(1, samples.SamplesSize());
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::HIST_RATE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "responseTimeMillis");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 2);
- auto h = ExponentialHistogram(6, 2);
- for (i64 i = 1; i < 100; i++) {
- h->Collect(i);
- }
- AssertPointEqual(s.GetPoints(0), now, *h->Snapshot());
- for (i64 i = 1; i < 100; i++) {
- h->Collect(i);
- }
- AssertPointEqual(s.GetPoints(1), now + TDuration::Seconds(15), *h->Snapshot());
- }
- Y_UNIT_TEST(IntGaugeEncode) {
- auto writeDocument = [](IMetricEncoder* e) {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::IGAUGE);
- {
- e->OnLabelsBegin();
- e->OnLabel("metric", "a");
- e->OnLabelsEnd();
- }
- e->OnInt64(now, Min<i64>());
- e->OnInt64(now + TDuration::Seconds(1), -1);
- e->OnInt64(now + TDuration::Seconds(2), 0);
- e->OnInt64(now + TDuration::Seconds(3), Max<i64>());
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- };
- TString result1 = EncodeToString(EncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result1, NResource::Find("/int_gauge.json"));
- TString result2 = EncodeToString(BufferedEncoderJson, writeDocument);
- UNIT_ASSERT_NO_DIFF(result2, NResource::Find("/int_gauge.json"));
- }
- Y_UNIT_TEST(InconsistentMetricTypes) {
- auto emitMetrics = [](IMetricEncoder& encoder, const TString& expectedError) {
- encoder.OnMetricBegin(EMetricType::GAUGE);
- {
- encoder.OnLabelsBegin();
- encoder.OnLabel("name", "m");
- encoder.OnLabel("l1", "v1");
- encoder.OnLabel("l2", "v2");
- encoder.OnLabelsEnd();
- }
- encoder.OnDouble(now, 1.0);
- encoder.OnMetricEnd();
- encoder.OnMetricBegin(EMetricType::COUNTER);
- {
- encoder.OnLabelsBegin();
- encoder.OnLabel("name", "m");
- encoder.OnLabel("l1", "v1");
- encoder.OnLabel("l2", "v2");
- encoder.OnLabelsEnd();
- }
- encoder.OnUint64(now, 1);
- UNIT_ASSERT_EXCEPTION_CONTAINS(encoder.OnMetricEnd(),
- yexception,
- expectedError);
- };
- {
- TStringStream out;
- auto encoder = BufferedEncoderJson(&out);
- encoder->OnStreamBegin();
- encoder->OnLabelsBegin();
- encoder->OnLabel("c", "cv");
- encoder->OnLabelsEnd();
- emitMetrics(*encoder,
- "Time series point type mismatch: expected DOUBLE but found UINT64, "
- "labels '{c=cv, l1=v1, l2=v2, name=m}'");
- }
- {
- TStringStream out;
- auto encoder = BufferedEncoderJson(&out);
- encoder->OnStreamBegin();
- encoder->OnLabelsBegin();
- encoder->OnLabel("l1", "v100");
- encoder->OnLabelsEnd();
- emitMetrics(*encoder,
- "Time series point type mismatch: expected DOUBLE but found UINT64, "
- "labels '{l1=v1, l2=v2, name=m}'");
- }
- }
- Y_UNIT_TEST(IntGaugeDecode) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString testJson = NResource::Find("/int_gauge.json");
- DecodeJson(testJson, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(1, samples.SamplesSize());
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::IGAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "metric", "a");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 4);
- AssertPointEqual(s.GetPoints(0), now, Min<i64>());
- AssertPointEqual(s.GetPoints(1), now + TDuration::Seconds(1), i64(-1));
- AssertPointEqual(s.GetPoints(2), now + TDuration::Seconds(2), i64(0));
- AssertPointEqual(s.GetPoints(3), now + TDuration::Seconds(3), Max<i64>());
- }
- Y_UNIT_TEST(FuzzerRegression) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- for (auto f : { "/hist_crash.json", "/crash.json" }) {
- TString testJson = NResource::Find(f);
- UNIT_ASSERT_EXCEPTION(DecodeJson(testJson, e.Get()), yexception);
- }
- }
- }
- Y_UNIT_TEST(LegacyNegativeRateThrows) {
- const auto input = R"({
- "sensors": [
- {
- "mode": "deriv",
- "value": -1,
- "labels": { "metric": "SystemTime" }
- },
- }
- ]}")";
- NProto::TMultiSamplesList samples;
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- UNIT_ASSERT_EXCEPTION(DecodeJson(input, e.Get()), yexception);
- }
- Y_UNIT_TEST(DecodeNamedMetrics) {
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TString metricsJson = NResource::Find("/named_metrics.json");
- DecodeJson(metricsJson, e.Get(), "sensor");
- }
- UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 2);
- {
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "sensor", "Memory");
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(1);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "sensor", "QueueSize");
- AssertLabelEqual(s.GetLabels(1), "export", "Oxygen");
- }
- }
- }
|