Skip to content

Commit 6561612

Browse files
authored
Clean up derived metrics (#39)
1 parent 395b6dd commit 6561612

File tree

9 files changed

+148
-210
lines changed

9 files changed

+148
-210
lines changed

examples/4-RateDerivedMetric.cxx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,16 @@
66
#include "Monitoring/MonitoringFactory.h"
77

88
using Monitoring = o2::monitoring::MonitoringFactory;
9+
using DerivedMetricMode = o2::monitoring::DerivedMetricMode;
910

1011
int main() {
1112
// Configure monitoring
1213
// Pass string with list of URLs as parameter
1314
auto monitoring = Monitoring::Get("infologger://");
1415

15-
// derived metric : rate
16-
monitoring->addDerivedMetric("myMetric", o2::monitoring::DerivedMetricMode::RATE);
17-
1816
// now send at least two metrics to see the result
1917
for (int i = 0; i < 101; i += 10) {
20-
monitoring->send({i, "myMetric"});
18+
monitoring->send({i, "myMetric"}, DerivedMetricMode::RATE);
2119
std::this_thread::sleep_for(std::chrono::milliseconds(250));
2220
}
2321
}

examples/6-Increment.cxx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
///
2-
/// \file 1-Basic.cxx
2+
/// \file 6-Increment.cxx
33
/// \author Adam Wegrzynek <[email protected]>
44
///
55

66
#include "Monitoring/MonitoringFactory.h"
77

88
using Monitoring = o2::monitoring::MonitoringFactory;
9+
using DerivedMetricMode = o2::monitoring::DerivedMetricMode;
910

1011
int main() {
1112
// Configure monitoring
1213
// Pass string with list of URLs as parameter
1314
auto monitoring = Monitoring::Get("infologger://");
1415

15-
// now send an application specific metric
16-
// 10 is the value
17-
// myMetric is the name of the metric
18-
//
19-
// 1. by copying values
20-
monitoring->increment(10, "myIncrementMetric");
21-
monitoring->increment(5, "myIncrementMetric");
22-
monitoring->increment(15, "myIncrementMetric");
16+
monitoring->send({10, "myIncrementMetric"}, DerivedMetricMode::INCREMENT);
17+
monitoring->send({5, "myIncrementMetric"}, DerivedMetricMode::INCREMENT);
18+
monitoring->send({15, "myIncrementMetric"}, DerivedMetricMode::INCREMENT);
2319
}

include/Monitoring/DerivedMetrics.h

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#ifndef ALICEO2_MONITORING_CORE_DERIVED_METRICS_H
77
#define ALICEO2_MONITORING_CORE_DERIVED_METRICS_H
88

9-
#include <map>
9+
#include <unordered_map>
1010
#include <memory>
1111
#include <string>
1212
#include <vector>
@@ -20,7 +20,7 @@ namespace monitoring
2020
{
2121

2222
/// Available derived metric modes : RATE and AVERAGE values
23-
enum class DerivedMetricMode { RATE, AVERAGE, NONE };
23+
enum class DerivedMetricMode { RATE, INCREMENT, NONE };
2424

2525
/// Calculates derived metrics
2626
///
@@ -31,47 +31,19 @@ class DerivedMetrics
3131
{
3232
public:
3333
/// Default constructor
34-
DerivedMetrics(const unsigned int cacheSize);
34+
DerivedMetrics() = default;
3535

3636
/// Default destructor
3737
~DerivedMetrics() = default;
3838

39-
/// States whether metric has been registered or not
40-
/// \param name metric name
41-
/// \return true when metric is present in mRegistered, false otherwise
42-
bool isRegistered(std::string name);
43-
44-
/// Registers metric to be processed (adds its name to mRegistered map)
45-
/// Processing modes are enumerated in DerivedMetricMode class
46-
/// \param name name, metrics name
47-
/// \param mode mode, see DerivedMetricMode
48-
void registerMetric(std::string name, DerivedMetricMode mode);
49-
50-
/// Handles actual metric processing; finds out whether metric needs to be processed or not
51-
/// If yes, passing it to one of methods that handles calculation of derived metric
52-
/// \param metric reference to metric instance
53-
/// \return metric object with calculated derived metric in it
54-
Metric processMetric(Metric& metric);
55-
56-
private:
5739
/// Calculates rate value based on metrics stored in mCache map
5840
/// \param name metric name
5941
/// \return metric with calculated rate value
60-
Metric calculateRate(std::string name);
61-
62-
/// Calculates average value based on metrics stored in mCache map
63-
/// \param name metric name
64-
/// \return metric with calculated average value
65-
Metric calculateAverage(std::string name);
66-
67-
/// maximum size of cache map
68-
const unsigned int mMaxVectorSize;
42+
Metric rate(Metric& metric);
43+
Metric increment(Metric& metric);
6944

7045
/// Cache of registered metrics (metric name / vector of metric pointers).
71-
std::map <std::string, std::vector<Metric>> mCache;
72-
73-
/// Registered metrics with their modes (metric name, registered mode).
74-
std::map <std::string, DerivedMetricMode> mRegistered;
46+
std::unordered_map <std::string, Metric> mStorage;
7547
};
7648

7749
} // namespace monitoring

include/Monitoring/Monitoring.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,10 @@ class Monitoring
6060
/// \param metrics list of metrics
6161
void send(std::string name, std::vector<Metric>&& metrics);
6262

63-
/// Adds metric to derived metric list - each time the metric arrives the derived metric is calculated and pushed to all backends
64-
/// Following processing modes are supported: DerivedMetricMode::RATE, DerivedMetricMode::AVERAGE
65-
/// \param name metric name
66-
/// \param mode mode
67-
void addDerivedMetric(std::string name, DerivedMetricMode mode);
68-
6963
/// Enables process monitoring
7064
/// \param interval refresh interval
7165
void enableProcessMonitoring(int interval = 5);
7266

73-
/// Increment value of a metric (or initialize if not exists)
74-
/// \@param value incremental value
75-
/// \@param name name of the metric
76-
template<typename T>
77-
void increment(T value, std::string name);
78-
7967
/// Starts timing
8068
/// Sets a start timestamp and timeout
8169
/// \@param name metric name
@@ -94,9 +82,6 @@ class Monitoring
9482
/// Vector of backends (where metrics are passed to)
9583
std::vector <std::unique_ptr<Backend>> mBackends;
9684

97-
/// Cache for the metric increment feature
98-
std::unordered_map <std::string, Metric> mIncrementCache;
99-
10085
/// List of timers
10186
std::unordered_map <std::string, std::chrono::time_point<std::chrono::steady_clock>> mTimers;
10287

@@ -112,10 +97,6 @@ class Monitoring
11297
/// Process Monitor thread loop
11398
/// \param interval sleep time in seconds
11499
void processMonitorLoop(int interval);
115-
116-
/// Increments metrics, stores calculated value in cache
117-
template<typename T>
118-
Metric incrementMetric(T value, std::string name);
119100
};
120101

121102
} // namespace monitoring

src/DerivedMetrics.cxx

Lines changed: 33 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -15,91 +15,64 @@
1515
#include <vector>
1616
#include "MonLogger.h"
1717
#include "VariantVisitorRate.h"
18+
#include "VariantVisitorAdd.h"
1819

1920
namespace o2
2021
{
2122
/// ALICE O2 Monitoring system
2223
namespace monitoring
2324
{
2425

25-
DerivedMetrics::DerivedMetrics(const unsigned int cacheSize) : mMaxVectorSize(cacheSize)
26+
Metric DerivedMetrics::rate(Metric& metric)
2627
{
27-
}
28-
29-
void DerivedMetrics::registerMetric(std::string name, DerivedMetricMode mode)
30-
{
31-
mRegistered.emplace(std::pair<std::string, DerivedMetricMode>(name, mode));
32-
MonLogger::Get() << "Monitoring : Metric " << name << " added to derived metrics"
33-
<< MonLogger::End();
34-
}
35-
36-
bool DerivedMetrics::isRegistered(std::string name)
37-
{
38-
auto search = mRegistered.find(name);
39-
return (search != mRegistered.end());
40-
}
28+
// disallow string
29+
std::string name = metric.getName();
30+
if (metric.getType() == MetricType::STRING) {
31+
throw MonitoringInternalException("DerivedMetrics/ProcessMetric", "Not able to process string values");
32+
}
4133

42-
Metric DerivedMetrics::calculateRate(std::string name)
43-
{
44-
auto search = mCache.find(name);
45-
int size = search->second.size();
46-
if (search == mCache.end() || size < 2) {
47-
throw MonitoringInternalException("DerivedMetrics/Calculate rate", "Not enough values");
34+
// search for previous value
35+
auto search = mStorage.find(name);
36+
if (search == mStorage.end()) {
37+
mStorage.insert(std::make_pair(name, metric));
38+
return Metric{(double) 0.0, name + "Rate"};
4839
}
4940

5041
auto timestampDifference = std::chrono::duration_cast<std::chrono::milliseconds>(
51-
search->second.at(size - 1).getTimestamp()
52-
- search->second.at(size - 2).getTimestamp()
42+
metric.getTimestamp()
43+
- search->second.getTimestamp()
5344
);
54-
boost::variant< int, std::string, double, uint64_t > current = search->second.at(size - 1).getValue();
55-
boost::variant< int, std::string, double, uint64_t > previous = search->second.at(size - 2).getValue();
5645
int timestampCount = timestampDifference.count();
57-
5846
// disallow dividing by 0
5947
if (timestampCount == 0) {
6048
throw MonitoringInternalException("DerivedMetrics/Calculate rate", "Division by 0");
6149
}
6250

51+
auto current = metric.getValue();
52+
auto previous = search->second.getValue();
6353
auto rate = boost::apply_visitor(VariantVisitorRate(timestampCount), current, previous);
64-
return Metric{rate, name + "Rate"};
65-
}
6654

67-
Metric DerivedMetrics::calculateAverage(std::string name)
68-
{
69-
double total = 0;
70-
for (auto& m : mCache.at(name)) {
71-
total += boost::lexical_cast<double>(m.getValue());
72-
}
73-
double average = total / mCache.at(name).size();
74-
return Metric{average, name + "Average"};
55+
// swap metrics
56+
mStorage.erase(name);
57+
mStorage.insert(std::make_pair(name, metric));
58+
59+
return Metric{rate, name + "Rate"};
7560
}
7661

77-
Metric DerivedMetrics::processMetric(Metric& metric)
78-
{
62+
Metric DerivedMetrics::increment(Metric& metric) {
7963
std::string name = metric.getName();
80-
if (metric.getType() == MetricType::STRING) {
81-
throw MonitoringInternalException("DerivedMetrics/ProcessMetric", "Not able to process string values");
82-
}
83-
auto search = mCache.find(name);
84-
// create vector if this is first metric of this kind
85-
if (search == mCache.end()) {
86-
mCache.emplace(std::make_pair(name, std::vector<Metric>()));
87-
}
88-
// remove first value if vector too large
89-
if (mCache.at(name).size() > mMaxVectorSize) {
90-
mCache.at(name).erase( mCache.at(name).begin() );
91-
}
92-
mCache[name].push_back(metric);
93-
94-
auto derived = mRegistered.find(name);
95-
if (derived->second == DerivedMetricMode::RATE) {
96-
return calculateRate(name);
97-
}
98-
else if (derived->second == DerivedMetricMode::AVERAGE) {
99-
return calculateAverage(name);
100-
} else {
101-
throw MonitoringInternalException("DerivedMetrics/ProcessMetric", "Processing mode not supported");
64+
auto search = mStorage.find(name);
65+
if (search != mStorage.end()) {
66+
auto currentValue = metric.getValue();
67+
auto storedValue = search->second.getValue();
68+
auto value = boost::apply_visitor(VariantVisitorAdd(), currentValue, storedValue);
69+
mStorage.erase(search);
70+
Metric result = Metric{value, name};
71+
mStorage.insert(std::make_pair(name, result));
72+
return result;
10273
}
74+
mStorage.insert(std::make_pair(name, metric));
75+
return metric;
10376
}
10477

10578
} // namespace monitoring

src/Monitoring.cxx

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace monitoring
3636

3737
Monitoring::Monitoring() {
3838
mProcessMonitor = std::make_unique<ProcessMonitor>();
39-
mDerivedHandler = std::make_unique<DerivedMetrics>(1000);
39+
mDerivedHandler = std::make_unique<DerivedMetrics>();
4040
}
4141

4242
void Monitoring::enableProcessMonitoring(int interval) {
@@ -71,24 +71,6 @@ void Monitoring::stopAndSendTimer(std::string name) {
7171
}
7272
}
7373

74-
template<typename T>
75-
Metric Monitoring::incrementMetric(T value, std::string name) {
76-
auto search = mIncrementCache.find(name);
77-
if (search != mIncrementCache.end()) {
78-
T current = boost::lexical_cast<T>(search->second.getValue());
79-
value += current;
80-
mIncrementCache.erase(search);
81-
}
82-
Metric result = Metric{value, name};
83-
mIncrementCache.insert(std::make_pair(name, result));
84-
return result;
85-
}
86-
87-
template<typename T>
88-
void Monitoring::increment(T value, std::string name) {
89-
send(incrementMetric(value, name));
90-
}
91-
9274
void Monitoring::addBackend(std::unique_ptr<Backend> backend) {
9375
ProcessDetails processDetails{};
9476
backend->addGlobalTag("hostname", processDetails.getHostname());
@@ -124,10 +106,6 @@ void Monitoring::processMonitorLoop(int interval)
124106
}
125107
}
126108

127-
void Monitoring::addDerivedMetric(std::string name, DerivedMetricMode mode) {
128-
mDerivedHandler->registerMetric(name, mode);
129-
}
130-
131109
void Monitoring::send(std::string measurement, std::vector<Metric>&& metrics)
132110
{
133111
for (auto& b: mBackends) {
@@ -137,21 +115,18 @@ void Monitoring::send(std::string measurement, std::vector<Metric>&& metrics)
137115

138116
void Monitoring::send(Metric&& metric, DerivedMetricMode mode)
139117
{
118+
if (mode == DerivedMetricMode::RATE) {
119+
metric = mDerivedHandler->rate(metric);
120+
}
121+
122+
if (mode == DerivedMetricMode::INCREMENT) {
123+
metric = mDerivedHandler->increment(metric);
124+
}
125+
140126
for (auto& b: mBackends) {
141127
b->send(metric);
142128
}
143-
if (mDerivedHandler->isRegistered(metric.getName())) {
144-
try {
145-
Metric&& derived = mDerivedHandler->processMetric(metric);
146-
for (auto& b: mBackends) {
147-
b->send(derived);
148-
}
149-
} catch (MonitoringInternalException&) { }
150-
}
151129
}
152130

153-
template void Monitoring::increment(int, std::string);
154-
template void Monitoring::increment(double, std::string);
155-
template void Monitoring::increment(uint64_t, std::string);
156131
} // namespace monitoring
157132
} // namespace o2

0 commit comments

Comments
 (0)