Skip to content

Commit 615dfed

Browse files
authored
Merge branch 'dev' into pr371
2 parents 1189c14 + 7012af4 commit 615dfed

25 files changed

Lines changed: 514 additions & 130 deletions

.github/workflows/build.yml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,24 @@ jobs:
4141
run: cd build && make -j
4242
- name: Test
4343
run: cd build && ctest --output-on-failure
44+
alma9:
45+
runs-on: [self-hosted, alma9]
46+
steps:
47+
- uses: actions/checkout@v2
48+
- name: CMake
49+
run: mkdir build && cd build && source /opt/rh/gcc-toolset-12/enable && cmake ..
50+
- name: Build
51+
run: cd build && make -j 2
52+
- name: Test
53+
run: cd build && ctest --output-on-failure
4454
cs8:
4555
runs-on: [self-hosted, cs8]
4656
steps:
4757
- uses: actions/checkout@v2
4858
- name: CMake
49-
run: mkdir build && cd build && source /opt/rh/gcc-toolset-10/enable && cmake ..
59+
run: mkdir build && cd build && source /opt/rh/gcc-toolset-12/enable && cmake ..
5060
- name: Build
51-
run: cd build && make -j
61+
run: cd build && make -j 2
5262
- name: Test
5363
run: cd build && ctest --output-on-failure
5464
cc7:
@@ -58,6 +68,6 @@ jobs:
5868
- name: CMake
5969
run: mkdir build && cd build && source /opt/rh/devtoolset-9/enable && cmake3 ..
6070
- name: Build
61-
run: cd build && make -j
71+
run: cd build && make -j 2
6272
- name: Test
6373
run: cd build && ctest3 --output-on-failure

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
*~
55
.idea
66
examples/config.ini
7+
/cmake-build-debug/

CMakeLists.txt

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019-2020 CERN and copyright holders of ALICE O2.
1+
# Copyright 2019-2024 CERN and copyright holders of ALICE O2.
22
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
33
# All rights not expressly granted are reserved.
44
#
@@ -16,22 +16,20 @@
1616
# General project definition
1717
####################################
1818

19-
CMAKE_MINIMUM_REQUIRED(VERSION 3.5.2 FATAL_ERROR)
19+
CMAKE_MINIMUM_REQUIRED(VERSION 3.26 FATAL_ERROR)
2020
set(Boost_USE_STATIC_RUNTIME OFF)
2121
set(Boost_USE_STATIC_LIBS OFF)
2222
set(BUILD_SHARED_LIBS ON)
2323
set(Boost_USE_MULTITHREADED ON)
24+
set(O2_MONITORING_KAFKA_ENABLE ON)
25+
set(O2_MONITORING_CONTROL_ENABLE ON)
2426

2527
# Set cmake policy by version: https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html
26-
if(${CMAKE_VERSION} VERSION_LESS 3.12)
27-
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
28-
else()
29-
cmake_policy(VERSION 3.12)
30-
endif()
28+
cmake_policy(VERSION 3.12)
3129

3230
# Define project
3331
project(Monitoring
34-
VERSION 3.17.5
32+
VERSION 3.19.12
3533
DESCRIPTION "O2 Monitoring library"
3634
LANGUAGES CXX
3735
)
@@ -73,13 +71,34 @@ endif()
7371

7472
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
7573

76-
find_package(Boost 1.70 REQUIRED COMPONENTS unit_test_framework program_options system)
74+
find_package(Boost 1.70 REQUIRED COMPONENTS unit_test_framework program_options)
7775
find_package(ApMon MODULE)
7876
find_package(CURL MODULE)
79-
find_package(RdKafka CONFIG)
8077
find_package(InfoLogger CONFIG)
81-
find_package(Protobuf)
82-
find_package(gRPC CONFIG)
78+
if(O2_MONITORING_KAFKA_ENABLE OR O2_MONITORING_CONTROL_ENABLE)
79+
find_package(Protobuf CONFIG)
80+
endif()
81+
if(O2_MONITORING_CONTROL_ENABLE)
82+
find_package(gRPC CONFIG)
83+
endif()
84+
85+
if(RDKAFKA_ROOT)
86+
message("RDKAFKA_ROOT set, we enable corresponding libs and binaries")
87+
find_library(RDKAFKA_LIB1 "rdkafka++" REQUIRED PATHS ${RDKAFKA_ROOT}/lib)
88+
find_library(RDKAFKA_LIB2 "rdkafka" REQUIRED PATHS ${RDKAFKA_ROOT}/lib)
89+
set(RDKAFKA_LIBS ${RDKAFKA_LIB1} ${RDKAFKA_LIB2})
90+
set(RDKAFKA_INCLUDE "${RDKAFKA_ROOT}/include")
91+
set(RdKafka_FOUND true)
92+
else()
93+
message("RDKAFKA_ROOT not set, corresponding libs and binaries won't be built")
94+
endif()
95+
96+
if(gRPC_FOUND)
97+
message("gRPC found, we enable corresponding libs and binaries")
98+
else()
99+
message("gRPC not found, corresponding libs and binaries won't be built")
100+
endif()
101+
83102

84103
####################################
85104
# Set OUTPUT vars
@@ -142,6 +161,7 @@ target_include_directories(Monitoring
142161
PUBLIC
143162
$<INSTALL_INTERFACE:include>
144163
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
164+
$<BUILD_INTERFACE:${RDKAFKA_INCLUDE}>
145165
PRIVATE
146166
${CMAKE_CURRENT_SOURCE_DIR}/src
147167
)
@@ -153,13 +173,12 @@ set_target_properties(Monitoring PROPERTIES OUTPUT_NAME "O2Monitoring")
153173
target_link_libraries(Monitoring
154174
PUBLIC
155175
Boost::boost
156-
$<$<BOOL:${RdKafka_FOUND}>:RdKafka::rdkafka++>
157176
PRIVATE
158-
Boost::system
159177
pthread
160178
$<$<BOOL:${ApMon_FOUND}>:ApMon::ApMon>
161179
$<$<BOOL:${CURL_FOUND}>:CURL::libcurl>
162180
$<$<BOOL:${InfoLogger_FOUND}>:AliceO2::InfoLogger>
181+
$<$<BOOL:${RdKafka_FOUND}>:${RDKAFKA_LIBS}>
163182
)
164183

165184
# Handle ApMon optional dependency
@@ -247,7 +266,10 @@ foreach (example ${EXAMPLES})
247266
add_executable(${example_name} ${example})
248267
target_link_libraries(${example_name}
249268
PRIVATE
269+
pthread
250270
Monitoring Boost::program_options
271+
$<$<BOOL:${CURL_FOUND}>:CURL::libcurl>
272+
$<$<BOOL:${RdKafka_FOUND}>:${RDKAFKA_LIBS}>
251273
)
252274
endforeach()
253275

@@ -258,6 +280,17 @@ if(RdKafka_FOUND)
258280
endif()
259281

260282

283+
# executable: o2-monitoring-send
284+
add_executable(
285+
o2-monitoring-send
286+
src/sendMetric.cxx
287+
)
288+
target_link_libraries(
289+
o2-monitoring-send
290+
Monitoring
291+
)
292+
install(TARGETS o2-monitoring-send)
293+
261294
####################################
262295
# Generate protobuf
263296
####################################
@@ -289,6 +322,7 @@ if(RdKafka_FOUND AND Protobuf_FOUND AND CURL_FOUND)
289322
Boost::program_options
290323
protobuf::libprotobuf
291324
$<$<BOOL:${InfoLogger_FOUND}>:AliceO2::InfoLogger>
325+
$<$<BOOL:${RdKafka_FOUND}>:${RDKAFKA_LIBS}>
292326
)
293327
target_compile_definitions(${example_name} PRIVATE $<$<BOOL:${InfoLogger_FOUND}>:O2_MONITORING_WITH_INFOLOGGER>)
294328
target_include_directories(${example_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

README.md

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ send(Metric{"throughput"}.addValue(100, "tx").addValue(200, "rx"))
110110
111111
See how it works in the example: [examples/1-Basic.cxx](examples/1-Basic.cxx).
112112
113+
Metrics can also be injected from the command line using the o2-monitoring-send utility (self-documented).
114+
113115
## Advanced features
114116
115117
### Metric verbosity
@@ -206,13 +208,15 @@ This guide explains manual installation. For `ansible` deployment see [AliceO2Gr
206208
## Receiving metrics from Monitoring system (development instructions)
207209

208210
### Requirements
209-
- CS8 or CC7 with `devtoolset-9`
210-
- Boost >= 1.70
211+
- Ubuntu, RHEL9, RHEL8, CS8, macOS, or CC7 with `devtoolset-9`
212+
- Boost >= 1.83, CMake
211213

212214
### Compile Monitoring library with Kafka backend
215+
216+
#### Manually
213217
- Compile `librdkafka`
214218
```bash
215-
git clone -b v1.8.2 https://github.com/edenhill/librdkafka && cd librdkafka
219+
git clone -b v2.3.0 https://github.com/edenhill/librdkafka && cd librdkafka
216220
cmake -H. -B./_cmake_build -DENABLE_LZ4_EXT=OFF -DCMAKE_INSTALL_LIBDIR=lib -DRDKAFKA_BUILD_TESTS=OFF -DRDKAFKA_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=~/librdkafka_install
217221
cmake --build ./_cmake_build --target install -j
218222
```
@@ -223,6 +227,11 @@ This guide explains manual installation. For `ansible` deployment see [AliceO2Gr
223227
cmake --build ./_cmake_build --target install -j
224228
```
225229

230+
#### aliBuild
231+
- Modify `monitoring.sh`: add `- librdkafka` to "requires"
232+
- Compile Monitoring: `aliBuild build Monitoring --defaults o2-dataflow --always-prefer-system`
233+
- Add `Monitoring` as dependency of your project
234+
226235
### Look for Monitoring library in your CMake
227236
As `librdkafka` is optional dependency of Monitoring it is not handled by CMakeConfig, therefore you need:
228237
```cmake
@@ -237,16 +246,24 @@ And then, link against `AliceO2::Monitoring` target.
237246
#include "Monitoring/MonitoringFactory.h"
238247
...
239248

240-
std::vector<std::string> topics = {"topic-to-subscribe"};
241-
auto client = MonitoringFactory::GetPullClient("kafka-server:9092", topics);
249+
std::vector<std::string> topics = {"<topic-to-subscribe>"};
250+
auto client = MonitoringFactory::GetPullClient("<kafka-server:9092>", topics, "<client-id>");
242251
for (;;) {
243252
auto metrics = client->pull();
244253
if (!metrics.empty()) {
245254
/// metric.first => topic name; metric.second => metric itself
255+
} else {
256+
// wait a bit if no data available
257+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
246258
}
247-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
248-
}
249259
```
250260
261+
Run-time parameters:
262+
- `<topic-to-subscribe>` - List of topics to subscribe
263+
- `<kafka-server:9092>` - Kafka broker (staging or production)
264+
- `<client_id>` - unique, self-explainable string describing the client, eg. `dcs-link-status` or `its-link-status`.
265+
266+
Metrics are returned in batch of maximum 100 for each pull() call.
267+
251268
### Data format
252269
Native data format is [Influx Line Protocol](https://docs.influxdata.com/influxdb/latest/reference/syntax/line-protocol/) but metrics can be converted into any format listed in here: https://docs.influxdata.com/telegraf/latest/data_formats/output/

examples/12-KafkaToInfluxDb.cxx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@
1818

1919
using namespace o2::monitoring;
2020

21+
22+
std::string getCreateBucketBody(const std::string& orgId, const int run) {
23+
std::stringstream postPayload;
24+
postPayload << R"({
25+
"orgID": ")" + orgId + R"(",
26+
"name": ")" + std::to_string(run) + R"(",
27+
"retentionRules": [{
28+
"type": "expire",
29+
"everySeconds": 86400,
30+
"shardGroupDurationSeconds": 86400
31+
}]
32+
})";
33+
return postPayload.str();
34+
}
35+
2136
int main(int argc, char* argv[])
2237
{
2338
boost::program_options::options_description desc("Program options");
@@ -26,7 +41,10 @@ int main(int argc, char* argv[])
2641
("influxdb-url", boost::program_options::value<std::string>()->required(), "InfluxDB hostname")
2742
("influxdb-token", boost::program_options::value<std::string>()->required(), "InfluxDB token")
2843
("influxdb-org", boost::program_options::value<std::string>()->default_value("cern"), "InfluxDB organisation")
29-
("influxdb-bucket", boost::program_options::value<std::string>()->default_value("aliecs"), "InfluxDB bucket");
44+
("influxdb-bucket", boost::program_options::value<std::string>()->default_value("aliecs"), "InfluxDB bucket")
45+
("influxdb-dpl-url", boost::program_options::value<std::string>(), "InfluxDB DPL ID")
46+
("influxdb-dpl-orgid", boost::program_options::value<std::string>(), "InfluxDB DPL organization ID")
47+
("influxdb-dpl-token", boost::program_options::value<std::string>(), "InfluxDB DPL token");
3048
boost::program_options::variables_map vm;
3149
boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
3250
boost::program_options::notify(vm);
@@ -41,6 +59,14 @@ int main(int argc, char* argv[])
4159
);
4260
httpTransport->addHeader("Authorization: Token " + vm["influxdb-token"].as<std::string>());
4361
auto influxdbBackend = std::make_unique<backends::InfluxDB>(std::move(httpTransport));
62+
63+
std::unique_ptr<transports::HTTP> influxBucketApi;
64+
if (vm.count("influxdb-dpl-orgid") && vm.count("influxdb-dpl-url") && vm.count("influxdb-dpl-token")) {
65+
MonLogger::Get() << "Creating bucket HTTP API for " << vm["influxdb-dpl-url"].as<std::string>() << MonLogger::End();
66+
influxBucketApi.reset(new transports::HTTP(vm["influxdb-dpl-url"].as<std::string>() + "/api/v2/buckets"));
67+
influxBucketApi->addHeader("Authorization: Token " + vm["influxdb-dpl-token"].as<std::string>());
68+
}
69+
4470
for (;;) {
4571
auto changes = kafkaConsumer->pull();
4672
if (!changes.empty()) {
@@ -50,15 +76,19 @@ int main(int argc, char* argv[])
5076
if (stateChange.envinfo().state().empty()) {
5177
continue;
5278
}
79+
int run = stateChange.envinfo().runnumber();
5380
auto metric = Metric{"run_times"};
5481
if (change.first.find("leave") != std::string::npos) {
5582
metric.addValue(stateChange.timestamp(), "eor");
5683
MonLogger::Get() << stateChange.envinfo().environmentid() << "/" << stateChange.envinfo().runnumber() << " " << change.first << " EOR: " << stateChange.timestamp() << MonLogger::End();
5784
} else {
5885
metric.addValue(stateChange.envinfo().runtype(), "type").addValue(stateChange.envinfo().enterstatetimestamp(), "sor");
5986
MonLogger::Get() << stateChange.envinfo().environmentid() << "/" << stateChange.envinfo().runnumber() << " " << change.first << " SOR: " <<stateChange.envinfo().enterstatetimestamp() << MonLogger::End();
87+
if (vm.count("influxdb-dpl-orgid") && run > 1) {
88+
MonLogger::Get() << "Request sent to create bucket " << stateChange.envinfo().runnumber() << " on " << vm["influxdb-dpl-url"].as<std::string>() << MonLogger::End();
89+
influxBucketApi->send(getCreateBucketBody(vm["influxdb-dpl-orgid"].as<std::string>(), stateChange.envinfo().runnumber()));
90+
}
6091
}
61-
int run = stateChange.envinfo().runnumber();
6292
if (run > 1) {
6393
influxdbBackend->sendWithRun(metric, stateChange.envinfo().environmentid(), std::to_string(run));
6494
}

examples/13-PullClient.cxx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using namespace o2::monitoring;
99

1010
int main()
1111
{
12+
//int ix=0;
1213
/// List of topics to subscribe
1314
std::vector<std::string> topics = {"cru.link_status"};
1415
/// Connect to server
@@ -21,7 +22,9 @@ int main()
2122
/// metric sample: link,serialId=983,endpoint=1,CRU=1,id=11,type=CRU pciAddress="b0:00.0",status=1i 1673940809860009855
2223
std::cout << metric.second << std::endl;
2324
}
25+
} else {
26+
// wait a bit if no data available
27+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
2428
}
25-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
2629
}
2730
}

0 commit comments

Comments
 (0)