123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845 |
- #include "spack_v1.h"
- #include <library/cpp/monlib/encode/protobuf/protobuf.h>
- #include <library/cpp/monlib/metrics/labels.h>
- #include <library/cpp/monlib/metrics/metric.h>
- #include <library/cpp/testing/unittest/registar.h>
- #include <util/generic/buffer.h>
- #include <util/stream/buffer.h>
- #include <util/string/hex.h>
- #include <utility>
- using namespace NMonitoring;
- #define UNIT_ASSERT_BINARY_EQUALS(a, b) \
- do { \
- auto size = Y_ARRAY_SIZE(b); \
- if (Y_UNLIKELY(::memcmp(a, b, size) != 0)) { \
- auto as = HexEncode(a, size); \
- auto bs = HexEncode(b, size); \
- UNIT_FAIL_IMPL("equal assertion failed " #a " == " #b, \
- "\n actual: " << as << "\nexpected: " << bs); \
- } \
- } while (0)
- 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 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);
- }
- Y_UNIT_TEST_SUITE(TSpackTest) {
- ui8 expectedHeader_v1_0[] = {
- 0x53, 0x50, // magic "SP" (fixed ui16)
- // minor, major
- 0x00, 0x01, // version (fixed ui16)
- 0x18, 0x00, // header size (fixed ui16)
- 0x00, // time precision (fixed ui8)
- 0x00, // compression algorithm (fixed ui8)
- 0x0d, 0x00, 0x00, 0x00, // label names size (fixed ui32)
- 0x40, 0x00, 0x00, 0x00, // labels values size (fixed ui32)
- 0x08, 0x00, 0x00, 0x00, // metric count (fixed ui32)
- 0x08, 0x00, 0x00, 0x00, // points count (fixed ui32)
- };
- ui8 expectedHeader[] = {
- 0x53, 0x50, // magic "SP" (fixed ui16)
- // minor, major
- 0x01, 0x01, // version (fixed ui16)
- 0x18, 0x00, // header size (fixed ui16)
- 0x00, // time precision (fixed ui8)
- 0x00, // compression algorithm (fixed ui8)
- 0x0d, 0x00, 0x00, 0x00, // label names size (fixed ui32)
- 0x40, 0x00, 0x00, 0x00, // labels values size (fixed ui32)
- 0x08, 0x00, 0x00, 0x00, // metric count (fixed ui32)
- 0x08, 0x00, 0x00, 0x00, // points count (fixed ui32)
- };
- ui8 expectedStringPools[] = {
- 0x6e, 0x61, 0x6d, 0x65, 0x00, // "name\0"
- 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x00, // "project\0"
- 0x73, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x00, // "solomon\0"
- 0x71, 0x31, 0x00, // "q1\0"
- 0x71, 0x32, 0x00, // "q2\0"
- 0x71, 0x33, 0x00, // "q3\0"
- 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x00, // "answer\0"
- 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, // "responseTimeMillis\0"
- 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x6c, 0x6c,
- 0x69, 0x73, 0x00,
- 0x62, 0x79, 0x74, 0x65, 0x73, 0x00, // "bytes\0"
- 0x74, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, // "temperature\0"
- 0x75, 0x72, 0x65, 0x00,
- 0x6d, 0x73, 0x00, // "ms\0"
- };
- ui8 expectedCommonTime[] = {
- 0x00, 0x2f, 0x68, 0x59, // common time in seconds (fixed ui32)
- };
- ui8 expectedCommonLabels[] = {
- 0x01, // common labels count (varint)
- 0x01, // label name index (varint)
- 0x00, // label value index (varint)
- };
- ui8 expectedMetric1[] = {
- 0x0C, // types (RATE | NONE) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (varint)
- 0x00, // label name index (varint)
- 0x01, // label value index (varint)
- };
- ui8 expectedMetric2[] = {
- 0x09, // types (COUNTER | ONE_WITHOUT_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (varint)
- 0x00, // label name index (varint)
- 0x02, // label value index (varint)
- 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value (fixed ui64)
- };
- ui8 expectedMetric3[] = {
- 0x0a, // types (COUNTER | ONE_WITH_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (varint)
- 0x00, // label name index (varint)
- 0x03, // label value index (varint)
- 0x0b, 0x63, 0xfe, 0x59, // time in seconds (fixed ui32)
- 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value (fixed ui64)
- };
- ui8 expectedMetric4[] = {
- 0x07, // types (GAUGE | MANY_WITH_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (varint)
- 0x00, // label name index (varint)
- 0x04, // label value index (varint)
- 0x02, // points count (varint)
- 0x0b, 0x63, 0xfe, 0x59, // time in seconds (fixed ui32)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, // value (double IEEE754)
- 0x1a, 0x63, 0xfe, 0x59, // time in seconds (fixed ui32)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4d, 0x40 // value (double IEEE754)
- };
- ui8 expectedMetric5_v1_0[] = {
- 0x16, // types (HIST | ONE_WITH_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (varint)
- 0x00, // label name index (varint)
- 0x05, // label value index (varint)
- 0x0b, 0x63, 0xfe, 0x59, // time in seconds (fixed ui32)
- 0x06, // histogram buckets count (varint)
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // histogram bucket bounds (array of fixed ui64)
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // histogram bucket values
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
- ui8 expectedMetric5[] = {
- 0x16, // types (HIST | ONE_WITH_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (varint)
- 0x00, // label name index (varint)
- 0x05, // label value index (varint)
- 0x0b, 0x63, 0xfe, 0x59, // time in seconds (fixed ui32)
- 0x06, // histogram buckets count (varint)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, // histogram bucket bounds (array of doubles)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // histogram bucket values
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
- ui8 expectedMetric6[] = {
- 0x12, // types (IGAUGE | ONE_WITH_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (varint)
- 0x00, // label name index (varint)
- 0x06, // label value index (varint)
- 0x0b, 0x63, 0xfe, 0x59, // time in seconds (fixed ui32)
- 0x39, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value (fixed i64)
- };
- ui8 expectedMetric7[] = {
- 0x1e, // types (DSUMMARY | ONE_WITH_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (varint)
- 0x00, // label name index (varint)
- 0x07, // label value index (varint)
- 0x0b, 0x63, 0xfe, 0x59, // time in seconds (fixed ui32)
- 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // count (fixed ui64)
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x24, 0x40, // sum (fixed double)
- 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xdc, 0xbf, // min (fixed double)
- 0x64, 0x3b, 0xdf, 0x4f, 0x8d, 0x97, 0xde, 0x3f, // max (fixed double)
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xd3, 0x3f, // last (fixed double)
- };
- ui8 expectedMetric8[] = {
- 0x26, // types (LOGHIST | ONE_WITH_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // metric labels count (variant)
- 0x00, // label name index (variant)
- 0x08, // label value index (variant)
- 0x0b, 0x63, 0xfe, 0x59, // time in seconds (fixed ui32)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, // base (fixed double)
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // zerosCount (fixed ui64)
- 0x00, // startPower (variant)
- 0x04, // buckets count (variant)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x3F,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x3F, // bucket values
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x3F,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x3F,
- };
- const size_t expectedSize =
- Y_ARRAY_SIZE(expectedHeader) +
- Y_ARRAY_SIZE(expectedStringPools) +
- Y_ARRAY_SIZE(expectedCommonTime) +
- Y_ARRAY_SIZE(expectedCommonLabels) +
- Y_ARRAY_SIZE(expectedMetric1) +
- Y_ARRAY_SIZE(expectedMetric2) +
- Y_ARRAY_SIZE(expectedMetric3) +
- Y_ARRAY_SIZE(expectedMetric4) +
- Y_ARRAY_SIZE(expectedMetric5) +
- Y_ARRAY_SIZE(expectedMetric6) +
- Y_ARRAY_SIZE(expectedMetric7) +
- Y_ARRAY_SIZE(expectedMetric8);
- const TInstant now = TInstant::ParseIso8601Deprecated("2017-11-05T01:02:03Z");
- // {1: 1, 2: 1, 4: 2, 8: 4, 16: 8, inf: 83}
- IHistogramSnapshotPtr TestHistogram() {
- auto h = ExponentialHistogram(6, 2);
- for (i64 i = 1; i < 100; i++) {
- h->Collect(i);
- }
- return h->Snapshot();
- }
- TLogHistogramSnapshotPtr TestLogHistogram() {
- TVector buckets{0.5, 0.25, 0.25, 0.5};
- return MakeIntrusive<TLogHistogramSnapshot>(1.5, 1u, 0, std::move(buckets));
- }
- ISummaryDoubleSnapshotPtr TestSummaryDouble() {
- return MakeIntrusive<TSummaryDoubleSnapshot>(10.1, -0.45, 0.478, 0.3, 30u);
- }
- Y_UNIT_TEST(Encode) {
- TBuffer buffer;
- TBufferOutput out(buffer);
- auto e = EncoderSpackV1(
- &out, ETimePrecision::SECONDS, ECompression::IDENTITY);
- e->OnStreamBegin();
- { // common time
- e->OnCommonTime(TInstant::Seconds(1500000000));
- }
- { // common labels
- e->OnLabelsBegin();
- e->OnLabel("project", "solomon");
- e->OnLabelsEnd();
- }
- { // metric #1
- e->OnMetricBegin(EMetricType::RATE);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "q1");
- e->OnLabelsEnd();
- }
- e->OnMetricEnd();
- }
- { // metric #2
- e->OnMetricBegin(EMetricType::COUNTER);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "q2");
- e->OnLabelsEnd();
- }
- // Only the last value will be encoded
- e->OnUint64(TInstant::Zero(), 10);
- e->OnUint64(TInstant::Zero(), 13);
- e->OnUint64(TInstant::Zero(), 17);
- e->OnMetricEnd();
- }
- { // metric #3
- e->OnMetricBegin(EMetricType::COUNTER);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "q3");
- e->OnLabelsEnd();
- }
- e->OnUint64(now, 10);
- e->OnUint64(now, 13);
- e->OnUint64(now, 17);
- e->OnMetricEnd();
- }
- { // metric #4
- e->OnMetricBegin(EMetricType::GAUGE);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "answer");
- e->OnLabelsEnd();
- }
- e->OnDouble(now, 42);
- e->OnDouble(now + TDuration::Seconds(15), 59);
- e->OnMetricEnd();
- }
- { // metric #5
- e->OnMetricBegin(EMetricType::HIST);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "responseTimeMillis");
- e->OnLabelsEnd();
- }
- auto histogram = TestHistogram();
- e->OnHistogram(now, histogram);
- e->OnMetricEnd();
- }
- { // metric #6
- e->OnMetricBegin(EMetricType::IGAUGE);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "bytes");
- e->OnLabelsEnd();
- }
- e->OnInt64(now, 1337);
- e->OnMetricEnd();
- }
- { // metric 7
- e->OnMetricBegin(EMetricType::DSUMMARY);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "temperature");
- e->OnLabelsEnd();
- }
- e->OnSummaryDouble(now, TestSummaryDouble());
- e->OnMetricEnd();
- }
- { // metric 8
- e->OnMetricBegin(EMetricType::LOGHIST);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "ms");
- e->OnLabelsEnd();
- }
- e->OnLogHistogram(now, TestLogHistogram());
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- e->Close();
- // Cout << "encoded: " << HexEncode(buffer.Data(), buffer.Size()) << Endl;
- // Cout << "size: " << buffer.Size() << Endl;
- UNIT_ASSERT_VALUES_EQUAL(buffer.Size(), expectedSize);
- ui8* p = reinterpret_cast<ui8*>(buffer.Data());
- UNIT_ASSERT_BINARY_EQUALS(p, expectedHeader);
- p += Y_ARRAY_SIZE(expectedHeader);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedStringPools);
- p += Y_ARRAY_SIZE(expectedStringPools);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedCommonTime);
- p += Y_ARRAY_SIZE(expectedCommonTime);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedCommonLabels);
- p += Y_ARRAY_SIZE(expectedCommonLabels);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedMetric1);
- p += Y_ARRAY_SIZE(expectedMetric1);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedMetric2);
- p += Y_ARRAY_SIZE(expectedMetric2);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedMetric3);
- p += Y_ARRAY_SIZE(expectedMetric3);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedMetric4);
- p += Y_ARRAY_SIZE(expectedMetric4);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedMetric5);
- p += Y_ARRAY_SIZE(expectedMetric5);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedMetric6);
- p += Y_ARRAY_SIZE(expectedMetric6);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedMetric7);
- p += Y_ARRAY_SIZE(expectedMetric7);
- UNIT_ASSERT_BINARY_EQUALS(p, expectedMetric8);
- p += Y_ARRAY_SIZE(expectedMetric8);
- }
- NProto::TMultiSamplesList GetMergingMetricSamples(EMetricsMergingMode mergingMode) {
- TBuffer buffer;
- TBufferOutput out(buffer);
- auto e = EncoderSpackV1(
- &out,
- ETimePrecision::SECONDS,
- ECompression::IDENTITY,
- mergingMode
- );
- e->OnStreamBegin();
- for (size_t i = 0; i != 3; ++i) {
- e->OnMetricBegin(EMetricType::COUNTER);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "my_counter");
- e->OnLabelsEnd();
- }
- e->OnUint64(TInstant::Zero() + TDuration::Seconds(i), i + 1);
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- e->Close();
- NProto::TMultiSamplesList samples;
- IMetricEncoderPtr eProto = EncoderProtobuf(&samples);
- TBufferInput in(buffer);
- DecodeSpackV1(&in, eProto.Get());
- return samples;
- }
- Y_UNIT_TEST(SpackEncoderMergesMetrics) {
- {
- NProto::TMultiSamplesList samples = GetMergingMetricSamples(EMetricsMergingMode::DEFAULT);
- UNIT_ASSERT_EQUAL(samples.SamplesSize(), 3);
- UNIT_ASSERT_EQUAL(samples.GetSamples(0).GetPoints(0).GetUint64(), 1);
- UNIT_ASSERT_EQUAL(samples.GetSamples(1).GetPoints(0).GetUint64(), 2);
- UNIT_ASSERT_EQUAL(samples.GetSamples(2).GetPoints(0).GetUint64(), 3);
- }
- {
- NProto::TMultiSamplesList samples = GetMergingMetricSamples(EMetricsMergingMode::MERGE_METRICS);
- UNIT_ASSERT_EQUAL(samples.SamplesSize(), 1);
- auto sample0 = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(sample0.GetPoints(0).GetUint64(), 1);
- UNIT_ASSERT_EQUAL(sample0.GetPoints(1).GetUint64(), 2);
- UNIT_ASSERT_EQUAL(sample0.GetPoints(2).GetUint64(), 3);
- }
- }
- void DecodeDataToSamples(NProto::TMultiSamplesList & samples, ui16 version) {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TBuffer data(expectedSize);
- if (SV1_00 == version) { // v1.0
- data.Append(reinterpret_cast<char*>(expectedHeader_v1_0), Y_ARRAY_SIZE(expectedHeader_v1_0));
- } else {
- data.Append(reinterpret_cast<char*>(expectedHeader), Y_ARRAY_SIZE(expectedHeader));
- }
- data.Append(reinterpret_cast<char*>(expectedStringPools), Y_ARRAY_SIZE(expectedStringPools));
- data.Append(reinterpret_cast<char*>(expectedCommonTime), Y_ARRAY_SIZE(expectedCommonTime));
- data.Append(reinterpret_cast<char*>(expectedCommonLabels), Y_ARRAY_SIZE(expectedCommonLabels));
- data.Append(reinterpret_cast<char*>(expectedMetric1), Y_ARRAY_SIZE(expectedMetric1));
- data.Append(reinterpret_cast<char*>(expectedMetric2), Y_ARRAY_SIZE(expectedMetric2));
- data.Append(reinterpret_cast<char*>(expectedMetric3), Y_ARRAY_SIZE(expectedMetric3));
- data.Append(reinterpret_cast<char*>(expectedMetric4), Y_ARRAY_SIZE(expectedMetric4));
- if (SV1_00 == version) { // v1.0
- data.Append(reinterpret_cast<char*>(expectedMetric5_v1_0), Y_ARRAY_SIZE(expectedMetric5_v1_0));
- } else {
- data.Append(reinterpret_cast<char*>(expectedMetric5), Y_ARRAY_SIZE(expectedMetric5));
- }
- data.Append(reinterpret_cast<char*>(expectedMetric6), Y_ARRAY_SIZE(expectedMetric6));
- data.Append(reinterpret_cast<char*>(expectedMetric7), Y_ARRAY_SIZE(expectedMetric7));
- data.Append(reinterpret_cast<char*>(expectedMetric8), Y_ARRAY_SIZE(expectedMetric8));
- TBufferInput in(data);
- DecodeSpackV1(&in, e.Get());
- }
- void DecodeDataToSamples(NProto::TMultiSamplesList & samples) {
- TSpackHeader header;
- header.Version = SV1_01;
- DecodeDataToSamples(samples, header.Version);
- }
- Y_UNIT_TEST(Decode) {
- NProto::TMultiSamplesList samples;
- DecodeDataToSamples(samples);
- 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(), 8);
- {
- const NProto::TMultiSample& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::RATE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "name", "q1");
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(1);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::COUNTER);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "name", "q2");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), TInstant::Zero(), ui64(17));
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(2);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::COUNTER);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "name", "q3");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), now, ui64(17));
- }
- {
- 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), "name", "answer");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 2);
- AssertPointEqual(s.GetPoints(0), now, double(42));
- AssertPointEqual(s.GetPoints(1), now + TDuration::Seconds(15), double(59));
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(4);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::HISTOGRAM);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "name", "responseTimeMillis");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- const NProto::TPoint& p = s.GetPoints(0);
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), now.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kHistogram);
- auto histogram = TestHistogram();
- const NProto::THistogram& pointHistogram = p.GetHistogram();
- UNIT_ASSERT_VALUES_EQUAL(pointHistogram.BoundsSize(), histogram->Count());
- UNIT_ASSERT_VALUES_EQUAL(pointHistogram.ValuesSize(), histogram->Count());
- for (size_t i = 0; i < pointHistogram.BoundsSize(); i++) {
- UNIT_ASSERT_DOUBLES_EQUAL(pointHistogram.GetBounds(i), histogram->UpperBound(i), Min<double>());
- UNIT_ASSERT_VALUES_EQUAL(pointHistogram.GetValues(i), histogram->Value(i));
- }
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(5);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::IGAUGE);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "name", "bytes");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), now, i64(1337));
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(6);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::DSUMMARY);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "name", "temperature");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- const NProto::TPoint& p = s.GetPoints(0);
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), now.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kSummaryDouble);
- auto expected = TestSummaryDouble();
- auto actual = p.GetSummaryDouble();
- UNIT_ASSERT_VALUES_EQUAL(expected->GetSum(), actual.GetSum());
- UNIT_ASSERT_VALUES_EQUAL(expected->GetMin(), actual.GetMin());
- UNIT_ASSERT_VALUES_EQUAL(expected->GetMax(), actual.GetMax());
- UNIT_ASSERT_VALUES_EQUAL(expected->GetLast(), actual.GetLast());
- UNIT_ASSERT_VALUES_EQUAL(expected->GetCount(), actual.GetCount());
- }
- {
- const NProto::TMultiSample& s = samples.GetSamples(7);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::LOGHISTOGRAM);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 1);
- AssertLabelEqual(s.GetLabels(0), "name", "ms");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- const NProto::TPoint& p = s.GetPoints(0);
- UNIT_ASSERT_VALUES_EQUAL(p.GetTime(), now.MilliSeconds());
- UNIT_ASSERT_EQUAL(p.GetValueCase(), NProto::TPoint::kLogHistogram);
- auto expected = TestLogHistogram();
- auto actual = p.GetLogHistogram();
- UNIT_ASSERT_VALUES_EQUAL(expected->ZerosCount(), actual.GetZerosCount());
- UNIT_ASSERT_VALUES_EQUAL(expected->Base(), actual.GetBase());
- UNIT_ASSERT_VALUES_EQUAL(expected->StartPower(), actual.GetStartPower());
- UNIT_ASSERT_VALUES_EQUAL(expected->Count(), actual.BucketsSize());
- for (size_t i = 0; i < expected->Count(); ++i) {
- UNIT_ASSERT_VALUES_EQUAL(expected->Bucket(i), actual.GetBuckets(i));
- }
- }
- }
- void TestCompression(ECompression alg) {
- TBuffer buffer;
- {
- TBufferOutput out(buffer);
- auto e = EncoderSpackV1(&out, ETimePrecision::MILLIS, alg);
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::GAUGE);
- {
- e->OnLabelsBegin();
- e->OnLabel("name", "answer");
- e->OnLabelsEnd();
- }
- e->OnDouble(now, 42);
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- e->Close();
- }
- auto* header = reinterpret_cast<const TSpackHeader*>(buffer.Data());
- UNIT_ASSERT_EQUAL(DecodeCompression(header->Compression), alg);
- NProto::TMultiSamplesList samples;
- {
- IMetricEncoderPtr e = EncoderProtobuf(&samples);
- TBufferInput in(buffer);
- DecodeSpackV1(&in, e.Get());
- }
- UNIT_ASSERT_VALUES_EQUAL(
- TInstant::MilliSeconds(samples.GetCommonTime()),
- TInstant::Zero());
- UNIT_ASSERT_VALUES_EQUAL(samples.CommonLabelsSize(), 0);
- UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1);
- {
- 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), "name", "answer");
- AssertPointEqual(s.GetPoints(0), now, 42.0);
- }
- }
- Y_UNIT_TEST(CompressionIdentity) {
- TestCompression(ECompression::IDENTITY);
- }
- Y_UNIT_TEST(CompressionZlib) {
- TestCompression(ECompression::ZLIB);
- }
- Y_UNIT_TEST(CompressionZstd) {
- TestCompression(ECompression::ZSTD);
- }
- Y_UNIT_TEST(CompressionLz4) {
- TestCompression(ECompression::LZ4);
- }
- Y_UNIT_TEST(Decode_v1_0_histograms) {
- // Check that histogram bounds decoded from different versions are the same
- NProto::TMultiSamplesList samples, samples_v1_0;
- DecodeDataToSamples(samples);
- DecodeDataToSamples(samples_v1_0, /*version = */ SV1_00);
- const NProto::THistogram& pointHistogram = samples.GetSamples(4).GetPoints(0).GetHistogram();
- const NProto::THistogram& pointHistogram_v1_0 = samples_v1_0.GetSamples(4).GetPoints(0).GetHistogram();
- for (size_t i = 0; i < pointHistogram.BoundsSize(); i++) {
- UNIT_ASSERT_DOUBLES_EQUAL(pointHistogram.GetBounds(i), pointHistogram_v1_0.GetBounds(i), Min<double>());
- }
- }
- Y_UNIT_TEST(SimpleV12) {
- ui8 expectedSerialized[] = {
- // header
- 0x53, 0x50, // magic "SP" (fixed ui16)
- // minor, major
- 0x02, 0x01, // version (fixed ui16)
- 0x18, 0x00, // header size (fixed ui16)
- 0x00, // time precision (fixed ui8)
- 0x00, // compression algorithm (fixed ui8)
- 0x0A, 0x00, 0x00, 0x00, // label names size (fixed ui32)
- 0x14, 0x00, 0x00, 0x00, // labels values size (fixed ui32)
- 0x01, 0x00, 0x00, 0x00, // metric count (fixed ui32)
- 0x01, 0x00, 0x00, 0x00, // points count (fixed ui32)
- // string pools
- 0x73, 0x00, // "s\0"
- 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x00, // "project\0"
- 0x73, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x00, // "solomon\0"
- 0x74, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, // temperature
- 0x75, 0x72, 0x65, 0x00,
- // common time
- 0x00, 0x2f, 0x68, 0x59, // common time in seconds (fixed ui32)
- // common labels
- 0x00, // common labels count (varint)
- // metric
- 0x09, // types (COUNTER | ONE_WITHOUT_TS) (fixed ui8)
- 0x00, // flags (fixed ui8)
- 0x01, // name index (varint)
- 0x01, // metric labels count (varint)
- 0x01, // 'project' label name index (varint)
- 0x00, // 'project' label value index (varint)
- 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value (fixed ui64)
- };
- // encode
- {
- TBuffer actualSerialized;
- {
- TBufferOutput out(actualSerialized);
- auto e = EncoderSpackV12(
- &out,
- ETimePrecision::SECONDS,
- ECompression::IDENTITY,
- EMetricsMergingMode::DEFAULT,
- "s");
- e->OnStreamBegin();
- e->OnCommonTime(TInstant::Seconds(1500000000));
- {
- e->OnMetricBegin(EMetricType::COUNTER);
- {
- e->OnLabelsBegin();
- e->OnLabel("project", "solomon");
- e->OnLabel("s", "temperature");
- e->OnLabelsEnd();
- }
- // Only the last value will be encoded
- e->OnUint64(TInstant::Zero(), 10);
- e->OnUint64(TInstant::Zero(), 13);
- e->OnUint64(TInstant::Zero(), 17);
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- e->Close();
- }
- UNIT_ASSERT_VALUES_EQUAL(actualSerialized.Size(), Y_ARRAY_SIZE(expectedSerialized));
- UNIT_ASSERT_BINARY_EQUALS(actualSerialized.Data(), expectedSerialized);
- }
- // decode
- {
- NProto::TMultiSamplesList samples;
- {
- auto input = TMemoryInput(expectedSerialized, Y_ARRAY_SIZE(expectedSerialized));
- auto encoder = EncoderProtobuf(&samples);
- DecodeSpackV1(&input, encoder.Get(), "s");
- }
- UNIT_ASSERT_VALUES_EQUAL(TInstant::MilliSeconds(samples.GetCommonTime()),
- TInstant::Seconds(1500000000));
- UNIT_ASSERT_VALUES_EQUAL(samples.CommonLabelsSize(), 0);
- UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1);
- {
- const auto& s = samples.GetSamples(0);
- UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::COUNTER);
- UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
- AssertLabelEqual(s.GetLabels(0), "s", "temperature");
- AssertLabelEqual(s.GetLabels(1), "project", "solomon");
- UNIT_ASSERT_VALUES_EQUAL(s.PointsSize(), 1);
- AssertPointEqual(s.GetPoints(0), TInstant::Zero(), ui64(17));
- }
- }
- }
- Y_UNIT_TEST(V12MissingNameForOneMetric) {
- TBuffer b;
- TBufferOutput out(b);
- auto e = EncoderSpackV12(
- &out,
- ETimePrecision::SECONDS,
- ECompression::IDENTITY,
- EMetricsMergingMode::DEFAULT,
- "s");
- UNIT_ASSERT_EXCEPTION_CONTAINS(
- [&]() {
- e->OnStreamBegin();
- {
- e->OnMetricBegin(EMetricType::COUNTER);
- {
- e->OnLabelsBegin();
- e->OnLabel("s", "s1");
- e->OnLabelsEnd();
- }
- e->OnUint64(TInstant::Zero(), 1);
- e->OnMetricEnd();
- e->OnMetricBegin(EMetricType::COUNTER);
- {
- e->OnLabelsBegin();
- e->OnLabel("project", "solomon");
- e->OnLabel("m", "v");
- e->OnLabelsEnd();
- }
- e->OnUint64(TInstant::Zero(), 2);
- e->OnMetricEnd();
- }
- e->OnStreamEnd();
- e->Close();
- }(),
- yexception,
- "metric name label 's' not found, all metric labels '{m=v, project=solomon}'");
- }
- }
|