#include "legacy_protobuf.h"
#include <library/cpp/testing/unittest/registar.h>
#include <library/cpp/monlib/encode/legacy_protobuf/ut/test_cases.pb.h>
#include <library/cpp/monlib/encode/legacy_protobuf/protos/metric_meta.pb.h>
#include <library/cpp/monlib/encode/protobuf/protobuf.h>
#include <library/cpp/monlib/encode/text/text.h>
#include <library/cpp/monlib/metrics/labels.h>
#include <util/generic/algorithm.h>
#include <util/generic/hash_set.h>
using namespace NMonitoring;
TSimple MakeSimpleMessage() {
TSimple msg;
msg.SetFoo(1);
msg.SetBar(2.);
msg.SetBaz(42.);
return msg;
}
IMetricEncoderPtr debugPrinter = EncoderText(&Cerr);
namespace NMonitoring {
inline bool operator<(const TLabel& lhs, const TLabel& rhs) {
return lhs.Name() < rhs.Name() ||
(lhs.Name() == rhs.Name() && lhs.Value() < rhs.Value());
}
}
void SetLabelValue(NMonProto::TExtraLabelMetrics::TValue& val, TString s) {
val.SetlabelValue(s);
}
void SetLabelValue(NMonProto::TExtraLabelMetrics::TValue& val, ui64 u) {
val.SetlabelValueUint(u);
}
template <typename T, typename V>
NMonProto::TExtraLabelMetrics MakeExtra(TString labelName, V labelValue, T value, bool isDeriv) {
NMonProto::TExtraLabelMetrics metric;
auto* val = metric.Addvalues();
metric.SetlabelName(labelName);
SetLabelValue(*val, labelValue);
if (isDeriv) {
val->SetlongValue(value);
} else {
val->SetdoubleValue(value);
}
return metric;
}
void AssertLabels(const TLabels& expected, const NProto::TMultiSample& actual) {
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 AssertSimpleMessage(const NProto::TMultiSamplesList& samples, TString pathPrefix = "/") {
UNIT_ASSERT_EQUAL(samples.SamplesSize(), 3);
THashSet<TString> expectedValues{pathPrefix + "Foo", pathPrefix + "Bar", pathPrefix + "Baz"};
for (const auto& s : samples.GetSamples()) {
UNIT_ASSERT_EQUAL(s.LabelsSize(), 1);
UNIT_ASSERT_EQUAL(s.PointsSize(), 1);
const auto labelVal = s.GetLabels(0).GetValue();
UNIT_ASSERT(expectedValues.contains(labelVal));
if (labelVal == pathPrefix + "Foo") {
UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 1, 1e-6);
} else if (labelVal == pathPrefix + "Bar") {
UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::GAUGE);
UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 2, 1e-6);
} else if (labelVal == pathPrefix + "Baz") {
UNIT_ASSERT_EQUAL(s.GetMetricType(), NProto::RATE);
UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 42);
}
}
}
Y_UNIT_TEST_SUITE(TLegacyProtoDecoderTest) {
Y_UNIT_TEST(SimpleProto) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
auto msg = MakeSimpleMessage();
DecodeLegacyProto(msg, e.Get());
AssertSimpleMessage(samples);
};
Y_UNIT_TEST(RepeatedProto) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
auto simple = MakeSimpleMessage();
TRepeated msg;
msg.AddMessages()->CopyFrom(simple);
DecodeLegacyProto(msg, e.Get());
AssertSimpleMessage(samples);
}
Y_UNIT_TEST(RepeatedProtoWithPath) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
auto simple = MakeSimpleMessage();
TRepeatedWithPath msg;
msg.AddNamespace()->CopyFrom(simple);
DecodeLegacyProto(msg, e.Get());
AssertSimpleMessage(samples, "/Namespace/");
}
Y_UNIT_TEST(DeepNesting) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
auto simple = MakeSimpleMessage();
TRepeatedWithPath internal;
internal.AddNamespace()->CopyFrom(simple);
TDeepNesting msg;
msg.MutableNested()->CopyFrom(internal);
DecodeLegacyProto(msg, e.Get());
AssertSimpleMessage(samples, "/Namespace/");
}
Y_UNIT_TEST(Keys) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
auto simple = MakeSimpleMessage();
simple.SetLabel("my_label_value");
TNestedWithKeys msg;
msg.AddNamespace()->CopyFrom(simple);
DecodeLegacyProto(msg, e.Get());
auto i = 0;
for (const auto& s : samples.GetSamples()) {
UNIT_ASSERT_EQUAL(s.LabelsSize(), 4);
bool foundLabel = false;
bool foundFixed = false;
bool foundNumbered = false;
for (const auto& label : s.GetLabels()) {
if (label.GetName() == "my_label") {
foundLabel = true;
UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "my_label_value");
} else if (label.GetName() == "fixed_label") {
foundFixed = true;
UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "fixed_value");
} else if (label.GetName() == "numbered") {
foundNumbered = true;
UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), ::ToString(i));
}
}
UNIT_ASSERT(foundLabel);
UNIT_ASSERT(foundFixed);
UNIT_ASSERT(foundNumbered);
}
}
Y_UNIT_TEST(NonStringKeys) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
TNonStringKeys msg;
msg.SetFoo(42);
msg.SetEnum(ENUM);
msg.SetInt(43);
TRepeatedNonStringKeys msgs;
msgs.AddNested()->CopyFrom(msg);
DecodeLegacyProto(msgs, e.Get());
for (const auto& s : samples.GetSamples()) {
bool foundEnum = false;
bool foundInt = false;
for (const auto& label : s.GetLabels()) {
if (label.GetName() == "enum") {
foundEnum = true;
UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "ENUM");
} else if (label.GetName() == "int") {
foundInt = true;
UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "43");
}
}
UNIT_ASSERT(foundEnum);
UNIT_ASSERT(foundInt);
UNIT_ASSERT_DOUBLES_EQUAL(s.GetPoints(0).GetFloat64(), 42, 1e-6);
}
}
Y_UNIT_TEST(KeysFromNonLeafNodes) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
auto simple = MakeSimpleMessage();
simple.SetLabel("label_value");
TRepeatedWithName nested;
nested.SetName("my_name");
nested.AddNested()->CopyFrom(simple);
TKeysFromNonLeaf msg;
msg.AddNested()->CopyFrom(nested);
DecodeLegacyProto(msg, e.Get());
AssertLabels({{"my_label", "label_value"}, {"path", "/Nested/Nested/Foo"}, {"name", "my_name"}}, samples.GetSamples(0));
}
Y_UNIT_TEST(SpacesAreGetReplaced) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
auto simple = MakeSimpleMessage();
simple.SetLabel("my label_value");
TNestedWithKeys msg;
msg.AddNamespace()->CopyFrom(simple);
DecodeLegacyProto(msg, e.Get());
for (const auto& s : samples.GetSamples()) {
UNIT_ASSERT_EQUAL(s.LabelsSize(), 4);
bool foundLabel = false;
for (const auto& label : s.GetLabels()) {
if (label.GetName() == "my_label") {
foundLabel = true;
UNIT_ASSERT_STRINGS_EQUAL(label.GetValue(), "my_label_value");
}
}
UNIT_ASSERT(foundLabel);
}
}
Y_UNIT_TEST(ExtraLabels) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
TExtraLabels msg;
msg.MutableExtraAsIs()->CopyFrom(MakeExtra("label", "foo", 42, false));
msg.MutableExtraDeriv()->CopyFrom(MakeExtra("deriv_label", "deriv_foo", 43, true));
DecodeLegacyProto(msg, e.Get());
UNIT_ASSERT_EQUAL(samples.SamplesSize(), 2);
{
auto s = samples.GetSamples(0);
AssertLabels({{"label", "foo"}, {"path", "/ExtraAsIs"}}, s);
UNIT_ASSERT_EQUAL(s.PointsSize(), 1);
auto point = s.GetPoints(0);
UNIT_ASSERT_DOUBLES_EQUAL(point.GetFloat64(), 42, 1e-6);
}
{
auto s = samples.GetSamples(1);
AssertLabels({{"deriv_label", "deriv_foo"}, {"path", "/ExtraDeriv"}}, s);
UNIT_ASSERT_EQUAL(s.PointsSize(), 1);
auto point = s.GetPoints(0);
UNIT_ASSERT_EQUAL(point.GetUint64(), 43);
}
}
Y_UNIT_TEST(NestedExtraLabels) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
TExtraLabels msg;
auto extra = MakeExtra("label", "foo", 42, false);
auto* val = extra.Mutablevalues(0);
{
auto child = MakeExtra("child1", "label1", 24, true);
child.Mutablevalues(0)->Settype(NMonProto::EMetricType::RATE);
val->Addchildren()->CopyFrom(child);
}
{
auto child = MakeExtra("child2", 34, 23, false);
val->Addchildren()->CopyFrom(child);
}
msg.MutableExtraAsIs()->CopyFrom(extra);
DecodeLegacyProto(msg, e.Get());
UNIT_ASSERT_EQUAL(samples.SamplesSize(), 3);
{
auto s = samples.GetSamples(0);
AssertLabels({{"label", "foo"}, {"path", "/ExtraAsIs"}}, s);
UNIT_ASSERT_EQUAL(s.PointsSize(), 1);
auto point = s.GetPoints(0);
UNIT_ASSERT_DOUBLES_EQUAL(point.GetFloat64(), 42, 1e-6);
}
{
auto s = samples.GetSamples(1);
AssertLabels({{"label", "foo"}, {"child1", "label1"}, {"path", "/ExtraAsIs"}}, s);
UNIT_ASSERT_EQUAL(s.PointsSize(), 1);
auto point = s.GetPoints(0);
UNIT_ASSERT_EQUAL(point.GetUint64(), 24);
}
{
auto s = samples.GetSamples(2);
AssertLabels({{"label", "foo"}, {"child2", "34"}, {"path", "/ExtraAsIs"}}, s);
UNIT_ASSERT_EQUAL(s.PointsSize(), 1);
auto point = s.GetPoints(0);
UNIT_ASSERT_EQUAL(point.GetFloat64(), 23);
}
}
Y_UNIT_TEST(RobotLabels) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
TNamedCounter responses;
responses.SetName("responses");
responses.SetCount(42);
TCrawlerCounters::TStatusCounters statusCounters;
statusCounters.AddZoraResponses()->CopyFrom(responses);
TCrawlerCounters::TPolicyCounters policyCounters;
policyCounters.SetSubComponent("mySubComponent");
policyCounters.SetName("myComponentName");
policyCounters.SetZone("myComponentZone");
policyCounters.MutableStatusCounters()->CopyFrom(statusCounters);
TCrawlerCounters counters;
counters.SetComponent("myComponent");
counters.AddPoliciesCounters()->CopyFrom(policyCounters);
DecodeLegacyProto(counters, e.Get());
UNIT_ASSERT_EQUAL(samples.SamplesSize(), 1);
auto s = samples.GetSamples(0);
AssertLabels({
{"SubComponent", "mySubComponent"}, {"Policy", "myComponentName"}, {"Zone", "myComponentZone"},
{"ZoraResponse", "responses"}, {"path", "/PoliciesCounters/StatusCounters/ZoraResponses/Count"}}, s);
}
Y_UNIT_TEST(ZoraLabels) {
NProto::TMultiSamplesList samples;
IMetricEncoderPtr e = EncoderProtobuf(&samples);
TTimeLogHist hist;
hist.AddBuckets(42);
hist.AddBuckets(0);
TKiwiCounters counters;
counters.MutableTimes()->CopyFrom(hist);
DecodeLegacyProto(counters, e.Get());
UNIT_ASSERT_EQUAL(samples.SamplesSize(), 2);
auto s = samples.GetSamples(0);
AssertLabels({{"slot", "0"}, {"path", "/Times/Buckets"}}, s);
UNIT_ASSERT_EQUAL(s.PointsSize(), 1);
UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 42);
s = samples.GetSamples(1);
AssertLabels({{"slot", "1"}, {"path", "/Times/Buckets"}}, s);
UNIT_ASSERT_EQUAL(s.GetPoints(0).GetUint64(), 0);
}
}