From ed22af8015e1e0412e59195dac8f58eff992b4d6 Mon Sep 17 00:00:00 2001 From: Adam Wegrzynek Date: Sun, 19 Apr 2020 16:41:34 +0200 Subject: [PATCH 1/4] Add CURL to deps list --- CMakeLists.txt | 14 ++- cmake/FindCURL.cmake | 203 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 cmake/FindCURL.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f73d9aea9..9e47f6818 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") find_package(Boost REQUIRED COMPONENTS unit_test_framework program_options system filesystem) find_package(Git QUIET) find_package(ApMon MODULE) +find_package(CURL MODULE) find_package(RdKafka CONFIG) #################################### @@ -105,11 +106,12 @@ add_library(Monitoring SHARED src/Exceptions/MonitoringException.cxx $<$:src/Backends/ApMonBackend.cxx> $<$:src/Transports/Kafka.cxx> + $<$:src/Transports/HTTP.cxx> ) target_include_directories(Monitoring - PUBLIC - $ + PUBLIC + $ $ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src @@ -127,6 +129,7 @@ target_link_libraries(Monitoring pthread $<$:ApMon::ApMon> $<$:RdKafka::rdkafka++> + $<$:CURL::libcurl> ) # Handle ApMon optional dependency @@ -138,6 +141,10 @@ if(RdKafka_FOUND) message(STATUS " Compiling Kafka transport") endif() +if(CURL_FOUND) + message(STATUS " Compiling HTTP transport/InfluxDB 2.x backend") +endif() + # Detect operating system if (UNIX AND NOT APPLE) message(STATUS "Detected Linux: Process monitor enabled") @@ -155,6 +162,7 @@ target_compile_definitions(Monitoring $<$:O2_MONITORING_OS_LINUX> $<$:O2_MONITORING_WITH_APPMON> $<$:O2_MONITORING_WITH_KAFKA> + $<$:O2_MONITORING_WITH_CURL> ) # Use C++17 @@ -217,7 +225,7 @@ foreach (test ${TEST_SRCS}) add_executable(${test_name} ${test}) target_link_libraries(${test_name} - PRIVATE + PRIVATE Monitoring Boost::unit_test_framework Boost::filesystem ) add_test(NAME ${test_name} COMMAND ${test_name}) diff --git a/cmake/FindCURL.cmake b/cmake/FindCURL.cmake new file mode 100644 index 000000000..919babcde --- /dev/null +++ b/cmake/FindCURL.cmake @@ -0,0 +1,203 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindCURL +-------- + +Find the native CURL headers and libraries. + +This module accept optional COMPONENTS to check supported features and +protocols:: + + PROTOCOLS: ICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 + POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP + FEATURES: SSL IPv6 UnixSockets libz AsynchDNS IDN GSS-API PSL SPNEGO + Kerberos NTLM NTLM_WB TLS-SRP HTTP2 HTTPS-proxy + +IMPORTED Targets +^^^^^^^^^^^^^^^^ + +This module defines :prop_tgt:`IMPORTED` target ``CURL::libcurl``, if +curl has been found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module defines the following variables: + +``CURL_FOUND`` + "True" if ``curl`` found. + +``CURL_INCLUDE_DIRS`` + where to find ``curl``/``curl.h``, etc. + +``CURL_LIBRARIES`` + List of libraries when using ``curl``. + +``CURL_VERSION_STRING`` + The version of ``curl`` found. + +CURL CMake +^^^^^^^^^^ + +If CURL was built using the CMake buildsystem then it provides its own +``CURLConfig.cmake`` file for use with the :command:`find_package` command's +config mode. This module looks for this file and, if found, +returns its results with no further action. + +Set ``CURL_NO_CURL_CMAKE`` to ``ON`` to disable this search. + +#]=======================================================================] + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +if(NOT CURL_NO_CURL_CMAKE) + # do a find package call to specifically look for the CMake version + # of curl + find_package(CURL QUIET NO_MODULE) + mark_as_advanced(CURL_DIR) + + # if we found the CURL cmake package then we are done, and + # can print what we found and return. + if(CURL_FOUND) + find_package_handle_standard_args(CURL HANDLE_COMPONENTS CONFIG_MODE) + return() + endif() +endif() + +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_CURL QUIET libcurl) + if(PC_CURL_FOUND) + set(CURL_VERSION_STRING ${PC_CURL_VERSION}) + pkg_get_variable(CURL_SUPPORTED_PROTOCOLS libcurl supported_protocols) + pkg_get_variable(CURL_SUPPORTED_FEATURES libcurl supported_features) + endif() +endif() + +# Look for the header file. +find_path(CURL_INCLUDE_DIR + NAMES curl/curl.h + HINTS ${PC_CURL_INCLUDE_DIRS}) +mark_as_advanced(CURL_INCLUDE_DIR) + +if(NOT CURL_LIBRARY) + # Look for the library (sorted from most current/relevant entry to least). + find_library(CURL_LIBRARY_RELEASE NAMES + curl + # Windows MSVC prebuilts: + curllib + libcurl_imp + curllib_static + # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip): + libcurl + HINTS ${PC_CURL_LIBRARY_DIRS} + ) + mark_as_advanced(CURL_LIBRARY_RELEASE) + + find_library(CURL_LIBRARY_DEBUG NAMES + # Windows MSVC CMake builds in debug configuration on vcpkg: + libcurl-d_imp + libcurl-d + HINTS ${PC_CURL_LIBRARY_DIRS} + ) + mark_as_advanced(CURL_LIBRARY_DEBUG) + + include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) + select_library_configurations(CURL) +endif() + +if(CURL_INCLUDE_DIR AND NOT CURL_VERSION_STRING) + foreach(_curl_version_header curlver.h curl.h) + if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}") + file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"") + + string(REGEX REPLACE "^#define[\t ]+LIBCURL_VERSION[\t ]+\"([^\"]*)\".*" "\\1" CURL_VERSION_STRING "${curl_version_str}") + unset(curl_version_str) + break() + endif() + endforeach() +endif() + +if(CURL_FIND_COMPONENTS) + set(CURL_KNOWN_PROTOCOLS ICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP) + set(CURL_KNOWN_FEATURES SSL IPv6 UnixSockets libz AsynchDNS IDN GSS-API PSL SPNEGO Kerberos NTLM NTLM_WB TLS-SRP HTTP2 HTTPS-proxy) + foreach(component IN LISTS CURL_KNOWN_PROTOCOLS CURL_KNOWN_FEATURES) + set(CURL_${component}_FOUND FALSE) + endforeach() + if(NOT PC_CURL_FOUND) + find_program(CURL_CONFIG_EXECUTABLE NAMES curl-config) + if(CURL_CONFIG_EXECUTABLE) + execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --version + OUTPUT_VARIABLE CURL_CONFIG_VERSION_STRING + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --feature + OUTPUT_VARIABLE CURL_CONFIG_FEATURES_STRING + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE "\n" ";" CURL_SUPPORTED_FEATURES "${CURL_CONFIG_FEATURES_STRING}") + execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --protocols + OUTPUT_VARIABLE CURL_CONFIG_PROTOCOLS_STRING + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE "\n" ";" CURL_SUPPORTED_PROTOCOLS "${CURL_CONFIG_PROTOCOLS_STRING}") + endif() + + endif() + foreach(component IN LISTS CURL_FIND_COMPONENTS) + list(FIND CURL_KNOWN_PROTOCOLS ${component} _found) + if(_found) + list(FIND CURL_SUPPORTED_PROTOCOLS ${component} _found) + if(_found) + set(CURL_${component}_FOUND TRUE) + elseif(CURL_FIND_REQUIRED) + message(FATAL_ERROR "CURL: Required protocol ${component} is not found") + endif() + else() + list(FIND CURL_SUPPORTED_FEATURES ${component} _found) + if(_found) + set(CURL_${component}_FOUND TRUE) + elseif(CURL_FIND_REQUIRED) + message(FATAL_ERROR "CURL: Required feature ${component} is not found") + endif() + endif() + endforeach() +endif() + +find_package_handle_standard_args(CURL + REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR + VERSION_VAR CURL_VERSION_STRING + HANDLE_COMPONENTS) + +if(CURL_FOUND) + set(CURL_LIBRARIES ${CURL_LIBRARY}) + set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR}) + + if(NOT TARGET CURL::libcurl) + add_library(CURL::libcurl UNKNOWN IMPORTED) + set_target_properties(CURL::libcurl PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}") + + if(EXISTS "${CURL_LIBRARY}") + set_target_properties(CURL::libcurl PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${CURL_LIBRARY}") + endif() + if(CURL_LIBRARY_RELEASE) + set_property(TARGET CURL::libcurl APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(CURL::libcurl PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION_RELEASE "${CURL_LIBRARY_RELEASE}") + endif() + if(CURL_LIBRARY_DEBUG) + set_property(TARGET CURL::libcurl APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(CURL::libcurl PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION_DEBUG "${CURL_LIBRARY_DEBUG}") + endif() + endif() +endif() From 17071b234caa9cc57e81aa8b44a9044b0a2885d7 Mon Sep 17 00:00:00 2001 From: Adam Wegrzynek Date: Mon, 20 Apr 2020 10:55:52 +0200 Subject: [PATCH 2/4] Add URL parsing --- cmake/FindCURL.cmake | 203 -------------------------------------- src/MonitoringFactory.cxx | 37 +++++++ test/testInfluxDb.cxx | 7 ++ 3 files changed, 44 insertions(+), 203 deletions(-) delete mode 100644 cmake/FindCURL.cmake diff --git a/cmake/FindCURL.cmake b/cmake/FindCURL.cmake deleted file mode 100644 index 919babcde..000000000 --- a/cmake/FindCURL.cmake +++ /dev/null @@ -1,203 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindCURL --------- - -Find the native CURL headers and libraries. - -This module accept optional COMPONENTS to check supported features and -protocols:: - - PROTOCOLS: ICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 - POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP - FEATURES: SSL IPv6 UnixSockets libz AsynchDNS IDN GSS-API PSL SPNEGO - Kerberos NTLM NTLM_WB TLS-SRP HTTP2 HTTPS-proxy - -IMPORTED Targets -^^^^^^^^^^^^^^^^ - -This module defines :prop_tgt:`IMPORTED` target ``CURL::libcurl``, if -curl has been found. - -Result Variables -^^^^^^^^^^^^^^^^ - -This module defines the following variables: - -``CURL_FOUND`` - "True" if ``curl`` found. - -``CURL_INCLUDE_DIRS`` - where to find ``curl``/``curl.h``, etc. - -``CURL_LIBRARIES`` - List of libraries when using ``curl``. - -``CURL_VERSION_STRING`` - The version of ``curl`` found. - -CURL CMake -^^^^^^^^^^ - -If CURL was built using the CMake buildsystem then it provides its own -``CURLConfig.cmake`` file for use with the :command:`find_package` command's -config mode. This module looks for this file and, if found, -returns its results with no further action. - -Set ``CURL_NO_CURL_CMAKE`` to ``ON`` to disable this search. - -#]=======================================================================] - -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) - -if(NOT CURL_NO_CURL_CMAKE) - # do a find package call to specifically look for the CMake version - # of curl - find_package(CURL QUIET NO_MODULE) - mark_as_advanced(CURL_DIR) - - # if we found the CURL cmake package then we are done, and - # can print what we found and return. - if(CURL_FOUND) - find_package_handle_standard_args(CURL HANDLE_COMPONENTS CONFIG_MODE) - return() - endif() -endif() - -find_package(PkgConfig QUIET) -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_CURL QUIET libcurl) - if(PC_CURL_FOUND) - set(CURL_VERSION_STRING ${PC_CURL_VERSION}) - pkg_get_variable(CURL_SUPPORTED_PROTOCOLS libcurl supported_protocols) - pkg_get_variable(CURL_SUPPORTED_FEATURES libcurl supported_features) - endif() -endif() - -# Look for the header file. -find_path(CURL_INCLUDE_DIR - NAMES curl/curl.h - HINTS ${PC_CURL_INCLUDE_DIRS}) -mark_as_advanced(CURL_INCLUDE_DIR) - -if(NOT CURL_LIBRARY) - # Look for the library (sorted from most current/relevant entry to least). - find_library(CURL_LIBRARY_RELEASE NAMES - curl - # Windows MSVC prebuilts: - curllib - libcurl_imp - curllib_static - # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip): - libcurl - HINTS ${PC_CURL_LIBRARY_DIRS} - ) - mark_as_advanced(CURL_LIBRARY_RELEASE) - - find_library(CURL_LIBRARY_DEBUG NAMES - # Windows MSVC CMake builds in debug configuration on vcpkg: - libcurl-d_imp - libcurl-d - HINTS ${PC_CURL_LIBRARY_DIRS} - ) - mark_as_advanced(CURL_LIBRARY_DEBUG) - - include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) - select_library_configurations(CURL) -endif() - -if(CURL_INCLUDE_DIR AND NOT CURL_VERSION_STRING) - foreach(_curl_version_header curlver.h curl.h) - if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}") - file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"") - - string(REGEX REPLACE "^#define[\t ]+LIBCURL_VERSION[\t ]+\"([^\"]*)\".*" "\\1" CURL_VERSION_STRING "${curl_version_str}") - unset(curl_version_str) - break() - endif() - endforeach() -endif() - -if(CURL_FIND_COMPONENTS) - set(CURL_KNOWN_PROTOCOLS ICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP) - set(CURL_KNOWN_FEATURES SSL IPv6 UnixSockets libz AsynchDNS IDN GSS-API PSL SPNEGO Kerberos NTLM NTLM_WB TLS-SRP HTTP2 HTTPS-proxy) - foreach(component IN LISTS CURL_KNOWN_PROTOCOLS CURL_KNOWN_FEATURES) - set(CURL_${component}_FOUND FALSE) - endforeach() - if(NOT PC_CURL_FOUND) - find_program(CURL_CONFIG_EXECUTABLE NAMES curl-config) - if(CURL_CONFIG_EXECUTABLE) - execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --version - OUTPUT_VARIABLE CURL_CONFIG_VERSION_STRING - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --feature - OUTPUT_VARIABLE CURL_CONFIG_FEATURES_STRING - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE "\n" ";" CURL_SUPPORTED_FEATURES "${CURL_CONFIG_FEATURES_STRING}") - execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --protocols - OUTPUT_VARIABLE CURL_CONFIG_PROTOCOLS_STRING - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE "\n" ";" CURL_SUPPORTED_PROTOCOLS "${CURL_CONFIG_PROTOCOLS_STRING}") - endif() - - endif() - foreach(component IN LISTS CURL_FIND_COMPONENTS) - list(FIND CURL_KNOWN_PROTOCOLS ${component} _found) - if(_found) - list(FIND CURL_SUPPORTED_PROTOCOLS ${component} _found) - if(_found) - set(CURL_${component}_FOUND TRUE) - elseif(CURL_FIND_REQUIRED) - message(FATAL_ERROR "CURL: Required protocol ${component} is not found") - endif() - else() - list(FIND CURL_SUPPORTED_FEATURES ${component} _found) - if(_found) - set(CURL_${component}_FOUND TRUE) - elseif(CURL_FIND_REQUIRED) - message(FATAL_ERROR "CURL: Required feature ${component} is not found") - endif() - endif() - endforeach() -endif() - -find_package_handle_standard_args(CURL - REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR - VERSION_VAR CURL_VERSION_STRING - HANDLE_COMPONENTS) - -if(CURL_FOUND) - set(CURL_LIBRARIES ${CURL_LIBRARY}) - set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR}) - - if(NOT TARGET CURL::libcurl) - add_library(CURL::libcurl UNKNOWN IMPORTED) - set_target_properties(CURL::libcurl PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}") - - if(EXISTS "${CURL_LIBRARY}") - set_target_properties(CURL::libcurl PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${CURL_LIBRARY}") - endif() - if(CURL_LIBRARY_RELEASE) - set_property(TARGET CURL::libcurl APPEND PROPERTY - IMPORTED_CONFIGURATIONS RELEASE) - set_target_properties(CURL::libcurl PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION_RELEASE "${CURL_LIBRARY_RELEASE}") - endif() - if(CURL_LIBRARY_DEBUG) - set_property(TARGET CURL::libcurl APPEND PROPERTY - IMPORTED_CONFIGURATIONS DEBUG) - set_target_properties(CURL::libcurl PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION_DEBUG "${CURL_LIBRARY_DEBUG}") - endif() - endif() -endif() diff --git a/src/MonitoringFactory.cxx b/src/MonitoringFactory.cxx index c22b327b8..1b85d0215 100644 --- a/src/MonitoringFactory.cxx +++ b/src/MonitoringFactory.cxx @@ -36,6 +36,10 @@ #include "Transports/Kafka.h" #endif +#ifdef O2_MONITORING_WITH_CURL +#include "Transports/HTTP.h" +#endif + namespace o2 { /// ALICE O2 Monitoring system @@ -56,6 +60,38 @@ std::unique_ptr getStdOut(http::url uri) } } +/// http://localhost:9999/?org=YOUR_ORG&bucket=YOUR_BUCKET&token=AUTH_TOKEN +/// -> +/// http://localhost:9999/api/v2/write?org=YOUR_ORG&bucket=YOUR_BUCKET +/// --header "Authorization: Token YOURAUTHTOKEN" +/// --data-raw "mem,host=host1 used_percent=23.43234543 1556896326" +std::unique_ptr getInfluxDbv2(http::url uri) +{ +#ifdef O2_MONITORING_WITH_CURL + std::string tokenLabel = "token="; + std::string path = "/api/v2/write"; + std::string query = uri.search; + + auto tokenStart = query.find(tokenLabel); + auto tokenEnd = query.find('&', tokenStart); + if (tokenEnd == std::string::npos) { + tokenEnd = query.length(); + } + std::string token = query.substr(tokenStart + tokenLabel.length(), tokenEnd-(tokenStart + tokenLabel.length())); + // make sure ampersand is removed + if (tokenEnd < query.length() && query.at(tokenEnd) == '&') tokenEnd++; + if (tokenStart > 0 && query.at(tokenStart-1) == '&') tokenStart--; + query.erase(tokenStart, tokenEnd - tokenStart); + + std::string headers = "Authorization: Token " + token; + auto transport = std::make_unique(uri.host, uri.port); + //auto transport = std::make_unique(uri.host + uri.port + path + query, headers); + return std::make_unique(std::move(transport)); +#else + throw std::runtime_error("HTTP transport is not enabled"); +#endif +} + std::unique_ptr getInfluxDb(http::url uri) { auto const position = uri.protocol.find_last_of('-'); @@ -129,6 +165,7 @@ std::unique_ptr MonitoringFactory::GetBackend(std::string& url) {"influxdb-unix", getInfluxDb}, {"influxdb-stdout", getInfluxDb}, {"influxdb-kafka", getInfluxDb}, + {"influxdbv2", getInfluxDbv2}, {"apmon", getApMon}, {"no-op", getNoop} }; diff --git a/test/testInfluxDb.cxx b/test/testInfluxDb.cxx index 6ae8c3e61..6a4b96c30 100644 --- a/test/testInfluxDb.cxx +++ b/test/testInfluxDb.cxx @@ -32,6 +32,13 @@ BOOST_AUTO_TEST_CASE(simplySendMetric2) monitoring->send(Metric{10, "myCrazyMetric"}); } +BOOST_AUTO_TEST_CASE(InfluxDbv2) +{ + MonitoringFactory::Get("influxdbv2://localhost:9999?org=YOUR_ORG&bucket=YOUR_BUCKET&token=AUTH_TOKEN"); + MonitoringFactory::Get("influxdbv2://localhost:9999?org=YOUR_ORG&token=AUTH_TOKEN&bucket=YOUR_BUCKET"); + MonitoringFactory::Get("influxdbv2://localhost:9999?token=AUTH_TOKEN&org=YOUR_ORG&bucket=YOUR_BUCKET"); +} + } // namespace Test } // namespace monitoring } // namespace o2 From 0f838aceef6dc91bf189f41a7d4680e3e433eb63 Mon Sep 17 00:00:00 2001 From: Adam Wegrzynek Date: Tue, 21 Apr 2020 21:47:15 +0200 Subject: [PATCH 3/4] First working version --- src/MonitoringFactory.cxx | 4 ++-- src/UriParser/UriParser.h | 4 ++-- test/testInfluxDb.cxx | 9 ++++----- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/MonitoringFactory.cxx b/src/MonitoringFactory.cxx index 1b85d0215..670e58721 100644 --- a/src/MonitoringFactory.cxx +++ b/src/MonitoringFactory.cxx @@ -82,10 +82,10 @@ std::unique_ptr getInfluxDbv2(http::url uri) if (tokenEnd < query.length() && query.at(tokenEnd) == '&') tokenEnd++; if (tokenStart > 0 && query.at(tokenStart-1) == '&') tokenStart--; query.erase(tokenStart, tokenEnd - tokenStart); + std::cout << uri.url << std::endl; std::string headers = "Authorization: Token " + token; - auto transport = std::make_unique(uri.host, uri.port); - //auto transport = std::make_unique(uri.host + uri.port + path + query, headers); + auto transport = std::make_unique("http://" + uri.host + ':' + std::to_string(uri.port) + path + '?' + query, headers); return std::make_unique(std::move(transport)); #else throw std::runtime_error("HTTP transport is not enabled"); diff --git a/src/UriParser/UriParser.h b/src/UriParser/UriParser.h index 00b199d1f..75fea158b 100644 --- a/src/UriParser/UriParser.h +++ b/src/UriParser/UriParser.h @@ -29,7 +29,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace http { struct url { - std::string protocol, user, password, host, path, search; + std::string protocol, user, password, host, path, search, url; int port; }; @@ -89,7 +89,7 @@ static inline url ParseHttpUrl(std::string& in) { url ret; ret.port = -1; - + ret.url = in; ret.protocol = ExtractProtocol(in); ret.search = ExtractSearch(in); ret.path = ExtractPath(in); diff --git a/test/testInfluxDb.cxx b/test/testInfluxDb.cxx index 6a4b96c30..261e15ced 100644 --- a/test/testInfluxDb.cxx +++ b/test/testInfluxDb.cxx @@ -19,7 +19,7 @@ namespace monitoring { namespace Test { - +/* BOOST_AUTO_TEST_CASE(simplySendMetric) { auto monitoring = MonitoringFactory::Get("influxdb-udp://localhost:1000"); @@ -31,12 +31,11 @@ BOOST_AUTO_TEST_CASE(simplySendMetric2) auto monitoring = MonitoringFactory::Get("influxdb-stdout://"); monitoring->send(Metric{10, "myCrazyMetric"}); } - +*/ BOOST_AUTO_TEST_CASE(InfluxDbv2) { - MonitoringFactory::Get("influxdbv2://localhost:9999?org=YOUR_ORG&bucket=YOUR_BUCKET&token=AUTH_TOKEN"); - MonitoringFactory::Get("influxdbv2://localhost:9999?org=YOUR_ORG&token=AUTH_TOKEN&bucket=YOUR_BUCKET"); - MonitoringFactory::Get("influxdbv2://localhost:9999?token=AUTH_TOKEN&org=YOUR_ORG&bucket=YOUR_BUCKET"); + auto monitoring = MonitoringFactory::Get("influxdbv2://localhost:9999?org=cern&bucket=test&token=c1WZvMvFK9KHrRAD68Ou8U4d9hljQm_haOjOL6Xn4oPM89nDZiJ5mwGrO-Z7YspoFnQP-4BIyhomf_Yq111fVg=="); + monitoring->send(Metric{10, "myCrazyMetric"}); } } // namespace Test From b16f2a750ee7c3d5a70462bc20b1d81923172134 Mon Sep 17 00:00:00 2001 From: Adam Wegrzynek Date: Wed, 22 Apr 2020 14:04:47 +0200 Subject: [PATCH 4/4] Clean up and docs --- README.md | 3 +- src/MonitoringFactory.cxx | 7 ++-- src/Transports/HTTP.cxx | 68 +++++++++++++++++++++++++++++++++++++++ src/Transports/HTTP.h | 54 +++++++++++++++++++++++++++++++ test/testInfluxDb.cxx | 6 ++-- 5 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 src/Transports/HTTP.cxx create mode 100644 src/Transports/HTTP.h diff --git a/README.md b/README.md index 0267821e1..646f41752 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ See the table below to find `URI`s for supported backends: | InfluxDB | Unix socket | `influxdb-unix` | - | `info` | | InfluxDB | StdOut | `influxdb-stdout` | - | `info` | | InfluxDB | Kafka | `influxdb-kafka` | Kafka topic | `info` | +| InfluxDB 2.x | HTTP | `influxdbv2` | `org=ORG&bucket=BUCKET&token=TOKEN` | `info` | | ApMon | UDP | `apmon` | - | `info` | | StdOut | - | `stdout`, `infologger` | [Prefix] | `debug` | @@ -62,7 +63,7 @@ A metric consist of 5 parameters: | Parameter name | Type | Required | Default | | -------------- |:--------------------------------:|:--------:| -----------------------:| | name | string | yes | - | -| values | map<string, int/double/string/uint64_t> | no/1 | - | +| values | map<string, int/double/string/uint64_t> | no/1 | - | | timestamp | time_point<system_clock> | no | current time | | verbosity | Enum (Debug/Info/Prod) | no | Verbosity::Info | | tags | map | no | host and process names | diff --git a/src/MonitoringFactory.cxx b/src/MonitoringFactory.cxx index 670e58721..83b1b2a00 100644 --- a/src/MonitoringFactory.cxx +++ b/src/MonitoringFactory.cxx @@ -60,11 +60,11 @@ std::unique_ptr getStdOut(http::url uri) } } +/// Extracts token from header add sets it as addition HTTP header /// http://localhost:9999/?org=YOUR_ORG&bucket=YOUR_BUCKET&token=AUTH_TOKEN /// -> /// http://localhost:9999/api/v2/write?org=YOUR_ORG&bucket=YOUR_BUCKET /// --header "Authorization: Token YOURAUTHTOKEN" -/// --data-raw "mem,host=host1 used_percent=23.43234543 1556896326" std::unique_ptr getInfluxDbv2(http::url uri) { #ifdef O2_MONITORING_WITH_CURL @@ -82,10 +82,9 @@ std::unique_ptr getInfluxDbv2(http::url uri) if (tokenEnd < query.length() && query.at(tokenEnd) == '&') tokenEnd++; if (tokenStart > 0 && query.at(tokenStart-1) == '&') tokenStart--; query.erase(tokenStart, tokenEnd - tokenStart); - std::cout << uri.url << std::endl; - std::string headers = "Authorization: Token " + token; - auto transport = std::make_unique("http://" + uri.host + ':' + std::to_string(uri.port) + path + '?' + query, headers); + auto transport = std::make_unique("http://" + uri.host + ':' + std::to_string(uri.port) + path + '?' + query); + transport->addHeader("Authorization: Token " + token); return std::make_unique(std::move(transport)); #else throw std::runtime_error("HTTP transport is not enabled"); diff --git a/src/Transports/HTTP.cxx b/src/Transports/HTTP.cxx new file mode 100644 index 000000000..6d86a2b7c --- /dev/null +++ b/src/Transports/HTTP.cxx @@ -0,0 +1,68 @@ +/// +/// \file HTTP.cxx +/// \author Adam Wegrzynek +/// + +#include "HTTP.h" +#include "../MonLogger.h" +#include "../Exceptions/MonitoringException.h" +#include + +namespace o2 +{ +/// ALICE O2 Monitoring system +namespace monitoring +{ +/// Monitoring transports +namespace transports +{ + +HTTP::HTTP(const std::string& url) +{ + mHeaders = NULL; + mCurl = curl_easy_init(); + curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 10); + curl_easy_setopt(mCurl, CURLOPT_TIMEOUT, 10); + curl_easy_setopt(mCurl, CURLOPT_POST, 1); + curl_easy_setopt(mCurl, CURLOPT_TCP_KEEPIDLE, 120L); + curl_easy_setopt(mCurl, CURLOPT_TCP_KEEPINTVL, 60L); + FILE *devnull = fopen("/dev/null", "w+"); + curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, devnull); + + MonLogger::Get() << "HTTP transport initialized (" << url << ")" << MonLogger::End(); +} + +HTTP::~HTTP() +{ + curl_slist_free_all(mHeaders); + curl_easy_cleanup(mCurl); + curl_global_cleanup(); +} + +void HTTP::addHeader(const std::string& header) +{ + mHeaders = curl_slist_append(mHeaders, header.c_str()); + curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaders); +} + +void HTTP::send(std::string&& post) +{ + CURLcode response; + long responseCode; + curl_easy_setopt(mCurl, CURLOPT_POSTFIELDS, post.c_str()); + curl_easy_setopt(mCurl, CURLOPT_POSTFIELDSIZE, (long) post.length()); + response = curl_easy_perform(mCurl); + curl_easy_getinfo(mCurl, CURLINFO_RESPONSE_CODE, &responseCode); + if (response != CURLE_OK) { + MonLogger::Get() << "HTTP Tranport " << curl_easy_strerror(response) << MonLogger::End(); + } + if (responseCode < 200 || responseCode > 206) { + MonLogger::Get() << "HTTP Transport: Response code : " << std::to_string(responseCode) << MonLogger::End(); + } +} + +} // namespace transports +} // namespace monitoring +} // namespace o2 diff --git a/src/Transports/HTTP.h b/src/Transports/HTTP.h new file mode 100644 index 000000000..bd9b9b4e9 --- /dev/null +++ b/src/Transports/HTTP.h @@ -0,0 +1,54 @@ +/// +/// \file HTTP.h +/// \author Adam Wegrzynek +/// + +#ifndef ALICEO2_MONITORING_TRANSPORTS_HTTP_H +#define ALICEO2_MONITORING_TRANSPORTS_HTTP_H + +#include "TransportInterface.h" + +#include +#include + +namespace o2 +{ +/// ALICE O2 Monitoring system +namespace monitoring +{ +/// Monitoring transports +namespace transports +{ + +/// \brief HTTP POST transport +/// +/// Allows to push string formatted metrics as HTTP POST requests via cURL +class HTTP : public TransportInterface +{ + public: + /// Constructor + /// \param url URL of HTTP server endpoint + HTTP(const std::string& url); + + /// Destructor + ~HTTP(); + + /// Sends metric via HTTP POST + /// \param post r-value reference string formatted metric + void send(std::string&& post); + + /// Adds custom HTTP header + void addHeader(const std::string& header); + private: + /// CURL pointers + CURL *mCurl; + + /// HTTP headers struct + struct curl_slist *mHeaders; +}; + +} // namespace transports +} // namespace monitoring +} // namespace o2 + +#endif // ALICEO2_MONITORING_TRANSPORTS_HTTP_H diff --git a/test/testInfluxDb.cxx b/test/testInfluxDb.cxx index 261e15ced..d34a43c5d 100644 --- a/test/testInfluxDb.cxx +++ b/test/testInfluxDb.cxx @@ -19,7 +19,6 @@ namespace monitoring { namespace Test { -/* BOOST_AUTO_TEST_CASE(simplySendMetric) { auto monitoring = MonitoringFactory::Get("influxdb-udp://localhost:1000"); @@ -31,11 +30,10 @@ BOOST_AUTO_TEST_CASE(simplySendMetric2) auto monitoring = MonitoringFactory::Get("influxdb-stdout://"); monitoring->send(Metric{10, "myCrazyMetric"}); } -*/ + BOOST_AUTO_TEST_CASE(InfluxDbv2) { - auto monitoring = MonitoringFactory::Get("influxdbv2://localhost:9999?org=cern&bucket=test&token=c1WZvMvFK9KHrRAD68Ou8U4d9hljQm_haOjOL6Xn4oPM89nDZiJ5mwGrO-Z7YspoFnQP-4BIyhomf_Yq111fVg=="); - monitoring->send(Metric{10, "myCrazyMetric"}); + auto monitoring = MonitoringFactory::Get("influxdbv2://localhost:9999?org=cern&bucket=test&token=TOKEN"); } } // namespace Test