Skip to content

Commit b263911

Browse files
authored
Metric buffering (#41)
1 parent b0ea0f2 commit b263911

File tree

6 files changed

+96
-56
lines changed

6 files changed

+96
-56
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ set(EXAMPLES
167167
examples/7-Latency.cxx
168168
examples/8-Multiple.cxx
169169
examples/9-Timer.cxx
170+
examples/10-Buffering.cxx
170171
)
171172

172173
foreach (example ${EXAMPLES})

README.md

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -49,45 +49,7 @@ eval `modulecmd bash load Monitoring/v1.5.0-1`
4949
The installation directory is: `/opt/alisw/el7/Monitoring/v1.5.0-1`
5050

5151
### aliBuild
52-
<details>
53-
<summary><strong>Click here if you don't have <i>aliBuild</i> installed</strong></summary>
54-
<br>
55-
56-
+ Enable Software Collections in order to install `devtoolset-6` which includes `gcc 6.2.0` **(as root)**
57-
~~~
58-
yum install -y centos-release-scl
59-
yum-config-manager --enable rhel-server-rhscl-7-rpms
60-
~~~
61-
62-
+ Install packages required by aliBuild **(as root)**
63-
~~~
64-
yum install -y curl curl-devel python python-devel devtoolset-6 \
65-
python-pip bzip2-devel autoconf automake texinfo git \
66-
gettext-devel libtool freetype freetype-devel libpng \
67-
libpng-devel sqlite sqlite-devel ncurses-devel gettext \
68-
mesa-libGLU-devel libX11-devel libXpm-devel libXext-devel \
69-
libXft-devel libxml2 libxml2-devel environment-modules
70-
~~~
71-
72-
+ Upgrade `pip` and `setuptools`, install [aliBuild](https://alisw.github.io/alibuild/) and missing python packags **(as root)**
73-
~~~
74-
pip install --upgrade pip
75-
pip install -U setuptools
76-
pip install alibuild matplotlib numpy certifi ipython==5.4.1 ipywidgets \
77-
ipykernel notebook metakernel pyyaml
78-
~~~
79-
80-
+ Enable `devtoolset-6`. It's recommened to add it to `~/.basrc` or similar file
81-
~~~
82-
source /opt/rh/devtoolset-6/enable
83-
~~~
84-
85-
+ Set `alienv` root directory and load the environment
86-
~~~
87-
mkdir alice; cd alice
88-
ALICE_WORK_DIR=`pwd`/sw; eval "`alienv shell-helper`"
89-
~~~
90-
</details>
52+
<strong>[Click here if you don't have aliBuild installed](https://alice-doc.github.io/alice-analysis-tutorial/building/)</strong>
9153
<br>
9254

9355
+ Compile `Monitoring` and its dependecies via `aliBuild`
@@ -140,19 +102,16 @@ See table below to find out how to create `URI` for each backend:
140102
| Flume | UDP | `flume` | - |
141103
142104
### Sending metric
143-
Simplified `send` method:
144-
```cpp
145-
send(T value, std::string name)
146-
```
147-
148-
Or more advanced overload of `send`:
149105
```cpp
150106
send(Metric&& metric)
151107
```
108+
Where metric constructor receives following parameters:
109+
- `T value`
110+
- `std::string& name`
111+
- `[time_point<system_clock> timestamp]`
152112

153113
For example:
154114
```cpp
155-
monitoring->send(10, "myMetricInt");
156115
monitoring->send({10, "myMetricInt"});
157116
```
158117

examples/10-Buffering.cxx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
///
2+
/// \file 10-Buffering.cxx
3+
/// \author Adam Wegrzynek <[email protected]>
4+
///
5+
6+
#include "Monitoring/MonitoringFactory.h"
7+
8+
using Monitoring = o2::monitoring::MonitoringFactory;
9+
10+
int main() {
11+
// Configure monitoring
12+
// Pass string with list of URLs as parameter
13+
auto monitoring = Monitoring::Get("infologger://,flume://localhost:1234");
14+
monitoring->enableBuffering(10);
15+
16+
// now send an application specific metric
17+
// 10 is the value
18+
// myMetric is the name of the metric by creating and moving Metric object
19+
for (int i = 0; i < 25; i++) {
20+
monitoring->send({10, "myMetricInt"});
21+
}
22+
monitoring->send({10.10, "myMetricFloat"});
23+
monitoring->flushBuffer();
24+
}

include/Monitoring/Monitoring.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Monitoring
5555
void send(Metric&& metric, DerivedMetricMode mode = DerivedMetricMode::NONE);
5656

5757
/// Sends multiple not related to each other metrics
58-
/// \@param metrics vector of metrics
58+
/// \param metrics vector of metrics
5959
void send(std::vector<Metric>&& metrics);
6060

6161
/// Sends multiple realated to each other metrics under a common measurement name
@@ -67,18 +67,25 @@ class Monitoring
6767

6868
/// Enables process monitoring
6969
/// \param interval refresh interval
70-
void enableProcessMonitoring(int interval = 5);
70+
void enableProcessMonitoring(const unsigned int interval = 5);
7171

7272
/// Starts timing
7373
/// Sets a start timestamp and timeout
74-
/// \@param name metric name
75-
/// \@param timeout timeout
74+
/// \param name metric name
75+
/// \param timeout timeout
7676
void startTimer(std::string name);
7777

7878
/// Stops timing
7979
/// Sets stop timestamp, calculates delta and sends value
80-
/// \@param name metric name
80+
/// \param name metric name
8181
void stopAndSendTimer(std::string name);
82+
83+
/// Flushes metric buffer (this can also happen when buffer is full)
84+
void flushBuffer();
85+
86+
/// Enables metric buffering
87+
/// \param size buffer size
88+
void enableBuffering(const unsigned int size = 20);
8289
private:
8390
/// Derived metrics handler
8491
/// \see class DerivedMetrics
@@ -102,6 +109,15 @@ class Monitoring
102109
/// Process Monitor thread loop
103110
/// \param interval sleep time in seconds
104111
void processMonitorLoop(int interval);
112+
113+
/// Metric buffer
114+
std::vector<Metric> mStorage;
115+
116+
/// Flag stating whether metric buffering is enabled
117+
bool mBuffering;
118+
119+
/// Size of buffer
120+
unsigned int mBufferSize;
105121
};
106122

107123
} // namespace monitoring

src/Monitoring.cxx

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,33 @@ namespace o2
3434
namespace monitoring
3535
{
3636

37-
Monitoring::Monitoring() {
37+
Monitoring::Monitoring()
38+
{
3839
mProcessMonitor = std::make_unique<ProcessMonitor>();
3940
mDerivedHandler = std::make_unique<DerivedMetrics>();
41+
mBuffering = false;
42+
}
43+
44+
void Monitoring::enableBuffering(const unsigned int size)
45+
{
46+
mBufferSize = size;
47+
mBuffering = true;
48+
mStorage.reserve(size);
49+
MonLogger::Get() << "Buffering enabled (" << mStorage.capacity() << ")" << MonLogger::End();
50+
}
51+
52+
void Monitoring::flushBuffer() {
53+
if (!mBuffering) {
54+
MonLogger::Get() << "Cannot flush as buffering is disabled" << MonLogger::End();
55+
return;
56+
}
57+
auto capacity = mStorage.capacity();
58+
auto size = mStorage.size();
59+
send(std::move(mStorage));
60+
mStorage.clear();
4061
}
4162

42-
void Monitoring::enableProcessMonitoring(int interval) {
63+
void Monitoring::enableProcessMonitoring(const unsigned int interval) {
4364
#ifdef _OS_LINUX
4465
mMonitorRunning = true;
4566
mMonitorThread = std::thread(&Monitoring::processMonitorLoop, this, interval);
@@ -84,6 +105,9 @@ Monitoring::~Monitoring()
84105
if (mMonitorThread.joinable()) {
85106
mMonitorThread.join();
86107
}
108+
if (mBuffering) {
109+
flushBuffer();
110+
}
87111
}
88112

89113
void Monitoring::processMonitorLoop(int interval)
@@ -128,9 +152,15 @@ void Monitoring::send(Metric&& metric, DerivedMetricMode mode)
128152
if (mode == DerivedMetricMode::INCREMENT) {
129153
metric = mDerivedHandler->increment(metric);
130154
}
131-
132-
for (auto& b: mBackends) {
133-
b->send(metric);
155+
if (mBuffering) {
156+
mStorage.push_back(std::move(metric));
157+
if (mStorage.size() >= mBufferSize) {
158+
flushBuffer();
159+
}
160+
} else {
161+
for (auto& b: mBackends) {
162+
b->send(metric);
163+
}
134164
}
135165
}
136166

test/testMonitoring.cxx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ BOOST_AUTO_TEST_CASE(createMonitoring)
2727
monitoring->send({doubleMetric, "myCrazyMetricD"});
2828
}
2929

30+
BOOST_AUTO_TEST_CASE(buffering)
31+
{
32+
auto monitoring = Monitoring::Get("infologger://,flume://localhost:1234");
33+
monitoring->enableBuffering(10);
34+
for (int i = 0; i < 25; i++) {
35+
monitoring->send({10, "myMetricInt"});
36+
}
37+
monitoring->flushBuffer();
38+
}
39+
3040
BOOST_AUTO_TEST_CASE(testTimer)
3141
{
3242
auto monitoring = Monitoring::Get("infologger://");

0 commit comments

Comments
 (0)