Skip to content

Commit e8acba6

Browse files
committed
using variant visitor to calculate rate
1 parent 69b4916 commit e8acba6

File tree

4 files changed

+104
-21
lines changed

4 files changed

+104
-21
lines changed

src/DerivedMetrics.cxx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,21 @@ Metric DerivedMetrics::calculateRate(std::string name)
4747
if (search == mCache.end() || size < 2) {
4848
throw MonitoringInternalException("DerivedMetrics/Calculate rate", "Not enough values");
4949
}
50-
std::chrono::duration<float> timestampDifference = (search->second.at(size - 1).getTimestamp()
51-
- search->second.at(size - 2).getTimestamp());
52-
5350

54-
double last = boost::lexical_cast<double>(search->second.at(size - 1).getValue());
55-
double beforelast = boost::lexical_cast<double>(search->second.at(size - 2).getValue());
51+
auto timestampDifference = std::chrono::duration_cast<std::chrono::milliseconds>(
52+
search->second.at(size - 1).getTimestamp()
53+
- search->second.at(size - 2).getTimestamp()
54+
);
55+
boost::variant< int, std::string, double, int64_t > current = search->second.at(size - 1).getValue();
56+
boost::variant< int, std::string, double, int64_t > previous = search->second.at(size - 2).getValue();
57+
int timestampCount = timestampDifference.count();
58+
5659
// disallow dividing by 0
57-
if (timestampDifference.count() == 0) {
60+
if (timestampCount == 0) {
5861
throw MonitoringInternalException("DerivedMetrics/Calculate rate", "Division by 0");
5962
}
60-
double rate = (last - beforelast ) / timestampDifference.count();
63+
64+
boost::variant< int, std::string, double, int64_t > rate = boost::apply_visitor(VariantVisitor(timestampCount), current, previous);
6165
return Metric{rate, name + "Rate"};
6266
}
6367

src/Metric.cxx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,15 @@ Metric::Metric(double value, const std::string& name, std::chrono::time_point<st
4242
mValue(value), mName(name), mTimestamp(timestamp)
4343
{}
4444

45-
Metric::Metric(uint64_t value, const std::string& name, std::chrono::time_point<std::chrono::system_clock> timestamp) :
45+
Metric::Metric(int64_t value, const std::string& name, std::chrono::time_point<std::chrono::system_clock> timestamp) :
4646
mValue(value), mName(name), mTimestamp(timestamp)
4747
{}
4848

49-
boost::variant< int, std::string, double, uint64_t > Metric::getValue() const
49+
Metric::Metric(boost::variant< int, std::string, double, int64_t > value, const std::string& name, std::chrono::time_point<std::chrono::system_clock> timestamp) :
50+
mValue(value), mName(name), mTimestamp(timestamp)
51+
{}
52+
53+
boost::variant< int, std::string, double, int64_t > Metric::getValue() const
5054
{
5155
return mValue;
5256
}

src/VariantVisitorRate.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace AliceO2
2+
{
3+
// ALICE O2 Monitoring system
4+
namespace Monitoring
5+
{
6+
7+
class VariantVisitor : public boost::static_visitor<boost::variant<int, std::string, double, int64_t>>
8+
{
9+
private:
10+
int timestampCount;
11+
public:
12+
VariantVisitor(int count) {
13+
timestampCount = count;
14+
}
15+
16+
boost::variant<int, std::string, double, int64_t> operator()(const std::string& a, const std::string& b) const {
17+
std::cout << "skipping string" << std::endl;
18+
}
19+
20+
template<typename T>
21+
boost::variant<int, std::string, double, int64_t> operator()(const T& a, const T& b) const {
22+
return (1000*(a - b)) / timestampCount;
23+
}
24+
25+
template<typename T, typename U>
26+
boost::variant<int, std::string, double, int64_t> operator()(const T& a, const U& b) const {
27+
throw std::invalid_argument("can't operate on different types");
28+
}
29+
};
30+
31+
}
32+
}

test/testDerived.cxx

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ BOOST_AUTO_TEST_CASE(derivedAverage)
2121
std::vector<AverageResults> results = {{10, 10}, {20, 15}, {30, 20}, {40, 25}, {50, 30}, {60, 35}, {70, 40}, {80, 45}, {90, 50}, {100, 55}};
2222
std::string name("metricName");
2323

24-
AliceO2::Monitoring::DerivedMetrics derivedHandler(1000);
24+
AliceO2::Monitoring::DerivedMetrics derivedHandler(100);
2525
derivedHandler.registerMetric(name, AliceO2::Monitoring::DerivedMetricMode::AVERAGE);
2626

2727
for (auto const result : results) {
@@ -32,30 +32,78 @@ BOOST_AUTO_TEST_CASE(derivedAverage)
3232
}
3333
}
3434

35-
BOOST_AUTO_TEST_CASE(derivedRate)
35+
BOOST_AUTO_TEST_CASE(derivedRateInt)
3636
{
3737
struct RateResults {
3838
int value;
39-
int average;
39+
int rate;
4040
};
4141
std::vector<RateResults> results = {{10, 0 }, {20, 100}, {30, 100}, {50, 200}, {60, 100}, {65, 50}, {70, 50}, {80, 100}, {90, 100}, {100, 100}};
42-
AliceO2::Monitoring::DerivedMetrics derivedHandler(1000);
43-
std::string name("metricName");
42+
AliceO2::Monitoring::DerivedMetrics derivedHandler(100);
43+
std::string name("metricInt");
4444
derivedHandler.registerMetric(name, AliceO2::Monitoring::DerivedMetricMode::RATE);
4545

4646
for (auto const result : results) {
4747
try {
4848
std::this_thread::sleep_for(std::chrono::milliseconds(100));
4949
AliceO2::Monitoring::Metric metric(result.value, name);
5050
AliceO2::Monitoring::Metric derived = derivedHandler.processMetric(metric);
51-
BOOST_CHECK_EQUAL(derived.getName(), "metricNameRate");
52-
BOOST_CHECK_CLOSE(boost::get<double>(derived.getValue()), result.average, 1);
51+
BOOST_CHECK_EQUAL(derived.getName(), "metricIntRate");
52+
BOOST_CHECK_EQUAL(boost::get<int>(derived.getValue()), result.rate);
5353
} catch(MonitoringInternalException &e) {
5454
BOOST_TEST(e.what() == std::string("Not enough values"));
5555
}
5656
}
5757
}
5858

59+
BOOST_AUTO_TEST_CASE(derivedRateDouble) {
60+
struct RateResults {
61+
double value;
62+
double rate;
63+
};
64+
std::vector<RateResults> results = {{1.2, 0 }, {11.2, 100}, {21.2, 100}, {41.2, 200}, {51.2, 100}, {61, 98}};
65+
AliceO2::Monitoring::DerivedMetrics derivedHandler(100);
66+
std::string name("metricDouble");
67+
derivedHandler.registerMetric(name, AliceO2::Monitoring::DerivedMetricMode::RATE);
68+
69+
for (auto const result : results) {
70+
try {
71+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
72+
AliceO2::Monitoring::Metric metric(result.value, name);
73+
AliceO2::Monitoring::Metric derived = derivedHandler.processMetric(metric);
74+
BOOST_CHECK_EQUAL(derived.getName(), "metricDoubleRate");
75+
BOOST_CHECK_CLOSE(boost::get<double>(derived.getValue()), result.rate, 0.1);
76+
} catch(MonitoringInternalException &e) {
77+
BOOST_TEST(e.what() == std::string("Not enough values"));
78+
}
79+
}
80+
}
81+
82+
BOOST_AUTO_TEST_CASE(derivedRateInt64_t) {
83+
struct RateResults {
84+
int64_t value;
85+
int64_t rate;
86+
};
87+
std::vector<RateResults> results = {{165535, 0 }, {165545, 100}, {165555, 100}, {165575, 200}, {165585, 100}, {165590, 50}};
88+
AliceO2::Monitoring::DerivedMetrics derivedHandler(100);
89+
std::string name("metricInt64_t");
90+
derivedHandler.registerMetric(name, AliceO2::Monitoring::DerivedMetricMode::RATE);
91+
92+
for (auto const result : results) {
93+
try {
94+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
95+
AliceO2::Monitoring::Metric metric(result.value, name);
96+
AliceO2::Monitoring::Metric derived = derivedHandler.processMetric(metric);
97+
BOOST_CHECK_EQUAL(derived.getName(), "metricInt64_tRate");
98+
BOOST_CHECK_EQUAL(boost::get<int64_t>(derived.getValue()), result.rate);
99+
} catch(MonitoringInternalException &e) {
100+
BOOST_TEST(e.what() == std::string("Not enough values"));
101+
}
102+
}
103+
104+
105+
}
106+
59107
bool exceptionCheck(const MonitoringInternalException &e)
60108
{
61109
if (e.what() == std::string("Not enough values")) return true;
@@ -76,11 +124,6 @@ BOOST_AUTO_TEST_CASE(divisionByZero)
76124

77125
}
78126

79-
BOOST_AUTO_TEST_CASE(stringValue)
80-
{
81-
82-
}
83-
84127
} // namespace Test
85128
} // namespace Monitoring
86129
} // namespace AliceO2

0 commit comments

Comments
 (0)