// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include #include #include #include #include namespace metrics { namespace { struct SubSubMetricSet : public MetricSet { const LoadTypeSet& loadTypes; int incVal; LongCountMetric count1; LongCountMetric count2; LoadMetric loadCount; SumMetric countSum; DoubleValueMetric value1; DoubleValueMetric value2; LoadMetric loadValue; SumMetric valueSum; DoubleAverageMetric average1; DoubleAverageMetric average2; LoadMetric loadAverage; SumMetric averageSum; SubSubMetricSet(vespalib::stringref name, const LoadTypeSet& loadTypes_, MetricSet* owner = 0); ~SubSubMetricSet(); MetricSet* clone(std::vector &ownerList, CopyType copyType, metrics::MetricSet* owner, bool includeUnused) const override; void incValues(); }; SubSubMetricSet::SubSubMetricSet(vespalib::stringref name, const LoadTypeSet& loadTypes_, MetricSet* owner) : MetricSet(name, {}, "", owner), loadTypes(loadTypes_), incVal(1), count1("count1", {}, "", this), count2("count2", {}, "", this), loadCount(loadTypes, LongCountMetric("loadCount", {}, ""), this), countSum("countSum", {}, "", this), value1("value1", {}, "", this), value2("value2", {}, "", this), loadValue(loadTypes, DoubleValueMetric("loadValue", {}, ""), this), valueSum("valueSum", {}, "", this), average1("average1", {}, "", this), average2("average2", {}, "", this), loadAverage(loadTypes, DoubleAverageMetric("loadAverage", {}, ""), this), averageSum("averageSum", {}, "", this) { countSum.addMetricToSum(count1); countSum.addMetricToSum(count2); valueSum.addMetricToSum(value1); valueSum.addMetricToSum(value2); averageSum.addMetricToSum(average1); averageSum.addMetricToSum(average2); } SubSubMetricSet::~SubSubMetricSet() = default; MetricSet* SubSubMetricSet::clone(std::vector &ownerList, CopyType copyType, metrics::MetricSet* owner, bool includeUnused) const { if (copyType == INACTIVE) { return MetricSet::clone(ownerList, INACTIVE, owner, includeUnused); } return (SubSubMetricSet*) (new SubSubMetricSet( getName(), loadTypes, owner)) ->assignValues(*this); } void SubSubMetricSet::incValues() { count1.inc(incVal); count2.inc(incVal); for (uint32_t i=0; i loadSet; SumMetric setSum; SubMetricSet(vespalib::stringref name, const LoadTypeSet& loadTypes_, MetricSet* owner = 0); ~SubMetricSet(); MetricSet* clone(std::vector &ownerList, CopyType copyType, metrics::MetricSet* owner, bool includeUnused) const override; void incValues(); }; SubMetricSet::SubMetricSet(vespalib::stringref name, const LoadTypeSet& loadTypes_, MetricSet* owner) : MetricSet(name, {}, "", owner), loadTypes(loadTypes_), set1("set1", loadTypes, this), set2("set2", loadTypes, this), loadSet(loadTypes, *std::unique_ptr(new SubSubMetricSet("loadSet", loadTypes)), this), setSum("setSum", {}, "", this) { setSum.addMetricToSum(set1); setSum.addMetricToSum(set2); } SubMetricSet::~SubMetricSet() = default; MetricSet* SubMetricSet::clone(std::vector &ownerList, CopyType copyType, metrics::MetricSet* owner, bool includeUnused) const { if (copyType == INACTIVE) { return MetricSet::clone(ownerList, INACTIVE, owner, includeUnused); } return (SubMetricSet*) (new SubMetricSet(getName(), loadTypes, owner)) ->assignValues(*this); } void SubMetricSet::incValues() { set1.incValues(); set2.incValues(); for (uint32_t i=0; i loadSet; SumMetric setSum; TestMetricSet(vespalib::stringref name, const LoadTypeSet& loadTypes_, MetricSet* owner = 0); ~TestMetricSet(); void incValues(); }; TestMetricSet::TestMetricSet(vespalib::stringref name, const LoadTypeSet& loadTypes_, MetricSet* owner) : MetricSet(name, {}, "", owner), loadTypes(loadTypes_), set1("set1", loadTypes, this), set2("set2", loadTypes, this), loadSet(loadTypes, *std::unique_ptr(new SubMetricSet("loadSet", loadTypes)), this), setSum("setSum", {}, "", this) { setSum.addMetricToSum(set1); setSum.addMetricToSum(set2); } TestMetricSet::~TestMetricSet() = default; void TestMetricSet::incValues() { set1.incValues(); set2.incValues(); for (uint32_t i=0; igetLongValue("value"))); } } struct SnapshotTest : public ::testing::Test { time_t tick(MetricManager& mgr, time_t currentTime) { return mgr.tick(mgr.getMetricLock(), currentTime); } }; TEST_F(SnapshotTest, test_snapshot_two_days) { // Create load types LoadTypeSet loadTypes; loadTypes.push_back(LoadType(1, "foo")); loadTypes.push_back(LoadType(2, "bar")); TestMetricSet set("test", loadTypes); FakeTimer* timer; FastOS_ThreadPool threadPool(256 * 1024); MetricManager mm( std::unique_ptr(timer = new FakeTimer)); { MetricLockGuard lockGuard(mm.getMetricLock()); mm.registerMetric(lockGuard, set); } mm.init("raw:consumer[1]\n" "consumer[0].name \"log\"", threadPool, false); tick(mm, timer->_timeInSecs * 1000); for (uint32_t days=0; days<2; ++days) { for (uint32_t hour=0; hour<24; ++hour) { for (uint32_t fiveMin=0; fiveMin<12; ++fiveMin) { set.incValues(); timer->_timeInSecs += 5 * 60; tick(mm, timer->_timeInSecs * 1000); } } } // Print all data. Useful for debugging. It's too much to verify // everything, so test will just verify some parts. Add more parts if you // find a failure. /* std::string regex = ".*"; bool verbose = true; std::cout << "\n" << mm.getActiveMetrics().toString(mm, "", regex, verbose) << "\n\n"; std::vector periods(mm.getSnapshotPeriods()); for (uint32_t i=0; i