123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- #include "metric_registry.h"
- #include <library/cpp/monlib/encode/protobuf/protobuf.h>
- #include <library/cpp/monlib/encode/json/json.h>
- #include <library/cpp/resource/resource.h>
- #include <library/cpp/testing/unittest/registar.h>
- #include <util/stream/str.h>
- using namespace NMonitoring;
- template<>
- void Out<NMonitoring::NProto::TSingleSample::ValueCase>(IOutputStream& os, NMonitoring::NProto::TSingleSample::ValueCase val) {
- switch (val) {
- case NMonitoring::NProto::TSingleSample::ValueCase::kInt64:
- os << "Int64";
- break;
- case NMonitoring::NProto::TSingleSample::ValueCase::kUint64:
- os << "Uint64";
- break;
- case NMonitoring::NProto::TSingleSample::ValueCase::kHistogram:
- os << "Histogram";
- break;
- case NMonitoring::NProto::TSingleSample::ValueCase::kFloat64:
- os << "Float64";
- break;
- case NMonitoring::NProto::TSingleSample::ValueCase::kSummaryDouble:
- os << "DSummary";
- break;
- case NMonitoring::NProto::TSingleSample::ValueCase::kLogHistogram:
- os << "LogHistogram";
- break;
- case NMonitoring::NProto::TSingleSample::ValueCase::VALUE_NOT_SET:
- os << "NOT SET";
- break;
- }
- }
- namespace {
- template<typename F>
- auto EnsureIdempotent(F&& f) {
- auto firstResult = f();
- auto secondResult = f();
- UNIT_ASSERT_VALUES_EQUAL(firstResult, secondResult);
- return secondResult;
- }
- }
- Y_UNIT_TEST_SUITE(TMetricRegistryTest) {
- Y_UNIT_TEST(Gauge) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- TGauge* g = EnsureIdempotent([&] { return registry.Gauge({{"my", "gauge"}}); });
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), 0.0, 1E-6);
- g->Set(12.34);
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), 12.34, 1E-6);
- double val;
- val = g->Add(1.2);
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), 13.54, 1E-6);
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), val, 1E-6);
- val = g->Add(-3.47);
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), 10.07, 1E-6);
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), val, 1E-6);
- }
- Y_UNIT_TEST(LazyGauge) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- double val = 0.0;
- TLazyGauge* g = EnsureIdempotent([&] { return registry.LazyGauge({{"my", "lazyGauge"}}, [&val](){return val;}); });
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), 0.0, 1E-6);
- val = 12.34;
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), 12.34, 1E-6);
- val += 1.2;
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), 13.54, 1E-6);
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), val, 1E-6);
- val += -3.47;
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), 10.07, 1E-6);
- UNIT_ASSERT_DOUBLES_EQUAL(g->Get(), val, 1E-6);
- }
- Y_UNIT_TEST(IntGauge) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- TIntGauge* g = EnsureIdempotent([&] { return registry.IntGauge({{"my", "gauge"}}); });
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), 0);
- i64 val;
- val = g->Inc();
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), 1);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), val);
- val = g->Dec();
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), 0);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), val);
- val = g->Add(1);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), 1);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), val);
- val = g->Add(2);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), 3);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), val);
- val = g->Add(-5);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), -2);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), val);
- }
- Y_UNIT_TEST(LazyIntGauge) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- i64 val = 0;
- TLazyIntGauge* g = EnsureIdempotent([&] { return registry.LazyIntGauge({{"my", "gauge"}}, [&val](){return val;}); });
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), 0);
- val += 1;
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), 1);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), val);
- val -= 1;
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), 0);
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), val);
- val = 42;
- UNIT_ASSERT_VALUES_EQUAL(g->Get(), val);
- }
- Y_UNIT_TEST(Counter) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- TCounter* c = EnsureIdempotent([&] { return registry.Counter({{"my", "counter"}}); });
- UNIT_ASSERT_VALUES_EQUAL(c->Get(), 0);
- UNIT_ASSERT_VALUES_EQUAL(c->Inc(), 1);
- UNIT_ASSERT_VALUES_EQUAL(c->Get(), 1);
- UNIT_ASSERT_VALUES_EQUAL(c->Add(10), 11);
- UNIT_ASSERT_VALUES_EQUAL(c->Get(), 11);
- }
- Y_UNIT_TEST(LazyCounter) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- ui64 val = 0;
- TLazyCounter* c = EnsureIdempotent([&] { return registry.LazyCounter({{"my", "counter"}}, [&val](){return val;}); });
- UNIT_ASSERT_VALUES_EQUAL(c->Get(), 0);
- val = 42;
- UNIT_ASSERT_VALUES_EQUAL(c->Get(), 42);
- }
- Y_UNIT_TEST(LazyRate) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- ui64 val = 0;
- TLazyRate* r = EnsureIdempotent([&] { return registry.LazyRate({{"my", "rate"}}, [&val](){return val;}); });
- UNIT_ASSERT_VALUES_EQUAL(r->Get(), 0);
- val = 42;
- UNIT_ASSERT_VALUES_EQUAL(r->Get(), 42);
- }
- Y_UNIT_TEST(DoubleCounter) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- TCounter* c = registry.Counter({{"my", "counter"}});
- UNIT_ASSERT_VALUES_EQUAL(c->Get(), 0);
- c->Add(10);
- c = registry.Counter({{"my", "counter"}});
- UNIT_ASSERT_VALUES_EQUAL(c->Get(), 10);
- }
- Y_UNIT_TEST(Sample) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- TGauge* g = registry.Gauge({{"my", "gauge"}});
- g->Set(12.34);
- TCounter* c = registry.Counter({{"my", "counter"}});
- c->Add(10);
- NProto::TSingleSamplesList samples;
- auto encoder = EncoderProtobuf(&samples);
- auto now = TInstant::Now();
- registry.Accept(now, encoder.Get());
- UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 2);
- UNIT_ASSERT_VALUES_EQUAL(samples.CommonLabelsSize(), 1);
- {
- const NProto::TLabel& label = samples.GetCommonLabels(0);
- UNIT_ASSERT_STRINGS_EQUAL(label.GetName(), "common");
- UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "label");
- }
- for (const NProto::TSingleSample& sample : samples.GetSamples()) {
- UNIT_ASSERT_VALUES_EQUAL(sample.LabelsSize(), 1);
- UNIT_ASSERT_VALUES_EQUAL(sample.GetTime(), now.MilliSeconds());
- if (sample.GetMetricType() == NProto::GAUGE) {
- UNIT_ASSERT_VALUES_EQUAL(sample.GetValueCase(), NProto::TSingleSample::kFloat64);
- UNIT_ASSERT_DOUBLES_EQUAL(sample.GetFloat64(), 12.34, 1E-6);
- const NProto::TLabel& label = sample.GetLabels(0);
- UNIT_ASSERT_STRINGS_EQUAL(label.GetName(), "my");
- UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "gauge");
- } else if (sample.GetMetricType() == NProto::COUNTER) {
- UNIT_ASSERT_VALUES_EQUAL(sample.GetValueCase(), NProto::TSingleSample::kUint64);
- UNIT_ASSERT_VALUES_EQUAL(sample.GetUint64(), 10);
- const NProto::TLabel& label = sample.GetLabels(0);
- UNIT_ASSERT_STRINGS_EQUAL(label.GetName(), "my");
- UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "counter");
- } else {
- UNIT_FAIL("unexpected sample type");
- }
- }
- }
- Y_UNIT_TEST(Histograms) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- THistogram* h1 = EnsureIdempotent([&] {
- return registry.HistogramCounter(
- {{"sensor", "readTimeMillis"}},
- ExponentialHistogram(5, 2));
- });
- THistogram* h2 = EnsureIdempotent([&] {
- return registry.HistogramRate(
- {{"sensor", "writeTimeMillis"}},
- ExplicitHistogram({1, 5, 15, 20, 25}));
- });
- for (i64 i = 0; i < 100; i++) {
- h1->Record(i);
- h2->Record(i);
- }
- TStringStream ss;
- {
- auto encoder = EncoderJson(&ss, 2);
- registry.Accept(TInstant::Zero(), encoder.Get());
- }
- ss << '\n';
- UNIT_ASSERT_NO_DIFF(ss.Str(), NResource::Find("/histograms.json"));
- }
- Y_UNIT_TEST(HistogramsFabric) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- bool called = false;
- auto collector = [&]() {
- called = true;
- return ExponentialHistogram(5, 2);
- };
- THistogram* h1 = registry.HistogramCounter(
- {{"sensor", "readTimeMillis"}},
- collector);
- UNIT_ASSERT_VALUES_EQUAL(called, true);
- called = false;
- h1 = registry.HistogramCounter(
- {{"sensor", "readTimeMillis"}},
- collector);
- UNIT_ASSERT_VALUES_EQUAL(called, false);
- THistogram* h2 = registry.HistogramRate(
- {{"sensor", "writeTimeMillis"}},
- ExplicitHistogram({1, 5, 15, 20, 25}));
- for (i64 i = 0; i < 100; i++) {
- h1->Record(i);
- h2->Record(i);
- }
- TStringStream ss;
- {
- auto encoder = EncoderJson(&ss, 2);
- registry.Accept(TInstant::Zero(), encoder.Get());
- }
- ss << '\n';
- UNIT_ASSERT_NO_DIFF(ss.Str(), NResource::Find("/histograms.json"));
- }
- Y_UNIT_TEST(StreamingEncoderTest) {
- const TString expected {
- "{\"commonLabels\":{\"common\":\"label\"},"
- "\"sensors\":[{\"kind\":\"GAUGE\",\"labels\":{\"my\":\"gauge\"},\"value\":12.34}]}"
- };
- TMetricRegistry registry(TLabels{{"common", "label"}});
- TGauge* g = registry.Gauge({{"my", "gauge"}});
- g->Set(12.34);
- TStringStream os;
- auto encoder = EncoderJson(&os);
- registry.Accept(TInstant::Zero(), encoder.Get());
- UNIT_ASSERT_STRINGS_EQUAL(os.Str(), expected);
- }
- Y_UNIT_TEST(CreatingSameMetricWithDifferentTypesShouldThrow) {
- TMetricRegistry registry;
- registry.Gauge({{"foo", "bar"}});
- UNIT_ASSERT_EXCEPTION(registry.Counter({{"foo", "bar"}}), yexception);
- registry.HistogramCounter({{"bar", "baz"}}, ExponentialHistogram(5, 2));
- UNIT_ASSERT_EXCEPTION(registry.HistogramRate({{"bar", "baz"}}, ExponentialHistogram(5, 2)), yexception);
- }
- Y_UNIT_TEST(EncodeRegistryWithCommonLabels) {
- TMetricRegistry registry(TLabels{{"common", "label"}});
- TGauge* g = registry.Gauge({{"my", "gauge"}});
- g->Set(12.34);
- // Append() adds common labels to each metric, allowing to combine
- // several metric registries in one resulting blob
- {
- TStringStream os;
- auto encoder = EncoderJson(&os);
- encoder->OnStreamBegin();
- registry.Append(TInstant::Zero(), encoder.Get());
- encoder->OnStreamEnd();
- UNIT_ASSERT_STRINGS_EQUAL(
- os.Str(),
- "{\"sensors\":[{\"kind\":\"GAUGE\",\"labels\":{\"common\":\"label\",\"my\":\"gauge\"},\"value\":12.34}]}");
- }
- // Accept() adds common labels to the beginning of the blob
- {
- TStringStream os;
- auto encoder = EncoderJson(&os);
- registry.Accept(TInstant::Zero(), encoder.Get());
- UNIT_ASSERT_STRINGS_EQUAL(
- os.Str(),
- "{\"commonLabels\":{\"common\":\"label\"},"
- "\"sensors\":[{\"kind\":\"GAUGE\",\"labels\":{\"my\":\"gauge\"},\"value\":12.34}]}");
- }
- }
- Y_UNIT_TEST(MetricsRegistryClear) {
- TMetricRegistry registry;
- registry.Gauge({{"some", "label"}})->Add(1);
- NProto::TSingleSamplesList samples;
- auto encoder = EncoderProtobuf(&samples);
- registry.Accept(TInstant::Now(), encoder.Get());
- UNIT_ASSERT(samples.SamplesSize() == 1);
- samples = {};
- registry.Clear();
- registry.Accept(TInstant::Now(), encoder.Get());
- UNIT_ASSERT(samples.SamplesSize() == 0);
- }
- Y_UNIT_TEST(AssignNewRegistry) {
- TMetricRegistry registry;
- registry.Gauge({{"some", "label"}})->Add(1);
- NProto::TSingleSamplesList samples;
- auto encoder = EncoderProtobuf(&samples);
- registry.Accept(TInstant::Now(), encoder.Get());
- UNIT_ASSERT(samples.CommonLabelsSize() == 0);
- UNIT_ASSERT(samples.SamplesSize() == 1);
- samples = {};
- auto newRegistry = TMetricRegistry{{{"common", "label"}}};
- registry = std::move(newRegistry);
- registry.Accept(TInstant::Now(), encoder.Get());
- const auto& commonLabels = samples.GetCommonLabels();
- UNIT_ASSERT(samples.GetSamples().size() == 0);
- UNIT_ASSERT(commonLabels.size() == 1);
- UNIT_ASSERT(commonLabels[0].GetName() == "common");
- UNIT_ASSERT(commonLabels[0].GetValue() == "label");
- }
- }
|